NOTE_INSN_DELETED_LABEL is used to mark what used to be a 'code_label', but was not used for other purposes than taking its address and was transformed to mark that no code jumps to it. NOTE_INSN_DELETED_LABEL is generated only in 3 places:
1. When delete_insn sees an unused label which is an explicit label in the input source code or its address is taken, it turns the label into a NOTE_INSN_DELETED_LABEL note. 2. When rtl_tidy_fallthru_edge deletes a tablejump, it turns the tablejump into a NOTE_INSN_DELETED_LABEL note. 3. ix86_init_large_pic_reg creats a NOTE_INSN_DELETED_LABEL note, .L2, to initialize large model PIC register: L2: movabsq $_GLOBAL_OFFSET_TABLE_-.L2, %r11 leaq .L2(%rip), %rax movabsq $val@GOT, %rdx addq %r11, %rax Among of them, ENDBR is needed only when the label address is taken. rest_of_insert_endbranch has if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn)) || (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)) /* TODO. Check /s bit also. */ { cet_eb = gen_nop_endbr (); emit_insn_after (cet_eb, insn); continue; } For NOTE_INSN_DELETED_LABEL, we should check if forced_labels to see if its address is taken. Also ix86_init_large_pic_reg shouldn't set LABEL_PRESERVE_P (in_struct) since NOTE_INSN_DELETED_LABEL is suffcient to keep the label. gcc/ PR target/89355 * config/i386/i386.c (rest_of_insert_endbranch): Check forced_labels to see if the address of NOTE_INSN_DELETED_LABEL is taken. (ix86_init_large_pic_reg): Don't set LABEL_PRESERVE_P. gcc/testsuite/ PR target/89355 * gcc.target/i386/cet-label-3.c: New test. * gcc.target/i386/cet-label-4.c: Likewise. * gcc.target/i386/cet-label-5.c: Likewise. --- gcc/config/i386/i386.c | 9 +++++--- gcc/testsuite/gcc.target/i386/cet-label-3.c | 23 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/cet-label-4.c | 12 +++++++++++ gcc/testsuite/gcc.target/i386/cet-label-5.c | 13 ++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/cet-label-3.c create mode 100644 gcc/testsuite/gcc.target/i386/cet-label-4.c create mode 100644 gcc/testsuite/gcc.target/i386/cet-label-5.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fd05873ba39..ed53fbea9ae 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2734,10 +2734,14 @@ rest_of_insert_endbranch (void) continue; } + /* NB: Add an ENDBR for NOTE_INSN_DELETED_LABEL only if its + addresss is taken. */ if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn)) || (NOTE_P (insn) - && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)) - /* TODO. Check /s bit also. */ + && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL + && vec_safe_contains<rtx_insn *> + (forced_labels, + static_cast<rtx_code_label *> (insn)))) { cet_eb = gen_nop_endbr (); emit_insn_after (cet_eb, insn); @@ -7002,7 +7006,6 @@ ix86_init_large_pic_reg (unsigned int tmp_regno) gcc_assert (Pmode == DImode); label = gen_label_rtx (); emit_label (label); - LABEL_PRESERVE_P (label) = 1; tmp_reg = gen_rtx_REG (Pmode, tmp_regno); gcc_assert (REGNO (pic_offset_table_rtx) != tmp_regno); emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx, diff --git a/gcc/testsuite/gcc.target/i386/cet-label-3.c b/gcc/testsuite/gcc.target/i386/cet-label-3.c new file mode 100644 index 00000000000..9f427a866f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cet-label-3.c @@ -0,0 +1,23 @@ +/* PR target/89355 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fcf-protection" } */ +/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */ +int +test (int* val) +{ + int status = 99; + + if (!val) + { + status = 22; + goto end; + } + + extern int x; + *val = x; + + status = 0; +end: + return status; +} diff --git a/gcc/testsuite/gcc.target/i386/cet-label-4.c b/gcc/testsuite/gcc.target/i386/cet-label-4.c new file mode 100644 index 00000000000..d743d2bf202 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cet-label-4.c @@ -0,0 +1,12 @@ +/* PR target/89355 */ +/* { dg-do compile { target { fpic && lp64 } } } */ +/* { dg-options "-O2 -fcf-protection -fPIC -mcmodel=large" } */ +/* { dg-final { scan-assembler-times "endbr64" 1 } } */ + +extern int val; + +int +test (void) +{ + return val; +} diff --git a/gcc/testsuite/gcc.target/i386/cet-label-5.c b/gcc/testsuite/gcc.target/i386/cet-label-5.c new file mode 100644 index 00000000000..4d5ca816598 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cet-label-5.c @@ -0,0 +1,13 @@ +/* PR target/89355 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fcf-protection -Wno-return-local-addr" } */ +/* { dg-final { scan-assembler-times "endbr32" 2 { target ia32 } } } */ +/* { dg-final { scan-assembler-times "endbr64" 2 { target { ! ia32 } } } } */ + +void * +func (void) +{ + return &&bar; +bar: + return 0; +} -- 2.20.1