move nsTraceMalloc out of XPCOM. Factory out stackwalking code into new files. 189221 r=chak, 186585 r=blythe sr=dbaron. Most of this patch was contributed by seawood.

This commit is contained in:
dougt%netscape.com 2003-01-15 20:40:06 +00:00
Родитель e09e5e0cf7
Коммит 927c29d1d6
29 изменённых файлов: 1423 добавлений и 1600 удалений

Просмотреть файл

@ -130,6 +130,10 @@ tier_2_dirs += \
xpcom \
$(NULL)
ifdef NS_TRACE_MALLOC
tier_2_dirs += tools/trace-malloc/lib tools/trace-malloc
endif
#
# tier 9 - core components (necko,gecko)
#
@ -208,10 +212,6 @@ ifdef MOZ_LEAKY
tier_9_dirs += tools/leaky
endif
ifdef NS_TRACE_MALLOC
tier_9_dirs += tools/trace-malloc
endif
ifdef MOZ_MAPINFO
tier_9_dirs += tools/codesighs
endif

Просмотреть файл

@ -996,7 +996,7 @@ fi
# tools/trace-malloc
if [ "$NS_TRACE_MALLOC" ]; then
MAKEFILES_tracemalloc="tools/trace-malloc/Makefile"
MAKEFILES_tracemalloc="tools/trace-malloc/Makefile tools/trace-malloc/lib/Makefile"
fi
# tools/codesighs

Просмотреть файл

@ -60,6 +60,10 @@ REQUIRES = xpcom \
intl \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CPPSRCS = \
nsBarProps.cpp \
nsDOMException.cpp \
@ -84,7 +88,4 @@ include $(topsrcdir)/config/rules.mk
CXXFLAGS += -I$(srcdir) -I$(srcdir)/../build
ifdef NS_TRACE_MALLOC
DEFINES += -DNS_TRACE_MALLOC
endif

Просмотреть файл

@ -52,6 +52,10 @@ ifeq ($(OS_ARCH),WINNT)
EXTRA_DSO_LIBS = gkgfx
endif
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
CPPSRCS = \
nsDOMFactory.cpp \
nsScriptNameSpaceManager.cpp \
@ -63,6 +67,7 @@ SHARED_LIBRARY_LIBS = \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(MOZ_JS_LIBS) \

Просмотреть файл

@ -31,6 +31,10 @@ REQUIRES = xpcom \
dom \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CPPSRCS = \
TestGtkEmbed.cpp \
TestGtkEmbedNotebook.cpp \
@ -77,6 +81,11 @@ EXTRA_LIBS += $(EXTRA_DSO_LIBS) $(STATIC_EXTRA_LIBS)
endif
ifdef NS_TRACE_MALLOC
EXTRA_LIBS += -ltracemalloc
endif
EXTRA_LIBS += $(MOZ_JS_LIBS)
EXTRA_LIBS += $(MOZ_COMPONENT_LIBS)

Просмотреть файл

@ -63,6 +63,10 @@ REQUIRES = \
webbrwsr \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CPPSRCS = \
CCustomPromptDialog.cpp \
CMarginHeaderFooter.cpp \
@ -87,6 +91,10 @@ CPPSRCS = \
EXTRA_DSO_LIBS = embed_base_s gkgfx mfcEmbedComponents
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
LIBS = \
$(EXTRA_DSO_LIBS) \
$(XPCOM_LIBS) \

Просмотреть файл

@ -55,10 +55,6 @@ endif
# and then the static data cells used for locking no longer work.
FORCE_SHARED_LIB = 1
ifdef NS_TRACE_MALLOC
REQUIRES = xpcom
endif
CSRCS = \
jsapi.c \
jsarena.c \

Просмотреть файл

@ -27,6 +27,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
REQUIRES = xpcom \
tracemalloc \
$(NULL)
SIMPLECSRCS += \
@ -51,9 +52,12 @@ endif
include $(topsrcdir)/config/config.mk
EXTRA_DSO_LIBS = tracemalloc
LIBS += \
$(LIBS_DIR) \
tmreader.$(OBJ_SUFFIX) \
$(EXTRA_DSO_LIBS) \
$(XPCOM_LIBS) \
$(NSPR_LIBS) \
$(NULL)

Просмотреть файл

@ -0,0 +1,59 @@
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2003 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = tracemalloc
LIBRARY_NAME = tracemalloc
EXPORT_LIBRARY = 1
DEFFILE = $(srcdir)/tm.def
REQUIRES = xpcom
CSRCS = \
nsTraceMalloc.c \
$(NULL)
CPPSRCS = \
nsTypeInfo.cpp \
$(NULL)
EXPORTS = nsTraceMalloc.h
EXTRA_DSO_LDOPTS = $(NSPR_LIBS)
ifdef MOZ_DEMANGLE_SYMBOLS
EXTRA_DSO_LDOPTS += -liberty
endif
ifeq ($(OS_ARCH),WINNT)
CPPSRCS += nsDebugHelpWin32.cpp nsWinTraceMalloc.cpp nsStackFrameWin.cpp
EXTRA_DSO_LDOPTS += $(XPCOM_LIBS)
OS_LIBS += shell32.lib ole32.lib uuid.lib imagehlp.lib
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -36,7 +36,6 @@
*
* ***** END LICENSE BLOCK ***** */
/* Win32 x86 code for stack walking, symbol resolution, and function hooking */
#if defined(_WIN32) && defined(_M_IX86)
// This is the .cpp file where the globals live
@ -48,19 +47,23 @@
#include "plstr.h"
#include "prlock.h"
#include "nscore.h"
#include "nsAutoLock.h"
#include "nsDebugHelpWin32.h"
#include "nsStackFrameWin.h"
#else
#error "nsDebugHelpWin32.cpp should only be built in Win32 x86 builds"
#endif
/***************************************************************************/
PRLock* DHWImportHooker::gLock = nsnull;
DHWImportHooker* DHWImportHooker::gHooks = nsnull;
GETPROCADDRESS DHWImportHooker::gRealGetProcAddress = nsnull;
PRBool
static PRBool
dhwEnsureImageHlpInitialized()
{
static PRBool gInitialized = PR_FALSE;
@ -82,24 +85,9 @@ dhwEnsureImageHlpInitialized()
dhw##name_ = (typename_) ::GetProcAddress(module, #name_); \
if(!dhw##name_) return PR_FALSE;
INIT_PROC(SYMINITIALIZEPROC, SymInitialize);
INIT_PROC(SYMSETOPTIONS, SymSetOptions);
INIT_PROC(SYMGETOPTIONS, SymGetOptions);
INIT_PROC(SYMGETMODULEINFO, SymGetModuleInfo);
INIT_PROC(SYMGETSYMFROMADDRPROC, SymGetSymFromAddr);
INIT_PROC(ENUMERATELOADEDMODULES, EnumerateLoadedModules);
INIT_PROC(IMAGEDIRECTORYENTRYTODATA, ImageDirectoryEntryToData);
// INIT_PROC(SYMGETLINEFROMADDR, SymGetLineFromAddr);
// INIT_PROC(SYMCLEANUPPROC, SymCleanup);
// INIT_PROC(STACKWALKPROC, StackWalk);
// INIT_PROC(SYMFUNCTIONTABLEACCESSPROC, SymFunctionTableAccess);
// INIT_PROC(SYMGETMODULEBASEPROC, SymGetModuleBase);
// INIT_PROC(SYMLOADMODULE, SymLoadModule);
// INIT_PROC(UNDECORATESYMBOLNAME, UnDecorateSymbolName);
// INIT_PROC(SYMUNDNAME, SymUnDName);
#undef INIT_PROC
gInitialized = PR_TRUE;
@ -108,33 +96,6 @@ dhwEnsureImageHlpInitialized()
return gInitialized;
}
PRBool
dhwEnsureSymInitialized()
{
static PRBool gInitialized = PR_FALSE;
if (! gInitialized) {
if (! dhwEnsureImageHlpInitialized())
return PR_FALSE;
dhwSymSetOptions(
#if defined(NS_TRACE_MALLOC)
SYMOPT_LOAD_LINES |
#endif
SYMOPT_UNDNAME);
// dhwSymSetOptions(SYMOPT_UNDNAME);
if (! dhwSymInitialize(::GetCurrentProcess(), NULL, TRUE))
return PR_FALSE;
gInitialized = PR_TRUE;
}
return gInitialized;
}
/***************************************************************************/
PRLock* DHWImportHooker::gLock = nsnull;
DHWImportHooker* DHWImportHooker::gHooks = nsnull;
GETPROCADDRESS DHWImportHooker::gRealGetProcAddress = nsnull;
DHWImportHooker&
DHWImportHooker::getGetProcAddressHooker()
@ -201,9 +162,10 @@ DHWImportHooker::DHWImportHooker(const char* aModuleName,
if(!gLock)
gLock = PR_NewLock();
nsAutoLock lock(gLock);
PR_Lock(gLock);
dhwEnsureImageHlpInitialized();
EnsureImageHlpInitialized();
dhwEnsureImageHlpInitialized(); // for the extra ones we care about.
if(!gRealGetProcAddress)
gRealGetProcAddress = ::GetProcAddress;
@ -215,11 +177,13 @@ DHWImportHooker::DHWImportHooker(const char* aModuleName,
gHooks = this;
PatchAllModules();
PR_Unlock(gLock);
}
DHWImportHooker::~DHWImportHooker()
{
nsAutoLock lock(gLock);
PR_Lock(gLock);
mHooking = PR_FALSE;
PatchAllModules();
@ -236,16 +200,18 @@ DHWImportHooker::~DHWImportHooker()
break;
}
}
NS_ASSERTION(cur, "we were not in the list!");
PR_ASSERT(cur); //we were not in the list!
}
if(!gHooks)
{
PRLock* theLock = gLock;
gLock = nsnull;
lock.unlock();
PR_Unlock(theLock);
PR_DestroyLock(theLock);
}
if (gLock)
PR_Unlock(gLock);
}
static BOOL CALLBACK ModuleEnumCallback(LPSTR ModuleName,
@ -351,11 +317,12 @@ DHWImportHooker::ModuleLoaded(HMODULE aModule, DWORD flags)
//printf("ModuleLoaded\n");
if(aModule && !(flags & LOAD_LIBRARY_AS_DATAFILE))
{
nsAutoLock lock(gLock);
PR_Lock(gLock);
// We don't know that the newly loaded module didn't drag in implicitly
// linked modules, so we patch everything in sight.
for(DHWImportHooker* cur = gHooks; cur; cur = cur->mNext)
cur->PatchAllModules();
PR_Unlock(gLock);
}
return PR_TRUE;
}
@ -413,7 +380,7 @@ DHWImportHooker::GetProcAddress(HMODULE aModule, PCSTR aFunctionName)
if(pfn)
{
nsAutoLock lock(gLock);
PR_Lock(gLock);
for(DHWImportHooker* cur = gHooks; cur; cur = cur->mNext)
{
if(pfn == cur->mOriginal)
@ -422,75 +389,9 @@ DHWImportHooker::GetProcAddress(HMODULE aModule, PCSTR aFunctionName)
break;
}
}
PR_Unlock(gLock);
}
return pfn;
}
/***************************************************************************/
#if 0
static _CRT_ALLOC_HOOK defaultDbgAllocHook = nsnull;
static DHWAllocationSizeDebugHook* gAllocationSizeHook = nsnull;
int __cdecl dhw_DbgAllocHook(int nAllocType, void *pvData,
size_t nSize, int nBlockUse, long lRequest,
const unsigned char * szFileName, int nLine )
{
DHWAllocationSizeDebugHook* hook = gAllocationSizeHook;
if(hook)
{
PRBool res;
_CrtSetAllocHook(defaultDbgAllocHook);
switch(nAllocType)
{
case _HOOK_ALLOC:
res = hook->AllocHook(nSize);
break;
case _HOOK_REALLOC:
res = hook->ReallocHook(nSize, pvData ?
_msize_dbg(pvData, nBlockUse) : 0);
break;
case _HOOK_FREE:
res = hook->FreeHook(pvData ?
_msize_dbg(pvData, nBlockUse) : 0);
break;
default:
NS_ASSERTION(0,"huh?");
res = PR_TRUE;
break;
}
_CrtSetAllocHook(dhw_DbgAllocHook);
return (int) res;
}
return 1;
}
PRBool
dhwSetAllocationSizeDebugHook(DHWAllocationSizeDebugHook* hook)
{
if(!hook || gAllocationSizeHook)
return PR_FALSE;
gAllocationSizeHook = hook;
if(!defaultDbgAllocHook)
defaultDbgAllocHook = _CrtSetAllocHook(dhw_DbgAllocHook);
else
_CrtSetAllocHook(dhw_DbgAllocHook);
return PR_TRUE;
}
PRBool
dhwClearAllocationSizeDebugHook()
{
if(!gAllocationSizeHook)
return PR_FALSE;
gAllocationSizeHook = nsnull;
_CrtSetAllocHook(defaultDbgAllocHook);
return PR_TRUE;
}
#endif //0

Просмотреть файл

@ -104,7 +104,7 @@
/***************************************************************************/
// Global declarations of entry points into ImgHelp functions
#if 0
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMINITIALIZEPROC, SymInitialize, \
BOOL, __stdcall, (HANDLE, LPSTR, BOOL));
@ -120,13 +120,14 @@ DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEINFO, SymGetModuleInfo, \
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETSYMFROMADDRPROC, SymGetSymFromAddr, \
BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL));
#endif
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(ENUMERATELOADEDMODULES, EnumerateLoadedModules, \
BOOL, __stdcall, (HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(IMAGEDIRECTORYENTRYTODATA, ImageDirectoryEntryToData, \
PVOID, __stdcall, (PVOID, BOOL, USHORT, PULONG));
// We aren't using any of the below yet...
/*
@ -167,9 +168,6 @@ DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETLINEFROMADDR, SymGetLineFromAddr, \
extern PRBool
dhwEnsureImageHlpInitialized();
extern PRBool
dhwEnsureSymInitialized();
/***************************************************************************/
DHW_DECLARE_FUN_TYPE(FARPROC, __stdcall, GETPROCADDRESS, (HMODULE, PCSTR));

Просмотреть файл

@ -0,0 +1,346 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Michael Judge, 20-December-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#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);
}
}
}

Просмотреть файл

@ -0,0 +1,121 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Michael Judge, 20-December-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#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___

Просмотреть файл

@ -7,6 +7,7 @@
#include "nscore.h"
#include "nsAutoLock.h"
#include "nsStackFrameWin.h"
#include "nsDebugHelpWin32.h"
#include "nsTraceMallocCallbacks.h"
@ -15,7 +16,7 @@
static PRBool GetSymbolFromAddress(uint32 addr, char* outBuf)
{
PRBool ok;
ok = dhwEnsureSymInitialized();
ok = EnsureSymInitialized();
if(!ok)
return ok;
@ -26,10 +27,10 @@ static PRBool GetSymbolFromAddress(uint32 addr, char* outBuf)
DWORD displacement;
ok = dhwSymGetSymFromAddr(::GetCurrentProcess(),
addr,
&displacement,
symbol);
ok = SymGetSymFromAddr(::GetCurrentProcess(),
addr,
&displacement,
symbol);
if(ok)
{
@ -45,7 +46,7 @@ static PRBool GetSymbolFromAddress(uint32 addr, char* outBuf)
static PRBool GetModuleFromAddress(uint32 addr, char* outBuf)
{
PRBool ok;
ok = dhwEnsureSymInitialized();
ok = EnsureSymInitialized();
if(!ok)
return ok;
@ -53,9 +54,9 @@ static PRBool GetModuleFromAddress(uint32 addr, char* outBuf)
IMAGEHLP_MODULE module;
module.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
ok = dhwSymGetModuleInfo(::GetCurrentProcess(),
addr,
&module);
ok = SymGetModuleInfo(::GetCurrentProcess(),
addr,
&module);
if(ok)
strcat(outBuf, module.ModuleName);
@ -368,7 +369,7 @@ private:
PR_IMPLEMENT(void)
StartupHooker()
{
if (!dhwEnsureSymInitialized())
if (!EnsureSymInitialized())
return;
//run through get all hookers

Просмотреть файл

@ -104,30 +104,32 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
GTK_GLUE = -lgtksuperwin
endif
XP_DIST_LIBS = \
-lgkgfx \
$(NULL)
EXTRA_DSO_LIBS = gkgfx
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
ifeq ($(OS_ARCH),WINNT)
RESFILE = viewer.res
XP_DIST_LIBS += -lxpwidgets_s -ldbgrobot -lwidget_windows
EXTRA_DSO_LIBS += xpwidgets_s dbgrobot widget_windows
endif
ifeq ($(OS_ARCH),OS2)
RESFILE = vieweros2.res
DEFINES += -DUSE_LOCAL_WIDGETS
XP_DIST_LIBS += $(DIST)/lib/components/wdgtos2.lib
EXTRA_DSO_LIBS += $(DIST)/lib/components/wdgtos2.lib
endif
ifdef MOZ_OJI
ifeq ($(OS_ARCH),WINNT)
XP_DIST_LIBS += -ljsj$(MOZ_BITS)$(VERSION_NUMBER)
EXTRA_DSO_LIBS += jsj$(MOZ_BITS)$(VERSION_NUMBER)
else
XP_DIST_LIBS += -ljsj
EXTRA_DSO_LIBS += jsj
endif
endif
ifdef MOZ_PERF_METRICS
XP_DIST_LIBS += -lmozutil_s
EXTRA_DSO_LIBS += mozutil_s
endif
XP_DIST_LIBS += \

Просмотреть файл

@ -41,6 +41,10 @@ REQUIRES = xpcom \
util \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CPPSRCS = \
nsGtkMain.cpp \
nsGtkMenu.cpp \

Просмотреть файл

@ -41,6 +41,10 @@ REQUIRES = xpcom \
util \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CPPSRCS = \
nsGtkMain.cpp \
nsGtkMenu.cpp \

Просмотреть файл

@ -42,6 +42,9 @@ REQUIRES = xpcom \
util \
unicharutil \
$(NULL)
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
CSRCS = \
keysym2ucs.c
@ -72,9 +75,16 @@ CPPSRCS = \
SHARED_LIBRARY_LIBS = $(DIST)/lib/libxpwidgets_s.a
EXTRA_DSO_LIBS = gkgfx
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
-lgkgfx \
$(MOZ_JS_LIBS) \
$(NULL)

Просмотреть файл

@ -64,23 +64,17 @@ EXPORTS = \
nsWeakPtr.h \
$(NULL)
ifdef NS_TRACE_MALLOC
CSRCS += nsTraceMalloc.c
CPPSRCS += nsTypeInfo.cpp
ifeq ($(OS_ARCH),WINNT)
CPPSRCS += nsDebugHelpWin32.cpp nsWinTraceMalloc.cpp
endif
EXPORTS += nsTraceMalloc.h
DEFINES += -DNS_TRACE_MALLOC
endif
ifeq ($(OS_ARCH),WINNT)
ifdef MOZ_DEBUG
CSRCS += pure_api.c
EXPORTS += pure.h
endif
CPPSRCS += nsStackFrameWin.cpp
endif
ifneq ($(OS_ARCH),WINNT)
CPPSRCS += nsStackFrameUnix.cpp
endif
SDK_XPIDLSRCS = \
nsIInterfaceRequestor.idl \

Просмотреть файл

@ -1,250 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Bandhauer <jband@netscape.com>
*
* 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 NPL, 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 NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Win32 x86 code for stack walking, symbol resolution, and function hooking */
#ifndef __nsDebugHelpWin32_h__
#define __nsDebugHelpWin32_h__
#if defined(_WIN32) && defined(_M_IX86)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <imagehlp.h>
#include <crtdbg.h>
#else
#error "nsDebugHelpWin32.h should only be included in Win32 x86 builds"
#endif
// XXX temporary hack...
//#include "hacky_defines.h"
/***************************************************************************/
// useful macros...
#define DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_) \
typedef retval_ ( conv_ * typename_ ) args_ ;
#ifdef DHW_IMPLEMENT_GLOBALS
#define DHW_DECLARE_FUN_GLOBAL(typename_, name_) typename_ dhw##name_
#else
#define DHW_DECLARE_FUN_GLOBAL(typename_, name_) extern typename_ dhw##name_
#endif
#define DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_) \
retval_ conv_ name_ args_
#define DHW_DECLARE_FUN_STATIC_PROTO(retval_, name_, args_) \
static retval_ conv_ name_ args_
#define DHW_DECLARE_FUN_TYPE_AND_PROTO(name_, retval_, conv_, typename_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_)
#define DHW_DECLARE_FUN_TYPE_AND_STATIC_PROTO(name_, retval_, conv_, typename_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_STATIC_PROTO(retval_, conv_, name_, args_)
#define DHW_DECLARE_FUN_TYPE_AND_GLOBAL(typename_, name_, retval_, conv_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_GLOBAL(typename_, name_)
/**********************************************************/
// These are used to get 'original' function addresses from DHWImportHooker.
#define DHW_DECLARE_ORIGINAL(type_, name_, hooker_) \
type_ name_ = (type_) hooker_ . GetOriginalFunction()
#define DHW_DECLARE_ORIGINAL_PTR(type_, name_, hooker_) \
type_ name_ = (type_) hooker_ -> GetOriginalFunction()
#define DHW_ORIGINAL(type_, hooker_) \
((type_) hooker_ . GetOriginalFunction())
#define DHW_ORIGINAL_PTR(type_, hooker_) \
((type_) hooker_ -> GetOriginalFunction())
/***************************************************************************/
// Global declarations of entry points into ImgHelp functions
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMINITIALIZEPROC, SymInitialize, \
BOOL, __stdcall, (HANDLE, LPSTR, BOOL));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMSETOPTIONS, SymSetOptions, \
DWORD, __stdcall, (DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETOPTIONS, SymGetOptions, \
DWORD, __stdcall, ());
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEINFO, SymGetModuleInfo, \
BOOL, __stdcall, (HANDLE, DWORD, PIMAGEHLP_MODULE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETSYMFROMADDRPROC, SymGetSymFromAddr, \
BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(ENUMERATELOADEDMODULES, EnumerateLoadedModules, \
BOOL, __stdcall, (HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(IMAGEDIRECTORYENTRYTODATA, ImageDirectoryEntryToData, \
PVOID, __stdcall, (PVOID, BOOL, USHORT, PULONG));
// We aren't using any of the below yet...
/*
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMCLEANUPPROC, SymCleanup, \
BOOL, __stdcall, (HANDLE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(STACKWALKPROC, StackWalk, \
BOOL,
__stdcall,
(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, \
PREAD_PROCESS_MEMORY_ROUTINE, \
PFUNCTION_TABLE_ACCESS_ROUTINE, \
PGET_MODULE_BASE_ROUTINE, \
PTRANSLATE_ADDRESS_ROUTINE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMFUNCTIONTABLEACCESSPROC, SymFunctionTableAccess, \
LPVOID, __stdcall, (HANDLE, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEBASEPROC, SymGetModuleBase, \
DWORD, __stdcall, (HANDLE, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMLOADMODULE, SymLoadModule, \
DWORD, __stdcall, (HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(UNDECORATESYMBOLNAME, _UnDecorateSymbolName, \
DWORD, __stdcall, (LPCSTR, LPSTR, DWORD, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMUNDNAME, SymUnDName, \
BOOL, __stdcall, (PIMAGEHLP_SYMBOL, LPSTR, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETLINEFROMADDR, SymGetLineFromAddr, \
BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE));
*/
/***************************************************************************/
extern PRBool
dhwEnsureImageHlpInitialized();
extern PRBool
dhwEnsureSymInitialized();
/***************************************************************************/
DHW_DECLARE_FUN_TYPE(FARPROC, __stdcall, GETPROCADDRESS, (HMODULE, PCSTR));
class DHWImportHooker
{
public:
DHWImportHooker(const char* aModuleName,
const char* aFunctionName,
PROC aHook,
PRBool aExcludeOurModule = PR_FALSE);
~DHWImportHooker();
PROC GetOriginalFunction() {return mOriginal;}
PRBool PatchAllModules();
PRBool PatchOneModule(HMODULE aModule, const char* name);
static PRBool ModuleLoaded(HMODULE aModule, DWORD flags);
// I think that these should be made not static members, but allocated
// things created in an explicit static 'init' method and cleaned up in
// an explicit static 'finish' method. This would allow the application
// to have proper lifetime control over all the hooks.
static DHWImportHooker &getLoadLibraryWHooker();
static DHWImportHooker &getLoadLibraryExWHooker();
static DHWImportHooker &getLoadLibraryAHooker();
static DHWImportHooker &getLoadLibraryExAHooker();
static DHWImportHooker &getGetProcAddressHooker();
static HMODULE WINAPI LoadLibraryA(PCSTR path);
private:
DHWImportHooker* mNext;
const char* mModuleName;
const char* mFunctionName;
PROC mOriginal;
PROC mHook;
HMODULE mIgnoreModule;
PRBool mHooking;
private:
static PRLock* gLock;
static DHWImportHooker* gHooks;
static GETPROCADDRESS gRealGetProcAddress;
static HMODULE WINAPI LoadLibraryW(PCWSTR path);
static HMODULE WINAPI LoadLibraryExW(PCWSTR path, HANDLE file, DWORD flags);
static HMODULE WINAPI LoadLibraryExA(PCSTR path, HANDLE file, DWORD flags);
static FARPROC WINAPI GetProcAddress(HMODULE aModule, PCSTR aFunctionName);
};
/***************************************************************************/
// This supports the _CrtSetAllocHook based hooking.
// This system sucks because you don't get to see the allocated pointer. I
// don't think it appropriate for nsTraceMalloc, but is useful as a means to make
// malloc fail for testing purposes.
#if 0 //comment out this stuff. not necessary
class DHWAllocationSizeDebugHook
{
public:
virtual PRBool AllocHook(size_t size) = 0;
virtual PRBool ReallocHook(size_t size, size_t sizeOld) = 0;
virtual PRBool FreeHook(size_t size) = 0;
};
extern PRBool dhwSetAllocationSizeDebugHook(DHWAllocationSizeDebugHook* hook);
extern PRBool dhwClearAllocationSizeDebugHook();
/***************************************************************************/
#endif //0
#endif /* __nsDebugHelpWin32_h__ */

Просмотреть файл

@ -0,0 +1,372 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Netscape are
* Copyright (C) 2003 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#include "nsStackFrameUnix.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "nscore.h"
#if defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code
#include <setjmp.h>
//
// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
// if __USE_GNU is defined. I suppose its some kind of standards
// adherence thing.
//
#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
#define __USE_GNU
#endif
#include <dlfcn.h>
#ifdef HAVE_LIBDL
#include <dlfcn.h>
#endif
// This thing is exported by libiberty.a (-liberty)
// Yes, this is a gcc only hack
#if defined(MOZ_DEMANGLE_SYMBOLS)
extern "C" char * cplus_demangle(const char *,int);
#include <stdlib.h> // for free()
#endif // MOZ_DEMANGLE_SYMBOLS
void DemangleSymbol(const char * aSymbol,
char * aBuffer,
int aBufLen)
{
aBuffer[0] = '\0';
#if defined(MOZ_DEMANGLE_SYMBOLS)
/* See demangle.h in the gcc source for the voodoo */
char * demangled = cplus_demangle(aSymbol,3);
if (demangled)
{
strncpy(aBuffer,demangled,aBufLen);
free(demangled);
}
#endif // MOZ_DEMANGLE_SYMBOLS
}
void DumpStackToFile(FILE* aStream)
{
jmp_buf jb;
setjmp(jb);
// Stack walking code courtesy Kipp's "leaky".
// Get the frame pointer out of the jmp_buf
#if defined(__i386)
unsigned long* bp = (unsigned long*) (jb[0].__jmpbuf[JB_BP]);
#elif defined(PPC)
unsigned long* bp = (unsigned long*) (jb[0].__jmpbuf[JB_GPR1]);
#endif
int skip = 2;
for (unsigned long *nextbp = (unsigned long*) *bp++, pc = *bp;
pc >= 0x08000000 && pc < 0x7fffffff && nextbp > bp;
bp = nextbp, nextbp = (unsigned long*) *bp++, pc = *bp) {
if (--skip <= 0) {
Dl_info info;
int ok = dladdr((void*) pc, &info);
if (!ok) {
fprintf(aStream, "UNKNOWN %p\n", (void *)pc);
continue;
}
PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
const char * symbol = info.dli_sname;
int len;
if (!symbol || !(len = strlen(symbol))) {
fprintf(aStream, "UNKNOWN [%s +0x%08X]\n",
info.dli_fname, foff);
continue;
}
char demangled[4096] = "\0";
DemangleSymbol(symbol, demangled, sizeof(demangled));
if (strlen(demangled)) {
symbol = demangled;
len = strlen(symbol);
}
PRUint32 off = (char*)pc - (char*)info.dli_saddr;
fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n",
symbol, off, info.dli_fname, foff);
}
}
}
#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
/*
* Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
*/
#include <synch.h>
#include <ucontext.h>
#include <sys/frame.h>
#include <sys/regset.h>
#include <sys/stack.h>
static int load_address ( void * pc, void * arg, FILE * aStream );
static int write_address_file ( void * pc );
static struct bucket * newbucket ( void * pc );
static struct frame * cs_getmyframeptr ( void );
static void cs_walk_stack ( void * (*read_func)(char * address),
struct frame * fp,
int (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
static void cs_operate ( void (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
#ifndef STACK_BIAS
#define STACK_BIAS 0
#endif /*STACK_BIAS*/
#define LOGSIZE 4096
/* type of demangling function */
typedef int demf_t(const char *, char *, size_t);
static demf_t *demf;
static int initialized = 0;
#if defined(sparc) || defined(__sparc)
#define FRAME_PTR_REGISTER REG_SP
#endif
#if defined(i386) || defined(__i386)
#define FRAME_PTR_REGISTER EBP
#endif
struct bucket {
void * pc;
int index;
struct bucket * next;
};
struct mybuf {
char * buffer;
int chars_left;
};
static void myinit();
#pragma init (myinit)
static void
myinit()
{
if (! initialized) {
#ifndef __GNUC__
void *handle;
const char *libdem = "libdemangle.so.1";
/* load libdemangle if we can and need to (only try this once) */
if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) {
demf = (demf_t *)dlsym(handle,
"cplus_demangle"); /*lint !e611 */
/*
* lint override above is to prevent lint from
* complaining about "suspicious cast".
*/
}
#endif /*__GNUC__*/
}
initialized = 1;
}
static int
write_address_file(void * pc, FILE* aStream)
{
static struct bucket table[2048];
static mutex_t lock;
struct bucket * ptr;
unsigned int val = NS_PTR_TO_INT32(pc);
ptr = table + ((val >> 2)&2047);
mutex_lock(&lock);
while (ptr->next) {
if (ptr->next->pc == pc)
break;
ptr = ptr->next;
}
if (ptr->next) {
mutex_unlock(&lock);
return (ptr->next->index);
} else {
char buffer[4096], dembuff[4096];
Dl_info info;
char *func, *lib;
ptr->next = newbucket(pc);
mutex_unlock(&lock);
if (dladdr(pc, & info) == 0) {
func = "??";
lib = "??";
} else {
lib = (char *) info.dli_fname;
func = (char *) info.dli_sname;
}
#ifdef __GNUC__
nsTraceRefcnt::DemangleSymbol(func, dembuff, sizeof(dembuff));
if (strlen(dembuff)) {
func = dembuff;
}
#else
if (demf) {
if (demf(func, dembuff, sizeof (dembuff)) == 0)
func = dembuff;
}
#endif /*__GNUC__*/
fprintf(aStream, "%u %s:%s+0x%x\n",
ptr->next->index,
lib,
func,
(char *)pc - (char*)info.dli_saddr);
return (ptr->next->index);
}
}
static int
load_address(void * pc, void * arg, FILE * aStream)
{
struct mybuf * buf = (struct mybuf *) arg;
char name[80];
int len;
sprintf(name, " %u", write_address_file(pc, aStream));
len = strlen(name);
if (len >= buf->chars_left)
return (1);
strcat(buf->buffer, name);
buf->chars_left -= len;
return (0);
}
static struct bucket *
newbucket(void * pc)
{
struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr));
static int index; /* protected by lock in caller */
ptr->index = index++;
ptr->next = NULL;
ptr->pc = pc;
return (ptr);
}
static struct frame *
csgetframeptr()
{
ucontext_t u;
struct frame *fp;
(void) getcontext(&u);
fp = (struct frame *)
((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
STACK_BIAS);
/* make sure to return parents frame pointer.... */
return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
}
static void
cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *),
void *usrarg, FILE * aStream)
{
while (fp != 0 && fp->fr_savpc != 0) {
if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0)
break;
/*
* watch out - libthread stacks look funny at the top
* so they may not have their STACK_BIAS set
*/
fp = (struct frame *)((ulong_t)fp->fr_savfp +
(fp->fr_savfp?(ulong_t)STACK_BIAS:0));
}
}
static void
cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream)
{
cswalkstack(csgetframeptr(), operate_func, usrarg, aStream);
}
void DumpStackToFile(FILE* aStream)
{
char buffer[LOGSIZE];
struct mybuf mybuf;
if (!initialized)
myinit();
mybuf.chars_left = LOGSIZE - strlen(buffer)-1;
mybuf.buffer = buffer;
cs_operate(load_address, &mybuf, aStream);
}
#endif

Просмотреть файл

@ -0,0 +1,41 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Netscape are
* Copyright (C) 2003 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#ifndef nsStackFrameUnix_h___
#define nsStackFrameUnix_h___
#include "stdio.h"
void DumpStackToFile(FILE* out);
#endif

Просмотреть файл

@ -0,0 +1,346 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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, 2003.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2003 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Michael Judge, 20-December-2000
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*/
#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);
}
}
}

Просмотреть файл

@ -37,6 +37,7 @@
#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
#include "nspr.h"
#include <windows.h>
#include <imagehlp.h>
@ -94,6 +95,8 @@ extern SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
PRBool EnsureSymInitialized();
PRBool EnsureImageHlpInitialized();
/*
* SymGetModuleInfoEspecial
*
@ -106,6 +109,9 @@ PRBool EnsureSymInitialized();
*/
BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo);
void DumpStackToFile(FILE* out);
PR_END_EXTERN_C
#endif //WIN32

Просмотреть файл

@ -852,599 +852,23 @@ static void InitTraceLog(void)
#endif
#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
#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
static 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
nsTraceRefcnt::WalkTheStack(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);
}
}
DumpStackToFile(aStream);
}
#elif defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code
// WIN32 x86 stack walking code
// i386 or PPC Linux stackwalking code or Solaris
#elif (defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
#include "nsStackFrameUnix.h"
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
{
jmp_buf jb;
setjmp(jb);
// Stack walking code courtesy Kipp's "leaky".
// Get the frame pointer out of the jmp_buf
#if defined(__i386)
u_long* bp = (u_long*) (jb[0].__jmpbuf[JB_BP]);
#elif defined(PPC)
u_long* bp = (u_long*) (jb[0].__jmpbuf[JB_GPR1]);
#endif
int skip = 2;
for (u_long *nextbp = (u_long*) *bp++, pc = *bp;
pc >= 0x08000000 && pc < 0x7fffffff && nextbp > bp;
bp = nextbp, nextbp = (u_long*) *bp++, pc = *bp) {
if (--skip <= 0) {
Dl_info info;
int ok = dladdr((void*) pc, &info);
if (!ok) {
fprintf(aStream, "UNKNOWN %p\n", (void *)pc);
continue;
}
PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
const char * symbol = info.dli_sname;
int len;
if (!symbol || !(len = strlen(symbol))) {
fprintf(aStream, "UNKNOWN [%s +0x%08X]\n",
info.dli_fname, foff);
continue;
}
char demangled[4096] = "\0";
DemangleSymbol(symbol, demangled, sizeof(demangled));
if (strlen(demangled)) {
symbol = demangled;
len = strlen(symbol);
}
PRUint32 off = (char*)pc - (char*)info.dli_saddr;
fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n",
symbol, off, info.dli_fname, foff);
}
}
}
#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
/*
* Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
*/
#include <synch.h>
#include <ucontext.h>
#include <sys/frame.h>
#include <sys/regset.h>
#include <sys/stack.h>
static int load_address ( void * pc, void * arg, FILE * aStream );
static int write_address_file ( void * pc );
static struct bucket * newbucket ( void * pc );
static struct frame * cs_getmyframeptr ( void );
static void cs_walk_stack ( void * (*read_func)(char * address),
struct frame * fp,
int (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
static void cs_operate ( void (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
#ifndef STACK_BIAS
#define STACK_BIAS 0
#endif /*STACK_BIAS*/
#define LOGSIZE 4096
/* type of demangling function */
typedef int demf_t(const char *, char *, size_t);
static demf_t *demf;
static int initialized = 0;
#if defined(sparc) || defined(__sparc)
#define FRAME_PTR_REGISTER REG_SP
#endif
#if defined(i386) || defined(__i386)
#define FRAME_PTR_REGISTER EBP
#endif
struct bucket {
void * pc;
int index;
struct bucket * next;
};
struct mybuf {
char * buffer;
int chars_left;
};
static void myinit();
#pragma init (myinit)
static void
myinit()
{
if (! initialized) {
#ifndef __GNUC__
void *handle;
const char *libdem = "libdemangle.so.1";
/* load libdemangle if we can and need to (only try this once) */
if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) {
demf = (demf_t *)dlsym(handle,
"cplus_demangle"); /*lint !e611 */
/*
* lint override above is to prevent lint from
* complaining about "suspicious cast".
*/
}
#endif /*__GNUC__*/
}
initialized = 1;
DumpStackToFile(aStream);
}
static int
write_address_file(void * pc, FILE* aStream)
{
static struct bucket table[2048];
static mutex_t lock;
struct bucket * ptr;
unsigned int val = NS_PTR_TO_INT32(pc);
ptr = table + ((val >> 2)&2047);
mutex_lock(&lock);
while (ptr->next) {
if (ptr->next->pc == pc)
break;
ptr = ptr->next;
}
if (ptr->next) {
mutex_unlock(&lock);
return (ptr->next->index);
} else {
char buffer[4096], dembuff[4096];
Dl_info info;
char *func, *lib;
ptr->next = newbucket(pc);
mutex_unlock(&lock);
if (dladdr(pc, & info) == 0) {
func = "??";
lib = "??";
} else {
lib = (char *) info.dli_fname;
func = (char *) info.dli_sname;
}
#ifdef __GNUC__
nsTraceRefcnt::DemangleSymbol(func, dembuff, sizeof(dembuff));
if (strlen(dembuff)) {
func = dembuff;
}
#else
if (demf) {
if (demf(func, dembuff, sizeof (dembuff)) == 0)
func = dembuff;
}
#endif /*__GNUC__*/
fprintf(aStream, "%u %s:%s+0x%x\n",
ptr->next->index,
lib,
func,
(char *)pc - (char*)info.dli_saddr);
return (ptr->next->index);
}
}
static int
load_address(void * pc, void * arg, FILE * aStream)
{
struct mybuf * buf = (struct mybuf *) arg;
char name[80];
int len;
sprintf(name, " %u", write_address_file(pc, aStream));
len = strlen(name);
if (len >= buf->chars_left)
return (1);
strcat(buf->buffer, name);
buf->chars_left -= len;
return (0);
}
static struct bucket *
newbucket(void * pc)
{
struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr));
static int index; /* protected by lock in caller */
ptr->index = index++;
ptr->next = NULL;
ptr->pc = pc;
return (ptr);
}
static struct frame *
csgetframeptr()
{
ucontext_t u;
struct frame *fp;
(void) getcontext(&u);
fp = (struct frame *)
((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
STACK_BIAS);
/* make sure to return parents frame pointer.... */
return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
}
static void
cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *),
void *usrarg, FILE * aStream)
{
while (fp != 0 && fp->fr_savpc != 0) {
if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0)
break;
/*
* watch out - libthread stacks look funny at the top
* so they may not have their STACK_BIAS set
*/
fp = (struct frame *)((ulong_t)fp->fr_savfp +
(fp->fr_savfp?(ulong_t)STACK_BIAS:0));
}
}
static void
cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream)
{
cswalkstack(csgetframeptr(), operate_func, usrarg, aStream);
}
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
{
char buffer[LOGSIZE];
struct mybuf mybuf;
if (!initialized)
myinit();
mybuf.chars_left = LOGSIZE - strlen(buffer)-1;
mybuf.buffer = buffer;
cs_operate(load_address, &mybuf, aStream);
}
#elif defined(XP_MAC)
/**

Просмотреть файл

@ -852,599 +852,23 @@ static void InitTraceLog(void)
#endif
#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
#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
static 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
nsTraceRefcnt::WalkTheStack(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);
}
}
DumpStackToFile(aStream);
}
#elif defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code
// WIN32 x86 stack walking code
// i386 or PPC Linux stackwalking code or Solaris
#elif (defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
#include "nsStackFrameUnix.h"
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
{
jmp_buf jb;
setjmp(jb);
// Stack walking code courtesy Kipp's "leaky".
// Get the frame pointer out of the jmp_buf
#if defined(__i386)
u_long* bp = (u_long*) (jb[0].__jmpbuf[JB_BP]);
#elif defined(PPC)
u_long* bp = (u_long*) (jb[0].__jmpbuf[JB_GPR1]);
#endif
int skip = 2;
for (u_long *nextbp = (u_long*) *bp++, pc = *bp;
pc >= 0x08000000 && pc < 0x7fffffff && nextbp > bp;
bp = nextbp, nextbp = (u_long*) *bp++, pc = *bp) {
if (--skip <= 0) {
Dl_info info;
int ok = dladdr((void*) pc, &info);
if (!ok) {
fprintf(aStream, "UNKNOWN %p\n", (void *)pc);
continue;
}
PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
const char * symbol = info.dli_sname;
int len;
if (!symbol || !(len = strlen(symbol))) {
fprintf(aStream, "UNKNOWN [%s +0x%08X]\n",
info.dli_fname, foff);
continue;
}
char demangled[4096] = "\0";
DemangleSymbol(symbol, demangled, sizeof(demangled));
if (strlen(demangled)) {
symbol = demangled;
len = strlen(symbol);
}
PRUint32 off = (char*)pc - (char*)info.dli_saddr;
fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n",
symbol, off, info.dli_fname, foff);
}
}
}
#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
/*
* Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
*/
#include <synch.h>
#include <ucontext.h>
#include <sys/frame.h>
#include <sys/regset.h>
#include <sys/stack.h>
static int load_address ( void * pc, void * arg, FILE * aStream );
static int write_address_file ( void * pc );
static struct bucket * newbucket ( void * pc );
static struct frame * cs_getmyframeptr ( void );
static void cs_walk_stack ( void * (*read_func)(char * address),
struct frame * fp,
int (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
static void cs_operate ( void (*operate_func)(void *, void *),
void * usrarg, FILE * aStream );
#ifndef STACK_BIAS
#define STACK_BIAS 0
#endif /*STACK_BIAS*/
#define LOGSIZE 4096
/* type of demangling function */
typedef int demf_t(const char *, char *, size_t);
static demf_t *demf;
static int initialized = 0;
#if defined(sparc) || defined(__sparc)
#define FRAME_PTR_REGISTER REG_SP
#endif
#if defined(i386) || defined(__i386)
#define FRAME_PTR_REGISTER EBP
#endif
struct bucket {
void * pc;
int index;
struct bucket * next;
};
struct mybuf {
char * buffer;
int chars_left;
};
static void myinit();
#pragma init (myinit)
static void
myinit()
{
if (! initialized) {
#ifndef __GNUC__
void *handle;
const char *libdem = "libdemangle.so.1";
/* load libdemangle if we can and need to (only try this once) */
if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) {
demf = (demf_t *)dlsym(handle,
"cplus_demangle"); /*lint !e611 */
/*
* lint override above is to prevent lint from
* complaining about "suspicious cast".
*/
}
#endif /*__GNUC__*/
}
initialized = 1;
DumpStackToFile(aStream);
}
static int
write_address_file(void * pc, FILE* aStream)
{
static struct bucket table[2048];
static mutex_t lock;
struct bucket * ptr;
unsigned int val = NS_PTR_TO_INT32(pc);
ptr = table + ((val >> 2)&2047);
mutex_lock(&lock);
while (ptr->next) {
if (ptr->next->pc == pc)
break;
ptr = ptr->next;
}
if (ptr->next) {
mutex_unlock(&lock);
return (ptr->next->index);
} else {
char buffer[4096], dembuff[4096];
Dl_info info;
char *func, *lib;
ptr->next = newbucket(pc);
mutex_unlock(&lock);
if (dladdr(pc, & info) == 0) {
func = "??";
lib = "??";
} else {
lib = (char *) info.dli_fname;
func = (char *) info.dli_sname;
}
#ifdef __GNUC__
nsTraceRefcnt::DemangleSymbol(func, dembuff, sizeof(dembuff));
if (strlen(dembuff)) {
func = dembuff;
}
#else
if (demf) {
if (demf(func, dembuff, sizeof (dembuff)) == 0)
func = dembuff;
}
#endif /*__GNUC__*/
fprintf(aStream, "%u %s:%s+0x%x\n",
ptr->next->index,
lib,
func,
(char *)pc - (char*)info.dli_saddr);
return (ptr->next->index);
}
}
static int
load_address(void * pc, void * arg, FILE * aStream)
{
struct mybuf * buf = (struct mybuf *) arg;
char name[80];
int len;
sprintf(name, " %u", write_address_file(pc, aStream));
len = strlen(name);
if (len >= buf->chars_left)
return (1);
strcat(buf->buffer, name);
buf->chars_left -= len;
return (0);
}
static struct bucket *
newbucket(void * pc)
{
struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr));
static int index; /* protected by lock in caller */
ptr->index = index++;
ptr->next = NULL;
ptr->pc = pc;
return (ptr);
}
static struct frame *
csgetframeptr()
{
ucontext_t u;
struct frame *fp;
(void) getcontext(&u);
fp = (struct frame *)
((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
STACK_BIAS);
/* make sure to return parents frame pointer.... */
return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
}
static void
cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *),
void *usrarg, FILE * aStream)
{
while (fp != 0 && fp->fr_savpc != 0) {
if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0)
break;
/*
* watch out - libthread stacks look funny at the top
* so they may not have their STACK_BIAS set
*/
fp = (struct frame *)((ulong_t)fp->fr_savfp +
(fp->fr_savfp?(ulong_t)STACK_BIAS:0));
}
}
static void
cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream)
{
cswalkstack(csgetframeptr(), operate_func, usrarg, aStream);
}
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
{
char buffer[LOGSIZE];
struct mybuf mybuf;
if (!initialized)
myinit();
mybuf.chars_left = LOGSIZE - strlen(buffer)-1;
mybuf.buffer = buffer;
cs_operate(load_address, &mybuf, aStream);
}
#elif defined(XP_MAC)
/**

Просмотреть файл

@ -90,9 +90,6 @@
#include "pure.h"
#endif
#include "pldhash.h"
#ifdef NS_TRACE_MALLOC
#include "nsTraceMalloc.h"
#endif
#include "nsVariant.h"
#ifdef DEBUG
@ -182,17 +179,5 @@ void XXXNeverCalled()
nsCOMArray<nsISupports> dummyArray;
NS_NewArray(nsnull, dummyArray);
NS_NewArrayEnumerator(nsnull, dummyArray);
#ifdef NS_TRACE_MALLOC
NS_TraceMallocStartup(0);
NS_TraceMallocStartupArgs(0, NULL);
NS_TraceMallocShutdown();
NS_TraceMallocDisable();
NS_TraceMallocEnable();
NS_TraceMallocChangeLogFD(0);
NS_TraceMallocCloseLogFD(0);
NS_TraceMallocLogTimestamp(NULL);
NS_TraceMallocDumpAllocations(NULL);
NS_TraceMallocFlushLogfiles();
#endif
nsVariant();
}

Просмотреть файл

@ -121,13 +121,21 @@ nsGREDirServiceProvider::GetGREDirectoryPath()
{
char *pGreLocation = nsnull;
#ifndef XP_UNIX
// If there exists a file named ".gre.conf" in the current working directory,
// then we will not use any GRE. The assumption here is that the GRE is in the
// same directory as the executable.
// we only do this on non-unix platforms per blizzard.
struct stat configStat;
if (stat(".gre.config", &configStat) != -1)
return nsnull;
#endif
// if USE_LOCAL_GRE is set, we just fall back on using no gre or rather,
// the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
if (PR_GetEnv("USE_LOCAL_GRE"))
return nsnull;
// check in the HOME directory
char * path = PR_GetEnv("HOME");

Просмотреть файл

@ -73,6 +73,10 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
REQUIRES += intl profile appcomps
endif
ifdef NS_TRACE_MALLOC
REQUIRES += tracemalloc
endif
include $(topsrcdir)/config/config.mk
ifeq ($(USE_SHORT_LIBNAME),1)
@ -107,6 +111,10 @@ EXTRA_DSO_LIBS += jsj
endif
endif
ifdef NS_TRACE_MALLOC
EXTRA_DSO_LIBS += tracemalloc
endif
else
include $(topsrcdir)/config/static-config.mk
@ -130,10 +138,6 @@ XP_LIBS += \
$(NSPR_LIBS) \
$(NULL)
ifdef NS_TRACE_MALLOC
DEFINES += -DNS_TRACE_MALLOC
endif
ifdef MOZ_JPROF
XP_LIBS += -ljprof
endif
@ -327,7 +331,7 @@ $(EXE_DEF_FILE):
@echo WinQueryProperty = PMMERGE.5450 >>$(EXE_DEF_FILE)
@echo WinRemoveProperty = PMMERGE.5451 >>$(EXE_DEF_FILE)
@echo WinSetProperty = PMMERGE.5452 >>$(EXE_DEF_FILE)
LDFLAGS += /NOE
endif
endif