[Bug debug/99334] Generated DWARF unwind table issue while on instructions where rbp is pointing to callers stack frame

cvs-commit at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Thu Apr 22 16:52:16 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99334

--- Comment #13 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-8 branch has been updated by Jakub Jelinek
<jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:698b03a66e5115c5dd5cf84bbb499e210df3e709

commit r8-10901-g698b03a66e5115c5dd5cf84bbb499e210df3e709
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Mar 27 00:20:42 2021 +0100

    dwarf2cfi: Defer queued register saves some more [PR99334]

    On the testcase in the PR with
    -fno-tree-sink -O3 -fPIC -fomit-frame-pointer -fno-strict-aliasing
-mstackrealign
    we have prologue:
    0000000000000000 <_func_with_dwarf_issue_>:
       0:   4c 8d 54 24 08          lea    0x8(%rsp),%r10
       5:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
       9:   41 ff 72 f8             pushq  -0x8(%r10)
       d:   55                      push   %rbp
       e:   48 89 e5                mov    %rsp,%rbp
      11:   41 57                   push   %r15
      13:   41 56                   push   %r14
      15:   41 55                   push   %r13
      17:   41 54                   push   %r12
      19:   41 52                   push   %r10
      1b:   53                      push   %rbx
      1c:   48 83 ec 20             sub    $0x20,%rsp
    and emit
    00000000 0000000000000014 00000000 CIE
      Version:               1
      Augmentation:          "zR"
      Code alignment factor: 1
      Data alignment factor: -8
      Return address column: 16
      Augmentation data:     1b
      DW_CFA_def_cfa: r7 (rsp) ofs 8
      DW_CFA_offset: r16 (rip) at cfa-8
      DW_CFA_nop
      DW_CFA_nop

    00000018 0000000000000044 0000001c FDE cie=00000000
pc=0000000000000000..00000000000001d5
      DW_CFA_advance_loc: 5 to 0000000000000005
      DW_CFA_def_cfa: r10 (r10) ofs 0
      DW_CFA_advance_loc: 9 to 000000000000000e
      DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)
      DW_CFA_advance_loc: 13 to 000000000000001b
      DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -40; DW_OP_deref)
      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)
    ...
    unwind info for that.  The problem is when async signal
    (or stepping through in the debugger) stops after the pushq %rbp
    instruction and before movq %rsp, %rbp, the unwind info says that
    caller's %rbp is saved there at *%rbp, but that is not true, caller's
    %rbp is either still available in the %rbp register, or in *%rsp,
    only after executing the next instruction - movq %rsp, %rbp - the
    location for %rbp is correct.  So, either we'd need to temporarily
    say:
      DW_CFA_advance_loc: 9 to 000000000000000e
      DW_CFA_expression: r6 (rbp) (DW_OP_breg7 (rsp): 0)
      DW_CFA_advance_loc: 3 to 0000000000000011
      DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)
      DW_CFA_advance_loc: 10 to 000000000000001b
    or to me it seems more compact to just say:
      DW_CFA_advance_loc: 12 to 0000000000000011
      DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)
      DW_CFA_advance_loc: 10 to 000000000000001b

    I've tried instead to deal with it through REG_FRAME_RELATED_EXPR
    from the backend, but that failed miserably as explained in the PR,
    dwarf2cfi.c has some rules (Rule 16 to Rule 19) that are specific to the
    dynamic stack realignment using drap register that only the i386 backend
    does right now, and by using REG_FRAME_RELATED_EXPR or REG_CFA* notes we
    can't emulate those rules.  The following patch instead does the deferring
    of the hard frame pointer save rule in dwarf2cfi.c Rule 18 handling and
    emits it on the (set hfp sp) assignment that must appear shortly after it
    and adds assertion that it is the case.

    The difference before/after the patch on the assembly is:
    --- pr99334.s~  2021-03-26 15:42:40.881749380 +0100
    +++ pr99334.s   2021-03-26 17:38:05.729161910 +0100
    @@ -11,8 +11,8 @@ _func_with_dwarf_issue_:
            andq    $-16, %rsp
            pushq   -8(%r10)
            pushq   %rbp
    -       .cfi_escape 0x10,0x6,0x2,0x76,0
            movq    %rsp, %rbp
    +       .cfi_escape 0x10,0x6,0x2,0x76,0
            pushq   %r15
            pushq   %r14
            pushq   %r13
    i.e. does just what we IMHO need, after pushq %rbp %rbp
    still contains parent's frame value and so the save rule doesn't
    need to be overridden there, ditto at the start of the next insn
    before the side-effect took effect, and we override it only after
    it when %rbp already has the right value.

    If some other target adds dynamic stack realignment in the future and
    the offset 0 case wouldn't be true there, the code can be adjusted so that
    it works on all the drap architectures, I'm pretty sure the code would
    need other adjustments too.

    For the rule 18 and for the (set hfp sp) after it we already have asserts
    for the drap cases that check whether the code looks the way i?86/x86_64
    emit it currently.

    2021-03-26  Jakub Jelinek  <jakub@redhat.com>

            PR debug/99334
            * dwarf2out.h (struct dw_fde_node): Add rule18 member.
            * dwarf2cfi.c (dwarf2out_frame_debug_expr): When handling (set hfp
sp)
            assignment with drap_reg active, queue reg save for hfp with offset
0
            and flush queued reg saves.  When handling a push with rule18,
            defer queueing reg save for hfp and just assert the offset is 0.
            (scan_trace): Assert that fde->rule18 is false.

    (cherry picked from commit f5df18504c1790413f293bfb50d40faa7f1ea860)


More information about the Gcc-bugs mailing list