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

Saurabh saurabhcv at yahoo.com
Wed Aug 18 17:14:26 PDT 2010


Sorry if I am pestering you guys more than I should. Can you tell where my 
calculation is wrong?

Foo calls function Dummy1, Current PC is somewhere in Dummy1. I can get to Foo 
by finding the CIE and the return address register since there is no CF 
instruction in Dummy1 FDE/CIE dealing with 31. So current value of 31 contains 
return address(Foo).
Using this I get to Foo's FDE/CIE. I am having trouble going beyond this. I am 
trying to find return address for previous function(Foo).
 
<  5><0x20055518:0x20055522><Dummy1><fde offset 0x1830 length: 0x10><eh offset 
none>
    0x20055518:   
<  5><0x20055524:0x200559f2><Foo><fde offset 0x1844 length: 0x5c><eh offset 
none>
    0x20055524:   
    0x20055526:   <off r13=-4(cfa) > 
    0x20055528:   <off r13=-4(cfa) > <off r14=-8(cfa) > 
    0x2005552a:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > 
    0x2005552e:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > 

    0x20055532:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > 

    0x20055536:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > 

    0x2005553a:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r19=-28(cfa) > 

    0x2005553c:    <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > 
<off r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r19=-28(cfa) > 
<off r31=-32(cfa) > 

    0x2005553e:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r19=-28(cfa) > <off 
r31=-32(cfa) > 

    0x200559d8:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r19=-28(cfa) > <off 
r31=-32(cfa) > 

    0x200559da:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r19=-28(cfa) > <off 
r31=-32(cfa) > 

    0x200559de:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r18=-24(cfa) > <off r31=-32(cfa) > 

    0x200559e2:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r17=-20(cfa) > <off r31=-32(cfa) > 

    0x200559e6:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r16=-16(cfa) > <off r31=-32(cfa) > 

    0x200559ea:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r15=-12(cfa) > <off 
r31=-32(cfa) > 

    0x200559ec:   <off r13=-4(cfa) > <off r14=-8(cfa) > <off r31=-32(cfa) > 
    0x200559ee:   <off r13=-4(cfa) > <off r31=-32(cfa) > 
    0x200559f0:    <off r31=-32(cfa) >
 
Foo function
DW_CFA_advance_loc: 2 to 20055526 
  DW_CFA_def_cfa_offset: 4 
  DW_CFA_offset: r13 at cfa-4 
  DW_CFA_advance_loc: 2 to 20055528 
  DW_CFA_def_cfa_offset: 8 
  DW_CFA_offset: r14 at cfa-8 
  DW_CFA_advance_loc: 2 to 2005552a 
  DW_CFA_def_cfa_offset: 12 
  DW_CFA_offset: r15 at cfa-12 
  DW_CFA_advance_loc: 4 to 2005552e 
  DW_CFA_def_cfa_offset: 16 
  DW_CFA_offset: r16 at cfa-16 
  DW_CFA_advance_loc: 4 to 20055532 
  DW_CFA_def_cfa_offset: 20 
  DW_CFA_offset: r17 at cfa-20 
  DW_CFA_advance_loc: 4 to 20055536 
  DW_CFA_def_cfa_offset: 24 
  DW_CFA_offset: r18 at cfa-24 
  DW_CFA_advance_loc: 4 to 2005553a 
  DW_CFA_def_cfa_offset: 28 
  DW_CFA_offset: r19 at cfa-28 
  DW_CFA_advance_loc: 2 to 2005553c 
  DW_CFA_def_cfa_offset: 32 
  DW_CFA_offset: r31 at cfa-32 
  DW_CFA_advance_loc: 2 to 2005553e 
  DW_CFA_def_cfa_offset: 36 
 
Current register values
CIE for the above FDE
168A: return reg=31
168B: 0x0c DW_CFA_def_cfa reg=28 offset=0
Current Register Dump
    r0 2007701e    r10 00000000    r20 01480404 r30 00000622
    r1 00000000    r11 00000000    r21 02000000  r31 200559d6
    r2 00000000    r12 00000004    r22 00801100 
    r3 0010f01c    r13 000001b0    r23 00842401    
    r4 000581af    r14 20088800    r24 00850204  
    r5 0a503ba0    r15 2007f000    r25 008c0000    
    r6 2007f000    r16 00000000     r26 21f7f8a0 
    r7 20025ddd    r17 20002000    r27 00000000  
    r8 00000000    r18 20050734     r28 20025f28
    r9 00000000    r19 2002e000     r29 02000400 

>From what I understand by looking at dwarf dumps and relevent Cframe instruction 
entries..
r31->[CFA-32]
CFA default register is 28
CFA default offset while finding location for R31 is 32. So CFA = [R28]+32
So Return address for previous frame is [CFA-32] = [[R28]+32-32]

By experimenting I found it should be [[R28]+4], but can't get to this by just 
looking at Call frame Instructions



________________________________
From: Saurabh <saurabhcv at yahoo.com>
To: John DelSignore <John.DelSignore at roguewave.com>
Cc: dwarf info <dwarf-discuss at lists.dwarfstd.org>
Sent: Tue, August 10, 2010 8:56:43 AM
Subject: Re: [Dwarf-Discuss] unwinding stack (CIE/FDE)


Thanks John for taking the time and patience to answer all the question.  Thanks 
a lot!!!
 
Assuming I get to the current FDE and get to the upper function FDE  using the 
return address. How would I be able to change register states to the one of 
upper frame? The FDE/CIE instructions of upper frame wouldn’t provide right 
address when the registers are still holding values of current frame. You said I 
need to maintain states, can you explain a little more?

My apologies if I am asking something that has already been discussed here.



________________________________
From: John DelSignore <John.DelSignore at roguewave.com>
To: Saurabh <saurabhcv at yahoo.com>
Cc: dwarf info <dwarf-discuss at lists.dwarfstd.org>
Sent: Mon, August 9, 2010 6:41:51 AM
Subject: Re: [Dwarf-Discuss] unwinding stack (CIE/FDE)

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
>>
>>
> 
> 


      
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dwarfstd.org/private.cgi/dwarf-discuss-dwarfstd.org/attachments/20100818/b05acfa0/attachment-0002.htm>


More information about the Dwarf-Discuss mailing list