Date: Tue, 27 May 2003 17:18:35 +0200
From: Michal Ludvig <mludvig@suse.cz>
Hi Mark,
why do you decrement unwound PC in dwarf_frame_cache() before using it?
The unwound PC is the return address, i.e. the instruction that will
be executed when the function returns.
foo:
...
call abort
bar:
push %ebp
mov %esp, %ebp
...
That's why the GCC unwinder does the same thing. Note that the
decrementing the PC is wrong for "interrupt frames", which is why the
if-statement is there in the code fragment you cite:
dwarf-frame.c:
478 /* Unwind the PC. */
479 fs->pc = frame_pc_unwind (next_frame);
480 if (get_frame_type (next_frame) == NORMAL_FRAME
481 && frame_relative_level (next_frame) >= 0)
482 fs->pc--;
This makes a problem for a signal trampoline.
If it is sitting on addresses say 0x40000140-0x40000150, the return
address from signal handler is 0x40000140, but dwarf_frame_cache() says
it is 0x4000013f and couldn't find it's CFI...
Do you have signal trampolnes with CFI? If the CFI is hand-generated,
you should probably "cheat" by adding a nop before the trampoline and
include it in the address range of the FDE (see the
arch/i386/kernel/vsyscall-sigreturn.S in the Linux kernel sources).
This has a tragic consequence few lines below were you look for FDE but
don't check if you find one. If you don't, line 488 segfaults.
484 /* Find the correct FDE. */
485 fde = dwarf_frame_find_fde (&fs->pc);
Hmm, a gdb_assert() is in order here.
487 /* Extract any interesting information from the CIE. */
488 fs->data_align = fde->cie->data_alignment_factor;
489 fs->code_align = fde->cie->code_alignment_factor;
490 fs->retaddr_column = fde->cie->return_address_register;
The problem is, that dwarf_frame_p() looks for the real return address
and says that there is a debug info and sets unwinder to use dwarf2
methods for this farme.
Hmm, it should do something similar as dwarf_frame_cache().
But the in unwinder itself in dwarf_frame_cache() looks for the
decreased one and of course doesn't find it.
That defenitely is a bug. It isn't immediately obvious to me how to
solve this :-(.