kernel: add extensive allocation tracking option

This commit is contained in:
K. Lange 2018-12-11 19:43:13 +09:00
parent 73a3dc1414
commit 5b45f72a37
2 changed files with 153 additions and 0 deletions

View File

@ -124,6 +124,32 @@
/* }}} */ /* }}} */
//#define _DEBUG_MALLOC
#ifdef _DEBUG_MALLOC
#define EARLY_LOG_DEVICE 0x3F8
static uint32_t _kmalloc_log_write(fs_node_t *node, uint64_t offset, uint32_t size, uint8_t *buffer) {
for (unsigned int i = 0; i < size; ++i) {
outportb(EARLY_LOG_DEVICE, buffer[i]);
}
return size;
}
static fs_node_t _kmalloc_log = { .write = &_kmalloc_log_write };
#define HALT_ON(_addr) do { \
if ((uintptr_t)ptr == _addr) { \
IRQ_OFF; \
struct { \
char c; \
uint32_t addr; \
uint32_t size; \
uint32_t extra; \
} __attribute__((packed)) log = {'h',0,0,0}; \
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log); \
while (1) {} \
} } while (0)
#endif
/* /*
* Internal functions. * Internal functions.
*/ */
@ -137,14 +163,52 @@ static spin_lock_t mem_lock = { 0 };
void * __attribute__ ((malloc)) malloc(uintptr_t size) { void * __attribute__ ((malloc)) malloc(uintptr_t size) {
spin_lock(mem_lock); spin_lock(mem_lock);
#ifdef _DEBUG_MALLOC
size += 8;
#endif
void * ret = klmalloc(size); void * ret = klmalloc(size);
#ifdef _DEBUG_MALLOC
if (ret) {
char * c = ret;
uintptr_t s = size-8;
memcpy(&c[size-4],&s,sizeof(uintptr_t));
s = 0xDEADBEEF;
memcpy(&c[size-8],&s,sizeof(uintptr_t));
}
struct {
char c;
uint32_t addr;
uint32_t size;
uint32_t extra;
} __attribute__((packed)) log = {'m',(uint32_t)ret,size-8,0xDEADBEEF};
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log);
#endif
spin_unlock(mem_lock); spin_unlock(mem_lock);
return ret; return ret;
} }
void * __attribute__ ((malloc)) realloc(void * ptr, uintptr_t size) { void * __attribute__ ((malloc)) realloc(void * ptr, uintptr_t size) {
spin_lock(mem_lock); spin_lock(mem_lock);
#ifdef _DEBUG_MALLOC
size += 8;
#endif
void * ret = klrealloc(ptr, size); void * ret = klrealloc(ptr, size);
#ifdef _DEBUG_MALLOC
if (ret) {
char * c = ret;
uintptr_t s = size-8;
memcpy(&c[size-4],&s,sizeof(uintptr_t));
s = 0xDEADBEEF;
memcpy(&c[size-8],&s,sizeof(uintptr_t));
}
struct {
char c;
uint32_t addr;
uint32_t size;
uint32_t extra;
} __attribute__((packed)) log = {'r',(uint32_t)ptr,size-8,(uint32_t)ret};
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log);
#endif
spin_unlock(mem_lock); spin_unlock(mem_lock);
return ret; return ret;
} }
@ -152,13 +216,41 @@ void * __attribute__ ((malloc)) realloc(void * ptr, uintptr_t size) {
void * __attribute__ ((malloc)) calloc(uintptr_t nmemb, uintptr_t size) { void * __attribute__ ((malloc)) calloc(uintptr_t nmemb, uintptr_t size) {
spin_lock(mem_lock); spin_lock(mem_lock);
void * ret = klcalloc(nmemb, size); void * ret = klcalloc(nmemb, size);
#ifdef _DEBUG_MALLOC
struct {
char c;
uint32_t addr;
uint32_t size;
uint32_t extra;
} __attribute__((packed)) log = {'c',(uint32_t)ret,size,nmemb};
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log);
#endif
spin_unlock(mem_lock); spin_unlock(mem_lock);
return ret; return ret;
} }
void * __attribute__ ((malloc)) valloc(uintptr_t size) { void * __attribute__ ((malloc)) valloc(uintptr_t size) {
spin_lock(mem_lock); spin_lock(mem_lock);
#ifdef _DEBUG_MALLOC
size += 8;
#endif
void * ret = klvalloc(size); void * ret = klvalloc(size);
#ifdef _DEBUG_MALLOC
if (ret) {
char * c = ret;
uintptr_t s = size-8;
memcpy(&c[size-4],&s,sizeof(uintptr_t));
s = 0xDEADBEEF;
memcpy(&c[size-8],&s,sizeof(uintptr_t));
}
struct {
char c;
uint32_t addr;
uint32_t size;
uint32_t extra;
} __attribute__((packed)) log = {'v',(uint32_t)ret,size-8,0xDEADBEEF};
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log);
#endif
spin_unlock(mem_lock); spin_unlock(mem_lock);
return ret; return ret;
} }
@ -166,6 +258,25 @@ void * __attribute__ ((malloc)) valloc(uintptr_t size) {
void free(void * ptr) { void free(void * ptr) {
spin_lock(mem_lock); spin_lock(mem_lock);
if ((uintptr_t)ptr > placement_pointer) { if ((uintptr_t)ptr > placement_pointer) {
#ifdef _DEBUG_MALLOC
HALT_ON(0x143c000);
IRQ_OFF;
char * tag = ptr;
uintptr_t i = 0;
uint32_t * x;
while (i < 102400) {
x = (uint32_t*)(tag + i);
if (*x == 0xDEADBEEF) break;
i++;
}
struct {
char c;
uint32_t addr;
uint32_t size;
uint32_t extra;
} __attribute__((packed)) log = {'f',(uint32_t)ptr,x[1],x[0]};
write_fs(&_kmalloc_log, 0, sizeof(log), (uint8_t *)&log);
#endif
klfree(ptr); klfree(ptr);
} }
spin_unlock(mem_lock); spin_unlock(mem_lock);

42
util/process_log.py Normal file
View File

@ -0,0 +1,42 @@
import struct
import sys
addresses = {}
while 1:
data = sys.stdin.read(13)
t, = struct.unpack_from("c",data,0)
addr, = struct.unpack_from("I",data,1)
size, = struct.unpack_from("I",data,5)
extra, = struct.unpack_from("I",data,9)
if t == 'm':
addresses[addr] = size
elif t == 'v':
addresses[addr] = size
elif t == 'c':
addresses[addr] = 'c'
elif t == 'r':
if addr not in addresses:
print("Bad realloc: 0x%x" % addr)
else:
addresses[addr] = None
addresses[extra] = size
elif t == 'f':
if addr not in addresses:
print("Bad free detected: 0x%x" % addr)
elif addresses[addr] is None:
print("Double free detected: 0x%x" % addr)
elif addresses[addr] == 'c':
print("freeing something that was calloced...")
addresses[addr] = None
elif addresses[addr] != size:
print("Size on free is incorrect: 0x%x %d %d" % (addr,addresses[addr], size))
elif extra != 0xDEADBEEF:
print("Extremely large buffer or otherwise bad free (but size is right?): 0x%x" % addr)
else:
addresses[addr] = None
else:
print("Garbage data detected: ", t, addr, size, extra)
break