[Dwarf-Discuss] unwinding stack (CIE/FDE)

John DelSignore John.DelSignore at roguewave.com
Sun Aug 8 15:08:28 PDT 2010


Saurabh wrote:
> Sorry guys,
> I think the discussion got diverted and I am still unclear on how to
> find the return address. The example in the Dwarf Appendix is confusing
> and varying compiler implementations have corroded my understanding further.
>  
> These are my questions.
> 1) I have not been able to fully interpret CFA instructions, so I am
> having trouble finding where the return address is saved. From what I
> understand CFA is same as SP at entry of a function. Which means that
> the CFA is what is pointing to the return address.

Not necessarily true. This may be true on all x86, but other architectures like Power, the return address is stored in a register.

> 2) I understand "advance loc" is used to add a line to the reg rule
> table. I have noticed that sometimes the prologoue can be missing, but
> that shouldn't stop me from getting the return address(CFA)
>  
> 3) I need to know which entry would tell me where the return address is
> saved or where CFA for the FDE is?

Look at an example using gcc on Linux x86_64 dumped with readelf:

"
The section .debug_frame contains:

00000000 00000014 ffffffff CIE
  Version:               1
  Augmentation:          ""
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16

  DW_CFA_def_cfa: r7 ofs 8
  DW_CFA_offset: r16 at cfa-8

00000018 0000001c 00000000 FDE cie=00000000 pc=00000000..00000070
  DW_CFA_advance_loc: 1 to 00000001
  DW_CFA_def_cfa_offset: 16
  DW_CFA_offset: r6 at cfa-16
  DW_CFA_advance_loc: 3 to 00000004
  DW_CFA_def_cfa_reg: r6
"

The CIE line "Return address column" tells you the column 16 is where the return address is stored. In this case, column 16 is a virtual register "r16", not an actual hardware register.

The CIE line "DW_CFA_offset: r16 at cfa-8" tells you that r16 (column 16) is at "cfa-8".

> 4) Which register is the one pointing to CFA?

The line before says the cfa is r7+8.

> 4) Where are the arguments being saved?

The unwind information doesn't tell you about the arguments. The DIEs do. In my example above, they are in the .debug_info section:

 <1><3e5>: Abbrev Number: 14 (DW_TAG_subprogram)
     DW_AT_sibling     : <42c>
     DW_AT_external    : 1
     DW_AT_name        : main
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 4
     DW_AT_prototyped  : 1
     DW_AT_type        : <a8>
     DW_AT_low_pc      : 0 0
     DW_AT_high_pc     : 0xb8 184
     DW_AT_frame_base  : 1 byte block: 6f       (DW_OP_reg31)
 <2><401>: Abbrev Number: 15 (DW_TAG_formal_parameter)
     DW_AT_name        : argc
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 3
     DW_AT_type        : <a8>
     DW_AT_location    : 2 byte block: 91 8     (DW_OP_fbreg: 8)
 <2><410>: Abbrev Number: 15 (DW_TAG_formal_parameter)
     DW_AT_name        : argv
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 3
     DW_AT_type        : <42c>
     DW_AT_location    : 2 byte block: 91 c     (DW_OP_fbreg: 12)

> 5) How to get to the CFA at next level, in order to make a tree. Do I
> simply use the return address to find the corrsponding FDE using
> start/end PC and repeat.

Yes, but you may also need to maintain register state as you go.

Good luck.

Cheers, John D.


> Below are dumps from dwarfdump and readelf of a sample run that you can
> refer to.
>  
> I have got the libunwinder library, but it has too much detail and I
> just need to understand the unlying basic logic.
>  
> fde:
> <  0><0x0:0x6><><fde offset 0x4c length: 0x10><eh offset none>
>     0x00000000: 
> *** DWARF CHECK: An fde low pc of 0x0 is not the first fde with that pc.
> The first is not named. ***
> <  0><0x0:0x6><><fde offset 0x60 length: 0x10><eh offset none>
>     0x00000000: 
> *** DWARF CHECK: An fde low pc of 0x0 is not the first fde with that pc.
> The first is not named. ***
> <  0><0x0:0x6><><fde offset 0x74 length: 0x10><eh offset none>
>     0x00000000: 
> *** DWARF CHECK: An fde low pc of 0x0 is not the first fde with that pc.
> The first is not named. ***
> <  0><0x0:0x1e><><fde offset 0x88 length: 0x1c><eh offset none>
>     0x00000000: 
>     0x00000002: <off r13=-4(cfa) >
>     0x00000004: <off r13=-4(cfa) > <off r31=r13 >
> =================
> 0000004c 00000010 00000000 FDE cie=00000000 pc=00000000..00000006
>   DW_CFA_advance_loc: 6 to 00000006
>   DW_CFA_nop
>   DW_CFA_nop
>   DW_CFA_nop
> 00000060 00000010 00000000 FDE cie=00000000 pc=00000008..0000000e
>   DW_CFA_advance_loc: 6 to 0000000e
>   DW_CFA_nop
>   DW_CFA_nop
>   DW_CFA_nop
> 00000074 00000010 00000000 FDE cie=00000000 pc=00000010..00000016
>   DW_CFA_advance_loc: 6 to 00000016
>   DW_CFA_nop
>   DW_CFA_nop
>   DW_CFA_nop
> 00000088 0000001c 00000000 FDE cie=00000000 pc=00000018..00000036
>   DW_CFA_advance_loc: 2 to 0000001a
>   DW_CFA_def_cfa_offset: 4
>   DW_CFA_offset: r13 at cfa-4
>   DW_CFA_advance_loc: 2 to 0000001c
>   DW_CFA_register: r31 in r13
>   DW_CFA_advance_loc: 26 to 00000036
>   DW_CFA_restore: r13
>   DW_CFA_def_cfa_offset: 0
> 
> ------------------------------------------------------------------------
> *From:* Mark Wielaard <mjw at redhat.com>
> *To:* Jason Molenda <jmolenda at apple.com>
> *Cc:* Frank Ch. Eigler <fche at redhat.com>; Saurabh <saurabhcv at yahoo.com>;
> dwarf-discuss at lists.dwarfstd.org
> *Sent:* Wed, August 4, 2010 1:06:08 AM
> *Subject:* Re: [Dwarf-Discuss] unwinding stack (CIE/FDE)
> 
> On Tue, 2010-08-03 at 17:37 -0700, Jason Molenda wrote:
>> On Aug 3, 2010, at 5:31 PM, Frank Ch. Eigler wrote:
>>
>> > Hi -
>> >
>> > On Tue, Aug 03, 2010 at 04:55:23PM -0700, Jason Molenda wrote:
>> >> [...]
>> >> Looking at the debug_frame that my compiler (gcc-4.2 in this case)
> outputs,
>> >> [...]
>> >> There's nothing about that stack movement in the FDE.
>> >
>> > Try again with CFLAGS+=-fasynchronous-unwind-tables.
>>
>> I'm not making this stuff up. :)  And the next question you'll ask
>> yourself is why -fasynchronous-unwind-tables isn't the default output
>> style for the debug_frame section in the first place.  But as you can
>> see, it doesn't make any difference - at least with gcc-4.2 with the
>> Apple local patches.
> 
> You might want to upgrade your compiler. gcc 4.2 is fairly old (2007,
> hasn't seen a point upgrade since 2008). Current is gcc 4.5 (which will
> output unwind info not just for function prologues, but also for
> epilogues). On my fedora machine -fasynchronous-unwind-tables is the
> default (although I couldn't replicate your situation there, since newer
> gcc seems to not generate that push/pop/call dance for me). You might
> also want to look at both the .debug_frame and the .eh_frame. If a
> location is described in one, the compiler might not also output it in
> the other.
> 
> Cheers,
> 
> Mark
> 
> 




More information about the Dwarf-Discuss mailing list