X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=stat.c;h=e46102da51d3ec8e337cfb49217615be63af7f56;hb=d9572e3e303929e1b6d7267d43c0904dac3078f5;hp=ffb5b227f26283b41add9cb27aefee081fa94c8c;hpb=89893f9a2468575e78eef64e8f6a2628034e9c56;p=xonotic%2Fgmqcc.git diff --git a/stat.c b/stat.c index ffb5b22..e46102d 100644 --- a/stat.c +++ b/stat.c @@ -56,6 +56,7 @@ typedef struct stat_mem_block_s { const char *file; size_t line; size_t size; + const char *expr; struct stat_mem_block_s *next; struct stat_mem_block_s *prev; } stat_mem_block_t; @@ -119,7 +120,7 @@ static void stat_size_put(stat_size_table_t table, size_t key, size_t value) { * information as a header, returns the memory + 1 past it, can be * retrieved again with - 1. Where type is stat_mem_block_t*. */ -void *stat_mem_allocate(size_t size, size_t line, const char *file) { +void *stat_mem_allocate(size_t size, size_t line, const char *file, const char *expr) { stat_mem_block_t *info = (stat_mem_block_t*)malloc(sizeof(stat_mem_block_t) + size); void *data = (void*)(info + 1); @@ -129,6 +130,7 @@ void *stat_mem_allocate(size_t size, size_t line, const char *file) { info->line = line; info->size = size; info->file = file; + info->expr = expr; info->prev = NULL; info->next = stat_mem_block_root; @@ -159,7 +161,7 @@ void stat_mem_deallocate(void *ptr) { info = ((stat_mem_block_t*)ptr - 1); - /* + /* * we need access to the redzone that represents the info block * so lets do that. */ @@ -193,12 +195,12 @@ void stat_mem_deallocate(void *ptr) { VALGRIND_FREELIKE_BLOCK(ptr, sizeof(stat_mem_block_t)); } -void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file) { +void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file, const char *expr) { stat_mem_block_t *oldinfo = NULL; stat_mem_block_t *newinfo; if (GMQCC_UNLIKELY(!ptr)) - return stat_mem_allocate(size, line, file); + return stat_mem_allocate(size, line, file, expr); /* stay consistent with glibc */ if (GMQCC_UNLIKELY(!size)) { @@ -228,7 +230,7 @@ void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file) /* don't need access anymore */ VALGRIND_MAKE_MEM_NOACCESS(oldinfo->prev, sizeof(stat_mem_block_t)); } - + if (oldinfo->next) { /* just need access for a short period */ VALGRIND_MAKE_MEM_DEFINED(oldinfo->next, sizeof(stat_mem_block_t)); @@ -247,10 +249,11 @@ void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file) newinfo->line = line; newinfo->size = size; newinfo->file = file; + newinfo->expr = expr; newinfo->prev = NULL; newinfo->next = stat_mem_block_root; - /* + /* * likely since the only time there is no root is when it's * being initialized first. */ @@ -268,7 +271,7 @@ void *stat_mem_reallocate(void *ptr, size_t size, size_t line, const char *file) stat_mem_allocated += newinfo->size; stat_mem_high += newinfo->size; - /* + /* * we're finished with the redzones, lets kill the access * to them. */ @@ -296,7 +299,7 @@ char *stat_mem_strdup(const char *src, size_t line, const char *file, bool empty return NULL; len = strlen(src); - if (((!empty) ? len : true) && (ptr = (char*)stat_mem_allocate(len + 1, line, file))) { + if (((!empty) ? len : true) && (ptr = (char*)stat_mem_allocate(len + 1, line, file, "strdup"))) { memcpy(ptr, src, len); ptr[len] = '\0'; } @@ -412,7 +415,7 @@ GMQCC_INLINE size_t util_hthash(hash_table_t *ht, const char *key) { uint32_t k; uint32_t h = 0x1EF0 ^ len; - for (i = -block; i; i++) { + for (i = -((int)block); i; i++) { k = blocks[i]; k *= mask1; k = GMQCC_ROTL32(k, 15); @@ -681,26 +684,34 @@ void util_htdel(hash_table_t *ht) { * The following functions below implement printing / dumping of statistical * information. */ -static void stat_dump_mem_contents(stat_mem_block_t *memory, uint16_t cols) { - uint32_t i, j; - for (i = 0; i < memory->size + ((memory->size % cols) ? (cols - memory->size % cols) : 0); i++) { - if (i % cols == 0) con_out(" 0x%06X: ", i); - if (i < memory->size) con_out("%02X " , 0xFF & ((unsigned char*)(memory + 1))[i]); - else con_out(" "); - - if ((uint16_t)(i % cols) == (cols - 1)) { - for (j = i - (cols - 1); j <= i; j++) { - con_out("%c", - (j >= memory->size) - ? ' ' - : (util_isprint(((unsigned char*)(memory + 1))[j])) - ? 0xFF & ((unsigned char*)(memory + 1)) [j] - : '.' - ); - } - con_out("\n"); +static void stat_dump_mem_contents(stat_mem_block_t *block, uint16_t cols) { + unsigned char *buffer = mem_a(cols); + unsigned char *memory = (unsigned char *)(block + 1); + size_t i; + + for (i = 0; i < block->size; i++) { + if (!(i % 16)) { + if (i != 0) + con_out(" %s\n", buffer); + con_out(" 0x%08X: ", i); } + + con_out(" %02X", memory[i]); + + buffer[i % cols] = ((memory[i] < 0x20) || (memory[i] > 0x7E)) + ? '.' + : memory[i]; + + buffer[(i % cols) + 1] = '\0'; } + + while ((i % cols) != 0) { + con_out(" "); + i++; + } + + con_out(" %s\n", buffer); + mem_d(buffer); } static void stat_dump_mem_leaks(void) { @@ -710,15 +721,16 @@ static void stat_dump_mem_leaks(void) { for (info = stat_mem_block_root; info; info = info->next) { /* we need access to the block */ VALGRIND_MAKE_MEM_DEFINED(info, sizeof(stat_mem_block_t)); - con_out("lost: %u (bytes) at %s:%u\n", + con_out("lost: %u (bytes) at %s:%u from expression `%s`\n", info->size, info->file, - info->line + info->line, + info->expr ); stat_dump_mem_contents(info, OPTS_OPTION_U16(OPTION_MEMDUMPCOLS)); - /* + /* * we're finished with the access, the redzone should be marked * inaccesible so that invalid read/writes that could 'step-into' * those redzones will show up as invalid read/writes in valgrind.