Split the address->symbol mapping from the rest of the stack walking code. b=374829 r=bsmedberg a=bzbarsky

This commit is contained in:
dbaron@dbaron.org 2007-08-10 14:29:37 -07:00
Родитель 103f60636e
Коммит 110f79280d
6 изменённых файлов: 370 добавлений и 157 удалений

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

@ -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);
}
}