diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index edb001b3c2d..773b360ce0f 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -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 diff --git a/memory/replace/dmd/moz.build b/memory/replace/dmd/moz.build index 3c08e77c3d6..0766c835554 100644 --- a/memory/replace/dmd/moz.build +++ b/memory/replace/dmd/moz.build @@ -13,7 +13,7 @@ EXPORTS += [ SOURCES += [ '../../../mfbt/HashFunctions.cpp', '../../../mfbt/JSONWriter.cpp', - '../../../xpcom/base/nsStackWalk.cpp', + '../../../mozglue/misc/StackWalk.cpp', 'DMD.cpp', ] diff --git a/xpcom/base/nsStackWalk.cpp b/mozglue/misc/StackWalk.cpp similarity index 92% rename from xpcom/base/nsStackWalk.cpp rename to mozglue/misc/StackWalk.cpp index 6cffec12e34..78d452a7198 100644 --- a/xpcom/base/nsStackWalk.cpp +++ b/mozglue/misc/StackWalk.cpp @@ -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 #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 #include #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(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 #include #include #include -#include "plstr.h" #include "mozilla/ArrayUtils.h" -#include "nspr.h" #include // 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(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 #include -#include "nscore.h" #include -#include "plstr.h" // On glibc 2.1, the Dl_info api defined in 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) diff --git a/xpcom/base/nsStackWalk.h b/mozglue/misc/StackWalk.h similarity index 78% rename from xpcom/base/nsStackWalk.h rename to mozglue/misc/StackWalk.h index addc032d7a7..4546f62d8c9 100644 --- a/xpcom/base/nsStackWalk.h +++ b/mozglue/misc/StackWalk.h @@ -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 -#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 diff --git a/mozglue/misc/moz.build b/mozglue/misc/moz.build index b3bc6af24ee..18216a9a667 100644 --- a/mozglue/misc/moz.build +++ b/mozglue/misc/moz.build @@ -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 diff --git a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h index 75747744b96..8599cfd9e6b 100644 --- a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h +++ b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h @@ -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(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); } } diff --git a/security/sandbox/linux/glue/SandboxCrash.cpp b/security/sandbox/linux/glue/SandboxCrash.cpp index c35e35f733e..b0225169893 100644 --- a/security/sandbox/linux/glue/SandboxCrash.cpp +++ b/security/sandbox/linux/glue/SandboxCrash.cpp @@ -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."); } diff --git a/toolkit/xre/nsSigHandlers.cpp b/toolkit/xre/nsSigHandlers.cpp index 5b8546e4923..56fa380c91d 100644 --- a/toolkit/xre/nsSigHandlers.cpp +++ b/toolkit/xre/nsSigHandlers.cpp @@ -56,7 +56,7 @@ static unsigned int _gdb_sleep_duration = 300; #include #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); diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index c74388d8775..d454d608cc3 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -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(-1); if (pt) stackEnd = static_cast(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 diff --git a/xpcom/base/CodeAddressService.h b/xpcom/base/CodeAddressService.h index c6372b6c3ee..7f91f93a662 100644 --- a/xpcom/base/CodeAddressService.h +++ b/xpcom/base/CodeAddressService.h @@ -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 (aPc), &details); + (void)MozDescribeCodeAddress(const_cast(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); } diff --git a/xpcom/base/StackWalk.h b/xpcom/base/StackWalk.h deleted file mode 100644 index a3c6b83db09..00000000000 --- a/xpcom/base/StackWalk.h +++ /dev/null @@ -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_) */ diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build index 93d0beec671..c9ddd3f42fd 100644 --- a/xpcom/base/moz.build +++ b/xpcom/base/moz.build @@ -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', diff --git a/xpcom/base/nsStackWalkPrivate.h b/xpcom/base/nsStackWalkPrivate.h deleted file mode 100644 index 9e1041d87ac..00000000000 --- a/xpcom/base/nsStackWalkPrivate.h +++ /dev/null @@ -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); diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index 59080c90fc5..f99e4af37b9 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -18,8 +18,7 @@ #include "nsCRT.h" #include #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 } diff --git a/xpcom/build/LateWriteChecks.cpp b/xpcom/build/LateWriteChecks.cpp index 84d4bcbef4f..de94ceb212d 100644 --- a/xpcom/build/LateWriteChecks.cpp +++ b/xpcom/build/LateWriteChecks.cpp @@ -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 rawStack; - NS_StackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0, + MozStackWalk(RecordStackWalker, /* skipFrames */ 0, /* maxFrames */ 0, reinterpret_cast(&rawStack), 0, nullptr); Telemetry::ProcessedStack stack = Telemetry::GetStackAndModules(rawStack); diff --git a/xpcom/build/PoisonIOInterposerMac.cpp b/xpcom/build/PoisonIOInterposerMac.cpp index 7b26156c210..f4552248634 100644 --- a/xpcom/build/PoisonIOInterposerMac.cpp +++ b/xpcom/build/PoisonIOInterposerMac.cpp @@ -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" diff --git a/xpcom/glue/BlockingResourceBase.cpp b/xpcom/glue/BlockingResourceBase.cpp index 887c90a8814..6b2ad1df392 100644 --- a/xpcom/glue/BlockingResourceBase.cpp +++ b/xpcom/glue/BlockingResourceBase.cpp @@ -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 } diff --git a/xpcom/threads/HangMonitor.cpp b/xpcom/threads/HangMonitor.cpp index 81b0f384faf..c49d541cb9a 100644 --- a/xpcom/threads/HangMonitor.cpp +++ b/xpcom/threads/HangMonitor.cpp @@ -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(&rawStack), reinterpret_cast(winMainThreadHandle), nullptr); ret = ::ResumeThread(winMainThreadHandle); diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index 59e6355931b..acfd6cd3eba 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -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"