@@ -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,15 @@ 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+ DoMozStackWalkThread (aCallback, CallerPC () , aMaxFrames, aClosure, aThread ,
458+ aContext);
440459}
441460
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 );
461+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
462+ const void * aFirstFramePC, uint32_t aMaxFrames,
463+ void * aClosure) {
464+ DoMozStackWalkThread (aCallback, aFirstFramePC ? aFirstFramePC : CallerPC (),
465+ aMaxFrames, aClosure, nullptr , nullptr );
446466}
447467
448468static BOOL CALLBACK callbackEspecial64 (PCSTR aModuleName, DWORD64 aModuleBase,
@@ -691,12 +711,13 @@ void DemangleSymbol(const char* aSymbol, char* aBuffer, int aBufLen) {
691711 (MOZ_STACKWALK_SUPPORTS_MACOSX || MOZ_STACKWALK_SUPPORTS_LINUX))
692712
693713static void DoFramePointerStackWalk (MozWalkStackCallback aCallback,
694- uint32_t aSkipFrames, uint32_t aMaxFrames ,
695- void * aClosure , void ** aBp ,
696- void * aStackEnd);
714+ const void * aFirstFramePC ,
715+ uint32_t aMaxFrames , void * aClosure ,
716+ void ** aBp, void * aStackEnd);
697717
698- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
699- uint32_t aMaxFrames, void * aClosure) {
718+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
719+ const void * aFirstFramePC, uint32_t aMaxFrames,
720+ void * aClosure) {
700721 // Get the frame pointer
701722 void ** bp = (void **)__builtin_frame_address (0 );
702723
@@ -733,7 +754,7 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
733754# else
734755# error Unsupported configuration
735756# endif
736- DoFramePointerStackWalk (aCallback, aSkipFrames , aMaxFrames, aClosure, bp,
757+ DoFramePointerStackWalk (aCallback, aFirstFramePC , aMaxFrames, aClosure, bp,
737758 stackEnd);
738759}
739760
@@ -744,7 +765,7 @@ MFBT_API void MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
744765
745766struct unwind_info {
746767 MozWalkStackCallback callback;
747- int skip ;
768+ FrameSkipper skipper ;
748769 int maxFrames;
749770 int numFrames;
750771 void * closure;
@@ -755,7 +776,7 @@ static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context,
755776 unwind_info* info = static_cast <unwind_info*>(closure);
756777 void * pc = reinterpret_cast <void *>(_Unwind_GetIP (context));
757778 // TODO Use something like '_Unwind_GetGR()' to get the stack pointer.
758- if (-- info->skip < 0 ) {
779+ if (! info->skipper . ShouldSkipPC (pc) ) {
759780 info->numFrames ++;
760781 (*info->callback )(info->numFrames , pc, nullptr , info->closure );
761782 if (info->maxFrames != 0 && info->numFrames == info->maxFrames ) {
@@ -766,11 +787,12 @@ static _Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context,
766787 return _URC_NO_REASON;
767788}
768789
769- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
770- uint32_t aMaxFrames, void * aClosure) {
790+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
791+ const void * aFirstFramePC, uint32_t aMaxFrames,
792+ void * aClosure) {
771793 unwind_info info;
772794 info.callback = aCallback;
773- info.skip = aSkipFrames + 1 ;
795+ info.skipper = FrameSkipper (aFirstFramePC ? aFirstFramePC : CallerPC ()) ;
774796 info.maxFrames = aMaxFrames;
775797 info.numFrames = 0 ;
776798 info.closure = aClosure;
@@ -840,8 +862,9 @@ bool MFBT_API MozDescribeCodeAddress(void* aPC,
840862
841863#else // unsupported platform.
842864
843- MFBT_API void MozStackWalk (MozWalkStackCallback aCallback, uint32_t aSkipFrames,
844- uint32_t aMaxFrames, void * aClosure) {}
865+ MFBT_API void MozStackWalk (MozWalkStackCallback aCallback,
866+ const void * aFirstFramePC, uint32_t aMaxFrames,
867+ void * aClosure) {}
845868
846869MFBT_API bool MozDescribeCodeAddress (void * aPC,
847870 MozCodeAddressDetails* aDetails) {
@@ -859,13 +882,14 @@ MFBT_API bool MozDescribeCodeAddress(void* aPC,
859882#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
860883MOZ_ASAN_BLACKLIST
861884static void DoFramePointerStackWalk (MozWalkStackCallback aCallback,
862- uint32_t aSkipFrames, uint32_t aMaxFrames ,
863- void * aClosure , void ** aBp ,
864- void * aStackEnd) {
885+ const void * aFirstFramePC ,
886+ uint32_t aMaxFrames , void * aClosure ,
887+ void ** aBp, void * aStackEnd) {
865888 // Stack walking code courtesy Kipp's "leaky".
866889
867- int32_t skip = aSkipFrames ;
890+ FrameSkipper skipper (aFirstFramePC) ;
868891 uint32_t numFrames = 0 ;
892+
869893 while (aBp) {
870894 void ** next = (void **)*aBp;
871895 // aBp may not be a frame pointer on i386 if code was compiled with
@@ -885,7 +909,7 @@ static void DoFramePointerStackWalk(MozWalkStackCallback aCallback,
885909 void * pc = *(aBp + 1 );
886910 aBp += 2 ;
887911# endif
888- if (--skip < 0 ) {
912+ if (!skipper. ShouldSkipPC (pc) ) {
889913 // Assume that the SP points to the BP of the function
890914 // it called. We can't know the exact location of the SP
891915 // but this should be sufficient for our use the SP
@@ -904,8 +928,10 @@ namespace mozilla {
904928
905929void FramePointerStackWalk (MozWalkStackCallback aCallback, uint32_t aMaxFrames,
906930 void * aClosure, void ** aBp, void * aStackEnd) {
907- DoFramePointerStackWalk (aCallback, /* aSkipFrames = */ 0 , aMaxFrames,
908- aClosure, aBp, aStackEnd);
931+ // We don't pass a aFirstFramePC because we start walking the stack from the
932+ // frame at aBp.
933+ DoFramePointerStackWalk (aCallback, nullptr , aMaxFrames, aClosure, aBp,
934+ aStackEnd);
909935}
910936
911937} // namespace mozilla
@@ -914,6 +940,7 @@ void FramePointerStackWalk(MozWalkStackCallback aCallback, uint32_t aMaxFrames,
914940
915941namespace mozilla {
916942MFBT_API void FramePointerStackWalk (MozWalkStackCallback aCallback,
943+ const void * aFirstFramePC,
917944 uint32_t aMaxFrames, void * aClosure,
918945 void ** aBp, void * aStackEnd) {}
919946} // namespace mozilla
@@ -1006,10 +1033,11 @@ static bool WalkTheStackEnabled() {
10061033 return result;
10071034}
10081035
1009- MFBT_API void MozWalkTheStack (FILE* aStream, uint32_t aSkipFrames ,
1036+ MFBT_API void MozWalkTheStack (FILE* aStream, const void * aFirstFramePC ,
10101037 uint32_t aMaxFrames) {
10111038 if (WalkTheStackEnabled ()) {
1012- MozStackWalk (PrintStackFrame, aSkipFrames + 1 , aMaxFrames, aStream);
1039+ MozStackWalk (PrintStackFrame, aFirstFramePC ? aFirstFramePC : CallerPC (),
1040+ aMaxFrames, aStream);
10131041 }
10141042}
10151043
@@ -1022,9 +1050,10 @@ static void WriteStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP,
10221050}
10231051
10241052MFBT_API void MozWalkTheStackWithWriter (void (*aWriter)(const char *),
1025- uint32_t aSkipFrames ,
1053+ const void* aFirstFramePC ,
10261054 uint32_t aMaxFrames) {
10271055 if (WalkTheStackEnabled ()) {
1028- MozStackWalk (WriteStackFrame, aSkipFrames + 1 , aMaxFrames, (void *)aWriter);
1056+ MozStackWalk (WriteStackFrame, aFirstFramePC ? aFirstFramePC : CallerPC (),
1057+ aMaxFrames, (void *)aWriter);
10291058 }
10301059}
0 commit comments