Skip to content

Commit a31e654

Browse files
author
hjl
committed
x86: Add -mindirect-branch=
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/ * 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): 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/ * 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/trunk@256660 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 9732f43 commit a31e654

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1571
-19
lines changed

gcc/ChangeLog

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,44 @@
1+
2018-01-14 H.J. Lu <[email protected]>
2+
3+
* config/i386/i386-opts.h (indirect_branch): New.
4+
* config/i386/i386-protos.h (ix86_output_indirect_jmp): Likewise.
5+
* config/i386/i386.c (ix86_using_red_zone): Disallow red-zone
6+
with local indirect jump when converting indirect call and jump.
7+
(ix86_set_indirect_branch_type): New.
8+
(ix86_set_current_function): Call ix86_set_indirect_branch_type.
9+
(indirectlabelno): New.
10+
(indirect_thunk_needed): Likewise.
11+
(indirect_thunk_bnd_needed): Likewise.
12+
(indirect_thunks_used): Likewise.
13+
(indirect_thunks_bnd_used): Likewise.
14+
(INDIRECT_LABEL): Likewise.
15+
(indirect_thunk_name): Likewise.
16+
(output_indirect_thunk): Likewise.
17+
(output_indirect_thunk_function): Likewise.
18+
(ix86_output_indirect_branch): Likewise.
19+
(ix86_output_indirect_jmp): Likewise.
20+
(ix86_code_end): Call output_indirect_thunk_function if needed.
21+
(ix86_output_call_insn): Call ix86_output_indirect_branch if
22+
needed.
23+
(ix86_handle_fndecl_attribute): Handle indirect_branch.
24+
(ix86_attribute_table): Add indirect_branch.
25+
* config/i386/i386.h (machine_function): Add indirect_branch_type
26+
and has_local_indirect_jump.
27+
* config/i386/i386.md (indirect_jump): Set has_local_indirect_jump
28+
to true.
29+
(tablejump): Likewise.
30+
(*indirect_jump): Use ix86_output_indirect_jmp.
31+
(*tablejump_1): Likewise.
32+
(simple_return_indirect_internal): Likewise.
33+
* config/i386/i386.opt (mindirect-branch=): New option.
34+
(indirect_branch): New.
35+
(keep): Likewise.
36+
(thunk): Likewise.
37+
(thunk-inline): Likewise.
38+
(thunk-extern): Likewise.
39+
* doc/extend.texi: Document indirect_branch function attribute.
40+
* doc/invoke.texi: Document -mindirect-branch= option.
41+
142
2018-01-14 Jan Hubicka <[email protected]>
243

344
PR ipa/83051

gcc/config/i386/i386-opts.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,17 @@ enum prefer_vector_width {
106106
PVW_AVX512
107107
};
108108

109+
/* This is used to mitigate variant #2 of the speculative execution
110+
vulnerabilities on x86 processors identified by CVE-2017-5715, aka
111+
Spectre. They convert indirect branches and function returns to
112+
call and return thunks to avoid speculative execution via indirect
113+
call, jmp and ret. */
114+
enum indirect_branch {
115+
indirect_branch_unset = 0,
116+
indirect_branch_keep,
117+
indirect_branch_thunk,
118+
indirect_branch_thunk_inline,
119+
indirect_branch_thunk_extern
120+
};
121+
109122
#endif

gcc/config/i386/i386-protos.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ extern enum attr_cpu ix86_schedule;
305305
#endif
306306

307307
extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
308+
extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
308309
extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
309310
machine_mode mode);
310311
extern int ix86_min_insn_size (rtx_insn *);

0 commit comments

Comments
 (0)