On Tue, Oct 13, 2020 at 5:10 AM AJ D via Gcc <gcc@gcc.gnu.org> wrote:
>
> 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?

In case you do not get a sufficient answer here it might be useful to
report a bug in bugzilla so it doesn't get lost.

Richard.

>
>
> Regards
>
> AJ

Reply via email to