[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libunwind-devel] question about is_signal_frame and usage

From: Corey Ashford
Subject: Re: [Libunwind-devel] question about is_signal_frame and usage
Date: Tue, 27 Feb 2007 14:19:13 -0800
User-agent: Thunderbird (Windows/20061207)

Jan Kratochvil <address@hidden> 02/27/2007 01:19 PM
        Corey J Ashford/Beaverton/address@hidden
        Re: [Libunwind-devel] question about is_signal_frame and usage

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:address@hidden:/cvs/frysk co libunwind

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:

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.

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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]