This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: dwarf-frame.c question


   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.

Yes, the resume address, or the next instruction that will be executed when the frame resumes.


frame_address_in_block() also tries to handle this.

 This is the instruction after
the call instruction.  The problem is that if the call instruction is
the last instruction of a function, the return address might point to
the next function:

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 :-(.

First an FYI. CFI has that return-address column. I'm left wondering if frame_pc_unwind() should try the frame for the unwound pc before trying for registers. However, there has so far been zero evidence supporting this need so I think, until there is, let it be. It also wouldn't help with this case - it to would still point back to beyond the function :-(


Second, another FYI. This isn't just a CFI problem. There have been earlier posts about how GDB, already gets confused by this - printing out the wrong function address for instance. This problem is generic.

Anyway, is it safe to always decrement the resume address before looking for the CFI info? Given a more complex sequence like:

	1: setup call
	2: call xxx with lots of side effects
	3: delay slot saved r0++
	4: discard call

then the CFI info for 4 could be very different to that for 2/3.

>  Andrew, it seems that we should tweak the frame code
> to make sure that frame_unwind_by_pc is always passed a PC *within* the
> function.

True, but how? It would effectively be frame_unwind_address_in_block() but how reliably/where could it be used?

Andrew



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]