зеркало из https://github.com/mozilla/pjs.git
Split the address->symbol mapping from the rest of the stack walking code. b=374829 r=bsmedberg a=bzbarsky
This commit is contained in:
Родитель
322b9b6ea1
Коммит
d9d01ad030
|
@ -42,6 +42,7 @@
|
|||
#include <math.h>
|
||||
#include "nscore.h"
|
||||
#include <stdio.h>
|
||||
#include "plstr.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
|
||||
|
@ -91,7 +92,6 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
|||
void *aClosure)
|
||||
{
|
||||
// Stack walking code courtesy Kipp's "leaky".
|
||||
char buf[512];
|
||||
|
||||
// Get the frame pointer
|
||||
void **bp;
|
||||
|
@ -110,43 +110,68 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
|||
for ( ; (void**)*bp > bp; bp = (void**)*bp) {
|
||||
void *pc = *(bp+1);
|
||||
if (--skip < 0) {
|
||||
Dl_info info;
|
||||
int ok = dladdr(pc, &info);
|
||||
if (!ok) {
|
||||
snprintf(buf, sizeof(buf), "UNKNOWN %p\n", pc);
|
||||
(*aCallback)(buf, aClosure);
|
||||
continue;
|
||||
}
|
||||
|
||||
PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
|
||||
|
||||
const char * symbol = info.dli_sname;
|
||||
int len;
|
||||
if (!symbol || !(len = strlen(symbol))) {
|
||||
snprintf(buf, sizeof(buf), "UNKNOWN [%s +0x%08X]\n",
|
||||
info.dli_fname, foff);
|
||||
(*aCallback)(buf, aClosure);
|
||||
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;
|
||||
snprintf(buf, sizeof(buf), "%s+0x%08X [%s +0x%08X]\n",
|
||||
symbol, off, info.dli_fname, foff);
|
||||
(*aCallback)(buf, aClosure);
|
||||
(*aCallback)(pc, aClosure);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
|
||||
{
|
||||
aDetails->library[0] = '\0';
|
||||
aDetails->loffset = 0;
|
||||
aDetails->filename[0] = '\0';
|
||||
aDetails->lineno = 0;
|
||||
aDetails->function[0] = '\0';
|
||||
aDetails->foffset = 0;
|
||||
|
||||
Dl_info info;
|
||||
int ok = dladdr(aPC, &info);
|
||||
if (!ok) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PL_strncpyz(aDetails->library, info.dli_fname, sizeof(aDetails->library));
|
||||
aDetails->loffset = (char*)aPC - (char*)info.dli_fbase;
|
||||
|
||||
const char * symbol = info.dli_sname;
|
||||
int len;
|
||||
if (!symbol || !(len = strlen(symbol))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char demangled[4096] = "\0";
|
||||
|
||||
DemangleSymbol(symbol, demangled, sizeof(demangled));
|
||||
|
||||
if (strlen(demangled)) {
|
||||
symbol = demangled;
|
||||
len = strlen(symbol);
|
||||
}
|
||||
|
||||
PL_strncpyz(aDetails->function, symbol, sizeof(aDetails->function));
|
||||
aDetails->foffset = (char*)aPC - (char*)info.dli_saddr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
char *aBuffer, PRUint32 aBufferSize)
|
||||
{
|
||||
if (!aDetails->library[0]) {
|
||||
snprintf(aBuffer, aBufferSize, "UNKNOWN %p\n", aPC);
|
||||
} else if (!aDetails->function[0]) {
|
||||
snprintf(aBuffer, aBufferSize, "UNKNOWN [%s +0x%08lX]\n",
|
||||
aDetails->library, aDetails->loffset);
|
||||
} else {
|
||||
snprintf(aBuffer, aBufferSize, "%s+0x%08lX [%s +0x%08lX]\n",
|
||||
aDetails->function, aDetails->foffset,
|
||||
aDetails->library, aDetails->loffset);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
|
||||
|
||||
/*
|
||||
|
@ -253,33 +278,10 @@ load_address(void * pc, void * arg )
|
|||
if (ptr->next) {
|
||||
mutex_unlock(&lock);
|
||||
} else {
|
||||
char buffer[4096], dembuff[4096];
|
||||
Dl_info info;
|
||||
const char *func = "??", *lib = "??";
|
||||
(*args.callback)(pc, args.closure);
|
||||
|
||||
ptr->next = newbucket(pc);
|
||||
mutex_unlock(&lock);
|
||||
|
||||
if (dladdr(pc, & info)) {
|
||||
if (info.dli_fname)
|
||||
lib = info.dli_fname;
|
||||
if (info.dli_sname)
|
||||
func = info.dli_sname;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
DemangleSymbol(func, dembuff, sizeof(dembuff));
|
||||
#else
|
||||
if (!demf || demf(func, dembuff, sizeof (dembuff)))
|
||||
dembuff[0] = 0;
|
||||
#endif /*__GNUC__*/
|
||||
if (strlen(dembuff)) {
|
||||
func = dembuff;
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), "%u %s:%s+0x%x\n",
|
||||
ptr->next->index, lib, func,
|
||||
(char *)pc - (char*)info.dli_saddr);
|
||||
(*args.callback)(buffer, args.closure);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -357,4 +359,53 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
|||
cs_operate(load_address, &args);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
|
||||
{
|
||||
aDetails->library[0] = '\0';
|
||||
aDetails->loffset = 0;
|
||||
aDetails->filename[0] = '\0';
|
||||
aDetails->lineno = 0;
|
||||
aDetails->function[0] = '\0';
|
||||
aDetails->foffset = 0;
|
||||
|
||||
char dembuff[4096];
|
||||
Dl_info info;
|
||||
|
||||
if (dladdr(aPC, & info)) {
|
||||
if (info.dli_fname) {
|
||||
PL_strncpyz(aDetails->library, info.dli_fname,
|
||||
sizeof(aDetails->library));
|
||||
aDetails->loffset = (char*)aPC - (char*)info.dli_fbase;
|
||||
}
|
||||
if (info.dli_sname) {
|
||||
aDetails->foffset = (char*)aPC - (char*)info.dli_saddr;
|
||||
#ifdef __GNUC__
|
||||
DemangleSymbol(func, dembuff, sizeof(dembuff));
|
||||
#else
|
||||
if (!demf || demf(func, dembuff, sizeof (dembuff)))
|
||||
dembuff[0] = 0;
|
||||
#endif /*__GNUC__*/
|
||||
PL_strncpyz(aDetails->function,
|
||||
(dembuff[0] != '\0') ? dembuff : info.dli_sname,
|
||||
sizeof(aDetails->function));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
char *aBuffer, PRUint32 aBufferSize)
|
||||
{
|
||||
snprintf(aBuffer, aBufferSize, "%p %s:%s+0x%lx\n",
|
||||
aPC,
|
||||
aDetails->library[0] ? aDetails->library : "??",
|
||||
aDetails->function[0] ? aDetails->function : "??",
|
||||
aDetails->foffset);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include "nsStackFrameWin.h"
|
||||
#include "plstr.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
|
||||
|
@ -123,7 +124,7 @@ PR_END_EXTERN_C
|
|||
|
||||
// Routine to print an error message to standard error.
|
||||
// Will also call callback with error, if data supplied.
|
||||
void PrintError(char *prefix, WalkStackData *data)
|
||||
void PrintError(char *prefix)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD lastErr = GetLastError();
|
||||
|
@ -139,8 +140,6 @@ void PrintError(char *prefix, WalkStackData *data)
|
|||
char buf[512];
|
||||
_snprintf(buf, sizeof(buf), "### ERROR: %s: %s", prefix, lpMsgBuf);
|
||||
fputs(buf, stderr);
|
||||
if (data)
|
||||
(*data->callback)(buf, data->closure);
|
||||
LocalFree( lpMsgBuf );
|
||||
}
|
||||
|
||||
|
@ -159,7 +158,7 @@ EnsureImageHlpInitialized()
|
|||
NULL); // unnamed mutex
|
||||
|
||||
if (hStackWalkMutex == NULL) {
|
||||
PrintError("CreateMutex", NULL);
|
||||
PrintError("CreateMutex");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -428,7 +427,7 @@ EnsureSymInitialized()
|
|||
_SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
|
||||
retStat = _SymInitialize(GetCurrentPIDorHandle(), NULL, TRUE);
|
||||
if (!retStat)
|
||||
PrintError("SymInitialize", NULL);
|
||||
PrintError("SymInitialize");
|
||||
|
||||
gInitialized = retStat;
|
||||
/* XXX At some point we need to arrange to call _SymCleanup */
|
||||
|
@ -475,12 +474,12 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
|||
if (walkerThread) {
|
||||
walkerReturn = ::WaitForSingleObject(walkerThread, 2000); // no timeout is never a good idea
|
||||
if (walkerReturn != WAIT_OBJECT_0) {
|
||||
PrintError("ThreadWait", &data);
|
||||
PrintError("ThreadWait");
|
||||
}
|
||||
CloseHandle(myThread);
|
||||
}
|
||||
else {
|
||||
PrintError("ThreadCreate", &data);
|
||||
PrintError("ThreadCreate");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -495,7 +494,7 @@ WalkStackThread(LPVOID lpdata)
|
|||
// He's currently waiting for us to finish so now should be a good time.
|
||||
ret = ::SuspendThread( data->thread );
|
||||
if (ret == -1) {
|
||||
PrintError("ThreadSuspend", data);
|
||||
PrintError("ThreadSuspend");
|
||||
}
|
||||
else {
|
||||
if (_StackWalk64)
|
||||
|
@ -504,7 +503,7 @@ WalkStackThread(LPVOID lpdata)
|
|||
WalkStackMain(data);
|
||||
ret = ::ResumeThread(data->thread);
|
||||
if (ret == -1) {
|
||||
PrintError("ThreadResume", data);
|
||||
PrintError("ThreadResume");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,7 +520,6 @@ WalkStackMain64(struct WalkStackData* data)
|
|||
CONTEXT context;
|
||||
HANDLE myProcess = data->process;
|
||||
HANDLE myThread = data->thread;
|
||||
char buf[512];
|
||||
DWORD64 addr;
|
||||
STACKFRAME64 frame64;
|
||||
int skip = 3 + data->skipFrames; // skip our own stack walking frames
|
||||
|
@ -531,7 +529,7 @@ WalkStackMain64(struct WalkStackData* data)
|
|||
memset(&context, 0, sizeof(CONTEXT));
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
if (!GetThreadContext(myThread, &context)) {
|
||||
PrintError("GetThreadContext", data);
|
||||
PrintError("GetThreadContext");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -550,7 +548,7 @@ WalkStackMain64(struct WalkStackData* data)
|
|||
frame64.AddrStack.Offset = context.SP;
|
||||
frame64.AddrFrame.Offset = context.RsBSP;
|
||||
#else
|
||||
PrintError("Unknown platform. No stack walking.", data);
|
||||
PrintError("Unknown platform. No stack walking.");
|
||||
return;
|
||||
#endif
|
||||
frame64.AddrPC.Mode = AddrModeFlat;
|
||||
|
@ -588,55 +586,36 @@ WalkStackMain64(struct WalkStackData* data)
|
|||
0
|
||||
);
|
||||
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
|
||||
if (ok)
|
||||
addr = frame64.AddrPC.Offset;
|
||||
else
|
||||
PrintError("WalkStack64", data);
|
||||
else {
|
||||
addr = 0;
|
||||
PrintError("WalkStack64");
|
||||
}
|
||||
|
||||
if (!ok || (addr == 0)) {
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip-- > 0) {
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to load module info before we attempt to reolve the symbol.
|
||||
// This just makes sure we get good info if available.
|
||||
//
|
||||
|
||||
IMAGEHLP_MODULE64 modInfo;
|
||||
modInfo.SizeOfStruct = sizeof(modInfo);
|
||||
BOOL modInfoRes;
|
||||
modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, nsnull);
|
||||
|
||||
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
||||
MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 displacement;
|
||||
ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
|
||||
|
||||
// All done with debug calls so release our lock.
|
||||
ReleaseMutex(hStackWalkMutex);
|
||||
|
||||
if (ok)
|
||||
_snprintf(buf, sizeof(buf), "%s!%s+0x%016X\n", modInfo.ModuleName, pSymbol->Name, displacement);
|
||||
else
|
||||
_snprintf(buf, sizeof(buf), "0x%016X\n", addr);
|
||||
(*data->callback)(buf, data->closure);
|
||||
(*data->callback)((void*)addr, data->closure);
|
||||
|
||||
#if 0
|
||||
// Stop walking when we get to kernel32.
|
||||
if (strcmp(modInfo.ModuleName, "kernel32") == 0)
|
||||
break;
|
||||
#else
|
||||
if (frame64.AddrReturn.Offset == 0)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
PrintError("LockError64", data);
|
||||
PrintError("LockError64");
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -653,7 +632,6 @@ WalkStackMain(struct WalkStackData* data)
|
|||
CONTEXT context;
|
||||
HANDLE myProcess = data->process;
|
||||
HANDLE myThread = data->thread;
|
||||
char buf[512];
|
||||
DWORD addr;
|
||||
STACKFRAME frame;
|
||||
int skip = data->skipFrames; // skip our own stack walking frames
|
||||
|
@ -663,7 +641,7 @@ WalkStackMain(struct WalkStackData* data)
|
|||
memset(&context, 0, sizeof(CONTEXT));
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
if (!GetThreadContext(myThread, &context)) {
|
||||
PrintError("GetThreadContext", data);
|
||||
PrintError("GetThreadContext");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -677,7 +655,7 @@ WalkStackMain(struct WalkStackData* data)
|
|||
frame.AddrFrame.Offset = context.Ebp;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
#else
|
||||
PrintError("Unknown platform. No stack walking.", data);
|
||||
PrintError("Unknown platform. No stack walking.");
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -703,71 +681,36 @@ WalkStackMain(struct WalkStackData* data)
|
|||
0 // translate address routine
|
||||
);
|
||||
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
|
||||
if (ok)
|
||||
addr = frame.AddrPC.Offset;
|
||||
else
|
||||
PrintError("WalkStack", data);
|
||||
else {
|
||||
addr = 0;
|
||||
PrintError("WalkStack");
|
||||
}
|
||||
|
||||
if (!ok || (addr == 0)) {
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
break;
|
||||
}
|
||||
|
||||
if (skip-- > 0) {
|
||||
ReleaseMutex(hStackWalkMutex); // release the lock
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to load module info before we attempt to resolve the symbol.
|
||||
// This just makes sure we get good info if available.
|
||||
//
|
||||
|
||||
IMAGEHLP_MODULE modInfo;
|
||||
modInfo.SizeOfStruct = sizeof(modInfo);
|
||||
BOOL modInfoRes;
|
||||
modInfoRes = SymGetModuleInfoEspecial(myProcess, addr, &modInfo, nsnull);
|
||||
|
||||
#ifdef USING_WXP_VERSION
|
||||
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
||||
MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 displacement;
|
||||
|
||||
ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
|
||||
#else
|
||||
char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
|
||||
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) buf;
|
||||
pSymbol->SizeOfStruct = sizeof(buf);
|
||||
pSymbol->MaxNameLength = 512;
|
||||
|
||||
DWORD displacement;
|
||||
|
||||
ok = _SymGetSymFromAddr(myProcess,
|
||||
frame.AddrPC.Offset,
|
||||
&displacement,
|
||||
pSymbol);
|
||||
#endif
|
||||
|
||||
// All done with debug calls so release our lock.
|
||||
ReleaseMutex(hStackWalkMutex);
|
||||
|
||||
if (ok)
|
||||
_snprintf(buf, sizeof(buf), "%s!%s+0x%08X\n", modInfo.ImageName, pSymbol->Name, displacement);
|
||||
else
|
||||
_snprintf(buf, sizeof(buf), "0x%08X\n", (DWORD) addr);
|
||||
(*data->callback)(buf, data->closure);
|
||||
(*data->callback)((void*)addr, data->closure);
|
||||
|
||||
#if 0
|
||||
// Stop walking when we get to kernel32.dll.
|
||||
if (strcmp(modInfo.ImageName, "kernel32.dll") == 0)
|
||||
break;
|
||||
|
||||
#else
|
||||
if (frame.AddrReturn.Offset == 0)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
PrintError("LockError", data);
|
||||
PrintError("LockError");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -775,3 +718,138 @@ WalkStackMain(struct WalkStackData* data)
|
|||
return;
|
||||
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
|
||||
{
|
||||
aDetails->library[0] = '\0';
|
||||
aDetails->loffset = 0;
|
||||
aDetails->filename[0] = '\0';
|
||||
aDetails->lineno = 0;
|
||||
aDetails->function[0] = '\0';
|
||||
aDetails->foffset = 0;
|
||||
|
||||
HANDLE myProcess = ::GetCurrentProcess();
|
||||
BOOL ok;
|
||||
|
||||
// debug routines are not threadsafe, so grab the lock.
|
||||
DWORD dwWaitResult;
|
||||
dwWaitResult = WaitForSingleObject(hStackWalkMutex, INFINITE);
|
||||
if (dwWaitResult != WAIT_OBJECT_0)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
#ifdef USING_WXP_VERSION
|
||||
if (_StackWalk64) {
|
||||
//
|
||||
// Attempt to load module info before we attempt to resolve the symbol.
|
||||
// This just makes sure we get good info if available.
|
||||
//
|
||||
|
||||
DWORD64 addr = (DWORD64)aPC;
|
||||
IMAGEHLP_MODULE64 modInfo;
|
||||
modInfo.SizeOfStruct = sizeof(modInfo);
|
||||
BOOL modInfoRes;
|
||||
modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, nsnull);
|
||||
|
||||
if (modInfoRes) {
|
||||
PL_strncpyz(aDetails->library, modInfo.ModuleName,
|
||||
sizeof(aDetails->library));
|
||||
aDetails->loffset = (char*) aPC - (char*) modInfo.BaseOfImage;
|
||||
// XXX We could get filename/lineno information from
|
||||
// SymGetModuleInfoEspecial64
|
||||
}
|
||||
|
||||
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
||||
MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 displacement;
|
||||
ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
|
||||
|
||||
if (ok) {
|
||||
PL_strncpyz(aDetails->function, pSymbol->Name,
|
||||
sizeof(aDetails->function));
|
||||
aDetails->foffset = displacement;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
//
|
||||
// Attempt to load module info before we attempt to resolve the symbol.
|
||||
// This just makes sure we get good info if available.
|
||||
//
|
||||
|
||||
DWORD addr = (DWORD)aPC;
|
||||
IMAGEHLP_MODULE modInfo;
|
||||
modInfo.SizeOfStruct = sizeof(modInfo);
|
||||
BOOL modInfoRes;
|
||||
modInfoRes = SymGetModuleInfoEspecial(myProcess, addr, &modInfo, nsnull);
|
||||
|
||||
if (modInfoRes) {
|
||||
PL_strncpyz(aDetails->library, modInfo.ModuleName,
|
||||
sizeof(aDetails->library));
|
||||
aDetails->loffset = (char*) aPC - (char*) modInfo.BaseOfImage;
|
||||
// XXX We could get filename/lineno information from
|
||||
// SymGetModuleInfoEspecial
|
||||
}
|
||||
|
||||
#ifdef USING_WXP_VERSION
|
||||
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
|
||||
MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
DWORD64 displacement;
|
||||
|
||||
ok = _SymFromAddr && _SymFromAddr(myProcess, addr, &displacement, pSymbol);
|
||||
#else
|
||||
char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
|
||||
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) buf;
|
||||
pSymbol->SizeOfStruct = sizeof(buf);
|
||||
pSymbol->MaxNameLength = 512;
|
||||
|
||||
DWORD displacement;
|
||||
|
||||
ok = _SymGetSymFromAddr(myProcess,
|
||||
frame.AddrPC.Offset,
|
||||
&displacement,
|
||||
pSymbol);
|
||||
#endif
|
||||
|
||||
if (ok) {
|
||||
PL_strncpyz(aDetails->function, pSymbol->Name,
|
||||
sizeof(aDetails->function));
|
||||
aDetails->foffset = displacement;
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseMutex(hStackWalkMutex); // release our lock
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
char *aBuffer, PRUint32 aBufferSize)
|
||||
{
|
||||
#ifdef USING_WXP_VERSION
|
||||
if (_StackWalk64) {
|
||||
if (aDetails->function[0])
|
||||
_snprintf(aBuffer, aBufferSize, "%s!%s+0x%016lX\n",
|
||||
aDetails->library, aDetails->function, aDetails->foffset);
|
||||
else
|
||||
_snprintf(aBuffer, aBufferSize, "0x%016lX\n", aPC);
|
||||
} else {
|
||||
#endif
|
||||
if (aDetails->function[0])
|
||||
_snprintf(aBuffer, aBufferSize, "%s!%s+0x%08lX\n",
|
||||
aDetails->library, aDetails->function, aDetails->foffset);
|
||||
else
|
||||
_snprintf(aBuffer, aBufferSize, "0x%08lX\n", aPC);
|
||||
#ifdef USING_WXP_VERSION
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -56,4 +56,24 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
|
||||
{
|
||||
aDetails->library[0] = '\0';
|
||||
aDetails->loffset = 0;
|
||||
aDetails->filename[0] = '\0';
|
||||
aDetails->lineno = 0;
|
||||
aDetails->function[0] = '\0';
|
||||
aDetails->foffset = 0;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
char *aBuffer, PRUint32 aBufferSize)
|
||||
{
|
||||
aBuffer[0] = '\0';
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
PR_BEGIN_EXTERN_C
|
||||
|
||||
typedef void
|
||||
(* PR_CALLBACK NS_WalkStackCallback)(char *aFrame, void *aClosure);
|
||||
(* PR_CALLBACK NS_WalkStackCallback)(void *aPC, void *aClosure);
|
||||
|
||||
/**
|
||||
* Call aCallback for the C/C++ stack frames on the current thread, from
|
||||
|
@ -69,6 +69,60 @@ XPCOM_API(nsresult)
|
|||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure);
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* The name of the shared library or executable containing an
|
||||
* address and the address's offset within that library, or empty
|
||||
* string and zero if unknown.
|
||||
*/
|
||||
char library[256];
|
||||
unsigned long loffset;
|
||||
/*
|
||||
* The name of the file name and line number of the code
|
||||
* corresponding to the address, or empty string and zero if
|
||||
* unknown.
|
||||
*/
|
||||
char filename[256];
|
||||
unsigned long lineno;
|
||||
/*
|
||||
* The name of the function containing an address and the address's
|
||||
* offset within that function, or empty string and zero if unknown.
|
||||
*/
|
||||
char function[256];
|
||||
unsigned long foffset;
|
||||
} nsCodeAddressDetails;
|
||||
|
||||
/**
|
||||
* For a given pointer to code, fill in the pieces of information used
|
||||
* when printing a stack trace.
|
||||
*
|
||||
* @param aPC The code address.
|
||||
* @param aDetails A structure to be filled in with the result.
|
||||
*/
|
||||
XPCOM_API(nsresult)
|
||||
NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails);
|
||||
|
||||
/**
|
||||
* Format the information about a code address in a format suitable for
|
||||
* stack traces on the current platform. When available, this string
|
||||
* should contain the function name, source file, and line number. When
|
||||
* these are not available, library and offset should be reported, if
|
||||
* possible.
|
||||
*
|
||||
* @param aPC The code address.
|
||||
* @param aDetails The value filled in by NS_DescribeCodeAddress(aPC).
|
||||
* @param aBuffer A string to be filled in with the description.
|
||||
* The string will always be null-terminated.
|
||||
* @param aBufferSize The size, in bytes, of aBuffer, including
|
||||
* room for the terminating null. If the information
|
||||
* to be printed would be larger than aBuffer, it
|
||||
* will be truncated so that aBuffer[aBufferSize-1]
|
||||
* is the terminating null.
|
||||
*/
|
||||
XPCOM_API(nsresult)
|
||||
NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
char *aBuffer, PRUint32 aBufferSize);
|
||||
|
||||
PR_END_EXTERN_C
|
||||
|
||||
#endif /* !defined(nsStackWalk_h_) */
|
||||
|
|
|
@ -829,10 +829,15 @@ static void InitTraceLog(void)
|
|||
|
||||
extern "C" {
|
||||
|
||||
PR_STATIC_CALLBACK(void) PrintStackFrame(char *aFrame, void *aClosure)
|
||||
PR_STATIC_CALLBACK(void) PrintStackFrame(void *aPC, void *aClosure)
|
||||
{
|
||||
FILE *stream = (FILE*)aClosure;
|
||||
fprintf(stream, aFrame);
|
||||
nsCodeAddressDetails details;
|
||||
char buf[1024];
|
||||
|
||||
NS_DescribeCodeAddress(aPC, &details);
|
||||
NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
|
||||
fprintf(stream, buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -118,9 +118,14 @@ void abnormal_exit_handler(int signum)
|
|||
|
||||
extern "C" {
|
||||
|
||||
PR_STATIC_CALLBACK(void) PrintStackFrame(char *aFrame, void *aClosure)
|
||||
PR_STATIC_CALLBACK(void) PrintStackFrame(void *aPC, void *aClosure)
|
||||
{
|
||||
fprintf(stdout, aFrame);
|
||||
char buf[1024];
|
||||
nsCodeAddressDetails details;
|
||||
|
||||
NS_DescribeCodeAddress(aPC, &details);
|
||||
NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
|
||||
fprintf(stdout, buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче