@@ -69,6 +69,26 @@ extern MOZ_EXPORT void* __libc_stack_end; // from ld-linux.so
6969# include < pthread.h>
7070#endif
7171
72+ class FrameSkipper {
73+ public:
74+ constexpr FrameSkipper () : mPc(0 ) {}
75+ bool ShouldSkipPC (void * aPC) {
76+ // Skip frames until we encounter the one we were initialized with,
77+ // and then never skip again.
78+ if (mPc != 0 ) {
79+ if (mPc != uintptr_t (aPC)) {
80+ return true ;
81+ }
82+ mPc = 0 ;
83+ }
84+ return false ;
85+ }
86+ explicit FrameSkipper (const void * aPc) : mPc(uintptr_t (aPc)) {}
87+
88+ private:
89+ uintptr_t mPc ;
90+ };
91+
7292#ifdef XP_WIN
7393
7494# include < windows.h>
@@ -92,7 +112,7 @@ struct WalkStackData {
92112 // Are we walking the stack of the calling thread? Note that we need to avoid
93113 // calling fprintf and friends if this is false, in order to avoid deadlocks.
94114 bool walkCallingThread;
95- uint32_t skipFrames ;
115+ const void * firstFramePC ;
96116 HANDLE thread;
97117 HANDLE process;
98118 HANDLE eventStart;
@@ -243,8 +263,7 @@ static void WalkStackMain64(struct WalkStackData* aData) {
243263 bool firstFrame = true ;
244264# endif
245265
246- // Skip our own stack walking frames.
247- int skip = (aData->walkCallingThread ? 3 : 0 ) + aData->skipFrames ;
266+ FrameSkipper skipper (aData->firstFramePC );
248267
249268 // Now walk the stack.
250269 while (true ) {
@@ -349,7 +368,7 @@ static void WalkStackMain64(struct WalkStackData* aData) {
349368 break ;
350369 }
351370
352- if (skip-- > 0 ) {
371+ if (skipper. ShouldSkipPC (( void *)addr) ) {
353372 continue ;
354373 }
355374
@@ -384,7 +403,7 @@ static void WalkStackMain64(struct WalkStackData* aData) {
384403 */
385404
386405static void DoMozStackWalkThread (MozWalkStackCallback aCallback,
387- uint32_t aSkipFrames , uint32_t aMaxFrames,
406+ const void * aFirstFramePC , uint32_t aMaxFrames,
388407 void * aClosure, HANDLE aThread,
389408 CONTEXT* aContext) {
390409 struct WalkStackData data;
@@ -401,7 +420,7 @@ static void DoMozStackWalkThread(MozWalkStackCallback aCallback,
401420 data.walkCallingThread = (threadId == currentThreadId);
402421 }
403422
404- data.skipFrames = aSkipFrames ;
423+ data.firstFramePC = aFirstFramePC ;
405424 data.thread = targetThread;
406425 data.process = ::GetCurrentProcess ();
407426 void * local_pcs[1024 ];
@@ -435,14 +454,17 @@ static void DoMozStackWalkThread(MozWalkStackCallback aCallback,
435454MFBT_API void MozStackWalkThread (MozWalkStackCallback aCallback,
436455 uint32_t aMaxFrames, void * aClosure,
437456 HANDLE aThread, CONTEXT* aContext) {
438- DoMozStackWalkThread (aCallback, /* aSkipFrames = */ 0 , aMaxFrames, aClosure,
439- aThread, aContext);
457+ // We don't pass a aFirstFramePC because we walk the stack for another
458+ // thread.
459+ DoMozStackWalkThread (aCallback, nullptr , aMaxFrames, aClosure, aThread,
460+ aContext);
440461}
441462
442- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
443- uint32_t aMaxFrames, void * aClosure) {
444- DoMozStackWalkThread (aCallback, aSkipFrames, aMaxFrames, aClosure, nullptr ,
445- nullptr );
463+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
464+ const void * aFirstFramePC, uint32_t aMaxFrames,
465+ void * aClosure) {
466+ DoMozStackWalkThread (aCallback, aFirstFramePC ? aFirstFramePC : CallerPC (),
467+ aMaxFrames, aClosure, nullptr , nullptr );
446468}
447469
448470static BOOL CALLBACK callbackEspecial64 (PCSTR aModuleName, DWORD64 aModuleBase,
@@ -691,12 +713,13 @@ void DemangleSymbol(const char* aSymbol, char* aBuffer, int aBufLen) {
691713 (MOZ_STACKWALK_SUPPORTS_MACOSX || MOZ_STACKWALK_SUPPORTS_LINUX))
692714
693715static void DoFramePointerStackWalk (MozWalkStackCallback aCallback,
694- uint32_t aSkipFrames, uint32_t aMaxFrames ,
695- void * aClosure , void ** aBp ,
696- void * aStackEnd);
716+ const void * aFirstFramePC ,
717+ uint32_t aMaxFrames , void * aClosure ,
718+ void ** aBp, void * aStackEnd);
697719
698- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
699- uint32_t aMaxFrames, void * aClosure) {
720+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
721+ const void * aFirstFramePC, uint32_t aMaxFrames,
722+ void * aClosure) {
700723 // Get the frame pointer
701724 void ** bp = (void **)__builtin_frame_address (0 );
702725
@@ -733,7 +756,7 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
733756# else
734757# error Unsupported configuration
735758# endif
736- DoFramePointerStackWalk (aCallback, aSkipFrames , aMaxFrames, aClosure, bp,
759+ DoFramePointerStackWalk (aCallback, aFirstFramePC , aMaxFrames, aClosure, bp,
737760 stackEnd);
738761}
739762
@@ -744,7 +767,7 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
744767
745768struct unwind_info {
746769 MozWalkStackCallback callback;
747- int skip ;
770+ FrameSkipper skipper ;
748771 int maxFrames;
749772 int numFrames;
750773 void * closure;
@@ -755,7 +778,7 @@ static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context,
755778 unwind_info* info = static_cast <unwind_info*>(closure);
756779 void * pc = reinterpret_cast <void *>(_Unwind_GetIP (context));
757780 // TODO Use something like '_Unwind_GetGR()' to get the stack pointer.
758- if (-- info->skip < 0 ) {
781+ if (! info->skipper . ShouldSkipPC (pc) ) {
759782 info->numFrames ++;
760783 (*info->callback )(info->numFrames , pc, nullptr , info->closure );
761784 if (info->maxFrames != 0 && info->numFrames == info->maxFrames ) {
@@ -766,11 +789,12 @@ static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context,
766789 return _URC_NO_REASON;
767790}
768791
769- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
770- uint32_t aMaxFrames, void * aClosure) {
792+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
793+ const void * aFirstFramePC, uint32_t aMaxFrames,
794+ void * aClosure) {
771795 unwind_info info;
772796 info.callback = aCallback;
773- info.skip = aSkipFrames + 1 ;
797+ info.skipper = FrameSkipper (aFirstFramePC ? aFirstFramePC : CallerPC ()) ;
774798 info.maxFrames = aMaxFrames;
775799 info.numFrames = 0 ;
776800 info.closure = aClosure;
@@ -840,8 +864,9 @@ bool MFBT_API MozDescribeCodeAddress(void* aPC,
840864
841865#else // unsupported platform.
842866
843- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
844- uint32_t aMaxFrames, void * aClosure) {}
867+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
868+ const void * aFirstFramePC, uint32_t aMaxFrames,
869+ void * aClosure) {}
845870
846871MFBT_API bool MozDescribeCodeAddress (void * aPC,
847872 MozCodeAddressDetails* aDetails) {
@@ -859,13 +884,14 @@ MFBT_API bool MozDescribeCodeAddress(void* aPC,
859884#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
860885MOZ_ASAN_BLACKLIST
861886static void DoFramePointerStackWalk (MozWalkStackCallback aCallback,
862- uint32_t aSkipFrames, uint32_t aMaxFrames ,
863- void * aClosure , void ** aBp ,
864- void * aStackEnd) {
887+ const void * aFirstFramePC ,
888+ uint32_t aMaxFrames , void * aClosure ,
889+ void ** aBp, void * aStackEnd) {
865890 // Stack walking code courtesy Kipp's "leaky".
866891
867- int32_t skip = aSkipFrames ;
892+ FrameSkipper skipper (aFirstFramePC) ;
868893 uint32_t numFrames = 0 ;
894+
869895 while (aBp) {
870896 void ** next = (void **)*aBp;
871897 // aBp may not be a frame pointer on i386 if code was compiled with
@@ -885,7 +911,7 @@ static void DoFramePointerStackWalk(MozWalkStackCallback aCallback,
885911 void * pc = *(aBp + 1 );
886912 aBp += 2 ;
887913# endif
888- if (--skip < 0 ) {
914+ if (!skipper. ShouldSkipPC (pc) ) {
889915 // Assume that the SP points to the BP of the function
890916 // it called. We can't know the exact location of the SP
891917 // but this should be sufficient for our use the SP
@@ -904,8 +930,10 @@ namespace mozilla {
904930
905931void FramePointerStackWalk (MozWalkStackCallback aCallback, uint32_t aMaxFrames,
906932 void * aClosure, void ** aBp, void * aStackEnd) {
907- DoFramePointerStackWalk (aCallback, /* aSkipFrames = */ 0 , aMaxFrames,
908- aClosure, aBp, aStackEnd);
933+ // We don't pass a aFirstFramePC because we start walking the stack from the
934+ // frame at aBp.
935+ DoFramePointerStackWalk (aCallback, nullptr , aMaxFrames, aClosure, aBp,
936+ aStackEnd);
909937}
910938
911939} // namespace mozilla
@@ -914,6 +942,7 @@ void FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aMaxFrames,
914942
915943namespace mozilla {
916944MFBT_API void FramePointerStackWalk (MozWalkStackCallback aCallback,
945+ const void * aFirstFramePC,
917946 uint32_t aMaxFrames, void * aClosure,
918947 void ** aBp, void * aStackEnd) {}
919948} // namespace mozilla
@@ -1006,10 +1035,11 @@ static bool WalkTheStackEnabled() {
10061035 return result;
10071036}
10081037
1009- MFBT_API void MozWalkTheStack (FILE* aStream, uint32_t aSkipFrames ,
1038+ MFBT_API void MozWalkTheStack (FILE* aStream, const void * aFirstFramePC ,
10101039 uint32_t aMaxFrames) {
10111040 if (WalkTheStackEnabled ()) {
1012- MozStackWalk (PrintStackFrame, aSkipFrames + 1 , aMaxFrames, aStream);
1041+ MozStackWalk (PrintStackFrame, aFirstFramePC ? aFirstFramePC : CallerPC (),
1042+ aMaxFrames, aStream);
10131043 }
10141044}
10151045
@@ -1022,9 +1052,10 @@ static void WriteStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP,
10221052}
10231053
10241054MFBT_API void MozWalkTheStackWithWriter (void (*aWriter)(const char *),
1025- uint32_t aSkipFrames ,
1055+ const void* aFirstFramePC ,
10261056 uint32_t aMaxFrames) {
10271057 if (WalkTheStackEnabled ()) {
1028- MozStackWalk (WriteStackFrame, aSkipFrames + 1 , aMaxFrames, (void *)aWriter);
1058+ MozStackWalk (WriteStackFrame, aFirstFramePC ? aFirstFramePC : CallerPC (),
1059+ aMaxFrames, (void *)aWriter);
10291060 }
10301061}
0 commit comments