Jan Kratochvil <[EMAIL PROTECTED]>
02/27/2007 01:19 PM
To
Corey J Ashford/Beaverton/[EMAIL PROTECTED]
cc
[email protected]
Subject
Re: [Libunwind-devel] question about is_signal_frame and usage
Hi,
this issue is out of the David Mosberger-Tang's code as this functionality
(`decrease_ip' code) is implemented only in the Frysk's fork of libunwind
cvs -d :pserver:[EMAIL PROTECTED]:/cvs/frysk co libunwind
http://sourceware.org/frysk/
On Tue, 27 Feb 2007 20:15:19 +0100, Corey Ashford wrote:
I've been debugging a test case (a variant of test-async-sig) that
run-ptrace-signull / test-ptrace-signull.c ?
occasionally gets an error during unwinding through a signal handler.
The error occurs when the signal interrupts the first instruction of
function.
I've narrowed down the problem to this sequence in dwarf/Gparser.c:
> static int
> fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int
> need_unwind_info)
> {
> int ret, dynamic = 1;
>
> /* In the current (lowest) frame we must not touch `ip' as the current
> address is where we stand. On the other hand any upper frames will
> stand
> on the next instruction behind our call which may have a different
> stack
> DWARF information (for `stdcall' called functions) or the next
> instruction
> even may belong already to a different continuing function.
> Also signal frames got invoked from the instruction we want to
> analyze. */
> if (c->decrease_ip)
> --ip;
>
...
The problem here is that the frame we are unwinding is no longer a
"signal frame" (I think). In my current PowerPC port, a signal frame is
recognized by looking for the signal return trampoline code at the
current IP address.
There are two code ways for handling signal handlers. One is by the DWARF CIE
augmentation "S" and the other is by raw disassembly / binary compare.
The former is by is_signal_frame() (dwarf/Gparser.c), the latter is by
unw_is_signal_frame() (ARCH/Gis_signal_frame.c).
Because this function IP is not recognized as a signal frame,
c->decrease_ip is set to true, which moves the IP out of the function to
whatever cruft precedes the function. Consequently, the proc info is
not found and returns an error.
There is that `decrease_ip' memory to remember that last frame's
is-signal-frame boolean in the cursor. The IP decrease must be applied one
step later. It is correct that in "this function" (where we stand at its first
instruction) the signal frame is not recognized. But it should have been
recognized and stored one step earlier.
Have I misunderstood how is_signal_frame is supposed to be implemented?
Currently, I use is_signal_frame in ppc64/Gstep.c to determine if I
should use the ucontext record on the stack to restore the registers.
I believe you exchange here the DWARF and non-DWARF way. In the DWARF way of
is_signal_frame() implementation by "S" augmentation we do not need to do
special ucontext handling as the DWARF general unwinder takes care of it.
In the non-DWARF way you need to handle ucontext by hand but you should
implement PPC unw_is_signal_frame() based on the disassembly / binary compare.
I would also rather implement the DWARF for signal frames in glibc.
I pushed it only for i386+x86_64 before:
http://sourceware.org/ml/libc-alpha/2006-11/msg00063.html
Kernel PPC VDSO looks to me a bit broken, it has DWARF but the augmentation for
__kernel_sigtramp_rt64() does not contain the "S" mark, weird.
On i386/x86_64 there is Linux kernel "/proc/sys/kernel/vdso" where the code
should work both with it being 1 (default - kernel VDSO) and 0 (glibc).
I did not find "/proc/sys/kernel/vdso" on PPC at all, though, it looks there as
always turned on.
[snip]
Thanks for the detailed response. This clarifies some of my muddy
understanding of DWARF-based unwind. I had hoped that implementing the
full recognition plus by-hand unwinding of the signal frame would solve
the problem without having to understand the real problem deeply. It
did not solve the problem. The by-hand unwinding seems to work as well
as the DWARF unwinding, but exhibits the same problem function_addr - 1
problem (which I just figured out today). And now I can see why my
extra code to do the by-hand signal frame unwinding didn't help. It
also means I should probably reverse the logic again, and give
preference back to DWARF unwinding when it is available.
This business of the augmentation string in the CIE specifying a signal
frame is news to me. I didn't see that in the 64-bit PowerPC ELF ABI or
the DWARF 2.0 doc. How does source code specify what augmentation
string to use in the CIE?
Anyway, I think I understand now that the is_signal_frame needs to be
memorized for one step, and I will see if I can understand how that is
done for x86_64, and perhaps why it is not happening for ppc64.
Thanks so much for your time.
- Corey
--
Corey Ashford
Software Engineer
IBM Linux Technology Center, Linux Toolchain
Beaverton, OR
503-578-3507
[EMAIL PROTECTED]
_______________________________________________
Libunwind-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/libunwind-devel