mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 724079. Add an internal stackwalk API. r=ehsan
This will be used by the profiler to be able to unwind arbitrary threads.
This commit is contained in:
parent
49ca7aac62
commit
c818deeaac
@ -103,6 +103,7 @@ EXPORTS_mozilla = \
|
||||
MapsMemoryReporter.h \
|
||||
ClearOnShutdown.h \
|
||||
AvailableMemoryTracker.h \
|
||||
StackWalk.h \
|
||||
$(NULL)
|
||||
|
||||
ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
52
xpcom/base/StackWalk.h
Normal file
52
xpcom/base/StackWalk.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Muizelaar <jmuizelaar@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* 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, PRUint32 aSkipFrames,
|
||||
void *aClosure, void **bp);
|
||||
|
||||
}
|
||||
|
||||
#endif /* !defined(StackWalk_h_) */
|
@ -41,11 +41,14 @@
|
||||
/* API for getting a stack trace of the C/C++ stack on the current thread */
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/StackWalk.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsStackWalkPrivate.h"
|
||||
|
||||
#include "nsStackWalk.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// The presence of this address is the stack must stop the stack walk. If
|
||||
// there is no such address, the structure will be {NULL, true}.
|
||||
struct CriticalAddress {
|
||||
@ -215,8 +218,6 @@ StackWalkInitCriticalAddress()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// Define these as static pointers so that we can load the DLL on the
|
||||
// fly (and not introduce a link-time dependency on it). Tip o' the
|
||||
// hat to Matt Pietrick for this idea. See:
|
||||
@ -1572,9 +1573,6 @@ NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
|
||||
#else // not __sun-specific
|
||||
|
||||
#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 __GLIBC__ > 2 || __GLIBC_MINOR > 1
|
||||
#define HAVE___LIBC_STACK_END 1
|
||||
#else
|
||||
@ -1584,26 +1582,13 @@ NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
#if HAVE___LIBC_STACK_END
|
||||
extern void *__libc_stack_end; // from ld-linux.so
|
||||
#endif
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure, uintptr_t aThread)
|
||||
namespace mozilla {
|
||||
nsresult
|
||||
FramePointerStackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure, void **bp)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
// Stack walking code courtesy Kipp's "leaky".
|
||||
|
||||
// Get the frame pointer
|
||||
void **bp;
|
||||
#if defined(__i386)
|
||||
__asm__( "movl %%ebp, %0" : "=g"(bp));
|
||||
#else
|
||||
// It would be nice if this worked uniformly, but at least on i386 and
|
||||
// x86_64, it stopped working with gcc 4.1, because it points to the
|
||||
// end of the saved registers instead of the start.
|
||||
bp = (void**) __builtin_frame_address(0);
|
||||
#endif
|
||||
|
||||
int skip = aSkipFrames;
|
||||
while (1) {
|
||||
void **next = (void**)*bp;
|
||||
@ -1636,6 +1621,33 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
|
||||
// Get the frame pointer
|
||||
void **bp;
|
||||
#if defined(__i386)
|
||||
__asm__( "movl %%ebp, %0" : "=g"(bp));
|
||||
#else
|
||||
// It would be nice if this worked uniformly, but at least on i386 and
|
||||
// x86_64, it stopped working with gcc 4.1, because it points to the
|
||||
// end of the saved registers instead of the start.
|
||||
bp = (void**) __builtin_frame_address(0);
|
||||
#endif
|
||||
return FramePointerStackWalk(aCallback, aSkipFrames,
|
||||
aClosure, bp);
|
||||
|
||||
}
|
||||
|
||||
#elif defined(HAVE__UNWIND_BACKTRACE)
|
||||
|
||||
// libgcc_s.so symbols _Unwind_Backtrace@@GCC_3.3 and _Unwind_GetIP@@GCC_3.0
|
||||
|
Loading…
Reference in New Issue
Block a user