Skip to content

Commit 08e54b7

Browse files
committed
Bug 1384819 (part 1) - Split MozStackWalk(). r=glandium.
MozStackWalk() is different on Windows to the other platforms. It has two extra arguments, which can be used to walk the stack of a different thread. This patch makes those differences clearer. Instead of having a single function and forbidding those two arguments on non-Windows, it removes those arguments from MozStackWalk, and splits off MozStackWalkThread() which retains them. This also allows those arguments to have more appropriate types (HANDLE instead of uintptr_t; CONTEXT* instead of than void*) and names (aContext instead of aPlatformData). The patch also removes unnecessary reinterpret_casts for the aClosure argument at a couple of MozStackWalk() callsites. --HG-- extra : rebase_source : 111ab7d6426d7be921facc2264f6db86c501d127
1 parent 1ebc477 commit 08e54b7

File tree

14 files changed

+104
-90
lines changed

14 files changed

+104
-90
lines changed

memory/replace/dmd/DMD.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,8 +811,7 @@ StackTrace::Get(Thread* aT)
811811
#else
812812
int skipFrames = 2;
813813
#endif
814-
bool ok = MozStackWalk(StackWalkCallback, skipFrames, MaxFrames, &tmp, 0,
815-
nullptr);
814+
bool ok = MozStackWalk(StackWalkCallback, skipFrames, MaxFrames, &tmp);
816815
#endif
817816
if (!ok) {
818817
tmp.mLength = 0; // re-zero in case the stack walk function changed it
@@ -1631,7 +1630,7 @@ Init(const malloc_table_t* aMallocTable)
16311630
// just call MozStackWalk, because that calls StackWalkInitCriticalAddress().
16321631
// See the comment above StackWalkInitCriticalAddress() for more details.
16331632
(void)MozStackWalk(NopStackWalkCallback, /* skipFrames */ 0,
1634-
/* maxFrames */ 1, nullptr, 0, nullptr);
1633+
/* maxFrames */ 1, nullptr);
16351634
#endif
16361635

16371636
gStateLock = InfallibleAllocPolicy::new_<Mutex>();

mozglue/misc/StackWalk.cpp

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ my_malloc_logger(uint32_t aType,
110110
// stack shows up as having two pthread_cond_wait$UNIX2003 frames.
111111
const char* name = "new_sem_from_pool";
112112
MozStackWalk(stack_callback, /* skipFrames */ 0, /* maxFrames */ 0,
113-
const_cast<char*>(name), 0, nullptr);
113+
const_cast<char*>(name));
114114
}
115115

116116
// This is called from NS_LogInit() and from the stack walking functions, but
@@ -186,7 +186,7 @@ StackWalkInitCriticalAddress()
186186
}
187187
#endif
188188

189-
#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)) // WIN32 x86 stack walking code
189+
#if MOZ_STACKWALK_SUPPORTS_WINDOWS
190190

191191
#include <windows.h>
192192
#include <process.h>
@@ -222,7 +222,7 @@ struct WalkStackData
222222
void** sps;
223223
uint32_t sp_size;
224224
uint32_t sp_count;
225-
void* platformData;
225+
CONTEXT* context;
226226
};
227227

228228
DWORD gStackWalkThread;
@@ -378,32 +378,34 @@ static void
378378
WalkStackMain64(struct WalkStackData* aData)
379379
{
380380
// Get a context for the specified thread.
381-
CONTEXT context;
382-
if (!aData->platformData) {
383-
memset(&context, 0, sizeof(CONTEXT));
384-
context.ContextFlags = CONTEXT_FULL;
385-
if (!GetThreadContext(aData->thread, &context)) {
381+
CONTEXT context_buf;
382+
CONTEXT* context;
383+
if (!aData->context) {
384+
context = &context_buf;
385+
memset(context, 0, sizeof(CONTEXT));
386+
context->ContextFlags = CONTEXT_FULL;
387+
if (!GetThreadContext(aData->thread, context)) {
386388
if (aData->walkCallingThread) {
387389
PrintError("GetThreadContext");
388390
}
389391
return;
390392
}
391393
} else {
392-
context = *static_cast<CONTEXT*>(aData->platformData);
394+
context = aData->context;
393395
}
394396

395397
#if defined(_M_IX86) || defined(_M_IA64)
396398
// Setup initial stack frame to walk from.
397399
STACKFRAME64 frame64;
398400
memset(&frame64, 0, sizeof(frame64));
399401
#ifdef _M_IX86
400-
frame64.AddrPC.Offset = context.Eip;
401-
frame64.AddrStack.Offset = context.Esp;
402-
frame64.AddrFrame.Offset = context.Ebp;
402+
frame64.AddrPC.Offset = context->Eip;
403+
frame64.AddrStack.Offset = context->Esp;
404+
frame64.AddrFrame.Offset = context->Ebp;
403405
#elif defined _M_IA64
404-
frame64.AddrPC.Offset = context.StIIP;
405-
frame64.AddrStack.Offset = context.SP;
406-
frame64.AddrFrame.Offset = context.RsBSP;
406+
frame64.AddrPC.Offset = context->StIIP;
407+
frame64.AddrStack.Offset = context->SP;
408+
frame64.AddrFrame.Offset = context->RsBSP;
407409
#endif
408410
frame64.AddrPC.Mode = AddrModeFlat;
409411
frame64.AddrStack.Mode = AddrModeFlat;
@@ -452,7 +454,7 @@ WalkStackMain64(struct WalkStackData* aData)
452454
aData->process,
453455
aData->thread,
454456
&frame64,
455-
&context,
457+
context,
456458
nullptr,
457459
SymFunctionTableAccess64, // function table access routine
458460
SymGetModuleBase64, // module base routine
@@ -479,48 +481,48 @@ WalkStackMain64(struct WalkStackData* aData)
479481
// If we reach a frame in JIT code, we don't have enough information to
480482
// unwind, so we have to give up.
481483
if (sJitCodeRegionStart &&
482-
(uint8_t*)context.Rip >= sJitCodeRegionStart &&
483-
(uint8_t*)context.Rip < sJitCodeRegionStart + sJitCodeRegionSize) {
484+
(uint8_t*)context->Rip >= sJitCodeRegionStart &&
485+
(uint8_t*)context->Rip < sJitCodeRegionStart + sJitCodeRegionSize) {
484486
break;
485487
}
486488

487489
// We must also avoid msmpeg2vdec.dll's JIT region: they don't generate
488490
// unwind data, so their JIT unwind callback just throws up its hands and
489491
// terminates the process.
490492
if (sMsMpegJitCodeRegionStart &&
491-
(uint8_t*)context.Rip >= sMsMpegJitCodeRegionStart &&
492-
(uint8_t*)context.Rip < sMsMpegJitCodeRegionStart + sMsMpegJitCodeRegionSize) {
493+
(uint8_t*)context->Rip >= sMsMpegJitCodeRegionStart &&
494+
(uint8_t*)context->Rip < sMsMpegJitCodeRegionStart + sMsMpegJitCodeRegionSize) {
493495
break;
494496
}
495497

496498
// 64-bit frame unwinding.
497499
// Try to look up unwind metadata for the current function.
498500
ULONG64 imageBase;
499501
PRUNTIME_FUNCTION runtimeFunction =
500-
RtlLookupFunctionEntry(context.Rip, &imageBase, NULL);
502+
RtlLookupFunctionEntry(context->Rip, &imageBase, NULL);
501503

502504
if (runtimeFunction) {
503505
PVOID dummyHandlerData;
504506
ULONG64 dummyEstablisherFrame;
505507
RtlVirtualUnwind(UNW_FLAG_NHANDLER,
506508
imageBase,
507-
context.Rip,
509+
context->Rip,
508510
runtimeFunction,
509-
&context,
511+
context,
510512
&dummyHandlerData,
511513
&dummyEstablisherFrame,
512514
nullptr);
513515
} else if (firstFrame) {
514516
// Leaf functions can be unwound by hand.
515-
context.Rip = *reinterpret_cast<DWORD64*>(context.Rsp);
516-
context.Rsp += sizeof(void*);
517+
context->Rip = *reinterpret_cast<DWORD64*>(context->Rsp);
518+
context->Rsp += sizeof(void*);
517519
} else {
518520
// Something went wrong.
519521
break;
520522
}
521523

522-
addr = context.Rip;
523-
spaddr = context.Rsp;
524+
addr = context->Rip;
525+
spaddr = context->Rsp;
524526
firstFrame = false;
525527
#else
526528
#error "unknown platform"
@@ -618,9 +620,9 @@ WalkStackThread(void* aData)
618620
*/
619621

620622
MFBT_API bool
621-
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
622-
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
623-
void* aPlatformData)
623+
MozStackWalkThread(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
624+
uint32_t aMaxFrames, void* aClosure,
625+
HANDLE aThread, CONTEXT* aContext)
624626
{
625627
StackWalkInitCriticalAddress();
626628
static HANDLE myProcess = nullptr;
@@ -637,8 +639,7 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
637639
}
638640

639641
HANDLE currentThread = ::GetCurrentThread();
640-
HANDLE targetThread =
641-
aThread ? reinterpret_cast<HANDLE>(aThread) : currentThread;
642+
HANDLE targetThread = aThread ? aThread : currentThread;
642643
data.walkCallingThread = (targetThread == currentThread);
643644

644645
// Have to duplicate handle to get a real handle.
@@ -677,7 +678,7 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
677678
data.sps = local_sps;
678679
data.sp_count = 0;
679680
data.sp_size = ArrayLength(local_sps);
680-
data.platformData = aPlatformData;
681+
data.context = aContext;
681682

682683
if (aThread) {
683684
// If we're walking the stack of another thread, we don't need to
@@ -734,6 +735,13 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
734735
return data.pc_count != 0;
735736
}
736737

738+
MFBT_API bool
739+
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
740+
uint32_t aMaxFrames, void* aClosure)
741+
{
742+
return MozStackWalkThread(aCallback, aSkipFrames, aMaxFrames, aClosure,
743+
nullptr, nullptr);
744+
}
737745

738746
static BOOL CALLBACK
739747
callbackEspecial64(
@@ -989,11 +997,8 @@ void DemangleSymbol(const char* aSymbol,
989997

990998
MFBT_API bool
991999
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
992-
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
993-
void* aPlatformData)
1000+
uint32_t aMaxFrames, void* aClosure)
9941001
{
995-
MOZ_ASSERT(!aThread);
996-
MOZ_ASSERT(!aPlatformData);
9971002
StackWalkInitCriticalAddress();
9981003

9991004
// Get the frame pointer
@@ -1077,11 +1082,8 @@ unwind_callback(struct _Unwind_Context* context, void* closure)
10771082

10781083
MFBT_API bool
10791084
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
1080-
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
1081-
void* aPlatformData)
1085+
uint32_t aMaxFrames, void* aClosure)
10821086
{
1083-
MOZ_ASSERT(!aThread);
1084-
MOZ_ASSERT(!aPlatformData);
10851087
StackWalkInitCriticalAddress();
10861088
unwind_info info;
10871089
info.callback = aCallback;
@@ -1150,11 +1152,8 @@ MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails)
11501152

11511153
MFBT_API bool
11521154
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
1153-
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
1154-
void* aPlatformData)
1155+
uint32_t aMaxFrames, void* aClosure)
11551156
{
1156-
MOZ_ASSERT(!aThread);
1157-
MOZ_ASSERT(!aPlatformData);
11581157
return false;
11591158
}
11601159

mozglue/misc/StackWalk.h

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
#include <stdint.h>
1616

1717
/**
18-
* The callback for MozStackWalk.
18+
* The callback for MozStackWalk and MozStackWalkThread.
1919
*
2020
* @param aFrameNumber The frame number (starts at 1, not 0).
2121
* @param aPC The program counter value.
2222
* @param aSP The best approximation possible of what the stack
2323
* pointer will be pointing to when the execution returns
2424
* to executing that at aPC. If no approximation can
2525
* be made it will be nullptr.
26-
* @param aClosure Extra data passed in via MozStackWalk().
26+
* @param aClosure Extra data passed in from MozStackWalk() or
27+
* MozStackWalkThread().
2728
*/
2829
typedef void
2930
(*MozWalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP,
@@ -39,24 +40,46 @@ typedef void
3940
* MozStackWalk.
4041
* @param aMaxFrames Maximum number of frames to trace. 0 means no limit.
4142
* @param aClosure Caller-supplied data passed through to aCallback.
42-
* @param aThread The thread for which the stack is to be retrieved.
43-
* Passing null causes us to walk the stack of the
44-
* current thread. On Windows, this is a thread HANDLE.
45-
* It is currently not supported on any other platform.
46-
* @param aPlatformData Platform specific data that can help in walking the
47-
* stack, this should be nullptr unless you really know
48-
* what you're doing! This needs to be a pointer to a
49-
* CONTEXT on Windows and should not be passed on other
50-
* platforms.
5143
*
5244
* May skip some stack frames due to compiler optimizations or code
5345
* generation.
54-
*
5546
*/
5647
MFBT_API bool
5748
MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
58-
uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
59-
void* aPlatformData);
49+
uint32_t aMaxFrames, void* aClosure);
50+
51+
#if defined(_WIN32) && \
52+
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64))
53+
54+
#include <windows.h>
55+
56+
#define MOZ_STACKWALK_SUPPORTS_WINDOWS 1
57+
58+
/**
59+
* Like MozStackWalk, but walks the stack for another thread.
60+
* Call aCallback for the C/C++ stack frames on the current thread, from
61+
* the caller of MozStackWalk to main (or above).
62+
*
63+
* @param aCallback Same as for MozStackWalk().
64+
* @param aSkipFrames Same as for MozStackWalk().
65+
* @param aMaxFrames Same as for MozStackWalk().
66+
* @param aClosure Same as for MozStackWalk().
67+
* @param aThread The handle of the thread whose stack is to be walked.
68+
* If 0, walks the current thread.
69+
* @param aContext A CONTEXT, presumably obtained with GetThreadContext()
70+
* after suspending the thread with SuspendThread(). If
71+
* null, the CONTEXT will be re-obtained.
72+
*/
73+
MFBT_API bool
74+
MozStackWalkThread(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
75+
uint32_t aMaxFrames, void* aClosure,
76+
HANDLE aThread, CONTEXT* aContext);
77+
78+
#else
79+
80+
#define MOZ_STACKWALK_SUPPORTS_WINDOWS 0
81+
82+
#endif
6083

6184
typedef struct
6285
{

security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Log(const char* aMessageType,
5959
if (sStackTraceDepth) {
6060
msgStream << std::endl << "Stack Trace:";
6161
MozStackWalk(StackFrameToOStringStream, aFramesToSkip, sStackTraceDepth,
62-
&msgStream, 0, nullptr);
62+
&msgStream);
6363
}
6464
}
6565

security/sandbox/linux/glue/SandboxCrash.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ SandboxLogCStack()
9898
// can't walk past the signal trampoline on ARM (bug 968531), and
9999
// x86 frame pointer walking may or may not work (bug 1082276).
100100

101-
MozStackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0,
102-
nullptr, 0, nullptr);
101+
MozStackWalk(SandboxPrintStackFrame, /* skip */ 3, /* max */ 0, nullptr);
103102
SANDBOX_LOG_ERROR("end of stack.");
104103
}
105104

toolkit/components/telemetry/KeyedStackCapturer.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ void KeyedStackCapturer::Capture(const nsACString& aKey) {
9898
static_cast<std::vector<uintptr_t>*>(aClosure);
9999
stack->push_back(reinterpret_cast<uintptr_t>(aPC));
100100
};
101-
MozStackWalk(callback, /* skipFrames */ 0,
102-
/* maxFrames */ 0, reinterpret_cast<void*>(&rawStack), 0, nullptr);
101+
MozStackWalk(callback, /* skipFrames */ 0, /* maxFrames */ 0, &rawStack);
103102
ProcessedStack stack = GetStackAndModules(rawStack);
104103

105104
// Store the new stack info.

toolkit/xre/nsSigHandlers.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ ah_crap_handler(int signum)
8989
signum);
9090

9191
printf("Stack:\n");
92-
MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0,
93-
nullptr, 0, nullptr);
92+
MozStackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0, nullptr);
9493

9594
printf("Sleeping for %d seconds.\n",_gdb_sleep_duration);
9695
printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",

tools/profiler/core/platform-win32.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ class PlatformData
9191
HANDLE mProfiledThread;
9292
};
9393

94-
uintptr_t
94+
HANDLE
9595
GetThreadHandle(PlatformData* aData)
9696
{
97-
return (uintptr_t) aData->ProfiledThread();
97+
return aData->ProfiledThread();
9898
}
9999

100100
static const HANDLE kNoThread = INVALID_HANDLE_VALUE;

0 commit comments

Comments
 (0)