From 774624470afcb6d19487ac53fee680ae1f4611bb Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Sun, 21 Aug 2016 12:55:11 -0400 Subject: [PATCH] Allocation debugging --- common.mk | 2 +- include/input.h | 5 +++ include/std/allocator.h | 29 ++++++++++++++++ source/firm/firm.c | 10 ++++-- source/input.c | 12 +++++++ source/interpreter.c | 1 - source/patch/reboot.c | 2 -- source/patcher.c | 10 ------ source/std/allocator.c | 76 ++++++++++++++++++++++++++++++++++++++--- source/std/fs.c | 28 ++++++++++----- 10 files changed, 145 insertions(+), 30 deletions(-) diff --git a/common.mk b/common.mk index 326bcab..51ab1d1 100644 --- a/common.mk +++ b/common.mk @@ -14,7 +14,7 @@ AM_CFLAGS= -std=gnu11 -Os -g -ffast-math \ -Wundef -Wno-unused -Werror -Wno-error=cast-align -Wno-error=strict-overflow -Wno-error=pedantic \ $(THUMBFLAGS) $(SIZE_OPTIMIZATION) $(INCPATHS) $(C9FLAGS) \ -fno-builtin -std=gnu11 -DREVISION=\"$(REVISION)\" \ - -DFW_NAME=\"corbenik\" $(PATHARGS) + -DFW_NAME=\"corbenik\" $(PATHARGS) -DMALLOC_DEBUG=1 AM_LDFLAGS=-Wl,--use-blx,--pic-veneer,-q -nostdlib -nodefaultlibs -Wl,-z,defs -lgcc \ diff --git a/include/input.h b/include/input.h index 3f94a17..be263f3 100644 --- a/include/input.h +++ b/include/input.h @@ -10,4 +10,9 @@ */ uint32_t wait_key(_UNUSED int sleep); +/* Displays a prompt on the bottom screen if the relevant option is enabled and waits on input + * to continue. + */ +void wait(); + #endif diff --git a/include/std/allocator.h b/include/std/allocator.h index 8605067..1f49a4a 100644 --- a/include/std/allocator.h +++ b/include/std/allocator.h @@ -12,6 +12,33 @@ */ void *sbrk(size_t bytes); +#ifdef MALLOC_DEBUG + +/* Prints stats for allocation to stderr. + */ +void print_alloc_stats(); + +/* Allocate memory for use (debugging only, don't call) + * + * \param size Size in bytes to allocate. + * \param info Info to store about malloc + */ +void* malloc_chkd(size_t size, char* info); + +/* Free in-use memory allocated by malloc (debugging only, don't call) + * + * \param ptr Pointer to free. + * \param info Info to store about free + */ +void free_chkd(void* ptr, char* info); + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define malloc(x) malloc_chkd( x , __FILE__ ":" TOSTRING(__LINE__) ) +#define free(x) free_chkd( x , __FILE__ ":" TOSTRING(__LINE__) ) + +#else + /* Allocate memory for use. * * \param size Size in bytes to allocate. @@ -25,3 +52,5 @@ void *malloc (size_t size); void free (void* ptr); #endif + +#endif diff --git a/source/firm/firm.c b/source/firm/firm.c index 6a6e9b2..c132cb8 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -409,8 +409,6 @@ load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uint32_ return 0; } -extern void wait(); - __attribute__ ((noreturn)) void boot_firm() @@ -439,6 +437,14 @@ boot_firm() fprintf(stderr, "Updated keyX keyslots.\n"); } +#ifdef MALLOC_DEBUG + print_alloc_stats(); + wait(); +#endif + + // Beyond this point, using malloc() memory is unsafe, since we're trashing memory possibly. + // free() is also irrelevant from here on. + for (firm_section_h *section = firm_loc->section; section < firm_loc->section + 4 && section->address != 0; section++) { memcpy((void *)section->address, (void *)((uint8_t*)firm_loc + section->offset), section->size); } diff --git a/source/input.c b/source/input.c index 12978aa..9d94003 100644 --- a/source/input.c +++ b/source/input.c @@ -38,3 +38,15 @@ wait_key(_UNUSED int sleep) return ret; } +extern int doing_autoboot; + +void +wait() +{ + if (config->options[OPTION_TRACE] && !doing_autoboot) { + fprintf(stderr, "[Waiting...]"); + wait_key(0); // No delay on traces. + } + fprintf(stderr, "\r \r"); +} + diff --git a/source/interpreter.c b/source/interpreter.c index f732ebf..58c55d8 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -56,7 +56,6 @@ } #else #define log(a) fprintf(stderr, a) - int wait(); #endif struct mode diff --git a/source/patch/reboot.c b/source/patch/reboot.c index 96ebd68..d50237f 100644 --- a/source/patch/reboot.c +++ b/source/patch/reboot.c @@ -4,8 +4,6 @@ #include #include -int wait(); - uint8_t* getProcess9(uint8_t *pos, uint32_t size, uint32_t *process9Size, uint32_t *process9MemAddr) { diff --git a/source/patcher.c b/source/patcher.c index 8cdcfc5..d24256f 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -13,16 +13,6 @@ extern uint8_t *enable_list; extern struct options_s* patches; -void -wait() -{ - if (config->options[OPTION_TRACE] && !doing_autoboot) { - fprintf(stderr, "[Waiting...]"); - wait_key(0); // No delay on traces. - } - fprintf(stderr, " \r"); -} - void list_patches_build(char *name, int desc_is_fname); void diff --git a/source/std/allocator.c b/source/std/allocator.c index 02d4dec..b9489be 100644 --- a/source/std/allocator.c +++ b/source/std/allocator.c @@ -26,38 +26,104 @@ void* sbrk(size_t incr) { typedef struct free_block { size_t size; +#ifdef MALLOC_DEBUG + char* info; +#endif struct free_block* next; } free_block; -static free_block free_block_list_head = { 0, 0 }; +static free_block free_block_list_head = { + 0, +#ifdef MALLOC_DEBUG + NULL, +#endif + 0 +}; // static const size_t overhead = sizeof(size_t); static const size_t align_to = 16; +#ifdef MALLOC_DEBUG +static size_t alloc_count = 0; +static size_t free_count = 0; +static size_t allocated_memory = 0; +#endif + +#ifdef MALLOC_DEBUG +void* malloc_chkd(size_t size, char* info) { +#else void* malloc(size_t size) { - size = (size + sizeof(free_block) + (align_to - 1)) & ~ (align_to - 1); +#endif + size_t bsize = (size + sizeof(free_block) + (align_to - 1)) & ~ (align_to - 1); + free_block* block = free_block_list_head.next; free_block** head = &(free_block_list_head.next); + while (block != 0) { - if (block->size >= size) { + if (block->size >= bsize) { *head = block->next; + +#ifdef MALLOC_DEBUG + block->info = info; + + ++alloc_count; + allocated_memory += block->size; +#endif + return ((char*)block) + sizeof(free_block); } head = &(block->next); block = block->next; } - block = (free_block*)sbrk(size); - block->size = size; + block = (free_block*)sbrk(bsize); + block->size = bsize; + +#ifdef MALLOC_DEBUG + block->info = info; + + ++alloc_count; + allocated_memory += bsize; +#endif return ((char*)block) + sizeof(free_block); } +void* malloc_zero(size_t size) { + void* ret = malloc(size); + + if (ret) + memset(ret, 0, size); + + return ret; +} + +#ifdef MALLOC_DEBUG +void free_chkd(void* ptr, char* info) { +#else void free(void* ptr) { +#endif if (ptr == NULL) return; free_block* block = (free_block*)(((char*)ptr) - sizeof(free_block )); + +#ifdef MALLOC_DEBUG + ++free_count; + if (allocated_memory < block->size) { + fprintf(stderr, "%s: Invalid free detected.\n" + " Allocated at: %s\n", + info, block->info); + } + allocated_memory -= block->size; +#endif + block->next = free_block_list_head.next; free_block_list_head.next = block; } + +#ifdef MALLOC_DEBUG +void print_alloc_stats() { + fprintf(stderr, "[A] %u [F] %u [M] %u [B] %lu\n", alloc_count, free_count, allocated_memory, (uint32_t)heap_end - (uint32_t)&__end__); +} +#endif diff --git a/source/std/fs.c b/source/std/fs.c index 7bc4dd8..610263c 100644 --- a/source/std/fs.c +++ b/source/std/fs.c @@ -104,7 +104,7 @@ fopen(const char *filename, const char *mode) if (f_open(&(fp->handle), filename, fp->mode)) { free(fp); return NULL; - } + } fp->is_open = 1; @@ -114,7 +114,7 @@ fopen(const char *filename, const char *mode) void fclose(FILE *fp) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return; f_close(&(fp->handle)); @@ -127,7 +127,7 @@ fclose(FILE *fp) void fseek(FILE *fp, int64_t offset, int whence) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return; uint32_t fixed_offset; @@ -151,7 +151,7 @@ fseek(FILE *fp, int64_t offset, int whence) size_t ftell(FILE *fp) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return 0; return f_tell(&(fp->handle)); @@ -160,7 +160,7 @@ ftell(FILE *fp) int feof(FILE *fp) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return 0; return f_eof(&(fp->handle)); @@ -169,7 +169,7 @@ feof(FILE *fp) size_t fsize(FILE *fp) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return 0; return f_size(&(fp->handle)); @@ -178,7 +178,7 @@ fsize(FILE *fp) size_t fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) { - if (!fp->is_open) + if (fp == NULL || !fp->is_open) return 0; UINT br; @@ -209,9 +209,14 @@ write_file(void *data, char *path, size_t size) { FILE *temp = fopen(path, "w"); - if (!temp || !temp->is_open) + if (!temp) return 0; + if (!temp->is_open) { + fclose(temp); + return 0; + } + size_t wrote = fwrite(data, 1, size, temp); fclose(temp); @@ -224,9 +229,14 @@ read_file(void *data, char *path, size_t size) { FILE *temp = fopen(path, "r"); - if (!temp || !temp->is_open) + if (!temp) return 0; + if (!temp->is_open) { + fclose(temp); + return 0; + } + size_t read = fread(data, 1, size, temp); fclose(temp); -- 2.39.5