Since nested function isn't only called directly, there is ENDBR32 at function entry and we need to skip it for direct jump in trampoline.
Tested on Linux/x86-64 CET machine with and without -m32. gcc/ PR target/93656 * config/i386/i386.c (ix86_trampoline_init): Skip ENDBR32 at nested function entry. gcc/testsuite/ PR target/93656 * gcc.target/i386/pr93656.c: New test. --- gcc/config/i386/i386.c | 7 ++++++- gcc/testsuite/gcc.target/i386/pr93656.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr93656.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 44bc0e0176a..dbcae244acb 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -16839,9 +16839,14 @@ ix86_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) the stack, we need to skip the first insn which pushes the (call-saved) register static chain; this push is 1 byte. */ offset += 5; + int skip = MEM_P (chain) ? 1 : 0; + /* Since nested function isn't only called directly, there is + ENDBR32 at function entry and we need to skip it. */ + if (need_endbr) + skip += 4; disp = expand_binop (SImode, sub_optab, fnaddr, plus_constant (Pmode, XEXP (m_tramp, 0), - offset - (MEM_P (chain) ? 1 : 0)), + offset - skip), NULL_RTX, 1, OPTAB_DIRECT); emit_move_insn (mem, disp); } diff --git a/gcc/testsuite/gcc.target/i386/pr93656.c b/gcc/testsuite/gcc.target/i386/pr93656.c new file mode 100644 index 00000000000..f0ac8c8edaa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr93656.c @@ -0,0 +1,4 @@ +/* { dg-do run { target { ia32 && cet } } } */ +/* { dg-options "-O2 -fcf-protection" } */ + +#include "pr67770.c" -- 2.24.1