Last active
November 9, 2018 18:12
-
-
Save multun/f8077d8ee5d9dcc2a6b5f947044c1da8 to your computer and use it in GitHub Desktop.
Poor man's embed-ish allocation tracker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
// random hash implementation from the internet | |
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) | |
#define mix(a, b, c) \ | |
{ \ | |
a -= c; a ^= rot(c, 4); c += b; \ | |
b -= a; b ^= rot(a, 6); a += c; \ | |
c -= b; c ^= rot(b, 8); b += a; \ | |
a -= c; a ^= rot(c,16); c += b; \ | |
b -= a; b ^= rot(a,19); a += c; \ | |
c -= b; c ^= rot(b, 4); b += a; \ | |
} | |
#define final(a, b, c) \ | |
{ \ | |
c ^= b; c -= rot(b,14); \ | |
a ^= c; a -= rot(c,11); \ | |
b ^= a; b -= rot(a,25); \ | |
c ^= b; c -= rot(b,16); \ | |
a ^= c; a -= rot(c,4); \ | |
b ^= a; b -= rot(a,14); \ | |
c ^= b; c -= rot(b,24); \ | |
} | |
uint32_t lookup3 (const void *key, | |
size_t length, | |
uint32_t initval) | |
{ | |
uint32_t a,b,c; | |
const uint8_t *k; | |
const uint32_t *data32Bit; | |
data32Bit = key; | |
a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; | |
while (length > 12) { | |
a += *(data32Bit++); | |
b += *(data32Bit++); | |
c += *(data32Bit++); | |
mix(a,b,c); | |
length -= 12; | |
} | |
k = (const uint8_t *)data32Bit; | |
switch (length) { | |
case 12: c += ((uint32_t)k[11])<<24; | |
case 11: c += ((uint32_t)k[10])<<16; | |
case 10: c += ((uint32_t)k[9])<<8; | |
case 9 : c += k[8]; | |
case 8 : b += ((uint32_t)k[7])<<24; | |
case 7 : b += ((uint32_t)k[6])<<16; | |
case 6 : b += ((uint32_t)k[5])<<8; | |
case 5 : b += k[4]; | |
case 4 : a += ((uint32_t)k[3])<<24; | |
case 3 : a += ((uint32_t)k[2])<<16; | |
case 2 : a += ((uint32_t)k[1])<<8; | |
case 1 : a += k[0]; | |
break; | |
case 0 : return c; | |
} | |
final(a,b,c); | |
return c; | |
} | |
static uint32_t pointer_hash(uint64_t pointer) | |
{ | |
return lookup3(&pointer, sizeof(uint64_t), 0); | |
} | |
// the last bit of the address if used to keep track of whether it's still there | |
#define PRESENT_FLAG (1uL << (sizeof(uint64_t) * 8 - 1)) | |
#define ALLOC_ADDRESS(Addr) ((Addr) & ~PRESENT_FLAG) | |
#define ALLOC_PRESENT(Addr) ((Addr) & PRESENT_FLAG) | |
uint64_t alloc_map[MAX_ALLOCS]; | |
uint64_t *find_registry(uint64_t target_addr) | |
{ | |
uint64_t *res; | |
uint64_t current_hash = target_addr; | |
uint64_t current_addr; | |
do { | |
current_hash = pointer_hash(current_hash); | |
res = &alloc_map[current_hash % MAX_ALLOCS]; | |
uint64_t alloc_meta = *res; | |
if (alloc_meta == 0) | |
return res; | |
current_addr = ALLOC_ADDRESS(alloc_meta); | |
} while (current_addr != target_addr); | |
return res; | |
} | |
void register_alloc(void *mem) | |
{ | |
uint64_t target_addr = (uint64_t)mem; | |
uint64_t *registry = find_registry(target_addr); | |
uint64_t metadata = *registry; | |
assert(!ALLOC_PRESENT(metadata)); | |
*registry = target_addr | PRESENT_FLAG; | |
} | |
void unregister_alloc(void *mem) | |
{ | |
uint64_t target_addr = (uint64_t)mem; | |
uint64_t *registry = find_registry(target_addr); | |
uint64_t metadata = *registry; | |
assert(ALLOC_PRESENT(metadata)); | |
*registry = target_addr; | |
} | |
int main() | |
{ | |
char arr[42]; | |
*find_registry((uint64_t)arr) = 42; | |
register_alloc(arr); | |
register_alloc(arr); | |
unregister_alloc(arr); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment