1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
| | 'Retpoline' mitigation technique for Spectre (branch target injection)
[CVE-2017-5715]:
https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
https://support.google.com/faqs/answer/7625886
https://spectreattack.com/
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
Patch copied from the 'retpoline-20180107' branch of upstream source repository
(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
appears):
http://git.infradead.org/users/dwmw2/gcc-retpoline.git
From f96e28553b0f2253184441f22852d76976e19968 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 12 Dec 2017 19:15:25 -0800
Subject: [PATCH 15/17] Disable red zone with local indirect jump
---
gcc/config/i386/i386-protos.h | 2 +-
gcc/config/i386/i386.c | 22 +++++++++++++++++-----
gcc/config/i386/i386.h | 4 ++++
gcc/config/i386/i386.md | 8 +++++---
4 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 213663811de..a78bfa00427 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -315,7 +315,7 @@ extern enum attr_cpu ix86_schedule;
#endif
extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
-extern const char * ix86_output_indirect_jmp (rtx call_op);
+extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
extern const char * ix86_output_function_return (bool long_p);
extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
enum machine_mode mode);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7ae3523095c..344cafe3dac 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4209,12 +4209,19 @@ make_pass_stv (gcc::context *ctxt)
return new pass_stv (ctxt);
}
-/* Return true if a red-zone is in use. */
+/* Return true if a red-zone is in use. We can't use red-zone when
+ there are local indirect jumps, like "indirect_jump" or "tablejump",
+ which jumps to another place in the function, since "call" in the
+ indirect thunk pushes the return address onto stack, destroying
+ red-zone. */
bool
ix86_using_red_zone (void)
{
- return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
+ return (TARGET_RED_ZONE
+ && !TARGET_64BIT_MS_ABI
+ && (!cfun->machine->has_local_indirect_jump
+ || cfun->machine->indirect_branch_type == indirect_branch_keep));
}
\f
/* Return a string that documents the current -m options. The caller is
@@ -28919,11 +28926,16 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
}
const char *
-ix86_output_indirect_jmp (rtx call_op)
+ix86_output_indirect_jmp (rtx call_op, bool ret_p)
{
- if (ix86_red_zone_size == 0
- && cfun->machine->indirect_branch_type != indirect_branch_keep)
+ if (cfun->machine->indirect_branch_type != indirect_branch_keep)
{
+ /* We can't have red-zone if this isn't a function return since
+ "call" in the indirect thunk pushes the return address onto
+ stack, destroying red-zone. */
+ if (!ret_p && ix86_red_zone_size != 0)
+ gcc_unreachable ();
+
ix86_output_indirect_branch (call_op, "%0", true);
return "";
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index f248f3ba2f5..5f30d3f8d19 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2607,6 +2607,10 @@ struct GTY(()) machine_function {
/* How to generate indirec branch. */
ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
+ /* If true, the current function has local indirect jumps, like
+ "indirect_jump" or "tablejump". */
+ BOOL_BITFIELD has_local_indirect_jump : 1;
+
/* How to generate function return. */
ENUM_BITFIELD(indirect_branch) function_return_type : 3;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 473fa5c089b..ea95aad7540 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11610,12 +11610,13 @@
{
if (TARGET_X32 || ix86_indirect_branch_thunk_register)
operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
})
(define_insn "*indirect_jump"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
""
- "* return ix86_output_indirect_jmp (operands[0]);"
+ "* return ix86_output_indirect_jmp (operands[0], false);"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
@@ -11659,13 +11660,14 @@
if (TARGET_X32 || ix86_indirect_branch_thunk_register)
operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
})
(define_insn "*tablejump_1"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
(use (label_ref (match_operand 1)))]
""
- "* return ix86_output_indirect_jmp (operands[0]);"
+ "* return ix86_output_indirect_jmp (operands[0], false);"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
@@ -12342,7 +12344,7 @@
[(simple_return)
(use (match_operand:SI 0 "register_operand" "r"))]
"reload_completed"
- "* return ix86_output_indirect_jmp (operands[0]);"
+ "* return ix86_output_indirect_jmp (operands[0], true);"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")
(set_attr "maybe_prefix_bnd" "1")])
--
2.15.1
|