Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
308 lines (217 sloc) 6.86 KB
#include "PancakeDebug.h"
#include "PancakeWorkers.h"
#ifdef PANCAKE_DEBUG
/* Directly allocate memory allocation information hash tables to prevent recursion in allocator */
#undef uthash_malloc
#undef uthash_free
#define uthash_malloc malloc
#define uthash_free(ptr, sz) free(ptr)
static PancakeAllocatedMemory *allocated = NULL;
static UNative totalAllocated = 0;
static UNative peakAllocated = 0;
#ifdef HAVE_PANCAKE_SIGSEGV
void PancakeDebugHandleSegfault(Int32 signum, siginfo_t *info, void *context) {
ucontext_t *ucontext = (ucontext_t*) context;
void *array[50], *caller;
Native size, i;
Byte **strings;
#ifdef PANCAKE_64
caller = (void*) ucontext->uc_mcontext.gregs[REG_RIP];
#else
caller = (void*) ucontext->uc_mcontext.gregs[REG_EIP];
#endif
printf("Segmentation fault at %p (called by %p)\n", info->si_addr, caller);
printf("Backtrace:\n");
size = backtrace(array, 50);
array[1] = caller;
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
printf("in worker %s\n", PancakeCurrentWorker->name.value);
exit(1);
}
#endif
PANCAKE_API void _PancakeAssert(Native result, Byte *condition, Byte *file, Int32 line) {
if(!result) {
printf("Assertion failed: %s in file %s on line %i\n", condition, file, line);
#ifdef HAVE_EXECINFO_H
void *array[50];
Native size, i;
Byte **strings;
printf("Backtrace:\n");
size = backtrace(array, 50);
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
#endif
exit(1);
}
}
PANCAKE_API void *_PancakeAllocate(Native size, Byte *file, Int32 line) {
void *ptr = malloc(size + 1);
PancakeAllocatedMemory *mem;
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = size;
totalAllocated += size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
((UByte*) ptr)[size] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API void *_PancakeReallocate(void *ptr, Native size, Byte *file, Int32 line) {
PancakeAllocatedMemory *mem;
void *newPtr;
if(ptr == NULL) {
return _PancakeAllocate(size, file, line);
}
if(size == 0) {
_PancakeFree(ptr, file, line);
return NULL;
}
HASH_FIND(hh, allocated, &ptr, sizeof(void*), mem);
_PancakeAssert(mem != NULL, "Trying to reallocate invalid pointer", file, line);
// Check for memory overflow
_PancakeAssert(((UByte*) ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
newPtr = realloc(ptr, size + 1);
_PancakeAssert(newPtr != NULL, "Out of memory", file, line);
// Set overflow detection byte
((UByte*) newPtr)[size] = 0xff;
totalAllocated -= mem->size;
mem->ptr = newPtr;
mem->size = size;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
HASH_DEL(allocated, mem);
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return newPtr;
}
PANCAKE_API void _PancakeFree(void *ptr, Byte *file, Int32 line) {
PancakeAllocatedMemory *mem;
_PancakeAssert(ptr != NULL, "Trying to free NULL pointer", file, line);
HASH_FIND(hh, allocated, &ptr, sizeof(void*), mem);
_PancakeAssert(mem != NULL, "Trying to free invalid pointer", file, line);
// Check for memory overflow
_PancakeAssert(((UByte*) ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
totalAllocated -= mem->size;
free(ptr);
HASH_DEL(allocated, mem);
free(mem);
}
PANCAKE_API Byte *_PancakeDuplicateString(Byte *string, Byte *file, Int32 line) {
Byte *ptr;
PancakeAllocatedMemory *mem;
UInt32 size;
_PancakeAssert(string != NULL, "Trying to duplicate NULL pointer", file, line);
size = strlen(string);
ptr = malloc(size + 2);
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
memcpy(ptr, string, size + 1);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = size + 1;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
ptr[size + 2] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API Byte *_PancakeDuplicateStringLength(Byte *string, Int32 length, Byte *file, Int32 line) {
Byte *ptr;
PancakeAllocatedMemory *mem;
_PancakeAssert(string != NULL, "Trying to duplicate NULL pointer", file, line);
ptr = malloc(length + 2);
_PancakeAssert(ptr != NULL, "Out of memory", file, line);
memcpy(ptr, string, length + 1);
mem = malloc(sizeof(PancakeAllocatedMemory));
_PancakeAssert(mem != NULL, "Out of memory", file, line);
mem->file = file;
mem->line = line;
mem->ptr = ptr;
mem->size = length + 1;
totalAllocated += mem->size;
if(totalAllocated > peakAllocated) {
peakAllocated = totalAllocated;
}
// Set overflow detection byte
ptr[length + 2] = 0xff;
HASH_ADD(hh, allocated, ptr, sizeof(void*), mem);
return ptr;
}
PANCAKE_API void PancakeCheckHeap() {
PancakeAllocatedMemory *mem;
for(mem = allocated; mem != NULL; mem = mem->hh.next) {
_PancakeAssert(((UByte*) mem->ptr)[mem->size] == 0xff, "Overflow detected in memory allocated", mem->file, mem->line);
}
}
PANCAKE_API void PancakeDumpHeap() {
PancakeAllocatedMemory *mem;
pid_t pid = getpid();
for(mem = allocated; mem != NULL; mem = mem->hh.next) {
printf("[%i] [%#lx] %u bytes allocated in %s on line %i\n", pid, (UNative) mem->ptr, mem->size, mem->file, mem->line);
}
}
PANCAKE_API void PancakeDumpMemoryUsage() {
pid_t pid = getpid();
if(totalAllocated) {
printf("[%i] %lu bytes total allocated\n", pid, totalAllocated);
}
printf("[%i] %lu bytes allocated at peak\n", pid, peakAllocated);
}
PANCAKE_API void PancakeFreeAllocatorMeta() {
PancakeAllocatedMemory *mem, *tmp;
HASH_ITER(hh, allocated, mem, tmp) {
HASH_DEL(allocated, mem);
free(mem);
}
}
PANCAKE_API void PancakePrintString(String *string) {
printf("String(%lu) \"%.*s\"\n", string->length, (Int32) string->length, string->value);
}
PANCAKE_API void PancakePrintNetworkBuffer(PancakeNetworkBuffer *buf) {
printf("NetworkBuffer(%u, %u) \"%.*s\"\n", buf->length, buf->size, buf->length, buf->value);
}
PANCAKE_API void PancakeBacktrace() {
#ifdef HAVE_EXECINFO_H
void *array[50];
Native size, i;
Byte **strings;
size = backtrace(array, 50);
strings = backtrace_symbols(array, size);
if(strings == NULL) {
exit(1);
}
for(i = 0; i < size; i++) {
printf("#%li %s\n", size - i, strings[i]);
}
free(strings);
#else
printf("Backtraces not available\n");
#endif
}
#endif