Open Bug 968531 Opened 12 years ago Updated 3 years ago

Make NS_StackWalk work on ARM Linux

Categories

(Core :: XPCOM, defect)

ARM
Gonk (Firefox OS)
defect

Tracking

()

People

(Reporter: jld, Assigned: jld)

References

Details

Currently we don't have an NS_StackWalk implementation that works on ARM Linux, and this can be a problem when investigating certain kinds of bug (e.g., on B2G). The existing option in nsStackWalk.cpp to use _Unwind_Backtrace might work if it were enabled(?), but we should make sure that the not-quite-sorted .ARM.exidx section seen in the B2G ICS libc.so (caused by a linker bug that probably also affects some versions of regular Android) doesn't cause problems. Alternately, there's an ARM EH unwinder in tools/profiler (bug 810526) that could be moved into xpcom/base with a replacement for (or along with) the code in that directory that enumerates loaded libraries. The core unwinder is async-signal-safe and relatively fast, but there's a setup step that has to be called first to locate (and, to work around the previously mentioned linker bug, sort) the exception indices of loaded objects.
So this works: static void __attribute__((naked)) CallStackWalk(NS_WalkStackCallback callback, const unsigned long *regs) { asm("push {r7, lr}\n\t" "mov r7, r1\n\t" ".save {r0 - r15}\n\t" ".setfp r7, sp, #0\n\t" "movs r1, #1\n\t" "movs r2, #0\n\t" "movs r3, #0\n\t" "push {r2, r3}\n\t" "bl NS_StackWalk\n\t" "pop {r2, r3, r7, pc}"); } If you call NS_StackWalk in a signal handler, it will call _Unwind_Backtrace, which will dutifully unwind your signal handler... and then hit the signal trampoline and stop. Which, if you're trying to get the stack of the code that caused the signal to be raised, is not helpful. But _Unwind_Backtrace is an interpreter for a well-specified language, and we control the program it's running. Thus, when the unwinder reaches this function, it will set the virtual stack pointer to our chosen value (kept in the callee-saved R7), as if it were a frame pointer, and then it will pop all 16 core registers — i.e., overwrite the simulated machine's register file with whatever we want. A better variation of this approach would be to pass the ucontext_t* into NS_StackWalk and have it set up the call to _Unwind_Backtrace this way. This could be a more general feature to use the provided context instead of applying the aSkipFrames argument to the current context, if implemented for the unwinder and platform in question.
Assignee: nobody → jld
See Also: → 1082276
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.