Hi! The indirect branch thunks we emit look like: __x86_indirect_thunk_rax: .cfi_startproc call .LIND1 .LIND0: pause lfence jmp .LIND0 .LIND1: mov %rax, (%rsp) ret .cfi_endproc
The problem is that the CFI is incorrect. On the first entry it is correct, the default is CFA %rsp+8 and rip at cfa-8, before call .LIND1 is executed, the return address (to whatever called the thunk) is at %rsp+8 like on entry to any other function. But the call insn pushes a word to the stack, which we don't want to show up as another caller, and worse is in the mov insn overwritten with something else. The following patch adds .cfi_def_cfa_offset 16 right after the .LIND1 label, so that the CFI is correct until the end of the thunk. It works properly also with -fno-dwarf2-cfi-asm. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-09-25 Jakub Jelinek <ja...@redhat.com> PR target/87414 * config/i386/i386.c: Include debug.h and dwarf2out.h. (output_indirect_thunk): Emit DW_CFA_def_cfa_offset after the call. --- gcc/config/i386/i386.c.jj 2018-09-24 10:36:54.559016673 +0200 +++ gcc/config/i386/i386.c 2018-09-24 22:09:48.218211652 +0200 @@ -89,6 +89,8 @@ along with GCC; see the file COPYING3. #include "ipa-fnsummary.h" #include "wide-int-bitmask.h" #include "tree-vector-builder.h" +#include "debug.h" +#include "dwarf2out.h" /* This file should be included last. */ #include "target-def.h" @@ -10464,6 +10466,23 @@ output_indirect_thunk (unsigned int regn ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2); + /* The above call insn pushed a word to stack. Adjust CFI info. */ + if (flag_asynchronous_unwind_tables && dwarf2out_do_frame ()) + { + if (! dwarf2out_do_cfi_asm ()) + { + dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> (); + xcfi->dw_cfi_opc = DW_CFA_advance_loc4; + xcfi->dw_cfi_oprnd1.dw_cfi_addr = ggc_strdup (indirectlabel2); + vec_safe_push (cfun->fde->dw_fde_cfi, xcfi); + } + dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> (); + xcfi->dw_cfi_opc = DW_CFA_def_cfa_offset; + xcfi->dw_cfi_oprnd1.dw_cfi_offset = 2 * UNITS_PER_WORD; + vec_safe_push (cfun->fde->dw_fde_cfi, xcfi); + dwarf2out_emit_cfi (xcfi); + } + if (regno != INVALID_REGNUM) { /* MOV. */ Jakub