Hi,

We have multiple ways of getting stack traces, and it is hard to keep track
of
them all. I wrote down some notes that reflect my understanding, and I
thought
I'd share it in case it's useful, and in case people have ideas on how to
improve things.

Nick


-----------------------------------------------------------------------------
mozglue/misc/StackWalk.{h,cpp}
-----------------------------------------------------------------------------
The main stackwalk function is MozStackWalk:

> MFBT_API bool
> MozStackWalk(MozWalkStackCallback aCallback,
>              uint32_t aSkipFrames,
>              uint32_t aMaxFrames,
>              void* aClosure,

Here's how it is implemented on different platforms.

- Win32       Custom code using StackWalk64()
- Win64       Custom code using RtlVirtualUnwind()
- Linux32     FramePointerStackWalk?[1]
- Linux64     _Unwind_Backtrace
- Mac32?      FramePointerStackWalk?[1]
- Mac64       _Unwind_Backtrace[2]
- Android     _Unwind_Backtrace?
- Other       (unimplemented, mostly)

[1] FramePointerStackWalk() is a straightforward FP-chasing unwind. It is a
public function and so can be called directly, too.

[2] _Unwind_Backtrace is really slow on some recent Mac versions, alas.

On Windows there is also MozStackWalkThread(), which differs from
MozStackWalk() by being able to walk the stack of a different thread.

-----------------------------------------------------------------------------
Gecko Profiler
-----------------------------------------------------------------------------
The Gecko Profiler has a couple of other stack walkers used on some
platforms.

- LUL: Linux-only stack walker that uses DWARF info to unwind.

- EHABI: Android-only stack walker that uses the ARM exception handling ABI.

-----------------------------------------------------------------------------
Places where stack walking is used.
-----------------------------------------------------------------------------
Lots of places use MozStackWalk() for all platforms: telemetry,
ah_crap_handler, HangMonitor, BlockingResourceBase,
TlsAllocationTracker.cpp,
nsTraceRefCnt.cpp, etc. These are all places where the number of stack walks
performed is small, so speed isn't that important.

The Gecko Profiler and DMD use a mixture of stack walkers, as per this
table.

            Gecko Profiler              DMD
            --------------              ---
Win32       FramePointerStackWalk       FramePointerStackWalk
Win64       MozStackWalk                MozStackWalk
Linux32     LUL                         MozStackWalk
Linux64     LUL                         MozStackWalk
Mac32?      FramePointerStackWalk[1]    FramePointerStackWalk[1]
Mac64       FramePointerStackWalk[1]    FramePointerStackWalk[1]
Android     EHABI                       MozStackWalk

[1] requires MOZ_PROFILING to be set so that frame pointers are used.

The Gecko Profiler and DMD do *lots* of stack walks, so speed is important
for
them.

Note that the Gecko Profiler needs to stackwalk other threads than the
current
one.

- Windows' MozStackWalkThread() allows that by naming the thread.

- FramePointerStackWalk() allows that, because you just give it the
  to-be-walked thread's registers.

- _Unwind_Backtrace() doesn't allow it.

HangMonitor also requires off-thread stackwalking, but it's Windows-only
(perhaps exactly because it requires off-thread stackwalking). It could
potentially use profiler_suspend_and_sample() instead (see next paragraph).

Finally, the Gecko Profiler also has a public function
profiler_suspend_and_sample_thread() that walks the stack of another thread
(using the abovementioned stackwalkers), and interleaves that with
pseudostacks
and JS stacks. BHR uses this function.
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to