Convert trace-malloc to using XPCOM stack walking API. b=374829 r+a=brendan

This commit is contained in:
dbaron@dbaron.org 2007-08-10 15:20:48 -07:00
parent def4dbe999
commit 593cd91cf8
9 changed files with 194 additions and 1506 deletions

View File

@ -55,17 +55,15 @@ CSRCS = \
$(NULL)
CPPSRCS = \
nsDemangle.cpp \
nsTypeInfo.cpp \
$(NULL)
EXPORTS = nsTraceMalloc.h
EXTRA_DSO_LDOPTS = $(NSPR_LIBS)
EXTRA_DSO_LDOPTS = $(NSPR_LIBS) $(XPCOM_LIBS)
ifeq ($(OS_ARCH),WINNT)
CPPSRCS += nsDebugHelpWin32.cpp nsWinTraceMalloc.cpp nsStackFrameWin.cpp
EXTRA_DSO_LDOPTS += $(XPCOM_LIBS)
CPPSRCS += nsDebugHelpWin32.cpp nsWinTraceMalloc.cpp
OS_LIBS += shell32.lib ole32.lib uuid.lib imagehlp.lib
endif

View File

@ -48,7 +48,6 @@
#include "prlock.h"
#include "nscore.h"
#include "nsDebugHelpWin32.h"
#include "nsStackFrameWin.h"
#else
#error "nsDebugHelpWin32.cpp should only be built in Win32 x86 builds"
#endif
@ -164,7 +163,6 @@ DHWImportHooker::DHWImportHooker(const char* aModuleName,
gLock = PR_NewLock();
PR_Lock(gLock);
EnsureImageHlpInitialized();
dhwEnsureImageHlpInitialized(); // for the extra ones we care about.
if(!gRealGetProcAddress)

View File

@ -1,49 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is trace-malloc/nsDemangle.cpp.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifdef MOZ_DEMANGLE_SYMBOLS
#include <cxxabi.h>
#include <stdlib.h>
extern "C" char *nsDemangle(const char *symbol);
char *nsDemangle(const char *symbol) {
return abi::__cxa_demangle(symbol, 0, 0, 0);
}
#endif

View File

@ -1,351 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is nsStackFrameWin.h code, released
* December 20, 2000.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Michael Judge, 20-December-2000
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nscore.h"
#include "windows.h"
#include "imagehlp.h"
#include "stdio.h"
#include "nsStackFrameWin.h"
// Define these as static pointers so that we can load the DLL on the
// fly (and not introduce a link-time dependency on it). Tip o' the
// hat to Matt Pietrick for this idea. See:
//
// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
//
PR_BEGIN_EXTERN_C
SYMSETOPTIONSPROC _SymSetOptions;
SYMINITIALIZEPROC _SymInitialize;
SYMCLEANUPPROC _SymCleanup;
STACKWALKPROC _StackWalk;
SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
SYMGETMODULEBASEPROC _SymGetModuleBase;
SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
SYMLOADMODULE _SymLoadModule;
SYMUNDNAME _SymUnDName;
SYMGETMODULEINFO _SymGetModuleInfo;
ENUMLOADEDMODULES _EnumerateLoadedModules;
SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
PR_END_EXTERN_C
PRBool
EnsureImageHlpInitialized()
{
static PRBool gInitialized = PR_FALSE;
if (! gInitialized) {
HMODULE module = ::LoadLibrary("IMAGEHLP.DLL");
if (!module) return PR_FALSE;
_SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions");
if (!_SymSetOptions) return PR_FALSE;
_SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize");
if (!_SymInitialize) return PR_FALSE;
_SymCleanup = (SYMCLEANUPPROC)GetProcAddress(module, "SymCleanup");
if (!_SymCleanup) return PR_FALSE;
_StackWalk = (STACKWALKPROC)GetProcAddress(module, "StackWalk");
if (!_StackWalk) return PR_FALSE;
_SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(module, "SymFunctionTableAccess");
if (!_SymFunctionTableAccess) return PR_FALSE;
_SymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(module, "SymGetModuleBase");
if (!_SymGetModuleBase) return PR_FALSE;
_SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr");
if (!_SymGetSymFromAddr) return PR_FALSE;
_SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule");
if (!_SymLoadModule) return PR_FALSE;
_SymUnDName = (SYMUNDNAME)GetProcAddress(module, "SymUnDName");
if (!_SymUnDName) return PR_FALSE;
_SymGetModuleInfo = (SYMGETMODULEINFO)GetProcAddress(module, "SymGetModuleInfo");
if (!_SymGetModuleInfo) return PR_FALSE;
_EnumerateLoadedModules = (ENUMLOADEDMODULES)GetProcAddress(module, "EnumerateLoadedModules");
if (!_EnumerateLoadedModules) return PR_FALSE;
_SymGetLineFromAddr = (SYMGETLINEFROMADDRPROC)GetProcAddress(module, "SymGetLineFromAddr");
if (!_SymGetLineFromAddr) return PR_FALSE;
gInitialized = PR_TRUE;
}
return gInitialized;
}
/*
* Callback used by SymGetModuleInfoEspecial
*/
static BOOL CALLBACK callbackEspecial(LPSTR aModuleName, ULONG aModuleBase, ULONG aModuleSize, PVOID aUserContext)
{
BOOL retval = TRUE;
DWORD addr = (DWORD)aUserContext;
/*
* You'll want to control this if we are running on an
* architecture where the addresses go the other direction.
* Not sure this is even a realistic consideration.
*/
const BOOL addressIncreases = TRUE;
/*
* If it falls in side the known range, load the symbols.
*/
if(addressIncreases
? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize))
: (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))
)
{
BOOL loadRes = FALSE;
HANDLE process = GetCurrentProcess();
loadRes = _SymLoadModule(process, NULL, aModuleName, NULL, aModuleBase, aModuleSize);
PR_ASSERT(FALSE != loadRes);
}
return retval;
}
/*
* SymGetModuleInfoEspecial
*
* Attempt to determine the module information.
* Bug 112196 says this DLL may not have been loaded at the time
* SymInitialize was called, and thus the module information
* and symbol information is not available.
* This code rectifies that problem.
*/
BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo)
{
BOOL retval = FALSE;
/*
* Init the vars if we have em.
*/
aModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE);
if (nsnull != aLineInfo) {
aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE);
}
/*
* Give it a go.
* It may already be loaded.
*/
retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
if (FALSE == retval) {
BOOL enumRes = FALSE;
/*
* Not loaded, here's the magic.
* Go through all the modules.
*/
enumRes = _EnumerateLoadedModules(aProcess, callbackEspecial, (PVOID)aAddr);
if(FALSE != enumRes)
{
/*
* One final go.
* If it fails, then well, we have other problems.
*/
retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
}
}
/*
* If we got module info, we may attempt line info as well.
* We will not report failure if this does not work.
*/
if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr) {
DWORD displacement = 0;
BOOL lineRes = FALSE;
lineRes = _SymGetLineFromAddr(aProcess, aAddr, &displacement, aLineInfo);
}
return retval;
}
PRBool
EnsureSymInitialized()
{
static PRBool gInitialized = PR_FALSE;
if (! gInitialized) {
if (! EnsureImageHlpInitialized())
return PR_FALSE;
_SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE);
}
return gInitialized;
}
/**
* Walk the stack, translating PC's found into strings and recording the
* chain in aBuffer. For this to work properly, the dll's must be rebased
* so that the address in the file agrees with the address in memory.
* Otherwise StackWalk will return FALSE when it hits a frame in a dll's
* whose in memory address doesn't match it's in-file address.
*
* Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does
* the rebasing and accordingly I've made a tool to use it to rebase the
* DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp).
*/
void
DumpStackToFile(FILE* aStream)
{
HANDLE myProcess = ::GetCurrentProcess();
HANDLE myThread = ::GetCurrentThread();
BOOL ok;
ok = EnsureSymInitialized();
if (! ok)
return;
// Get the context information for this thread. That way we will
// know where our sp, fp, pc, etc. are and can fill in the
// STACKFRAME with the initial values.
CONTEXT context;
context.ContextFlags = CONTEXT_FULL;
ok = GetThreadContext(myThread, &context);
if (! ok)
return;
// Setup initial stack frame to walk from
STACKFRAME frame;
memset(&frame, 0, sizeof(frame));
frame.AddrPC.Offset = context.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
// Now walk the stack and map the pc's to symbol names
int skip = 2;
while (1) {
ok = _StackWalk(IMAGE_FILE_MACHINE_I386,
myProcess,
myThread,
&frame,
&context,
0, // read process memory routine
_SymFunctionTableAccess, // function table access routine
_SymGetModuleBase, // module base routine
0); // translate address routine
if (!ok) {
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf);
fflush(aStream);
LocalFree( lpMsgBuf );
}
if (!ok || frame.AddrPC.Offset == 0)
break;
if (skip-- > 0)
continue;
//
// Attempt to load module info before we attempt to reolve the symbol.
// This just makes sure we get good info if available.
//
IMAGEHLP_MODULE modInfo;
modInfo.SizeOfStruct = sizeof(modInfo);
BOOL modInfoRes = TRUE;
modInfoRes = SymGetModuleInfoEspecial(myProcess, frame.AddrPC.Offset, &modInfo, nsnull);
char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
symbol->SizeOfStruct = sizeof(buf);
symbol->MaxNameLength = 512;
DWORD displacement;
ok = _SymGetSymFromAddr(myProcess,
frame.AddrPC.Offset,
&displacement,
symbol);
if (ok) {
fprintf(aStream, "%s+0x%08X\n", symbol->Name, displacement);
}
else {
fprintf(aStream, "0x%08X\n", frame.AddrPC.Offset);
}
}
}

View File

@ -1,126 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is nsStackFrameWin.h code, released
* December 20, 2000.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Michael Judge, 20-December-2000
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsStackFrameWin_h___
#define nsStackFrameWin_h___
#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
#include "nspr.h"
#include <windows.h>
#include <imagehlp.h>
// Define these as static pointers so that we can load the DLL on the
// fly (and not introduce a link-time dependency on it). Tip o' the
// hat to Matt Pietrick for this idea. See:
//
// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
//
PR_BEGIN_EXTERN_C
typedef DWORD (__stdcall *SYMSETOPTIONSPROC)(DWORD);
extern SYMSETOPTIONSPROC _SymSetOptions;
typedef BOOL (__stdcall *SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
extern SYMINITIALIZEPROC _SymInitialize;
typedef BOOL (__stdcall *SYMCLEANUPPROC)(HANDLE);
extern SYMCLEANUPPROC _SymCleanup;
typedef BOOL (__stdcall *STACKWALKPROC)(DWORD,
HANDLE,
HANDLE,
LPSTACKFRAME,
LPVOID,
PREAD_PROCESS_MEMORY_ROUTINE,
PFUNCTION_TABLE_ACCESS_ROUTINE,
PGET_MODULE_BASE_ROUTINE,
PTRANSLATE_ADDRESS_ROUTINE);
extern STACKWALKPROC _StackWalk;
typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
extern SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
extern SYMGETMODULEBASEPROC _SymGetModuleBase;
typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
extern SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD);
extern SYMLOADMODULE _SymLoadModule;
typedef DWORD ( __stdcall *SYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
extern SYMUNDNAME _SymUnDName;
typedef DWORD ( __stdcall *SYMGETMODULEINFO)( HANDLE, DWORD, PIMAGEHLP_MODULE);
extern SYMGETMODULEINFO _SymGetModuleInfo;
typedef BOOL ( __stdcall *ENUMLOADEDMODULES)( HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
extern ENUMLOADEDMODULES _EnumerateLoadedModules;
typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE);
extern SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
PRBool EnsureSymInitialized();
PRBool EnsureImageHlpInitialized();
/*
* SymGetModuleInfoEspecial
*
* Attempt to determine the module information.
* Bug 112196 says this DLL may not have been loaded at the time
* SymInitialize was called, and thus the module information
* and symbol information is not available.
* This code rectifies that problem.
* Line information is optional.
*/
BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo);
void DumpStackToFile(FILE* out);
PR_END_EXTERN_C
#endif //WIN32
#endif //nsStackFrameWin_h___

File diff suppressed because it is too large Load Diff

View File

@ -7,122 +7,9 @@
#include "nscore.h"
#include "nsAutoLock.h"
#include "nsStackFrameWin.h"
#include "nsDebugHelpWin32.h"
#include "nsTraceMallocCallbacks.h"
// XXX These are *very* quick hacks and need improvement!
static PRBool GetSymbolFromAddress(uint32 addr, char* outBuf)
{
PRBool ok;
ok = EnsureSymInitialized();
if(!ok)
return ok;
char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
symbol->SizeOfStruct = sizeof(buf);
symbol->MaxNameLength = 512;
DWORD displacement;
ok = SymGetSymFromAddr(::GetCurrentProcess(),
addr,
&displacement,
symbol);
if(ok)
{
char buf2[512];
sprintf(buf2, "%s+0x%08X", symbol->Name, displacement);
strcat(outBuf, buf2);
}
else
strcat(outBuf, "dunno");
return ok;
}
static PRBool GetModuleFromAddress(uint32 addr, char* outBuf)
{
PRBool ok;
ok = EnsureSymInitialized();
if(!ok)
return ok;
IMAGEHLP_MODULE module;
module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
ok = SymGetModuleInfo(::GetCurrentProcess(),
addr,
&module);
if(ok)
strcat(outBuf, module.ModuleName);
else
strcat(outBuf, "dunno");
return ok;
}
/***************************************************************************/
#ifdef VERBOSE
#define SHOW(x_, buf_) \
printf(#x_" = %#x... %s\n", x_, \
(buf_[0] = 0, \
GetModuleFromAddress((uint32)x_, buf_), \
strcat(buf," :: "), \
GetSymbolFromAddress((uint32)x_, buf_), \
buf_));
#else
#define SHOW(x_, buf_)
#endif //VERBOSE
/***************************************************************************/
#ifdef VERBOSE
// XXX This is a quick hack to show that x86 Win32 stack walking can be done
// with this sort of loop following the bp.
void dumpStack()
{
uint32* bp_;
uint32* bpdown;
uint32 pc;
char buf[512];
_asm { mov bp_ , ebp }
/* Stack walking code adapted from Kipp's "leaky". */
while (1) {
bpdown = (uint32*) *bp_++;
pc = *bp_;
// These addresses are iffy...
if (pc < 0x00400000 || pc > 0x7fffffff || bpdown < bp_)
break;
SHOW(pc, buf);
bp_ = bpdown;
}
printf("\n");
}
#endif
char* _stdcall call2(void* v)
{
// dumpStack();
// return 0;
return (char *)malloc(123);
}
int call1(char c, int i, double d, ... )
{
free(call2(0));
return 0;
}
/***************************************************************************/
// shows how to use the dhw stuff to hook imported functions
@ -239,93 +126,10 @@ void __cdecl dhw_delete(void* p)
FreeCallback(p, start, end);
}
/***************************************************************************/
// A demonstration of using the _CrtSetAllocHook based hooking.
// This system sucks because you don't get to see the allocated pointer.
#if 0
class myAllocationSizePrinter : public DHWAllocationSizeDebugHook
{
public:
PRBool AllocHook(size_t size)
{
alloc_calls++ ;
total_mem += size;
if(verbosity)
{
printf("alloc called to get %d bytes.\n", size);
dumpStack();
}
return PR_TRUE;
}
PRBool ReallocHook(size_t size, size_t sizeOld)
{
realloc_calls++ ;
total_mem += size;
total_mem -= sizeOld;
if(verbosity)
{
printf("realloc called to size to %d bytes. Old size: %d.\n",
size, sizeOld);
dumpStack();
}
return PR_TRUE;
}
PRBool FreeHook(size_t size)
{
free_calls++ ;
total_mem -= size;
if(verbosity)
{
printf("free called to release %d bytes.\n", size);
dumpStack();
}
return PR_TRUE;
}
myAllocationSizePrinter(int v)
: verbosity(v),
alloc_calls(0),
realloc_calls(0),
free_calls(0),
total_mem(0) {}
virtual ~myAllocationSizePrinter(){}
void report()
{
printf("%d allocs, %d reallocs, %d frees, %d bytes leaked\n",
alloc_calls, realloc_calls, free_calls, total_mem);
}
private:
void dumpStack()
{
if(verbosity == 2)
::dumpStack();
}
int verbosity;
int alloc_calls;
int realloc_calls;
int free_calls;
size_t total_mem;
};
#endif
/*C Callbacks*/
PR_IMPLEMENT(void)
StartupHooker()
{
if (!EnsureSymInitialized())
return;
//run through get all hookers
DHWImportHooker &loadlibraryW = DHWImportHooker::getLoadLibraryWHooker();
DHWImportHooker &loadlibraryExW = DHWImportHooker::getLoadLibraryExWHooker();
@ -344,50 +148,3 @@ PR_IMPLEMENT(void)
ShutdownHooker()
{
}
#if 0
int main()
{
// A demonstration of using the (sucky) _CrtSetAllocHook based hooking.
myAllocationSizePrinter ap(0);
dhwSetAllocationSizeDebugHook(&ap);
// show that the ImportHooker is hooking calls from loaded dll
DHW_DECLARE_FUN_TYPE(void, __stdcall, SOMECALL_, (void));
HMODULE module = ::LoadLibrary("Other.dll");
if(module) {
SOMECALL_ _SomeCall = (SOMECALL_) GetProcAddress(module, "SomeCall");
if(_SomeCall)
_SomeCall();
}
// show that the ImportHooker is hooking sneaky calls made from this dll.
HMODULE module2 = ::LoadLibrary(NS_DEBUG_CRT);
if(module2) {
MALLOC_ _sneakyMalloc = (MALLOC_) GetProcAddress(module2, "malloc");
if(_sneakyMalloc)
{
void* p = _sneakyMalloc(987);
free(p);
}
}
call1('x', 1, 1.0, "hi there", 2);
char* p = new char[10];
delete p;
void* v = malloc(10);
v = realloc(v, 15);
v = realloc(v, 5);
free(v);`
ap.report();
dhwClearAllocationSizeDebugHook();
return 0;
}
#endif //0

View File

@ -137,9 +137,8 @@ void PrintError(char *prefix)
0,
NULL
);
char buf[512];
_snprintf(buf, sizeof(buf), "### ERROR: %s: %s", prefix, lpMsgBuf);
fputs(buf, stderr);
fprintf(stderr, "### ERROR: %s: %s", prefix, lpMsgBuf);
fflush(stderr);
LocalFree( lpMsgBuf );
}
@ -448,8 +447,7 @@ EXPORT_XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
void *aClosure)
{
HANDLE myProcess = ::GetCurrentProcess();
HANDLE myThread, walkerThread;
HANDLE myProcess, myThread, walkerThread;
DWORD walkerReturn;
struct WalkStackData data;
@ -457,13 +455,23 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
return NS_ERROR_FAILURE;
// Have to duplicate handle to get a real handle.
::DuplicateHandle(
::GetCurrentProcess(),
::GetCurrentThread(),
::GetCurrentProcess(),
&myThread,
THREAD_ALL_ACCESS, FALSE, 0
);
if (!::DuplicateHandle(::GetCurrentProcess(),
::GetCurrentProcess(),
::GetCurrentProcess(),
&myProcess,
THREAD_ALL_ACCESS, FALSE, 0)) {
PrintError("DuplicateHandle (process)");
return NS_ERROR_FAILURE;
}
if (!::DuplicateHandle(::GetCurrentProcess(),
::GetCurrentThread(),
::GetCurrentProcess(),
&myThread,
THREAD_ALL_ACCESS, FALSE, 0)) {
PrintError("DuplicateHandle (thread)");
::CloseHandle(myProcess);
return NS_ERROR_FAILURE;
}
data.callback = aCallback;
data.skipFrames = aSkipFrames;
@ -476,11 +484,13 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
if (walkerReturn != WAIT_OBJECT_0) {
PrintError("ThreadWait");
}
CloseHandle(myThread);
::CloseHandle(walkerThread);
}
else {
PrintError("ThreadCreate");
}
::CloseHandle(myThread);
::CloseHandle(myProcess);
return NS_OK;
}

View File

@ -40,6 +40,7 @@
#include "nsStackWalk.h"
#if defined(_WIN32) && defined(_M_IX86) && !defined(WINCE) // WIN32 x86 stack walking code
#include "nsStackFrameWin.cpp"
// WIN32 x86 stack walking code