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

John DelSignore John.DelSignore at roguewave.com
Mon Aug 9 06:41:51 PDT 2010


Saurabh wrote:
> Thanks for the enlightenment!!!
> 
> I was wondering  ... isn't the instruction " DW_CFA_def_cfa_offset: 16"
> redundant?

No, it means that, at offset +1 into the function, the cfa is r7+16, instead of r7+8.

> The location for r6 is easily described by DW_CFA_offset. All
> dumps I have seen have this instruction.
> 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

I believe that the above means that, at offset +1 into the function, r6 is stored at cfa-16. I think readelf is probably multiplying the offset by the "Data alignment factor" before printing it out, so the LEB128 factored offset in the CFA was probably 2.

>   DW_CFA_advance_loc: 3 to 00000004
>   DW_CFA_def_cfa_reg: r6

The above means that, at offset +4 into the function, the cfa register is now r6 and the offset stays the same, so the cfa is r6+16.

Cheers, John D.


> 
> 
> 
> ------------------------------------------------------------------------
> *From:* John DelSignore <John.DelSignore at roguewave.com>
> *To:* Saurabh <saurabhcv at yahoo.com>
> *Cc:* "dwarf-discuss at lists.dwarfstd.org" <dwarf-discuss at lists.dwarfstd.org>
> *Sent:* Sun, August 8, 2010 3:08:28 PM
> *Subject:* Re: [Dwarf-Discuss] unwinding stack (CIE/FDE)
> 
> 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 <mailto:mjw at redhat.com>>
>> *To:* Jason Molenda <jmolenda at apple.com <mailto:jmolenda at apple.com>>
>> *Cc:* Frank Ch. Eigler <fche at redhat.com <mailto:fche at redhat.com>>;
> Saurabh <saurabhcv at yahoo.com <mailto:saurabhcv at yahoo.com>>;
>> dwarf-discuss at lists.dwarfstd.org <mailto: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