From c6b72be421ded17e0c156070ba6e90aa6c335ed6 Mon Sep 17 00:00:00 2001 From: hjl Date: Tue, 16 Jan 2018 10:59:42 +0000 Subject: [PATCH 5/9] x86: Add -mindirect-branch= (documentation) Add -mindirect-branch= option to convert indirect call and jump to call and return thunks. The default is 'keep', which keeps indirect call and jump unmodified. 'thunk' converts indirect call and jump to call and return thunk. 'thunk-inline' converts indirect call and jump to inlined call and return thunk. 'thunk-extern' converts indirect call and jump to external call and return thunk provided in a separate object file. You can control this behavior for a specific function by using the function attribute indirect_branch. 2 kinds of thunks are geneated. Memory thunk where the function address is at the top of the stack: __x86_indirect_thunk: call L2 L1: pause lfence jmp L1 L2: lea 8(%rsp), %rsp|lea 4(%esp), %esp ret Indirect jmp via memory, "jmp mem", is converted to push memory jmp __x86_indirect_thunk Indirect call via memory, "call mem", is converted to jmp L2 L1: push [mem] jmp __x86_indirect_thunk L2: call L1 Register thunk where the function address is in a register, reg: __x86_indirect_thunk_reg: call L2 L1: pause lfence jmp L1 L2: movq %reg, (%rsp)|movl %reg, (%esp) ret where reg is one of (r|e)ax, (r|e)dx, (r|e)cx, (r|e)bx, (r|e)si, (r|e)di, (r|e)bp, r8, r9, r10, r11, r12, r13, r14 and r15. Indirect jmp via register, "jmp reg", is converted to jmp __x86_indirect_thunk_reg Indirect call via register, "call reg", is converted to call __x86_indirect_thunk_reg gcc/ Backport from mainline * config/i386/i386-opts.h (indirect_branch): New. * config/i386/i386-protos.h (ix86_output_indirect_jmp): Likewise. * config/i386/i386.c (ix86_using_red_zone): Disallow red-zone with local indirect jump when converting indirect call and jump. (ix86_set_indirect_branch_type): New. (ix86_set_current_function): Call ix86_set_indirect_branch_type. (indirectlabelno): New. (indirect_thunk_needed): Likewise. (indirect_thunk_bnd_needed): Likewise. (indirect_thunks_used): Likewise. (indirect_thunks_bnd_used): Likewise. (INDIRECT_LABEL): Likewise. (indirect_thunk_name): Likewise. (output_indirect_thunk): Likewise. (output_indirect_thunk_function): Likewise. (ix86_output_indirect_branch_via_reg): Likewise. (ix86_output_indirect_branch_via_push): Likewise. (ix86_output_indirect_branch): Likewise. (ix86_output_indirect_jmp): Likewise. (ix86_code_end): Call output_indirect_thunk_function if needed. (ix86_output_call_insn): Call ix86_output_indirect_branch if needed. (ix86_handle_fndecl_attribute): Handle indirect_branch. (ix86_attribute_table): Add indirect_branch. * config/i386/i386.h (machine_function): Add indirect_branch_type and has_local_indirect_jump. * config/i386/i386.md (indirect_jump): Set has_local_indirect_jump to true. (tablejump): Likewise. (*indirect_jump): Use ix86_output_indirect_jmp. (*tablejump_1): Likewise. (simple_return_indirect_internal): Likewise. * config/i386/i386.opt (mindirect-branch=): New option. (indirect_branch): New. (keep): Likewise. (thunk): Likewise. (thunk-inline): Likewise. (thunk-extern): Likewise. * doc/extend.texi: Document indirect_branch function attribute. * doc/invoke.texi: Document -mindirect-branch= option. gcc/testsuite/ Backport from mainline * gcc.target/i386/indirect-thunk-1.c: New test. * gcc.target/i386/indirect-thunk-2.c: Likewise. * gcc.target/i386/indirect-thunk-3.c: Likewise. * gcc.target/i386/indirect-thunk-4.c: Likewise. * gcc.target/i386/indirect-thunk-5.c: Likewise. * gcc.target/i386/indirect-thunk-6.c: Likewise. * gcc.target/i386/indirect-thunk-7.c: Likewise. * gcc.target/i386/indirect-thunk-attr-1.c: Likewise. * gcc.target/i386/indirect-thunk-attr-2.c: Likewise. * gcc.target/i386/indirect-thunk-attr-3.c: Likewise. * gcc.target/i386/indirect-thunk-attr-4.c: Likewise. * gcc.target/i386/indirect-thunk-attr-5.c: Likewise. * gcc.target/i386/indirect-thunk-attr-6.c: Likewise. * gcc.target/i386/indirect-thunk-attr-7.c: Likewise. * gcc.target/i386/indirect-thunk-attr-8.c: Likewise. * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise. * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise. * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise. * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise. * gcc.target/i386/indirect-thunk-extern-1.c: Likewise. * gcc.target/i386/indirect-thunk-extern-2.c: Likewise. * gcc.target/i386/indirect-thunk-extern-3.c: Likewise. * gcc.target/i386/indirect-thunk-extern-4.c: Likewise. * gcc.target/i386/indirect-thunk-extern-5.c: Likewise. * gcc.target/i386/indirect-thunk-extern-6.c: Likewise. * gcc.target/i386/indirect-thunk-extern-7.c: Likewise. * gcc.target/i386/indirect-thunk-inline-1.c: Likewise. * gcc.target/i386/indirect-thunk-inline-2.c: Likewise. * gcc.target/i386/indirect-thunk-inline-3.c: Likewise. * gcc.target/i386/indirect-thunk-inline-4.c: Likewise. * gcc.target/i386/indirect-thunk-inline-5.c: Likewise. * gcc.target/i386/indirect-thunk-inline-6.c: Likewise. * gcc.target/i386/indirect-thunk-inline-7.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@256732 138bc75d-0d04-0410-961f-82ee72b054a4 [UBUNTU NOTES: Updated for gcc-5.4 to include defines for FIRST_INT_REG, LAST_INT_REG, and LEGACY_INT_REGNO_P as defined in https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=222269. Dropped indirect-thunk-5.c, indirect-thunk-6.c, indirect-thunk-bnd-3.c, indirect-thunk-bnd-4.c, indirect-thunk-extern-5.c, indirect-thunk-extern-6.c, indirect-thunk-inline-5.c, and indirect-thunk-inline-6.c tests due to gcc 5.4 and earlier not supporting the -fno-plt option. --sbeattie, tyhicks] --- src/gcc/config/i386/i386-opts.h | 13 src/gcc/config/i386/i386-protos.h | 1 src/gcc/config/i386/i386.c | 621 +++++++++++- src/gcc/config/i386/i386.h | 12 src/gcc/config/i386/i386.md | 26 src/gcc/config/i386/i386.opt | 20 src/gcc/doc/extend.texi | 10 src/gcc/doc/invoke.texi | 14 src/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 44 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 23 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 23 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 22 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 22 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 44 src/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c | 42 src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 19 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 19 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 43 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 20 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 21 src/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 44 33 files changed, 1334 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-3.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-4.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-7.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c Index: b/src/gcc/doc/extend.texi =================================================================== --- a/src/gcc/doc/extend.texi +++ b/src/gcc/doc/extend.texi @@ -4119,6 +4119,16 @@ Specify which floating-point unit to use @code{target("fpmath=sse,387")} option must be specified as @code{target("fpmath=sse+387")} because the comma would separate different options. + +@item indirect_branch("@var{choice}") +@cindex @code{indirect_branch} function attribute, x86 +On x86 targets, the @code{indirect_branch} attribute causes the compiler +to convert indirect call and jump with @var{choice}. @samp{keep} +keeps indirect call and jump unmodified. @samp{thunk} converts indirect +call and jump to call and return thunk. @samp{thunk-inline} converts +indirect call and jump to inlined call and return thunk. +@samp{thunk-extern} converts indirect call and jump to external call +and return thunk provided in a separate object file. @end table On the PowerPC, the following options are allowed: Index: b/src/gcc/doc/invoke.texi =================================================================== --- a/src/gcc/doc/invoke.texi +++ b/src/gcc/doc/invoke.texi @@ -1090,7 +1090,8 @@ See RS/6000 and PowerPC Options. -m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol --malign-data=@var{type} -mstack-protector-guard=@var{guard}} +-malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol +-mindirect-branch=@var{choice}} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -24017,6 +24018,17 @@ The default value of this option is enab of the option is @option{-fno-sync-libcalls}. This option is used in the implementation of the @file{libatomic} runtime library. +@item -mindirect-branch=@var{choice} +@opindex -mindirect-branch +Convert indirect call and jump with @var{choice}. The default is +@samp{keep}, which keeps indirect call and jump unmodified. +@samp{thunk} converts indirect call and jump to call and return thunk. +@samp{thunk-inline} converts indirect call and jump to inlined call +and return thunk. @samp{thunk-extern} converts indirect call and jump +to external call and return thunk provided in a separate object file. +You can control this behavior for a specific function by using the +function attribute @code{indirect_branch}. @xref{Function Attributes}. + @end table @c man end