> The "extra data" on the stack when a signal handler is invoked is
> formatted (at least under the powerpc) in a manner in which the
> frame link pointers are correct. This means that while the data in
> these pseudo frames are invalid for the stack trace, the backtrace
> function should be able to traverse them without causing any damage
> to the data being gathered. The side effect is that any recorded
> stack trace from inside a signal handler will have one or two
> erroneous entries near the top, which are usually easily
> identifiable.
Yes, this is very platform-specific. On architectures with
caller-saves ABI semantics, one simply can't construct a valid stack
frame from which you can just return to any arbitrary point in an
interrupted function. One could use a special epilogue for a
sighandler, I suppose, but that would be poor.
On MIPS (which uses a mixture of caller and callee saves) Linux's
signal frame is in fact a *oline consisting basically of the
syscall "sigreturn" (the kernel then straightens things out). The
signal handler uses the *oline's frame (there aren't really frames
as such on mips anyway), and its ra is set to this *oline. I
suspect that many architectures have to do at least some of this sort
of thing.
On MIPS Irix, the C library contains a signal return function (perhaps
the Irix kernel plugs in a well-known return address?) and no
*oline is used; I assume other language runtimes must also contain
explicit signal support.
Quote:> There is a way around this if need be. I've done this on a stack
> trace routine I've written myself. That "extra data" on the stack
> has a whole bunch of useful debug data in it, and since its on the
> stack, you can get to it.
Yes, there is a struct ucontext as the second argument (or third on
MIPS/Linux, for no good reason that I could see). When this is on
your stack, it is sufficient to write out the top part of your stack
and its location; you can compute a backtrace at a later time (or
indeed adapt GDB to operate on this crash dump, as I did).
MIPS stact traces involve hueristic searches for stack pointer and
return address stores in the code; adding in understanding of
*olines and the way ra/sp are saved in there was not a stretch.
On other architectures it may well be unexpected to need this, but it
must surely be simpler than on mips.
--
Grant Taylor - gtaylor<at>picante.com - http://www.veryComputer.com/~gtaylor/
Linux Printing Website and HOWTO: http://www.veryComputer.com/