mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 989499 - Part 2: Use FramePointerStackwalk on windows. r=rjmuizel
This commit is contained in:
parent
789be3e18f
commit
d70c905083
@ -54,6 +54,16 @@ static CriticalAddress gCriticalAddress;
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
|
||||
#define HAVE___LIBC_STACK_END 1
|
||||
#else
|
||||
#define HAVE___LIBC_STACK_END 0
|
||||
#endif
|
||||
|
||||
#if HAVE___LIBC_STACK_END
|
||||
extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so
|
||||
#endif
|
||||
|
||||
typedef void
|
||||
malloc_logger_t(uint32_t aType,
|
||||
uintptr_t aArg1, uintptr_t aArg2, uintptr_t aArg3,
|
||||
@ -873,67 +883,6 @@ void DemangleSymbol(const char* aSymbol,
|
||||
#endif // MOZ_DEMANGLE_SYMBOLS
|
||||
}
|
||||
|
||||
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
|
||||
#define HAVE___LIBC_STACK_END 1
|
||||
#else
|
||||
#define HAVE___LIBC_STACK_END 0
|
||||
#endif
|
||||
|
||||
#if HAVE___LIBC_STACK_END
|
||||
extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so
|
||||
#endif
|
||||
namespace mozilla {
|
||||
bool
|
||||
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
uint32_t aMaxFrames, void* aClosure, void** bp,
|
||||
void* aStackEnd)
|
||||
{
|
||||
// Stack walking code courtesy Kipp's "leaky".
|
||||
|
||||
int32_t skip = aSkipFrames;
|
||||
uint32_t numFrames = 0;
|
||||
while (bp) {
|
||||
void** next = (void**)*bp;
|
||||
// bp may not be a frame pointer on i386 if code was compiled with
|
||||
// -fomit-frame-pointer, so do some sanity checks.
|
||||
// (bp should be a frame pointer on ppc(64) but checking anyway may help
|
||||
// a little if the stack has been corrupted.)
|
||||
// We don't need to check against the begining of the stack because
|
||||
// we can assume that bp > sp
|
||||
if (next <= bp ||
|
||||
next > aStackEnd ||
|
||||
(long(next) & 3)) {
|
||||
break;
|
||||
}
|
||||
#if (defined(__ppc__) && defined(XP_MACOSX)) || defined(__powerpc64__)
|
||||
// ppc mac or powerpc64 linux
|
||||
void* pc = *(bp + 2);
|
||||
bp += 3;
|
||||
#else // i386 or powerpc32 linux
|
||||
void* pc = *(bp + 1);
|
||||
bp += 2;
|
||||
#endif
|
||||
if (IsCriticalAddress(pc)) {
|
||||
return false;
|
||||
}
|
||||
if (--skip < 0) {
|
||||
// Assume that the SP points to the BP of the function
|
||||
// it called. We can't know the exact location of the SP
|
||||
// but this should be sufficient for our use the SP
|
||||
// to order elements on the stack.
|
||||
numFrames++;
|
||||
(*aCallback)(numFrames, pc, bp, aClosure);
|
||||
if (aMaxFrames != 0 && numFrames == aMaxFrames) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bp = next;
|
||||
}
|
||||
return numFrames != 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#define X86_OR_PPC (defined(__i386) || defined(PPC) || defined(__ppc__))
|
||||
#if X86_OR_PPC && (MOZ_STACKWALK_SUPPORTS_MACOSX || MOZ_STACKWALK_SUPPORTS_LINUX) // i386 or PPC Linux or Mac stackwalking code
|
||||
|
||||
@ -1089,15 +1038,6 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
MFBT_API bool
|
||||
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
void* aClosure, void** aBp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MFBT_API bool
|
||||
MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
|
||||
{
|
||||
@ -1112,6 +1052,71 @@ MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) || defined (XP_MACOSX) || defined (XP_LINUX)
|
||||
namespace mozilla {
|
||||
bool
|
||||
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
uint32_t aMaxFrames, void* aClosure, void** bp,
|
||||
void* aStackEnd)
|
||||
{
|
||||
// Stack walking code courtesy Kipp's "leaky".
|
||||
|
||||
int32_t skip = aSkipFrames;
|
||||
uint32_t numFrames = 0;
|
||||
while (bp) {
|
||||
void** next = (void**)*bp;
|
||||
// bp may not be a frame pointer on i386 if code was compiled with
|
||||
// -fomit-frame-pointer, so do some sanity checks.
|
||||
// (bp should be a frame pointer on ppc(64) but checking anyway may help
|
||||
// a little if the stack has been corrupted.)
|
||||
// We don't need to check against the begining of the stack because
|
||||
// we can assume that bp > sp
|
||||
if (next <= bp ||
|
||||
next > aStackEnd ||
|
||||
(long(next) & 3)) {
|
||||
break;
|
||||
}
|
||||
#if (defined(__ppc__) && defined(XP_MACOSX)) || defined(__powerpc64__)
|
||||
// ppc mac or powerpc64 linux
|
||||
void* pc = *(bp + 2);
|
||||
bp += 3;
|
||||
#else // i386 or powerpc32 linux
|
||||
void* pc = *(bp + 1);
|
||||
bp += 2;
|
||||
#endif
|
||||
if (IsCriticalAddress(pc)) {
|
||||
return false;
|
||||
}
|
||||
if (--skip < 0) {
|
||||
// Assume that the SP points to the BP of the function
|
||||
// it called. We can't know the exact location of the SP
|
||||
// but this should be sufficient for our use the SP
|
||||
// to order elements on the stack.
|
||||
numFrames++;
|
||||
(*aCallback)(numFrames, pc, bp, aClosure);
|
||||
if (aMaxFrames != 0 && numFrames == aMaxFrames) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bp = next;
|
||||
}
|
||||
return numFrames != 0;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
#else
|
||||
|
||||
namespace mozilla {
|
||||
MFBT_API bool
|
||||
FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
void* aClosure, void** aBp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
MFBT_API void
|
||||
MozFormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
|
||||
uint32_t aFrameNumber, void* aPC,
|
||||
|
@ -929,10 +929,6 @@ void StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP,
|
||||
|
||||
void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
|
||||
{
|
||||
#ifndef XP_MACOSX
|
||||
uintptr_t thread = GetThreadHandle(aSample->threadProfile->GetPlatformData());
|
||||
MOZ_ASSERT(thread);
|
||||
#endif
|
||||
void* pc_array[1000];
|
||||
void* sp_array[1000];
|
||||
NativeStack nativeStack = {
|
||||
@ -949,7 +945,7 @@ void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSampl
|
||||
StackWalkCallback(/* frameNumber */ 0, aSample->pc, aSample->sp, &nativeStack);
|
||||
|
||||
uint32_t maxFrames = uint32_t(nativeStack.size - nativeStack.count);
|
||||
#ifdef XP_MACOSX
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
void *stackEnd = aSample->threadProfile->GetStackTop();
|
||||
bool rv = true;
|
||||
if (aSample->fp >= aSample->sp && aSample->fp <= stackEnd)
|
||||
@ -958,15 +954,9 @@ void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSampl
|
||||
reinterpret_cast<void**>(aSample->fp), stackEnd);
|
||||
#else
|
||||
void *platformData = nullptr;
|
||||
#ifdef XP_WIN
|
||||
if (aSample->isSamplingCurrentThread) {
|
||||
// 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
|
||||
|
||||
uintptr_t thread = GetThreadHandle(aSample->threadProfile->GetPlatformData());
|
||||
MOZ_ASSERT(thread);
|
||||
bool rv = MozStackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames,
|
||||
&nativeStack, thread, platformData);
|
||||
#endif
|
||||
|
@ -38,7 +38,7 @@ void *GetStackTop(void *guess) {
|
||||
return static_cast<void*>(pTib->StackBase);
|
||||
#elif defined(_M_X64) || defined(__x86_64)
|
||||
PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
|
||||
return static_cast<void*>(pTib->StackBase);
|
||||
return reinterpret_cast<void*>(pTib->StackBase);
|
||||
#else
|
||||
#error Need a way to get the stack bounds on this platform (Windows)
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "nsITimer.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "ProfileEntry.h"
|
||||
#include "ThreadProfile.h"
|
||||
|
||||
using mozilla::Monitor;
|
||||
using mozilla::MonitorAutoLock;
|
||||
|
Loading…
Reference in New Issue
Block a user