Bug 1172216 - Move nsStackwalk to mozglue. r=glandium

This commit is contained in:
Benoit Girard 2015-06-10 16:32:45 -04:00
parent aace26e2a9
commit 9b4532466d
19 changed files with 161 additions and 231 deletions

View File

@ -27,7 +27,7 @@
#endif
#include "nscore.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@ -123,7 +123,7 @@ static bool gIsDMDInitialized = false;
// - Indirect allocations in js::{Vector,HashSet,HashMap} -- this class serves
// as their AllocPolicy.
//
// - Other indirect allocations (e.g. NS_StackWalk) -- see the comments on
// - Other indirect allocations (e.g. MozStackWalk) -- see the comments on
// Thread::mBlockIntercepts and in replace_malloc for how these work.
//
// It would be nice if we could use the InfallibleAllocPolicy from mozalloc,
@ -512,7 +512,7 @@ class Thread
// When true, this blocks intercepts, which allows malloc interception
// functions to themselves call malloc. (Nb: for direct calls to malloc we
// can just use InfallibleAllocPolicy::{malloc_,new_}, but we sometimes
// indirectly call vanilla malloc via functions like NS_StackWalk.)
// indirectly call vanilla malloc via functions like MozStackWalk.)
bool mBlockIntercepts;
Thread()
@ -735,40 +735,23 @@ StackTrace::Get(Thread* aT)
MOZ_ASSERT(gStateLock->IsLocked());
MOZ_ASSERT(aT->InterceptsAreBlocked());
// On Windows, NS_StackWalk can acquire a lock from the shared library
// On Windows, MozStackWalk can acquire a lock from the shared library
// loader. Another thread might call malloc while holding that lock (when
// loading a shared library). So we can't be in gStateLock during the call
// to NS_StackWalk. For details, see
// to MozStackWalk. For details, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=374829#c8
// On Linux, something similar can happen; see bug 824340.
// So let's just release it on all platforms.
nsresult rv;
StackTrace tmp;
{
AutoUnlockState unlock;
uint32_t skipFrames = 2;
rv = NS_StackWalk(StackWalkCallback, skipFrames,
gOptions->MaxFrames(), &tmp, 0, nullptr);
}
if (rv == NS_OK) {
// Handle the common case first. All is ok. Nothing to do.
} else if (rv == NS_ERROR_NOT_IMPLEMENTED || rv == NS_ERROR_FAILURE) {
tmp.mLength = 0;
} else if (rv == NS_ERROR_UNEXPECTED) {
// XXX: This |rv| only happens on Mac, and it indicates that we're handling
// a call to malloc that happened inside a mutex-handling function. Any
// attempt to create a semaphore (which can happen in printf) could
// deadlock.
//
// However, the most complex thing DMD does after Get() returns is to put
// something in a hash table, which might call
// InfallibleAllocPolicy::malloc_. I'm not yet sure if this needs special
// handling, hence the forced abort. Sorry. If you hit this, please file
// a bug and CC nnethercote.
MOZ_CRASH("unexpected case in StackTrace::Get()");
} else {
MOZ_CRASH("impossible case in StackTrace::Get()");
if (MozStackWalk(StackWalkCallback, skipFrames,
gOptions->MaxFrames(), &tmp, 0, nullptr)) {
// Handle the common case first. All is ok. Nothing to do.
} else {
tmp.mLength = 0;
}
}
StackTraceTable::AddPtr p = gStackTraceTable->lookupForAdd(&tmp);
@ -1232,7 +1215,7 @@ replace_malloc(size_t aSize)
Thread* t = Thread::Fetch();
if (t->InterceptsAreBlocked()) {
// Intercepts are blocked, which means this must be a call to malloc
// triggered indirectly by DMD (e.g. via NS_StackWalk). Be infallible.
// triggered indirectly by DMD (e.g. via MozStackWalk). Be infallible.
return InfallibleAllocPolicy::malloc_(aSize);
}
@ -1555,9 +1538,9 @@ Init(const malloc_table_t* aMallocTable)
// (prior to the creation of any mutexes, apparently) otherwise we can get
// hangs when getting stack traces (bug 821577). But
// StackWalkInitCriticalAddress() isn't exported from xpcom/, so instead we
// just call NS_StackWalk, because that calls StackWalkInitCriticalAddress().
// just call MozStackWalk, because that calls StackWalkInitCriticalAddress().
// See the comment above StackWalkInitCriticalAddress() for more details.
(void)NS_StackWalk(NopStackWalkCallback, /* skipFrames */ 0,
(void)MozStackWalk(NopStackWalkCallback, /* skipFrames */ 0,
/* maxFrames */ 1, nullptr, 0, nullptr);
#endif

View File

@ -13,7 +13,7 @@ EXPORTS += [
SOURCES += [
'../../../mfbt/HashFunctions.cpp',
'../../../mfbt/JSONWriter.cpp',
'../../../xpcom/base/nsStackWalk.cpp',
'../../../mozglue/misc/StackWalk.cpp',
'DMD.cpp',
]

View File

@ -9,9 +9,6 @@
#include "mozilla/Assertions.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/StackWalk.h"
#include "nsStackWalkPrivate.h"
#include "nsStackWalk.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@ -38,16 +35,16 @@ static CriticalAddress gCriticalAddress;
#include <dlfcn.h>
#endif
#define NSSTACKWALK_SUPPORTS_MACOSX \
#define MOZ_STACKWALK_SUPPORTS_MACOSX \
(defined(XP_DARWIN) && \
(defined(__i386) || defined(__ppc__) || defined(HAVE__UNWIND_BACKTRACE)))
#define NSSTACKWALK_SUPPORTS_LINUX \
#define MOZ_STACKWALK_SUPPORTS_LINUX \
(defined(linux) && \
((defined(__GNUC__) && (defined(__i386) || defined(PPC))) || \
defined(HAVE__UNWIND_BACKTRACE)))
#if NSSTACKWALK_SUPPORTS_MACOSX
#if MOZ_STACKWALK_SUPPORTS_MACOSX
#include <pthread.h>
#include <sys/errno.h>
#ifdef MOZ_WIDGET_COCOA
@ -110,7 +107,7 @@ my_malloc_logger(uint32_t aType,
// On Leopard dladdr returns the wrong value for "new_sem_from_pool". The
// stack shows up as having two pthread_cond_wait$UNIX2003 frames.
const char* name = "new_sem_from_pool";
NS_StackWalk(stack_callback, /* skipFrames */ 0, /* maxFrames */ 0,
MozStackWalk(stack_callback, /* skipFrames */ 0, /* maxFrames */ 0,
const_cast<char*>(name), 0, nullptr);
}
@ -121,7 +118,7 @@ my_malloc_logger(uint32_t aType,
// function during NS_LogInit() ensures that we meet the first criterion, and
// running this function during the stack walking functions ensures we meet the
// second criterion.
void
MFBT_API void
StackWalkInitCriticalAddress()
{
if (gCriticalAddress.mInit) {
@ -181,7 +178,7 @@ IsCriticalAddress(void* aPC)
// We still initialize gCriticalAddress.mInit so that this code behaves
// the same on all platforms. Otherwise a failure to init would be visible
// only on OS X.
void
MFBT_API void
StackWalkInitCriticalAddress()
{
gCriticalAddress.mInit = true;
@ -190,15 +187,12 @@ StackWalkInitCriticalAddress()
#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)) // WIN32 x86 stack walking code
#include "nscore.h"
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <malloc.h>
#include "plstr.h"
#include "mozilla/ArrayUtils.h"
#include "nspr.h"
#include <imagehlp.h>
// We need a way to know if we are building for WXP (or later), as if we are, we
// need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill.
@ -512,8 +506,8 @@ WalkStackThread(void* aData)
* whose in memory address doesn't match its in-file address.
*/
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
void* aPlatformData)
{
@ -524,7 +518,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
struct WalkStackData data;
if (!EnsureWalkThreadReady()) {
return NS_ERROR_FAILURE;
return false;
}
HANDLE currentThread = ::GetCurrentThread();
@ -542,7 +536,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
if (data.walkCallingThread) {
PrintError("DuplicateHandle (process)");
}
return NS_ERROR_FAILURE;
return false;
}
}
if (!::DuplicateHandle(::GetCurrentProcess(),
@ -553,7 +547,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
if (data.walkCallingThread) {
PrintError("DuplicateHandle (thread)");
}
return NS_ERROR_FAILURE;
return false;
}
data.skipFrames = aSkipFrames;
@ -622,7 +616,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
(*aCallback)(i + 1, data.pcs[i], data.sps[i], aClosure);
}
return data.pc_count == 0 ? NS_ERROR_FAILURE : NS_OK;
return data.pc_count != 0;
}
@ -772,8 +766,8 @@ EnsureSymInitialized()
}
XPCOM_API(nsresult)
NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
MFBT_API bool
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
{
aDetails->library[0] = '\0';
aDetails->loffset = 0;
@ -783,7 +777,7 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
aDetails->foffset = 0;
if (!EnsureSymInitialized()) {
return NS_ERROR_FAILURE;
return false;
}
HANDLE myProcess = ::GetCurrentProcess();
@ -804,12 +798,12 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo);
if (modInfoRes) {
PL_strncpyz(aDetails->library, modInfo.ModuleName,
strncpy(aDetails->library, modInfo.ModuleName,
sizeof(aDetails->library));
aDetails->loffset = (char*)aPC - (char*)modInfo.BaseOfImage;
if (lineInfo.FileName) {
PL_strncpyz(aDetails->filename, lineInfo.FileName,
strncpy(aDetails->filename, lineInfo.FileName,
sizeof(aDetails->filename));
aDetails->lineno = lineInfo.LineNumber;
}
@ -825,23 +819,21 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
ok = SymFromAddr(myProcess, addr, &displacement, pSymbol);
if (ok) {
PL_strncpyz(aDetails->function, pSymbol->Name,
strncpy(aDetails->function, pSymbol->Name,
sizeof(aDetails->function));
aDetails->foffset = static_cast<ptrdiff_t>(displacement);
}
LeaveCriticalSection(&gDbgHelpCS); // release our lock
return NS_OK;
return true;
}
// i386 or PPC Linux stackwalking code
#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || NSSTACKWALK_SUPPORTS_LINUX || NSSTACKWALK_SUPPORTS_MACOSX)
#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || MOZ_STACKWALK_SUPPORTS_LINUX || MOZ_STACKWALK_SUPPORTS_MACOSX)
#include <stdlib.h>
#include <string.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
@ -868,7 +860,7 @@ void DemangleSymbol(const char* aSymbol,
char* demangled = abi::__cxa_demangle(aSymbol, 0, 0, 0);
if (demangled) {
PL_strncpyz(aBuffer, demangled, aBufLen);
strncpy(aBuffer, demangled, aBufLen);
free(demangled);
}
#endif // MOZ_DEMANGLE_SYMBOLS
@ -884,8 +876,8 @@ void DemangleSymbol(const char* aSymbol,
extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so
#endif
namespace mozilla {
nsresult
FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
bool
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, void** bp,
void* aStackEnd)
{
@ -915,7 +907,7 @@ FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
bp += 2;
#endif
if (IsCriticalAddress(pc)) {
return NS_ERROR_UNEXPECTED;
return false;
}
if (--skip < 0) {
// Assume that the SP points to the BP of the function
@ -930,16 +922,16 @@ FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
}
bp = next;
}
return numFrames == 0 ? NS_ERROR_FAILURE : NS_OK;
return numFrames != 0;
}
}
#define X86_OR_PPC (defined(__i386) || defined(PPC) || defined(__ppc__))
#if X86_OR_PPC && (NSSTACKWALK_SUPPORTS_MACOSX || NSSTACKWALK_SUPPORTS_LINUX) // i386 or PPC Linux or Mac stackwalking code
#if X86_OR_PPC && (MOZ_STACKWALK_SUPPORTS_MACOSX || MOZ_STACKWALK_SUPPORTS_LINUX) // i386 or PPC Linux or Mac stackwalking code
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
void* aPlatformData)
{
@ -975,7 +967,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
struct unwind_info
{
NS_WalkStackCallback callback;
MozWalkStackCallback callback;
int skip;
int maxFrames;
int numFrames;
@ -1007,8 +999,8 @@ unwind_callback(struct _Unwind_Context* context, void* closure)
return _URC_NO_REASON;
}
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
void* aPlatformData)
{
@ -1034,15 +1026,15 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
// is to make unwind_callback return something other than _URC_NO_REASON,
// which causes _Unwind_Backtrace to return a non-success code.
if (info.isCriticalAbort) {
return NS_ERROR_UNEXPECTED;
return false;
}
return info.numFrames == 0 ? NS_ERROR_FAILURE : NS_OK;
return info.numFrames != 0;
}
#endif
XPCOM_API(nsresult)
NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
bool MFBT_API
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
{
aDetails->library[0] = '\0';
aDetails->loffset = 0;
@ -1054,51 +1046,51 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
Dl_info info;
int ok = dladdr(aPC, &info);
if (!ok) {
return NS_OK;
return true;
}
PL_strncpyz(aDetails->library, info.dli_fname, sizeof(aDetails->library));
strncpy(aDetails->library, info.dli_fname, sizeof(aDetails->library));
aDetails->loffset = (char*)aPC - (char*)info.dli_fbase;
const char* symbol = info.dli_sname;
if (!symbol || symbol[0] == '\0') {
return NS_OK;
return true;
}
DemangleSymbol(symbol, aDetails->function, sizeof(aDetails->function));
if (aDetails->function[0] == '\0') {
// Just use the mangled symbol if demangling failed.
PL_strncpyz(aDetails->function, symbol, sizeof(aDetails->function));
strncpy(aDetails->function, symbol, sizeof(aDetails->function));
}
aDetails->foffset = (char*)aPC - (char*)info.dli_saddr;
return NS_OK;
return true;
}
#else // unsupported platform.
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
void* aPlatformData)
{
MOZ_ASSERT(!aThread);
MOZ_ASSERT(!aPlatformData);
return NS_ERROR_NOT_IMPLEMENTED;
return false;
}
namespace mozilla {
nsresult
FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
void* aClosure, void** aBp)
{
return NS_ERROR_NOT_IMPLEMENTED;
return false;
}
}
XPCOM_API(nsresult)
NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
MFBT_API bool
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
{
aDetails->library[0] = '\0';
aDetails->loffset = 0;
@ -1106,24 +1098,24 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
aDetails->lineno = 0;
aDetails->function[0] = '\0';
aDetails->foffset = 0;
return NS_ERROR_NOT_IMPLEMENTED;
return false;
}
#endif
XPCOM_API(void)
NS_FormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
MFBT_API void
MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
uint32_t aFrameNumber, void* aPC,
const nsCodeAddressDetails* aDetails)
const MozCodeAddressDetails* aDetails)
{
NS_FormatCodeAddress(aBuffer, aBufferSize,
MozFormatCodeAddress(aBuffer, aBufferSize,
aFrameNumber, aPC, aDetails->function,
aDetails->library, aDetails->loffset,
aDetails->filename, aDetails->lineno);
}
XPCOM_API(void)
NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
MFBT_API void
MozFormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
const void* aPC, const char* aFunction,
const char* aLibrary, ptrdiff_t aLOffset,
const char* aFileName, uint32_t aLineNo)

View File

@ -6,20 +6,16 @@
/* API for getting a stack trace of the C/C++ stack on the current thread */
#ifndef nsStackWalk_h_
#define nsStackWalk_h_
#ifndef mozilla_StackWalk_h
#define mozilla_StackWalk_h
/* WARNING: This file is intended to be included from C or C++ files. */
#include "nscore.h"
#include "mozilla/Types.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The callback for NS_StackWalk.
* The callback for MozStackWalk.
*
* @param aFrameNumber The frame number (starts at 1, not 0).
* @param aPC The program counter value.
@ -27,20 +23,20 @@ extern "C" {
* pointer will be pointing to when the execution returns
* to executing that at aPC. If no approximation can
* be made it will be nullptr.
* @param aClosure Extra data passed in via NS_StackWalk().
* @param aClosure Extra data passed in via MozStackWalk().
*/
typedef void
(*NS_WalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP,
(*MozWalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP,
void* aClosure);
/**
* Call aCallback for the C/C++ stack frames on the current thread, from
* the caller of NS_StackWalk to main (or above).
* the caller of MozStackWalk to main (or above).
*
* @param aCallback Callback function, called once per frame.
* @param aSkipFrames Number of initial frames to skip. 0 means that
* the first callback will be for the caller of
* NS_StackWalk.
* MozStackWalk.
* @param aMaxFrames Maximum number of frames to trace. 0 means no limit.
* @param aClosure Caller-supplied data passed through to aCallback.
* @param aThread The thread for which the stack is to be retrieved.
@ -53,27 +49,14 @@ typedef void
* CONTEXT on Windows and should not be passed on other
* platforms.
*
* Return values:
* - NS_ERROR_NOT_IMPLEMENTED. Occurs on platforms where it is unimplemented.
*
* - NS_ERROR_UNEXPECTED. Occurs when the stack indicates that the thread
* is in a very dangerous situation (e.g., holding sem_pool_lock in Mac OS X
* pthreads code). Callers should then bail out immediately.
*
* - NS_ERROR_FAILURE. Occurs when stack walking completely failed, i.e.
* aCallback was never called.
*
* - NS_OK. Occurs when stack walking succeeded, i.e. aCallback was called at
* least once (and there was no need to exit with NS_ERROR_UNEXPECTED).
*
* May skip some stack frames due to compiler optimizations or code
* generation.
*
* Note: this (and other helper methods) will only be available when
* MOZ_STACKWALKING is defined, so any new consumers must #if based on that.
*/
XPCOM_API(nsresult)
NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
MFBT_API bool
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
void* aPlatformData);
@ -99,7 +82,7 @@ typedef struct
*/
char function[256];
ptrdiff_t foffset;
} nsCodeAddressDetails;
} MozCodeAddressDetails;
/**
* For a given pointer to code, fill in the pieces of information used
@ -108,8 +91,8 @@ typedef struct
* @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);
MFBT_API bool
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails);
/**
* Format the information about a code address in a format suitable for
@ -137,15 +120,15 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails);
* @param aFileName The filename. Possibly null or the empty string.
* @param aLineNo The line number. Possibly zero.
*/
XPCOM_API(void)
NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
MFBT_API void
MozFormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
const void* aPC, const char* aFunction,
const char* aLibrary, ptrdiff_t aLOffset,
const char* aFileName, uint32_t aLineNo);
/**
* Format the information about a code address in the same fashion as
* NS_FormatCodeAddress.
* MozFormatCodeAddress.
*
* @param aBuffer A string to be filled in with the description.
* The string will always be null-terminated.
@ -156,15 +139,27 @@ NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
* is the terminating null.
* @param aFrameNumber The frame number.
* @param aPC The code address.
* @param aDetails The value filled in by NS_DescribeCodeAddress(aPC).
* @param aDetails The value filled in by MozDescribeCodeAddress(aPC).
*/
XPCOM_API(void)
NS_FormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
MFBT_API void
MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
uint32_t aFrameNumber, void* aPC,
const nsCodeAddressDetails* aDetails);
const MozCodeAddressDetails* aDetails);
namespace mozilla {
MFBT_API bool
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, void** aBp,
void* aStackEnd);
#ifdef __cplusplus
}
#endif
#endif /* !defined(nsStackWalk_h_) */
/**
* Initialize the critical sections for this platform so that we can
* abort stack walks when needed.
*/
MFBT_API void
StackWalkInitCriticalAddress(void);
#endif

View File

@ -1,6 +1,7 @@
FINAL_LIBRARY = 'mozglue'
EXPORTS.mozilla += [
'StackWalk.h',
'TimeStamp.h',
]
@ -21,6 +22,7 @@ if CONFIG['OS_ARCH'] == 'WINNT':
SOURCES += [
'TimeStamp_windows.cpp',
]
OS_LIBS += ['dbghelp']
elif CONFIG['HAVE_CLOCK_MONOTONIC']:
SOURCES += [
'TimeStamp_posix.cpp',
@ -32,4 +34,14 @@ elif CONFIG['OS_ARCH'] == 'Darwin':
elif CONFIG['COMPILE_ENVIRONMENT']:
error('No TimeStamp implementation on this platform. Build will not succeed')
# MOZ_STACKWALKING is defined in configure.in when the build configuration meets
# the conditions for GeckoStackWalk to work correctly.
# We exclude this file from other build configurations so that if somebody adds a
# new usage of NS_StackWalk it will cause a link error, which is better than having
# GeckoStackWalk silently return garbage at runtime.
if CONFIG['MOZ_STACKWALKING']:
SOURCES += [
'StackWalk.cpp',
]
FAIL_ON_WARNINGS = True

View File

@ -18,7 +18,7 @@
#include "nsContentUtils.h"
#ifdef MOZ_STACKWALKING
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#endif
#define TARGET_SANDBOX_EXPORT __declspec(dllexport)
@ -63,10 +63,10 @@ StackFrameToOStringStream(uint32_t aFrameNumber, void* aPC, void* aSP,
void* aClosure)
{
std::ostringstream* stream = static_cast<std::ostringstream*>(aClosure);
nsCodeAddressDetails details;
MozCodeAddressDetails details;
char buf[1024];
NS_DescribeCodeAddress(aPC, &details);
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
MozDescribeCodeAddress(aPC, &details);
MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
*stream << std::endl << "--" << buf;
stream->flush();
}
@ -90,7 +90,7 @@ Log(const char* aMessageType,
if (aShouldLogStackTrace) {
if (sStackTraceDepth) {
msgStream << std::endl << "Stack Trace:";
NS_StackWalk(StackFrameToOStringStream, aFramesToSkip, sStackTraceDepth,
MozStackWalk(StackFrameToOStringStream, aFramesToSkip, sStackTraceDepth,
&msgStream, 0, nullptr);
}
}

View File

@ -21,7 +21,7 @@
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "nsString.h"
#include "nsThreadUtils.h"
@ -77,10 +77,10 @@ static void SandboxPrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP,
void *aClosure)
{
char buf[1024];
nsCodeAddressDetails details;
MozCodeAddressDetails details;
NS_DescribeCodeAddress(aPC, &details);
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
MozDescribeCodeAddress(aPC, &details);
MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
SANDBOX_LOG_ERROR("frame %s", buf);
}
@ -90,11 +90,11 @@ SandboxLogCStack()
// Skip 3 frames: one for this module, one for the signal handler in
// libmozsandbox, and one for the signal trampoline.
//
// Warning: this might not print any stack frames. NS_StackWalk
// Warning: this might not print any stack frames. MozStackWalk
// can't walk past the signal trampoline on ARM (bug 968531), and
// x86 frame pointer walking may or may not work (bug 1082276).
NS_StackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0,
MozStackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0,
nullptr, 0, nullptr);
SANDBOX_LOG_ERROR("end of stack.");
}

View File

@ -56,7 +56,7 @@ static unsigned int _gdb_sleep_duration = 300;
#include <unistd.h>
#include "nsISupportsUtils.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
// NB: keep me up to date with the same variable in
// ipc/chromium/chrome/common/ipc_channel_posix.cc
@ -68,10 +68,10 @@ static void PrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP,
void *aClosure)
{
char buf[1024];
nsCodeAddressDetails details;
MozCodeAddressDetails details;
NS_DescribeCodeAddress(aPC, &details);
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
MozDescribeCodeAddress(aPC, &details);
MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
fprintf(stdout, "%s\n", buf);
fflush(stdout);
}
@ -87,7 +87,7 @@ ah_crap_handler(int signum)
signum);
printf("Stack:\n");
NS_StackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0,
MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0,
nullptr, 0, nullptr);
printf("Sleeping for %d seconds.\n",_gdb_sleep_duration);

View File

@ -49,9 +49,6 @@
#if defined(MOZ_PROFILING) && (defined(XP_MACOSX) || defined(XP_WIN))
#define USE_NS_STACKWALK
#endif
#ifdef USE_NS_STACKWALK
#include "nsStackWalk.h"
#endif
#if defined(XP_WIN)
typedef CONTEXT tickcontext_t;
@ -880,7 +877,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample
};
// Start with the current function. We use 0 as the frame number here because
// the FramePointerStackWalk() and NS_StackWalk() calls below will use 1..N.
// the FramePointerStackWalk() and MozStackWalk() calls below will use 1..N.
// This is a bit weird but it doesn't matter because StackWalkCallback()
// doesn't use the frame number argument.
StackWalkCallback(/* frameNumber */ 0, aSample->pc, aSample->sp, &nativeStack);
@ -891,7 +888,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample
void *stackEnd = reinterpret_cast<void*>(-1);
if (pt)
stackEnd = static_cast<char*>(pthread_get_stackaddr_np(pt));
nsresult rv = NS_OK;
bool rv = true;
if (aSample->fp >= aSample->sp && aSample->fp <= stackEnd)
rv = FramePointerStackWalk(StackWalkCallback, /* skipFrames */ 0,
maxFrames, &nativeStack,
@ -900,17 +897,17 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample
void *platformData = nullptr;
#ifdef XP_WIN
if (aSample->isSamplingCurrentThread) {
// In this case we want NS_StackWalk to know that it's walking the
// In this case we want MozStackWalk to know that it's walking the
// current thread's stack, so we pass 0 as the thread handle.
thread = 0;
}
platformData = aSample->context;
#endif // XP_WIN
nsresult rv = NS_StackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames,
bool rv = MozStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames,
&nativeStack, thread, platformData);
#endif
if (NS_SUCCEEDED(rv))
if (rv)
mergeStacksIntoProfile(aProfile, aSample, nativeStack);
}
#endif

View File

@ -13,7 +13,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Types.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
namespace mozilla {
@ -27,7 +27,7 @@ namespace mozilla {
// while |free| is used to free strings created by |copy|.
//
// |DescribeCodeAddressLock| is needed when the callers may be holding a lock
// used by NS_DescribeCodeAddress. |DescribeCodeAddressLock| must implement
// used by MozDescribeCodeAddress. |DescribeCodeAddressLock| must implement
// static methods IsLocked(), Unlock() and Lock().
template <class StringTable,
class StringAlloc,
@ -35,9 +35,9 @@ template <class StringTable,
class CodeAddressService
{
// GetLocation() is the key function in this class. It's basically a wrapper
// around NS_DescribeCodeAddress.
// around MozDescribeCodeAddress.
//
// However, NS_DescribeCodeAddress is very slow on some platforms, and we
// However, MozDescribeCodeAddress is very slow on some platforms, and we
// have lots of repeated (i.e. same PC) calls to it. So we do some caching
// of results. Each cached result includes two strings (|mFunction| and
// |mLibrary|), so we also optimize them for space in the following ways.
@ -137,15 +137,15 @@ public:
if (!entry.mInUse || entry.mPc != aPc) {
mNumCacheMisses++;
// NS_DescribeCodeAddress can (on Linux) acquire a lock inside
// MozDescribeCodeAddress can (on Linux) acquire a lock inside
// the shared library loader. Another thread might call malloc
// while holding that lock (when loading a shared library). So
// we have to exit the lock around this call. For details, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=363334#c3
nsCodeAddressDetails details;
MozCodeAddressDetails details;
{
DescribeCodeAddressLock::Unlock();
(void)NS_DescribeCodeAddress(const_cast<void*>(aPc), &details);
(void)MozDescribeCodeAddress(const_cast<void*>(aPc), &details);
DescribeCodeAddressLock::Lock();
}
@ -159,7 +159,7 @@ public:
MOZ_ASSERT(entry.mPc == aPc);
NS_FormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc,
MozFormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc,
entry.mFunction, entry.mLibrary, entry.mLOffset,
entry.mFileName, entry.mLineNo);
}

View File

@ -1,24 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* API for getting a stack trace of the C/C++ */
#ifndef StackWalk_h_
#define StackWalk_h_
// XXX: it would be nice to eventually remove this header dependency on nsStackWalk.h
#include "nsStackWalk.h"
namespace mozilla {
nsresult
FramePointerStackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
uint32_t aMaxFrames, void* aClosure, void** aBp,
void* aStackEnd);
}
#endif /* !defined(StackWalk_h_) */

View File

@ -56,7 +56,6 @@ EXPORTS += [
'nsObjCExceptions.h',
'nsQueryObject.h',
'nsRefPtr.h',
'nsStackWalk.h',
'nsTraceRefcnt.h',
'nsWeakPtr.h',
]
@ -78,7 +77,6 @@ EXPORTS.mozilla += [
'HoldDropJSObjects.h',
'LinuxUtils.h',
'nsMemoryInfoDumper.h',
'StackWalk.h',
'StaticMutex.h',
'StaticPtr.h',
'SystemMemoryReporter.h',
@ -119,16 +117,6 @@ UNIFIED_SOURCES += [
'nsVersionComparatorImpl.cpp',
]
# MOZ_STACKWALKING is defined in configure.in when the build configuration meets
# the conditions for NS_StackWalk to work correctly.
# We exclude this file from other build configurations so that if somebody adds a
# new usage of NS_StackWalk it will cause a link error, which is better than having
# NS_StackWalk silently return garbage at runtime.
if CONFIG['MOZ_STACKWALKING']:
SOURCES += [
'nsStackWalk.cpp',
]
if CONFIG['OS_ARCH'] == 'Linux':
SOURCES += [
'LinuxUtils.cpp',

View File

@ -1,12 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Initialize the critical sections for this platform so that we can
* abort stack walks when needed.
*/
void
StackWalkInitCriticalAddress(void);

View File

@ -18,8 +18,7 @@
#include "nsCRT.h"
#include <math.h>
#include "nsHashKeys.h"
#include "nsStackWalkPrivate.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "CodeAddressService.h"
@ -238,7 +237,7 @@ struct CodeAddressServiceStringAlloc final
static void free(char* aPtr) { ::free(aPtr); }
};
// WalkTheStack does not hold any locks needed by NS_DescribeCodeAddress, so
// WalkTheStack does not hold any locks needed by MozDescribeCodeAddress, so
// this class does not need to do anything.
struct CodeAddressServiceLock final
{
@ -837,11 +836,11 @@ static void
PrintStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure)
{
FILE* stream = (FILE*)aClosure;
nsCodeAddressDetails details;
MozCodeAddressDetails details;
char buf[1024];
NS_DescribeCodeAddress(aPC, &details);
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
MozDescribeCodeAddress(aPC, &details);
MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
fprintf(stream, "%s\n", buf);
fflush(stream);
}
@ -865,7 +864,7 @@ void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
{
#ifdef MOZ_STACKWALKING
NS_StackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, aStream,
MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, aStream,
0, nullptr);
#endif
}
@ -877,7 +876,7 @@ nsTraceRefcnt::WalkTheStackCached(FILE* aStream)
if (!gCodeAddressService) {
gCodeAddressService = new WalkTheStackCodeAddressService();
}
NS_StackWalk(PrintStackFrameCached, /* skipFrames */ 2, /* maxFrames */ 0,
MozStackWalk(PrintStackFrameCached, /* skipFrames */ 2, /* maxFrames */ 0,
aStream, 0, nullptr);
#endif
}

View File

@ -16,7 +16,7 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "nsPrintfCString.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "plstr.h"
#include "prio.h"
@ -129,7 +129,7 @@ LateWriteObserver::Observe(IOInterposeObserver::Observation& aOb)
// concurrently from many writes, so we use multiple temporary files.
std::vector<uintptr_t> rawStack;
NS_StackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0,
MozStackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0,
reinterpret_cast<void*>(&rawStack), 0, nullptr);
Telemetry::ProcessedStack stack = Telemetry::GetStackAndModules(rawStack);

View File

@ -16,7 +16,7 @@
#include "mozilla/Scoped.h"
#include "mozilla/Telemetry.h"
#include "nsPrintfCString.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "nsTraceRefcnt.h"
#include "plstr.h"
#include "prio.h"

View File

@ -14,7 +14,7 @@
#ifndef MOZ_CALLSTACK_DISABLED
#include "CodeAddressService.h"
#include "nsHashKeys.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "nsTHashtable.h"
#endif
@ -68,7 +68,7 @@ BlockingResourceBase::GetStackTrace(AcquisitionState& aState)
// NB: Ignore the return value, there's nothing useful we can do if this
// this fails.
NS_StackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr);
MozStackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr);
#endif
}

View File

@ -15,7 +15,7 @@
#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "nsReadableUtils.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
@ -146,7 +146,7 @@ GetChromeHangReport(Telemetry::ProcessedStack& aStack,
if (ret == -1) {
return;
}
NS_StackWalk(ChromeStackWalker, /* skipFrames */ 0, /* maxFrames */ 0,
MozStackWalk(ChromeStackWalker, /* skipFrames */ 0, /* maxFrames */ 0,
reinterpret_cast<void*>(&rawStack),
reinterpret_cast<uintptr_t>(winMainThreadHandle), nullptr);
ret = ::ResumeThread(winMainThreadHandle);

View File

@ -64,7 +64,7 @@
#if defined(NS_FUNCTION_TIMER) && defined(_MSC_VER)
#include "nsTimerImpl.h"
#include "nsStackWalk.h"
#include "mozilla/StackWalk.h"
#endif
#ifdef NS_FUNCTION_TIMER
#include "nsCRT.h"