libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fwd: GCC DWARF Issue - Frame Pointer Dependency


From: AJ D
Subject: Fwd: GCC DWARF Issue - Frame Pointer Dependency
Date: Mon, 12 Oct 2020 20:14:16 -0700

Is there a known solution to this issue?

---------- Forwarded message ---------
From: AJ D <aatsnps@gmail.com>
Date: Mon, Oct 12, 2020 at 8:08 PM
Subject: GCC DWARF Issue - Frame Pointer Dependency
To: <gcc@gcc.gnu.org>


Hi,

 

I have a function for which GCC is generating the following code (just showing the relevant snippet here).

 

0000000000005a70 <some_func>:

    5a70:   4c 8d 54 24 08          lea    0x8(%rsp),%r10

    5a75:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp

    5a79:   41 ff 72 f8             pushq  -0x8(%r10)

    5a7d:   55                      push   %rbp

    5a7e:   48 89 e5                mov    %rsp,%rbp

    5a81:   41 57                   push   %r15

    5a83:   41 56                   push   %r14

    5a85:   41 55                   push   %r13

    5a87:   41 54                   push   %r12

    :

    5b08:   5b                      pop    %rbx

    5b09:   41 5a                   pop    %r10

    5b0b:   41 5c                   pop    %r12

    5b0d:   41 5d                   pop    %r13

    5b0f:   41 5e                   pop    %r14

    5b11:   41 5f                   pop    %r15

    5b13:   5d                      pop    %rbp

=>    5b14:   49 8d 62 f8      lea    -0x8(%r10),%rsp

    5b18:   c3                      retq

 

I am using a SIGPROF based CPU profiler (Google CPU Profiler) to profile my code. The SIGPROF handler (of the Google CPU Profiler) tries to unwind the stack (using libunwind) every time it gets a SIGPROF. And libunwind (used for unwinding the stack) uses DWARF unwind table (dumped by gcc -O3 -mstackrealign -fomit-frame-pointer).


And I noticed that I get a crash every time my code gets interrupted by SIGPROF while my program is in the middle of setting / resetting frame pointer and the frame pointer %rbp happens to point to the parent/previous frame at that point, for example, in instruction 5b14 (shown above with => and red). 

 

=>    5b14:   49 8d 62 f8      lea    -0x8(%r10),%rsp


DWARF dumped by GCC for the snippet shown above is the following:

 

000002f4 0000000000000044 000002f8 FDE cie=00000000 pc=0000000000005a70..0000000000005d7c

  DW_CFA_advance_loc: 5 to 0000000000005a75

  DW_CFA_def_cfa: r10 (r10) ofs 0

  DW_CFA_advance_loc: 9 to 0000000000005a7e

  DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)

  DW_CFA_advance_loc: 11 to 0000000000005a89

  DW_CFA_expression: r15 (r15) (DW_OP_breg6 (rbp): -8)

  DW_CFA_expression: r14 (r14) (DW_OP_breg6 (rbp): -16)

  DW_CFA_expression: r13 (r13) (DW_OP_breg6 (rbp): -24)

  DW_CFA_expression: r12 (r12) (DW_OP_breg6 (rbp): -32)

  DW_CFA_advance_loc: 5 to 0000000000005a8e

  DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -40; DW_OP_deref)

  DW_CFA_advance_loc: 4 to 0000000000005a92

>>  DW_CFA_expression: r3 (rbx) (DW_OP_breg6 (rbp): -48)

  DW_CFA_advance_loc1: 121 to 0000000000005b0b

  DW_CFA_remember_state

>>  DW_CFA_def_cfa: r10 (r10) ofs 0

  DW_CFA_advance_loc: 13 to 0000000000005b18

  DW_CFA_def_cfa: r7 (rsp) ofs 8

  DW_CFA_advance_loc: 8 to 0000000000005b20

  DW_CFA_restore_state

 

000002f4 0000000000000044 000002f8 FDE cie=00000000 pc=0000000000005a70..0000000000005d7c

   LOC           CFA      rbx   rbp   r12   r13   r14   r15   ra

0000000000005a70 rsp+8    u     u     u     u     u     u     c-8

0000000000005a75 r10+0    u     u     u     u     u     u     c-8

0000000000005a7e r10+0    u     exp   u     u     u     u     c-8

0000000000005a89 r10+0    u     exp   exp   exp   exp   exp   c-8

0000000000005a8e exp      u     exp   exp   exp   exp   exp   c-8

0000000000005a92 exp      exp   exp   exp   exp   exp   exp   c-8

0000000000005b0b r10+0    exp   exp   exp   exp   exp   exp   c-8

0000000000005b18 rsp+8    exp   exp   exp   exp   exp   exp   c-8

0000000000005b20 exp      exp   exp   exp   exp   exp   exp   c-8

 

And if you see here, the DWARF _expression_ for fetching the CFA is correct, but what about the DWARF _expression_ for fetching the value of %rbx?

 

>>  DW_CFA_expression: r3 (rbx) (DW_OP_breg6 (rbp): -48)

 

Value of %rbx is (in DWARF) is “%rbp relative” and since %rbp is pointing to the wrong (parent/previous) frame, we will obviously get garbage for the value of %rbx.

 

If you look at the generated DWARF carefully, pretty much everything is ‘%rbp relative’, so values for each of these registers cannot be restored in this scenario.

 

  DW_CFA_expression: r15 (r15) (DW_OP_breg6 (rbp): -8)

  DW_CFA_expression: r14 (r14) (DW_OP_breg6 (rbp): -16)

  DW_CFA_expression: r13 (r13) (DW_OP_breg6 (rbp): -24)

  DW_CFA_expression: r12 (r12) (DW_OP_breg6 (rbp): -32)

 

I was just wondering, instead of making these %rbp-relative, could we have made this CFA-relative? That would have taken care of this particular issue, since CFA is correctly maintained/restored in this example.

 

Another question, is there a known work around for this issue?

 

Regards

AJ


reply via email to

[Prev in Thread] Current Thread [Next in Thread]