michael@0: /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "prinrval.h" michael@0: #include "prlock.h" michael@0: #include "nscore.h" michael@0: michael@0: #include "nsDebugHelpWin32.h" michael@0: #include "nsTraceMallocCallbacks.h" michael@0: michael@0: /***************************************************************************/ michael@0: // shows how to use the dhw stuff to hook imported functions michael@0: michael@0: #if _MSC_VER < 1300 michael@0: #define NS_DEBUG_CRT "MSVCRTD.dll" michael@0: #elif _MSC_VER == 1300 michael@0: #define NS_DEBUG_CRT "msvcr70d.dll" michael@0: #elif _MSC_VER == 1310 michael@0: #define NS_DEBUG_CRT "msvcr71d.dll" michael@0: #elif _MSC_VER == 1400 michael@0: #define NS_DEBUG_CRT "msvcr80d.dll" michael@0: #elif _MSC_VER == 1500 michael@0: #define NS_DEBUG_CRT "msvcr90d.dll" michael@0: #elif _MSC_VER == 1600 michael@0: #define NS_DEBUG_CRT "msvcr100d.dll" michael@0: #elif _MSC_VER == 1700 michael@0: #define NS_DEBUG_CRT "msvcr110d.dll" michael@0: #elif _MSC_VER == 1800 michael@0: #define NS_DEBUG_CRT "msvcr120d.dll" michael@0: #else michael@0: #error "Don't know filename of MSVC debug library." michael@0: #endif michael@0: michael@0: decltype(malloc) dhw_malloc; michael@0: michael@0: DHWImportHooker &getMallocHooker() michael@0: { michael@0: static DHWImportHooker gMallocHooker(NS_DEBUG_CRT, "malloc", (PROC) dhw_malloc); michael@0: return gMallocHooker; michael@0: } michael@0: michael@0: void * __cdecl dhw_malloc( size_t size ) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: void* result = DHW_ORIGINAL(malloc, getMallocHooker())(size); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: MallocCallback(result, size, start, end, t); michael@0: return result; michael@0: } michael@0: michael@0: decltype(calloc) dhw_calloc; michael@0: michael@0: DHWImportHooker &getCallocHooker() michael@0: { michael@0: static DHWImportHooker gCallocHooker(NS_DEBUG_CRT, "calloc", (PROC) dhw_calloc); michael@0: return gCallocHooker; michael@0: } michael@0: michael@0: void * __cdecl dhw_calloc( size_t count, size_t size ) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: void* result = DHW_ORIGINAL(calloc, getCallocHooker())(count,size); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: CallocCallback(result, count, size, start, end, t); michael@0: return result; michael@0: } michael@0: michael@0: decltype(free) dhw_free; michael@0: DHWImportHooker &getFreeHooker() michael@0: { michael@0: static DHWImportHooker gFreeHooker(NS_DEBUG_CRT, "free", (PROC) dhw_free); michael@0: return gFreeHooker; michael@0: } michael@0: michael@0: void __cdecl dhw_free( void* p ) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: DHW_ORIGINAL(free, getFreeHooker())(p); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: /* FIXME bug 392008: We could race with reallocation of p. */ michael@0: FreeCallback(p, start, end, t); michael@0: } michael@0: michael@0: michael@0: decltype(realloc) dhw_realloc; michael@0: DHWImportHooker &getReallocHooker() michael@0: { michael@0: static DHWImportHooker gReallocHooker(NS_DEBUG_CRT, "realloc", (PROC) dhw_realloc); michael@0: return gReallocHooker; michael@0: } michael@0: michael@0: void * __cdecl dhw_realloc(void * pin, size_t size) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: void* pout = DHW_ORIGINAL(realloc, getReallocHooker())(pin, size); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: /* FIXME bug 392008: We could race with reallocation of pin. */ michael@0: ReallocCallback(pin, pout, size, start, end, t); michael@0: return pout; michael@0: } michael@0: michael@0: // Note the mangled name! michael@0: void * __cdecl dhw_new(size_t size); michael@0: DHWImportHooker &getNewHooker() michael@0: { michael@0: static DHWImportHooker gNewHooker(NS_DEBUG_CRT, "??2@YAPAXI@Z", (PROC) dhw_new); michael@0: return gNewHooker; michael@0: } michael@0: michael@0: void * __cdecl dhw_new(size_t size) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: void* result = DHW_ORIGINAL(dhw_new, getNewHooker())(size); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: MallocCallback(result, size, start, end, t);//do we need a different one for new? michael@0: return result; michael@0: } michael@0: michael@0: // Note the mangled name! michael@0: void __cdecl dhw_delete(void* p); michael@0: DHWImportHooker &getDeleteHooker() michael@0: { michael@0: static DHWImportHooker gDeleteHooker(NS_DEBUG_CRT, "??3@YAXPAX@Z", (PROC) dhw_delete); michael@0: return gDeleteHooker; michael@0: } michael@0: michael@0: void __cdecl dhw_delete(void* p) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: DHW_ORIGINAL(dhw_delete, getDeleteHooker())(p); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: FreeCallback(p, start, end, t); michael@0: } michael@0: michael@0: // Note the mangled name! michael@0: void * __cdecl dhw_vec_new(size_t size); michael@0: DHWImportHooker &getVecNewHooker() michael@0: { michael@0: static DHWImportHooker gVecNewHooker(NS_DEBUG_CRT, "??_U@YAPAXI@Z", (PROC) dhw_vec_new); michael@0: return gVecNewHooker; michael@0: } michael@0: michael@0: void * __cdecl dhw_vec_new(size_t size) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; // need to suppress since new[] calls new michael@0: uint32_t start = PR_IntervalNow(); michael@0: void* result = DHW_ORIGINAL(dhw_vec_new, getVecNewHooker())(size); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: MallocCallback(result, size, start, end, t);//do we need a different one for new[]? michael@0: return result; michael@0: } michael@0: michael@0: // Note the mangled name! michael@0: void __cdecl dhw_vec_delete(void* p); michael@0: DHWImportHooker &getVecDeleteHooker() michael@0: { michael@0: static DHWImportHooker gVecDeleteHooker(NS_DEBUG_CRT, "??_V@YAXPAX@Z", (PROC) dhw_vec_delete); michael@0: return gVecDeleteHooker; michael@0: } michael@0: michael@0: void __cdecl dhw_vec_delete(void* p) michael@0: { michael@0: tm_thread *t = tm_get_thread(); michael@0: ++t->suppress_tracing; michael@0: uint32_t start = PR_IntervalNow(); michael@0: DHW_ORIGINAL(dhw_vec_delete, getVecDeleteHooker())(p); michael@0: uint32_t end = PR_IntervalNow(); michael@0: --t->suppress_tracing; michael@0: FreeCallback(p, start, end, t); michael@0: } michael@0: michael@0: /*C Callbacks*/ michael@0: PR_IMPLEMENT(void) michael@0: StartupHooker() michael@0: { michael@0: //run through get all hookers michael@0: DHWImportHooker &loadlibraryW = DHWImportHooker::getLoadLibraryWHooker(); michael@0: DHWImportHooker &loadlibraryExW = DHWImportHooker::getLoadLibraryExWHooker(); michael@0: DHWImportHooker &loadlibraryA = DHWImportHooker::getLoadLibraryAHooker(); michael@0: DHWImportHooker &loadlibraryExA = DHWImportHooker::getLoadLibraryExAHooker(); michael@0: DHWImportHooker &mallochooker = getMallocHooker(); michael@0: DHWImportHooker &reallochooker = getReallocHooker(); michael@0: DHWImportHooker &callochooker = getCallocHooker(); michael@0: DHWImportHooker &freehooker = getFreeHooker(); michael@0: DHWImportHooker &newhooker = getNewHooker(); michael@0: DHWImportHooker &deletehooker = getDeleteHooker(); michael@0: DHWImportHooker &vecnewhooker = getVecNewHooker(); michael@0: DHWImportHooker &vecdeletehooker = getVecDeleteHooker(); michael@0: printf("Startup Hooker\n"); michael@0: } michael@0: michael@0: PR_IMPLEMENT(void) michael@0: ShutdownHooker() michael@0: { michael@0: } michael@0: michael@0: extern "C" { michael@0: void* dhw_orig_malloc(size_t); michael@0: void* dhw_orig_calloc(size_t, size_t); michael@0: void* dhw_orig_realloc(void*, size_t); michael@0: void dhw_orig_free(void*); michael@0: } michael@0: michael@0: void* michael@0: dhw_orig_malloc(size_t size) michael@0: { michael@0: return DHW_ORIGINAL(malloc, getMallocHooker())(size); michael@0: } michael@0: michael@0: void* michael@0: dhw_orig_calloc(size_t count, size_t size) michael@0: { michael@0: return DHW_ORIGINAL(calloc, getCallocHooker())(count,size); michael@0: } michael@0: michael@0: void* michael@0: dhw_orig_realloc(void* pin, size_t size) michael@0: { michael@0: return DHW_ORIGINAL(realloc, getReallocHooker())(pin, size); michael@0: } michael@0: michael@0: void michael@0: dhw_orig_free(void* p) michael@0: { michael@0: DHW_ORIGINAL(free, getFreeHooker())(p); michael@0: }