From: H.J. Lu Date: Thu, 22 Feb 2018 17:09:06 +0000 (+0000) Subject: i386: Add __x86_indirect_thunk_nt_reg for -fcf-protection -mcet X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=73b8b82295fb286c2d5b01c200fcd6732a96c2a8;p=gcc.git i386: Add __x86_indirect_thunk_nt_reg for -fcf-protection -mcet nocf_check attribute can be used with -fcf-protection -mcet to disable control-flow check by adding NOTRACK prefix before indirect branch. When -mindirect-branch=thunk-extern -mindirect-branch-register is added, indirect branch via register, "notrack call/jmp reg", is converted to call/jmp __x86_indirect_thunk_nt_reg When running on machines with CET enabled, __x86_indirect_thunk_nt_reg can be updated to notrack jmp reg at run-time to restore NOTRACK prefix in the original indirect branch. Since we don't support -mindirect-branch=thunk-extern, CET and MPX at the same time, -mindirect-branch=thunk-extern is disallowed with -fcf-protection=branch and -fcheck-pointer-bounds. Tested on i686 and x86-64. gcc/ PR target/84176 * config/i386/i386.c (ix86_set_indirect_branch_type): Issue an error when -mindirect-branch=thunk-extern, -fcf-protection=branch and -fcheck-pointer-bounds are used together. (indirect_thunk_prefix): New enum. (indirect_thunk_need_prefix): New function. (indirect_thunk_name): Replace need_bnd_p with need_prefix. Use "_nt" instead of "_bnd" for NOTRACK prefix. (output_indirect_thunk): Replace need_bnd_p with need_prefix. (output_indirect_thunk_function): Likewise. (): Likewise. (ix86_code_end): Update output_indirect_thunk_function calls. (ix86_output_indirect_branch_via_reg): Replace ix86_bnd_prefixed_insn_p with indirect_thunk_need_prefix. (ix86_output_indirect_branch_via_push): Likewise. (ix86_output_function_return): Likewise. * doc/invoke.texi: Document -mindirect-branch=thunk-extern is incompatible with -fcf-protection=branch and -fcheck-pointer-bounds. gcc/testsuite/ PR target/84176 * gcc.target/i386/indirect-thunk-11.c: New test. * gcc.target/i386/indirect-thunk-12.c: Likewise. * gcc.target/i386/indirect-thunk-attr-12.c: Likewise. * gcc.target/i386/indirect-thunk-attr-13.c: Likewise. * gcc.target/i386/indirect-thunk-attr-14.c: Likewise. * gcc.target/i386/indirect-thunk-attr-15.c: Likewise. * gcc.target/i386/indirect-thunk-attr-16.c: Likewise. * gcc.target/i386/indirect-thunk-extern-10.c: Likewise. * gcc.target/i386/indirect-thunk-extern-8.c: Likewise. * gcc.target/i386/indirect-thunk-extern-9.c: Likewise. From-SVN: r257909 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac6ab859a54..1868bb6d83f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2018-02-22 H.J. Lu + + PR target/84176 + * config/i386/i386.c (ix86_set_indirect_branch_type): Issue an + error when -mindirect-branch=thunk-extern, -fcf-protection=branch + and -fcheck-pointer-bounds are used together. + (indirect_thunk_prefix): New enum. + (indirect_thunk_need_prefix): New function. + (indirect_thunk_name): Replace need_bnd_p with need_prefix. Use + "_nt" instead of "_bnd" for NOTRACK prefix. + (output_indirect_thunk): Replace need_bnd_p with need_prefix. + (output_indirect_thunk_function): Likewise. + (): Likewise. + (ix86_code_end): Update output_indirect_thunk_function calls. + (ix86_output_indirect_branch_via_reg): Replace + ix86_bnd_prefixed_insn_p with indirect_thunk_need_prefix. + (ix86_output_indirect_branch_via_push): Likewise. + (ix86_output_function_return): Likewise. + * doc/invoke.texi: Document -mindirect-branch=thunk-extern is + incompatible with -fcf-protection=branch and + -fcheck-pointer-bounds. + 2018-02-22 Steve Ellcey PR target/83335 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 18d9084fd30..640c5921863 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5898,6 +5898,16 @@ ix86_set_indirect_branch_type (tree fndecl) ((cfun->machine->indirect_branch_type == indirect_branch_thunk_extern) ? "thunk-extern" : "thunk")); + + /* -mindirect-branch=thunk-extern, -fcf-protection=branch and + -fcheck-pointer-bounds are not compatible. */ + if ((cfun->machine->indirect_branch_type + == indirect_branch_thunk_extern) + && flag_check_pointer_bounds + && (flag_cf_protection & CF_BRANCH) != 0) + error ("%<-mindirect-branch=thunk-extern%>, " + "%<-fcf-protection=branch%> and " + "%<-fcheck-pointer-bounds%> are not compatible"); } if (cfun->machine->function_return_type == indirect_branch_unset) @@ -10806,18 +10816,62 @@ static int indirect_thunks_bnd_used; # define INDIRECT_LABEL "LIND" #endif +/* Indicate what prefix is needed for an indirect branch. */ +enum indirect_thunk_prefix +{ + indirect_thunk_prefix_none, + indirect_thunk_prefix_bnd, + indirect_thunk_prefix_nt +}; + +/* Return the prefix needed for an indirect branch INSN. */ + +enum indirect_thunk_prefix +indirect_thunk_need_prefix (rtx_insn *insn) +{ + enum indirect_thunk_prefix need_prefix; + if (ix86_bnd_prefixed_insn_p (insn)) + need_prefix = indirect_thunk_prefix_bnd; + else if ((cfun->machine->indirect_branch_type + == indirect_branch_thunk_extern) + && ix86_notrack_prefixed_insn_p (insn)) + { + /* NOTRACK prefix is only used with external thunk so that it + can be properly updated to support CET at run-time. */ + need_prefix = indirect_thunk_prefix_nt; + } + else + need_prefix = indirect_thunk_prefix_none; + return need_prefix; +} + /* Fills in the label name that should be used for the indirect thunk. */ static void indirect_thunk_name (char name[32], unsigned int regno, - bool need_bnd_p, bool ret_p) + enum indirect_thunk_prefix need_prefix, + bool ret_p) { if (regno != INVALID_REGNUM && ret_p) gcc_unreachable (); if (USE_HIDDEN_LINKONCE) { - const char *bnd = need_bnd_p ? "_bnd" : ""; + const char *prefix; + + if (need_prefix == indirect_thunk_prefix_bnd) + prefix = "_bnd"; + else if (need_prefix == indirect_thunk_prefix_nt + && regno != INVALID_REGNUM) + { + /* NOTRACK prefix is only used with external thunk via + register so that NOTRACK prefix can be added to indirect + branch via register to support CET at run-time. */ + prefix = "_nt"; + } + else + prefix = ""; + if (regno != INVALID_REGNUM) { const char *reg_prefix; @@ -10826,19 +10880,19 @@ indirect_thunk_name (char name[32], unsigned int regno, else reg_prefix = ""; sprintf (name, "__x86_indirect_thunk%s_%s%s", - bnd, reg_prefix, reg_names[regno]); + prefix, reg_prefix, reg_names[regno]); } else { const char *ret = ret_p ? "return" : "indirect"; - sprintf (name, "__x86_%s_thunk%s", ret, bnd); + sprintf (name, "__x86_%s_thunk%s", ret, prefix); } } else { if (regno != INVALID_REGNUM) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno); else ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno); @@ -10847,14 +10901,14 @@ indirect_thunk_name (char name[32], unsigned int regno, { if (ret_p) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0); else ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0); } else { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0); else ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0); @@ -10890,7 +10944,8 @@ indirect_thunk_name (char name[32], unsigned int regno, */ static void -output_indirect_thunk (bool need_bnd_p, unsigned int regno) +output_indirect_thunk (enum indirect_thunk_prefix need_prefix, + unsigned int regno) { char indirectlabel1[32]; char indirectlabel2[32]; @@ -10901,7 +10956,7 @@ output_indirect_thunk (bool need_bnd_p, unsigned int regno) indirectlabelno++); /* Call */ - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd call\t", asm_out_file); else fputs ("\tcall\t", asm_out_file); @@ -10938,7 +10993,7 @@ output_indirect_thunk (bool need_bnd_p, unsigned int regno) output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops); } - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd ret\n", asm_out_file); else fputs ("\tret\n", asm_out_file); @@ -10950,13 +11005,14 @@ output_indirect_thunk (bool need_bnd_p, unsigned int regno) on the top of stack. */ static void -output_indirect_thunk_function (bool need_bnd_p, unsigned int regno) +output_indirect_thunk_function (enum indirect_thunk_prefix need_prefix, + unsigned int regno) { char name[32]; tree decl; /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */ - indirect_thunk_name (name, regno, need_bnd_p, false); + indirect_thunk_name (name, regno, need_prefix, false); decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, get_identifier (name), build_function_type_list (void_type_node, NULL_TREE)); @@ -11004,7 +11060,7 @@ output_indirect_thunk_function (bool need_bnd_p, unsigned int regno) /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */ char alias[32]; - indirect_thunk_name (alias, regno, need_bnd_p, true); + indirect_thunk_name (alias, regno, need_prefix, true); #if TARGET_MACHO if (TARGET_MACHO) { @@ -11040,7 +11096,7 @@ output_indirect_thunk_function (bool need_bnd_p, unsigned int regno) /* Make sure unwind info is emitted for the thunk if needed. */ final_start_function (emit_barrier (), asm_out_file, 1); - output_indirect_thunk (need_bnd_p, regno); + output_indirect_thunk (need_prefix, regno); final_end_function (); init_insn_lengths (); @@ -11076,18 +11132,22 @@ ix86_code_end (void) unsigned int regno; if (indirect_thunk_needed) - output_indirect_thunk_function (false, INVALID_REGNUM); + output_indirect_thunk_function (indirect_thunk_prefix_none, + INVALID_REGNUM); if (indirect_thunk_bnd_needed) - output_indirect_thunk_function (true, INVALID_REGNUM); + output_indirect_thunk_function (indirect_thunk_prefix_bnd, + INVALID_REGNUM); for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++) { unsigned int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1; if ((indirect_thunks_used & (1 << i))) - output_indirect_thunk_function (false, regno); + output_indirect_thunk_function (indirect_thunk_prefix_none, + regno); if ((indirect_thunks_bnd_used & (1 << i))) - output_indirect_thunk_function (true, regno); + output_indirect_thunk_function (indirect_thunk_prefix_bnd, + regno); } for (regno = FIRST_INT_REG; regno <= LAST_INT_REG; regno++) @@ -11096,10 +11156,12 @@ ix86_code_end (void) tree decl; if ((indirect_thunks_used & (1 << regno))) - output_indirect_thunk_function (false, regno); + output_indirect_thunk_function (indirect_thunk_prefix_none, + regno); if ((indirect_thunks_bnd_used & (1 << regno))) - output_indirect_thunk_function (true, regno); + output_indirect_thunk_function (indirect_thunk_prefix_bnd, + regno); if (!(pic_labels_used & (1 << regno))) continue; @@ -28676,7 +28738,8 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) { char thunk_name_buf[32]; char *thunk_name; - bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn); + enum indirect_thunk_prefix need_prefix + = indirect_thunk_need_prefix (current_output_insn); int regno = REGNO (call_op); if (cfun->machine->indirect_branch_type @@ -28687,12 +28750,12 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) int i = regno; if (i >= FIRST_REX_INT_REG) i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1); - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) indirect_thunks_bnd_used |= 1 << i; else indirect_thunks_used |= 1 << i; } - indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false); + indirect_thunk_name (thunk_name_buf, regno, need_prefix, false); thunk_name = thunk_name_buf; } else @@ -28702,19 +28765,19 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) { if (thunk_name != NULL) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); else fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); } else - output_indirect_thunk (need_bnd_p, regno); + output_indirect_thunk (need_prefix, regno); } else { if (thunk_name != NULL) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name); else fprintf (asm_out_file, "\tcall\t%s\n", thunk_name); @@ -28732,7 +28795,7 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) indirectlabelno++); /* Jump. */ - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd jmp\t", asm_out_file); else fputs ("\tjmp\t", asm_out_file); @@ -28743,18 +28806,18 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) if (thunk_name != NULL) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); else fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); } else - output_indirect_thunk (need_bnd_p, regno); + output_indirect_thunk (need_prefix, regno); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2); /* Call. */ - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd call\t", asm_out_file); else fputs ("\tcall\t", asm_out_file); @@ -28788,7 +28851,8 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm, char thunk_name_buf[32]; char *thunk_name; char push_buf[64]; - bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn); + enum indirect_thunk_prefix need_prefix + = indirect_thunk_need_prefix (current_output_insn); int regno = -1; if (cfun->machine->indirect_branch_type @@ -28796,12 +28860,12 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm, { if (cfun->machine->indirect_branch_type == indirect_branch_thunk) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) indirect_thunk_bnd_needed = true; else indirect_thunk_needed = true; } - indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false); + indirect_thunk_name (thunk_name_buf, regno, need_prefix, false); thunk_name = thunk_name_buf; } else @@ -28815,13 +28879,13 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm, output_asm_insn (push_buf, &call_op); if (thunk_name != NULL) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); else fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); } else - output_indirect_thunk (need_bnd_p, regno); + output_indirect_thunk (need_prefix, regno); } else { @@ -28836,7 +28900,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm, indirectlabelno++); /* Jump. */ - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd jmp\t", asm_out_file); else fputs ("\tjmp\t", asm_out_file); @@ -28882,18 +28946,18 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm, if (thunk_name != NULL) { - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); else fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); } else - output_indirect_thunk (need_bnd_p, regno); + output_indirect_thunk (need_prefix, regno); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2); /* Call. */ - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) fputs ("\tbnd call\t", asm_out_file); else fputs ("\tcall\t", asm_out_file); @@ -28945,16 +29009,17 @@ ix86_output_function_return (bool long_p) if (cfun->machine->function_return_type != indirect_branch_keep) { char thunk_name[32]; - bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn); + enum indirect_thunk_prefix need_prefix + = indirect_thunk_need_prefix (current_output_insn); if (cfun->machine->function_return_type != indirect_branch_thunk_inline) { bool need_thunk = (cfun->machine->function_return_type == indirect_branch_thunk); - indirect_thunk_name (thunk_name, INVALID_REGNUM, need_bnd_p, + indirect_thunk_name (thunk_name, INVALID_REGNUM, need_prefix, true); - if (need_bnd_p) + if (need_prefix == indirect_thunk_prefix_bnd) { indirect_thunk_bnd_needed |= need_thunk; fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); @@ -28966,7 +29031,7 @@ ix86_output_function_return (bool long_p) } } else - output_indirect_thunk (need_bnd_p, INVALID_REGNUM); + output_indirect_thunk (need_prefix, INVALID_REGNUM); return ""; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 973d77d47bf..e70e2bad4d8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -27837,6 +27837,11 @@ Note that @option{-mcmodel=large} is incompatible with @option{-mindirect-branch=thunk-extern} since the thunk function may not be reachable in large code model. +Note that @option{-mindirect-branch=thunk-extern} is incompatible with +@option{-fcf-protection=branch} and @option{-fcheck-pointer-bounds} +since the external thunk can not be modified to disable control-flow +check. + @item -mfunction-return=@var{choice} @opindex -mfunction-return Convert function return with @var{choice}. The default is @samp{keep}, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 71adf91e09f..d85d8a52dd6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2018-02-22 H.J. Lu + + PR target/84176 + * gcc.target/i386/indirect-thunk-11.c: New test. + * gcc.target/i386/indirect-thunk-12.c: Likewise. + * gcc.target/i386/indirect-thunk-attr-12.c: Likewise. + * gcc.target/i386/indirect-thunk-attr-13.c: Likewise. + * gcc.target/i386/indirect-thunk-attr-14.c: Likewise. + * gcc.target/i386/indirect-thunk-attr-15.c: Likewise. + * gcc.target/i386/indirect-thunk-attr-16.c: Likewise. + * gcc.target/i386/indirect-thunk-extern-10.c: Likewise. + * gcc.target/i386/indirect-thunk-extern-8.c: Likewise. + * gcc.target/i386/indirect-thunk-extern-9.c: Likewise. + 2018-02-22 Steve Ellcey PR target/83335 diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-11.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-11.c new file mode 100644 index 00000000000..afa89ff227b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-11.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { ! x32 } } } */ +/* { dg-options "-O2 -mindirect-branch=thunk-extern -fcf-protection -mcet -fcheck-pointer-bounds -mmpx" } */ + +void +bar (void) +{ /* { dg-error "'-mindirect-branch=thunk-extern', '-fcf-protection=branch' and '-fcheck-pointer-bounds' are not compatible" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-12.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-12.c new file mode 100644 index 00000000000..d456973ee6d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-12.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { ! x32 } } } */ +/* { dg-options "-O2 -mindirect-branch=thunk -fcf-protection -mcet -fcheck-pointer-bounds -mmpx" } */ + +void +bar (void) +{ +} diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-12.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-12.c new file mode 100644 index 00000000000..24a1a08a3ca --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-12.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { ! x32 } } } */ +/* { dg-options "-O2 -mindirect-branch=keep -fcf-protection -mcet -fcheck-pointer-bounds -mmpx" } */ + +__attribute__ ((indirect_branch("thunk-extern"))) +void +bar (void) +{ /* { dg-error "'-mindirect-branch=thunk-extern', '-fcf-protection=branch' and '-fcheck-pointer-bounds' are not compatible" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-13.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-13.c new file mode 100644 index 00000000000..ff2fccae935 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-13.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target { ! x32 } } } */ +/* { dg-options "-O2 -mindirect-branch=keep -fcf-protection -mcet -fcheck-pointer-bounds -mmpx" } */ + +__attribute__ ((indirect_branch("thunk-inline"))) +void +bar (void) +{ +} diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-14.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-14.c new file mode 100644 index 00000000000..669e56d7726 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-14.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=keep -fcf-protection -mcet" } */ + +extern void (*bar) (void); + +__attribute__ ((indirect_branch("thunk-extern"))) +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */ +/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk_nt" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-15.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-15.c new file mode 100644 index 00000000000..c033fb23879 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-15.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mindirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=keep -fcf-protection -mcet" } */ + +extern void (*bar) (void); + +__attribute__ ((indirect_branch("thunk-extern"))) +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */ +/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk_nt" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-16.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-16.c new file mode 100644 index 00000000000..0244edf53b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-16.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mindirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=keep -fcf-protection -mcet" } */ + +extern void (*bar) (void) __attribute__((nocf_check)); + +__attribute__ ((indirect_branch("thunk-extern"))) +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_nt_(r|e)" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-10.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-10.c new file mode 100644 index 00000000000..2a982ab69f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-10.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mindirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=thunk-extern -fcf-protection -mcet" } */ + +extern void (*bar) (void) __attribute__((nocf_check)); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_nt_(r|e)" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-8.c new file mode 100644 index 00000000000..30d12cc0711 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-8.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=thunk-extern -fcf-protection -mcet" } */ + +extern void (*bar) (void); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */ +/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk_nt" } } */ diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-9.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-9.c new file mode 100644 index 00000000000..d714b0155df --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-9.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mindirect-branch-register -mfunction-return=keep -fno-pic -fplt -mindirect-branch=thunk-extern -fcf-protection -mcet" } */ + +extern void (*bar) (void); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */ +/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk_nt" } } */