1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #include "gcc-common.h"
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun __visible int plugin_is_GPL_compatible;
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun static unsigned int sp_mask, canary_offset;
8*4882a593Smuzhiyun
arm_pertask_ssp_rtl_execute(void)9*4882a593Smuzhiyun static unsigned int arm_pertask_ssp_rtl_execute(void)
10*4882a593Smuzhiyun {
11*4882a593Smuzhiyun rtx_insn *insn;
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
14*4882a593Smuzhiyun const char *sym;
15*4882a593Smuzhiyun rtx body;
16*4882a593Smuzhiyun rtx mask, masked_sp;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /*
19*4882a593Smuzhiyun * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
20*4882a593Smuzhiyun */
21*4882a593Smuzhiyun if (!INSN_P(insn))
22*4882a593Smuzhiyun continue;
23*4882a593Smuzhiyun body = PATTERN(insn);
24*4882a593Smuzhiyun if (GET_CODE(body) != SET ||
25*4882a593Smuzhiyun GET_CODE(SET_SRC(body)) != SYMBOL_REF)
26*4882a593Smuzhiyun continue;
27*4882a593Smuzhiyun sym = XSTR(SET_SRC(body), 0);
28*4882a593Smuzhiyun if (strcmp(sym, "__stack_chk_guard"))
29*4882a593Smuzhiyun continue;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun * Replace the source of the SET insn with an expression that
33*4882a593Smuzhiyun * produces the address of the copy of the stack canary value
34*4882a593Smuzhiyun * stored in struct thread_info
35*4882a593Smuzhiyun */
36*4882a593Smuzhiyun mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
37*4882a593Smuzhiyun masked_sp = gen_reg_rtx(Pmode);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun emit_insn_before(gen_rtx_set(masked_sp,
40*4882a593Smuzhiyun gen_rtx_AND(Pmode,
41*4882a593Smuzhiyun stack_pointer_rtx,
42*4882a593Smuzhiyun mask)),
43*4882a593Smuzhiyun insn);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
46*4882a593Smuzhiyun GEN_INT(canary_offset));
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun return 0;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define PASS_NAME arm_pertask_ssp_rtl
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define NO_GATE
54*4882a593Smuzhiyun #include "gcc-generate-rtl-pass.h"
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #if BUILDING_GCC_VERSION >= 9000
no(void)57*4882a593Smuzhiyun static bool no(void)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun return false;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
arm_pertask_ssp_start_unit(void * gcc_data,void * user_data)62*4882a593Smuzhiyun static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun targetm.have_stack_protect_combined_set = no;
65*4882a593Smuzhiyun targetm.have_stack_protect_combined_test = no;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun
plugin_init(struct plugin_name_args * plugin_info,struct plugin_gcc_version * version)69*4882a593Smuzhiyun __visible int plugin_init(struct plugin_name_args *plugin_info,
70*4882a593Smuzhiyun struct plugin_gcc_version *version)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun const char * const plugin_name = plugin_info->base_name;
73*4882a593Smuzhiyun const int argc = plugin_info->argc;
74*4882a593Smuzhiyun const struct plugin_argument *argv = plugin_info->argv;
75*4882a593Smuzhiyun int tso = 0;
76*4882a593Smuzhiyun int i;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if (!plugin_default_version_check(version, &gcc_version)) {
79*4882a593Smuzhiyun error(G_("incompatible gcc/plugin versions"));
80*4882a593Smuzhiyun return 1;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun for (i = 0; i < argc; ++i) {
84*4882a593Smuzhiyun if (!strcmp(argv[i].key, "disable"))
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* all remaining options require a value */
88*4882a593Smuzhiyun if (!argv[i].value) {
89*4882a593Smuzhiyun error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
90*4882a593Smuzhiyun plugin_name, argv[i].key);
91*4882a593Smuzhiyun return 1;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (!strcmp(argv[i].key, "tso")) {
95*4882a593Smuzhiyun tso = atoi(argv[i].value);
96*4882a593Smuzhiyun continue;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (!strcmp(argv[i].key, "offset")) {
100*4882a593Smuzhiyun canary_offset = atoi(argv[i].value);
101*4882a593Smuzhiyun continue;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun error(G_("unknown option '-fplugin-arg-%s-%s'"),
104*4882a593Smuzhiyun plugin_name, argv[i].key);
105*4882a593Smuzhiyun return 1;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* create the mask that produces the base of the stack */
109*4882a593Smuzhiyun sp_mask = ~((1U << (12 + tso)) - 1);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
114*4882a593Smuzhiyun NULL, &arm_pertask_ssp_rtl_pass_info);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun #if BUILDING_GCC_VERSION >= 9000
117*4882a593Smuzhiyun register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
118*4882a593Smuzhiyun arm_pertask_ssp_start_unit, NULL);
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun return 0;
122*4882a593Smuzhiyun }
123