From 337a22147abb2a991ac2b91f4c7f14559a85247b Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Tue, 25 Sep 2007 01:13:17 +0000 Subject: [PATCH] Reduce code duplication among platforms, support hooking and unhooking (392009, r=dbaron). git-svn-id: svn://10.0.0.236/trunk@236629 18797224-902f-48f8-a5cc-f745e15eee43 --- .../tools/trace-malloc/lib/nsTraceMalloc.c | 661 ++++++------------ .../trace-malloc/lib/nsTraceMallocCallbacks.h | 2 - 2 files changed, 217 insertions(+), 446 deletions(-) diff --git a/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c b/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c index f137de37761..360f9d9de9a 100644 --- a/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c +++ b/mozilla/tools/trace-malloc/lib/nsTraceMalloc.c @@ -40,12 +40,10 @@ * ***** END LICENSE BLOCK ***** */ #ifdef NS_TRACE_MALLOC /* - * TODO: - * - extend logfile so 'F' record tells free stack - * - diagnose rusty's SMP realloc oldsize corruption bug - * - #ifdef __linux__/x86 and port to other platforms - * - unify calltree with gc/boehm somehow (common utility lib?) - */ + * TODO: + * - FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=392008 + * - extend logfile so 'F' record tells free stack + */ #include #include #include @@ -77,41 +75,43 @@ #define WRITE_FLAGS "w" #define __libc_malloc(x) malloc(x) -#define __libc_calloc(x, y) calloc(x, y) #define __libc_realloc(x, y) realloc(x, y) #define __libc_free(x) free(x) #elif defined(XP_UNIX) +#include + #define WRITE_FLAGS "w" #ifdef WRAP_SYSTEM_INCLUDES #pragma GCC visibility push(default) #endif extern __ptr_t __libc_malloc(size_t); -extern __ptr_t __libc_calloc(size_t, size_t); extern __ptr_t __libc_realloc(__ptr_t, size_t); extern void __libc_free(__ptr_t); extern __ptr_t __libc_memalign(size_t, size_t); -extern __ptr_t __libc_valloc(size_t); #ifdef WRAP_SYSTEM_INCLUDES #pragma GCC visibility pop #endif #elif defined(XP_WIN32) -#include /*for timeb*/ -#include /*for fstat*/ +#include /* for timeb */ +#include /* for fstat */ #include /*for write*/ #define WRITE_FLAGS "w" #define __libc_malloc(x) dhw_orig_malloc(x) -#define __libc_calloc(x, y) dhw_orig_calloc(x,y) #define __libc_realloc(x, y) dhw_orig_realloc(x,y) #define __libc_free(x) dhw_orig_free(x) +#else /* not XP_MACOSX, XP_UNIX, or XP_WIN32 */ + +# error "Unknown build configuration!" + #endif typedef struct logfile logfile; @@ -144,11 +144,11 @@ static char *sdlogname = NULL; /* filename for shutdown leak log */ * This enables/disables trace-malloc logging. * * It is separate from suppress_tracing so that we do not have to pay - * the performance cost of repeated PR_GetThreadPrivate calls when + * the performance cost of repeated TM_TLS_GET_DATA calls when * trace-malloc is disabled (which is not as bad as the locking we used * to have). */ -static int tracing_enabled = 1; +static uint32 tracing_enabled = 1; /* * This lock must be held while manipulating the calltree, the @@ -575,7 +575,8 @@ static PLHashTable *filenames = NULL; /* Table mapping method names to logged 'N' record serial numbers. */ static PLHashTable *methods = NULL; -static callsite *calltree(void **stack, size_t num_stack_entries) +static callsite * +calltree(void **stack, size_t num_stack_entries) { logfile *fp = logfp; void *pc; @@ -862,16 +863,17 @@ static callsite *calltree(void **stack, size_t num_stack_entries) calltree_maxstack_top = site; TM_EXIT_LOCK(); - return site; + fail: TM_EXIT_LOCK(); return NULL; } - -/* buffer the stack so that we can reverse it */ - +/* + * Buffer the stack from top at low index to bottom at high, so that we can + * reverse it in calltree. + */ PR_STATIC_CALLBACK(void) stack_callback(void *pc, void *closure) { @@ -889,7 +891,6 @@ stack_callback(void *pc, void *closure) /* * The caller MUST NOT be holding tmlock when calling backtrace. */ - callsite * backtrace(tm_thread *t, int skip) { @@ -1027,386 +1028,13 @@ static PLHashTable *new_allocations(void) #define get_allocations() (allocations ? allocations : new_allocations()) -#if defined(XP_UNIX) && !defined(XP_MACOSX) - -NS_EXTERNAL_VIS_(__ptr_t) -malloc(size_t size) -{ - PRUint32 start, end; - __ptr_t ptr; - callsite *site; - PLHashEntry *he; - allocation *alloc; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_malloc(size); - } - - start = PR_IntervalNow(); - ptr = __libc_malloc(size); - end = PR_IntervalNow(); - - site = backtrace(t, 1); - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.malloc_calls++; - if (!ptr) { - tmstats.malloc_failures++; - } else { - if (site) - log_event5(logfp, TM_EVENT_MALLOC, - site->serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size); - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - - return ptr; -} - -NS_EXTERNAL_VIS_(__ptr_t) -calloc(size_t count, size_t size) -{ - PRUint32 start, end; - __ptr_t ptr; - callsite *site; - PLHashEntry *he; - allocation *alloc; - tm_thread *t; - - /** - * During the initialization of the glibc/libpthread, and - * before main() is running, ld-linux.so.2 tries to allocate memory - * using calloc (call from _dl_tls_setup). - * - * Thus, our calloc replacement is invoked too early, tries to - * initialize NSPR, which calls dlopen, which calls into the dl - * -> crash. - * - * Delaying NSPR calls until NSPR is initialized helps. - */ - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_calloc(count, size); - } - - start = PR_IntervalNow(); - ptr = __libc_calloc(count, size); - end = PR_IntervalNow(); - - site = backtrace(t, 1); - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.calloc_calls++; - if (!ptr) { - tmstats.calloc_failures++; - } else { - size *= count; - if (site) { - log_event5(logfp, TM_EVENT_CALLOC, - site->serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size); - } - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - return ptr; -} - -NS_EXTERNAL_VIS_(__ptr_t) -realloc(__ptr_t ptr, size_t size) -{ - PRUint32 start, end; - __ptr_t oldptr; - callsite *oldsite, *site; - size_t oldsize; - PLHashNumber hash; - PLHashEntry **hep, *he; - allocation *alloc; - FILE *trackfp = NULL; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_realloc(ptr, size); - } - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.realloc_calls++; - if (PR_TRUE) { - oldptr = ptr; - oldsite = NULL; - oldsize = 0; - he = NULL; - if (oldptr && get_allocations()) { - hash = hash_pointer(oldptr); - hep = PL_HashTableRawLookup(allocations, hash, oldptr); - he = *hep; - if (he) { - oldsite = (callsite*) he->value; - alloc = (allocation*) he; - oldsize = alloc->size; - trackfp = alloc->trackfp; - if (trackfp) { - fprintf(alloc->trackfp, - "\nrealloc(%p, %lu), oldsize %lu, alloc site %p\n", - (void*) ptr, (unsigned long) size, - (unsigned long) oldsize, (void*) oldsite); - NS_TraceStack(1, trackfp); - } - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - - start = PR_IntervalNow(); - ptr = __libc_realloc(ptr, size); - end = PR_IntervalNow(); - - site = backtrace(t, 1); - - t->suppress_tracing++; - TM_ENTER_LOCK(); - if (!ptr && size) { - /* - * When realloc() fails, the original block is not freed or moved, so - * we'll leave the allocation entry untouched. - */ - tmstats.realloc_failures++; - } else { - if (site) { - log_event8(logfp, TM_EVENT_REALLOC, - site->serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size, - oldsite ? oldsite->serial : 0, - (uint32)NS_PTR_TO_INT32(oldptr), oldsize); - } - if (ptr && allocations) { - if (ptr != oldptr) { - /* - * If we're reallocating (not merely allocating new space by - * passing null to realloc) and realloc has moved the block, - * free oldptr. - */ - if (he) - PL_HashTableRemove(allocations, oldptr); - - /* Record the new allocation now, setting he. */ - he = PL_HashTableAdd(allocations, ptr, site); - } else { - /* - * If we haven't yet recorded an allocation (possibly due to - * a temporary memory shortage), do it now. - */ - if (!he) - he = PL_HashTableAdd(allocations, ptr, site); - } - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = trackfp; - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - return ptr; -} - -NS_EXTERNAL_VIS_(void*) -valloc(size_t size) -{ - PRUint32 start, end; - __ptr_t ptr; - callsite *site; - PLHashEntry *he; - allocation *alloc; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_valloc(size); - } - - start = PR_IntervalNow(); - ptr = __libc_valloc(size); - end = PR_IntervalNow(); - - site = backtrace(t, 1); - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.malloc_calls++; /* XXX valloc_calls ? */ - if (!ptr) { - tmstats.malloc_failures++; /* XXX valloc_failures ? */ - } else { - if (site) - log_event5(logfp, TM_EVENT_MALLOC, /* XXX TM_EVENT_VALLOC? */ - site->serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size); - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - return ptr; -} - -NS_EXTERNAL_VIS_(void*) -memalign(size_t boundary, size_t size) -{ - PRUint32 start, end; - __ptr_t ptr; - callsite *site; - PLHashEntry *he; - allocation *alloc; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_memalign(boundary, size); - } - - start = PR_IntervalNow(); - ptr = __libc_memalign(boundary, size); - end = PR_IntervalNow(); - - site = backtrace(t, 1); - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.malloc_calls++; /* XXX memalign_calls ? */ - if (!ptr) { - tmstats.malloc_failures++; /* XXX memalign_failures ? */ - } else { - if (site) { - log_event5(logfp, TM_EVENT_MALLOC, /* XXX TM_EVENT_MEMALIGN? */ - site->serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size); - } - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - return ptr; -} - -NS_EXTERNAL_VIS_(int) -posix_memalign(void **memptr, size_t alignment, size_t size) -{ - __ptr_t ptr = memalign(alignment, size); - if (!ptr) - return ENOMEM; - *memptr = ptr; - return 0; -} - -NS_EXTERNAL_VIS_(void) -free(__ptr_t ptr) -{ - PLHashEntry **hep, *he; - callsite *site; - allocation *alloc; - uint32 serial = 0, size = 0; - PRUint32 start, end; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - __libc_free(ptr); - return; - } - - t->suppress_tracing++; - TM_ENTER_LOCK(); - tmstats.free_calls++; - if (!ptr) { - tmstats.null_free_calls++; - } else { - if (get_allocations()) { - hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr); - he = *hep; - if (he) { - site = (callsite*) he->value; - if (site) { - alloc = (allocation*) he; - serial = site->serial; - size = alloc->size; - if (alloc->trackfp) { - fprintf(alloc->trackfp, "\nfree(%p), alloc site %p\n", - (void*) ptr, (void*) site); - NS_TraceStack(1, alloc->trackfp); - } - } - PL_HashTableRawRemove(allocations, hep, he); - } - } - } - TM_EXIT_LOCK(); - t->suppress_tracing--; - - start = PR_IntervalNow(); - __libc_free(ptr); - end = PR_IntervalNow(); - - if (size != 0) { - t->suppress_tracing++; - TM_ENTER_LOCK(); - log_event5(logfp, TM_EVENT_FREE, - serial, start, end - start, - (uint32)NS_PTR_TO_INT32(ptr), size); - TM_EXIT_LOCK(); - t->suppress_tracing--; - } -} - -NS_EXTERNAL_VIS_(void) -cfree(void *ptr) -{ - free(ptr); -} - -#endif /* XP_UNIX */ - -#ifdef XP_MACOSX +#if defined(XP_MACOSX) /* from malloc.c in Libc */ -typedef void (malloc_logger_t)(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3, unsigned result, unsigned num_hot_frames_to_skip); +typedef void +malloc_logger_t(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3, + unsigned result, unsigned num_hot_frames_to_skip); + extern malloc_logger_t *malloc_logger; #define MALLOC_LOG_TYPE_ALLOCATE 2 @@ -1438,6 +1066,128 @@ my_malloc_logger(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3, } } +static void +StartupHooker(void) +{ + PR_ASSERT(!malloc_logger); + malloc_logger = my_malloc_logger; +} + +static void +ShutdownHooker(void) +{ + PR_ASSERT(malloc_logger == my_malloc_logger); + malloc_logger = NULL; +} + +#elif defined(XP_UNIX) + +static __ptr_t (*old_malloc_hook)(size_t size, __const __malloc_ptr_t caller); +static __ptr_t (*old_realloc_hook)(__ptr_t ptr, size_t size, __const __malloc_ptr_t caller); +static __ptr_t (*old_memalign_hook)(size_t boundary, size_t size, __const __malloc_ptr_t caller); +static void (*old_free_hook)(__ptr_t ptr, __const __malloc_ptr_t caller); + +static __ptr_t +my_malloc_hook(size_t size, __const __malloc_ptr_t caller) +{ + tm_thread *t; + PRUint32 start, end; + __ptr_t ptr; + + PR_ASSERT(tracing_enabled); + t = tm_get_thread(); + __malloc_hook = old_malloc_hook; + start = PR_IntervalNow(); + ptr = __libc_malloc(size); + end = PR_IntervalNow(); + __malloc_hook = my_malloc_hook; + MallocCallback(ptr, size, start, end, t); + return ptr; +} + +static __ptr_t +my_realloc_hook(__ptr_t oldptr, size_t size, __const __malloc_ptr_t caller) +{ + tm_thread *t; + PRUint32 start, end; + __ptr_t ptr; + + PR_ASSERT(tracing_enabled); + t = tm_get_thread(); + __realloc_hook = old_realloc_hook; + start = PR_IntervalNow(); + ptr = __libc_realloc(oldptr, size); + end = PR_IntervalNow(); + __realloc_hook = my_realloc_hook; + ReallocCallback(oldptr, ptr, size, start, end, t); + return ptr; +} + +static __ptr_t +my_memalign_hook(size_t boundary, size_t size, __const __malloc_ptr_t caller) +{ + tm_thread *t; + PRUint32 start, end; + __ptr_t ptr; + + PR_ASSERT(tracing_enabled); + t = tm_get_thread(); + __memalign_hook = old_memalign_hook; + start = PR_IntervalNow(); + ptr = __libc_memalign(boundary, size); + end = PR_IntervalNow(); + __memalign_hook = my_memalign_hook; + MallocCallback(ptr, size, start, end, t); + return ptr; +} + +static void +my_free_hook(__ptr_t ptr, __const __malloc_ptr_t caller) +{ + tm_thread *t; + PRUint32 start, end; + + PR_ASSERT(tracing_enabled); + t = tm_get_thread(); + __free_hook = old_free_hook; + start = PR_IntervalNow(); + __libc_free(ptr); + end = PR_IntervalNow(); + __free_hook = my_free_hook; + FreeCallback(ptr, start, end, t); +} + +static void +StartupHooker(void) +{ + PR_ASSERT(__malloc_hook != my_malloc_hook); + + old_malloc_hook = __malloc_hook; + old_realloc_hook = __realloc_hook; + old_memalign_hook = __memalign_hook; + old_free_hook = __free_hook; + + __malloc_hook = my_malloc_hook; + __realloc_hook = my_realloc_hook; + __memalign_hook = my_memalign_hook; + __free_hook = my_free_hook; +} + +static void +ShutdownHooker(void) +{ + PR_ASSERT(__malloc_hook == my_malloc_hook); + + __malloc_hook = old_malloc_hook; + __realloc_hook = old_realloc_hook; + __memalign_hook = old_memalign_hook; + __free_hook = old_free_hook; +} + +#elif defined(XP_WIN32) + +/* See nsWinTraceMalloc.cpp. */ + #endif static const char magic[] = NS_TRACE_MALLOC_MAGIC; @@ -1450,7 +1200,8 @@ log_header(int logfd) (void) write(logfd, &ticksPerSec, sizeof ticksPerSec); } -PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd) +PR_IMPLEMENT(void) +NS_TraceMallocStartup(int logfd) { /* We must be running on the primordial thread. */ PR_ASSERT(tracing_enabled == 1); @@ -1482,18 +1233,10 @@ PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd) tmlock = PR_NewLock(); main_thread.suppress_tracing--; -#ifdef XP_WIN32 - /* Register listeners for win32. */ - if (tracing_enabled) { + if (tracing_enabled) StartupHooker(); - } -#endif -#ifdef XP_MACOSX - malloc_logger = my_malloc_logger; -#endif } - /* * Options for log files, with the log file name either as the next option * or separated by '=' (e.g. "./mozilla --trace-malloc * malloc.log" or @@ -1517,7 +1260,8 @@ static const char SDLOG_OPTION[] = "--shutdown-leaks"; } \ PR_END_MACRO -PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[]) +PR_IMPLEMENT(int) +NS_TraceMallocStartupArgs(int argc, char **argv) { int i, logfd = -1, consumed, logflags; char *tmlogname = NULL; /* note global |sdlogname| */ @@ -1636,7 +1380,8 @@ PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[]) return argc; } -PR_IMPLEMENT(void) NS_TraceMallocShutdown(void) +PR_IMPLEMENT(void) +NS_TraceMallocShutdown(void) { logfile *fp; @@ -1669,39 +1414,52 @@ PR_IMPLEMENT(void) NS_TraceMallocShutdown(void) tmlock = NULL; PR_DestroyLock(lock); } -#ifdef XP_WIN32 if (tracing_enabled) { + tracing_enabled = 0; ShutdownHooker(); } -#endif } -PR_IMPLEMENT(void) NS_TraceMallocDisable(void) +PR_IMPLEMENT(void) +NS_TraceMallocDisable(void) { - logfile *fp; tm_thread *t = tm_get_thread(); + logfile *fp; + uint32 sample; + + /* Robustify in case of duplicate call. */ + PR_ASSERT(tracing_enabled); + if (tracing_enabled == 0) + return; t->suppress_tracing++; TM_ENTER_LOCK(); for (fp = logfile_list; fp; fp = fp->next) flush_logfile(fp); - tracing_enabled = 0; + sample = --tracing_enabled; TM_EXIT_LOCK(); t->suppress_tracing--; + if (sample == 0) + ShutdownHooker(); } -PR_IMPLEMENT(void) NS_TraceMallocEnable(void) +PR_IMPLEMENT(void) +NS_TraceMallocEnable(void) { tm_thread *t = tm_get_thread(); + uint32 sample; t->suppress_tracing++; TM_ENTER_LOCK(); - tracing_enabled = 1; + sample = ++tracing_enabled; TM_EXIT_LOCK(); t->suppress_tracing--; + if (sample == 1) + StartupHooker(); } -PR_IMPLEMENT(int) NS_TraceMallocChangeLogFD(int fd) +PR_IMPLEMENT(int) +NS_TraceMallocChangeLogFD(int fd) { logfile *oldfp, *fp; struct stat sb; @@ -1841,8 +1599,9 @@ allocation_enumerator(PLHashEntry *he, PRIntn i, void *arg) for (p = (unsigned long*) he->key, end = (unsigned long*) ((char*)he->key + alloc->size); - p < end; ++p) + p < end; ++p) { fprintf(ofp, "\t0x%08lX\n", *p); + } while (site) { if (site->name || site->parent) { @@ -1884,9 +1643,10 @@ NS_TraceMallocDumpAllocations(const char *pathname) ofp = fopen(pathname, WRITE_FLAGS); if (ofp) { - if (allocations) + if (allocations) { PL_HashTableEnumerateEntries(allocations, allocation_enumerator, ofp); + } rv = ferror(ofp) ? -1 : 0; fclose(ofp); } else { @@ -1918,7 +1678,6 @@ NS_TraceMallocFlushLogfiles(void) PR_IMPLEMENT(void) NS_TrackAllocation(void* ptr, FILE *ofp) { - PLHashEntry **hep; allocation *alloc; tm_thread *t = tm_get_thread(); @@ -1928,8 +1687,8 @@ NS_TrackAllocation(void* ptr, FILE *ofp) t->suppress_tracing++; TM_ENTER_LOCK(); if (get_allocations()) { - hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr); - alloc = (allocation*) *hep; + alloc = (allocation*) + *PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr); if (alloc) { fprintf(ofp, "Tracking %p\n", (void*) ptr); alloc->trackfp = ofp; @@ -1941,8 +1700,6 @@ NS_TrackAllocation(void* ptr, FILE *ofp) t->suppress_tracing--; } -#if defined(XP_WIN32) || defined(XP_MACOSX) - PR_IMPLEMENT(void) MallocCallback(void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread *t) { @@ -1961,15 +1718,17 @@ MallocCallback(void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread * if (!ptr) { tmstats.malloc_failures++; } else { - if (site) + if (site) { log_event5(logfp, TM_EVENT_MALLOC, site->serial, start, end - start, (uint32)NS_PTR_TO_INT32(ptr), size); + } if (get_allocations()) { he = PL_HashTableAdd(allocations, ptr, site); if (he) { alloc = (allocation*) he; alloc->size = size; + alloc->trackfp = NULL; } } } @@ -1996,15 +1755,17 @@ CallocCallback(void *ptr, size_t count, size_t size, PRUint32 start, PRUint32 en tmstats.calloc_failures++; } else { size *= count; - if (site) + if (site) { log_event5(logfp, TM_EVENT_CALLOC, site->serial, start, end - start, (uint32)NS_PTR_TO_INT32(ptr), size); + } if (get_allocations()) { he = PL_HashTableAdd(allocations, ptr, site); if (he) { alloc = (allocation*) he; alloc->size = size; + alloc->trackfp = NULL; } } } @@ -2013,13 +1774,15 @@ CallocCallback(void *ptr, size_t count, size_t size, PRUint32 start, PRUint32 en } PR_IMPLEMENT(void) -ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32 end, tm_thread *t) +ReallocCallback(void * oldptr, void *ptr, size_t size, + PRUint32 start, PRUint32 end, tm_thread *t) { callsite *oldsite, *site; size_t oldsize; PLHashNumber hash; PLHashEntry **hep, *he; allocation *alloc; + FILE *trackfp = NULL; if (!tracing_enabled || t->suppress_tracing != 0) return; @@ -2029,28 +1792,34 @@ ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32 t->suppress_tracing++; TM_ENTER_LOCK(); tmstats.realloc_calls++; - if (PR_TRUE) { - oldsite = NULL; - oldsize = 0; - he = NULL; - if (oldptr && get_allocations()) { - hash = hash_pointer(oldptr); - hep = PL_HashTableRawLookup(allocations, hash, oldptr); - he = *hep; - if (he) { - oldsite = (callsite*) he->value; - alloc = (allocation*) he; - oldsize = alloc->size; + oldsite = NULL; + oldsize = 0; + hep = NULL; + he = NULL; + if (oldptr && get_allocations()) { + hash = hash_pointer(oldptr); + hep = PL_HashTableRawLookup(allocations, hash, oldptr); + he = *hep; + if (he) { + oldsite = (callsite*) he->value; + alloc = (allocation*) he; + oldsize = alloc->size; + trackfp = alloc->trackfp; + if (trackfp) { + fprintf(alloc->trackfp, + "\nrealloc(%p, %lu), oldsize %lu, alloc site %p\n", + (void*) ptr, (unsigned long) size, + (unsigned long) oldsize, (void*) oldsite); + NS_TraceStack(1, trackfp); } } } if (!ptr && size) { - tmstats.realloc_failures++; - /* * When realloc() fails, the original block is not freed or moved, so * we'll leave the allocation entry untouched. */ + tmstats.realloc_failures++; } else { if (site) { log_event8(logfp, TM_EVENT_REALLOC, @@ -2081,6 +1850,7 @@ ReallocCallback(void * oldptr, void *ptr, size_t size, PRUint32 start, PRUint32 if (he) { alloc = (allocation*) he; alloc->size = size; + alloc->trackfp = trackfp; } } } @@ -2111,6 +1881,11 @@ FreeCallback(void * ptr, PRUint32 start, PRUint32 end, tm_thread *t) site = (callsite*) he->value; if (site) { alloc = (allocation*) he; + if (alloc->trackfp) { + fprintf(alloc->trackfp, "\nfree(%p), alloc site %p\n", + (void*) ptr, (void*) site); + NS_TraceStack(1, alloc->trackfp); + } log_event5(logfp, TM_EVENT_FREE, site->serial, start, end - start, (uint32)NS_PTR_TO_INT32(ptr), alloc->size); @@ -2123,6 +1898,4 @@ FreeCallback(void * ptr, PRUint32 start, PRUint32 end, tm_thread *t) t->suppress_tracing--; } -#endif /* defined(XP_WIN32) || defined(XP_MACOSX) */ - #endif /* NS_TRACE_MALLOC */ diff --git a/mozilla/tools/trace-malloc/lib/nsTraceMallocCallbacks.h b/mozilla/tools/trace-malloc/lib/nsTraceMallocCallbacks.h index e3f2db232ad..61f5a46b61e 100644 --- a/mozilla/tools/trace-malloc/lib/nsTraceMallocCallbacks.h +++ b/mozilla/tools/trace-malloc/lib/nsTraceMallocCallbacks.h @@ -69,13 +69,11 @@ struct tm_thread { /* implemented in nsTraceMalloc.c */ tm_thread * tm_get_thread(void); -#if defined(XP_WIN32) || defined(XP_MACOSX) /* implemented in nsTraceMalloc.c */ PR_EXTERN(void) MallocCallback(void *aPtr, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t); PR_EXTERN(void) CallocCallback(void *aPtr, size_t aCount, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t); PR_EXTERN(void) ReallocCallback(void *aPin, void* aPout, size_t aSize, PRUint32 start, PRUint32 end, tm_thread *t); PR_EXTERN(void) FreeCallback(void *aPtr, PRUint32 start, PRUint32 end, tm_thread *t); -#endif #ifdef XP_WIN32 /* implemented in nsTraceMalloc.c */