'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 7f4f2bf1688c81496107993080e68a29a24de702 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 15 Nov 2017 11:20:31 -0800 Subject: [PATCH 06/17] Add -mindirect-branch=thunk-inline Add -mindirect-branch=thunk-inline tests --- gcc/config/i386/i386-opts.h | 3 +- gcc/config/i386/i386.c | 30 +++++++++++----- gcc/config/i386/i386.opt | 3 ++ .../gcc.target/i386/indirect-thunk-inline-1.c | 18 ++++++++++ .../gcc.target/i386/indirect-thunk-inline-2.c | 18 ++++++++++ .../gcc.target/i386/indirect-thunk-inline-3.c | 19 ++++++++++ .../gcc.target/i386/indirect-thunk-inline-4.c | 19 ++++++++++ .../gcc.target/i386/indirect-thunk-inline-5.c | 15 ++++++++ .../gcc.target/i386/indirect-thunk-inline-6.c | 16 +++++++++ .../gcc.target/i386/indirect-thunk-inline-7.c | 42 ++++++++++++++++++++++ 10 files changed, 173 insertions(+), 10 deletions(-) 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 diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h index 1565d8fdc65..f301890575a 100644 --- a/gcc/config/i386/i386-opts.h +++ b/gcc/config/i386/i386-opts.h @@ -101,7 +101,8 @@ enum stack_protector_guard { enum indirect_branch { indirect_branch_keep, - indirect_branch_thunk + indirect_branch_thunk, + indirect_branch_thunk_inline }; #endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 96424361a1c..ac542f79846 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -28600,16 +28600,23 @@ static void ix86_output_indirect_branch (rtx call_op, const char *xasm, bool sibcall_p) { - char thunk_name[32]; + char thunk_name_buf[32]; + char *thunk_name; char push_buf[64]; bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn); - bool need_thunk = ix86_indirect_branch == indirect_branch_thunk; - if (need_bnd_p) - indirect_thunk_bnd_needed |= need_thunk; + if (ix86_indirect_branch != indirect_branch_thunk_inline) + { + bool need_thunk = ix86_indirect_branch == indirect_branch_thunk; + if (need_bnd_p) + indirect_thunk_bnd_needed |= need_thunk; + else + indirect_thunk_needed |= need_thunk; + indirect_thunk_name (thunk_name_buf, need_bnd_p); + thunk_name = thunk_name_buf; + } else - indirect_thunk_needed |= need_thunk; - indirect_thunk_name (thunk_name, need_bnd_p); + thunk_name = NULL; snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s", TARGET_64BIT ? 'q' : 'l', xasm); @@ -28683,10 +28690,15 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm, output_asm_insn (push_buf, &call_op); - if (need_bnd_p) - fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); + if (thunk_name != NULL) + { + if (need_bnd_p) + fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); + else + fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); + } else - fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); + output_indirect_thunk (need_bnd_p); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2); diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 1773e5614cf..68484a75022 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -941,3 +941,6 @@ Enum(indirect_branch) String(keep) Value(indirect_branch_keep) EnumValue Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk) + +EnumValue +Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline) diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c new file mode 100644 index 00000000000..071e6c89ac7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +void +male_indirect_jump (long offset) +{ + dispatch(offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c new file mode 100644 index 00000000000..804c7ccdba7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch[256]; + +void +male_indirect_jump (long offset) +{ + dispatch[offset](offset); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c new file mode 100644 index 00000000000..545a981add5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch; + +int +male_indirect_jump (long offset) +{ + dispatch(offset); + return 0; +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */ +/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c new file mode 100644 index 00000000000..d9ff4722cff --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */ + +typedef void (*dispatch_t)(long offset); + +dispatch_t dispatch[256]; + +int +male_indirect_jump (long offset) +{ + dispatch[offset](offset); + return 0; +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */ +/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c new file mode 100644 index 00000000000..f4890fe97b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */ + +extern void bar (void); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c new file mode 100644 index 00000000000..81b09e73ab8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */ + +extern void bar (void); + +int +foo (void) +{ + bar (); + return 0; +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */ +/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c new file mode 100644 index 00000000000..a0ce06b8232 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */ + +void func0 (void); +void func1 (void); +void func2 (void); +void func3 (void); +void func4 (void); +void func4 (void); +void func5 (void); + +void +bar (int i) +{ + switch (i) + { + default: + func0 (); + break; + case 1: + func1 (); + break; + case 2: + func2 (); + break; + case 3: + func3 (); + break; + case 4: + func4 (); + break; + case 5: + func5 (); + break; + } +} + +/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */ +/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ +/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */ -- 2.15.1