summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-12-10 06:52:49 -0800
committerH.J. Lu <hjl.tools@gmail.com>2017-12-14 21:06:33 -0800
commit57f97de3aee237801e39245cfb20fd95ef865a09 (patch)
tree70b83039d1ec554ce9470d0c8d1597c7fe143af6
parent63df0dfd960679bc165b468318a48f57fa8640db (diff)
downloadgcc-hjl/pr81842.tar.gz
Add ix86_check_ucontext_function_referencehjl/pr81842
-rw-r--r--gcc/config/i386/i386.c47
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/linux-common.h17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-1.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-2.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-3.c32
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-4.c28
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-5.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81842-6.c9
9 files changed, 203 insertions, 3 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 35037434bf5..feeb533056e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2679,6 +2679,39 @@ rest_of_insert_endbranch (void)
return 0;
}
+/* Check if FNDECL is a ucontext function. */
+
+void
+ix86_check_ucontext_function_reference (location_t loc,
+ tree fndecl)
+{
+ if (!ix86_check_ucontext_functions
+ || !TARGET_SHSTK
+ || !DECL_FILE_SCOPE_P (fndecl)
+ || !TREE_PUBLIC (fndecl))
+ return;
+
+ /* For instrumentation clones, we want to derive flags from the
+ original name. */
+ cgraph_node *node = cgraph_node::get (fndecl);
+ if (node && node->instrumentation_clone)
+ fndecl = node->orig_decl;
+
+ tree name_decl = DECL_NAME (fndecl);
+ if (name_decl
+ && (IDENTIFIER_LENGTH (name_decl) == 10
+ || IDENTIFIER_LENGTH (name_decl) == 11))
+ {
+ const char *name = IDENTIFIER_POINTER (name_decl);
+
+ if (! strcmp (name, "getcontext")
+ || ! strcmp (name, "setcontext")
+ || ! strcmp (name, "makecontext")
+ || ! strcmp (name, "swapcontext"))
+ error_at (loc, "%qE cannot be used with -mshstk", fndecl);
+ }
+}
+
namespace {
const pass_data pass_data_insert_endbranch =
@@ -18117,10 +18150,18 @@ ix86_print_operand (FILE *file, rtx x, int code)
}
if (CONST_INT_P (x))
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- else if (flag_pic || MACHOPIC_INDIRECT)
- output_pic_addr_const (file, x, code);
else
- output_addr_const (file, x);
+ {
+ if (GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_DECL (x)
+ && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
+ ix86_check_ucontext_function_reference (input_location,
+ SYMBOL_REF_DECL (x));
+ if (flag_pic || MACHOPIC_INDIRECT)
+ output_pic_addr_const (file, x, code);
+ else
+ output_addr_const (file, x);
+ }
}
}
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 04e391d311d..13b9697ba7e 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1005,6 +1005,10 @@ Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags2) Save
Specifically enables an shadow stack support feature from Control-flow
Enforcment Technology (CET).
+mcheck-ucontext-functions
+Target Report Var(ix86_check_ucontext_functions) Init(1)
+Check references to ucontext functions.
+
mcet-switch
Target Report Undocumented Var(flag_cet_switch) Init(0)
Turn on CET instrumentation for switch statements, which use jump table and
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index 6613807180e..5dff543ab76 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -126,3 +126,20 @@ extern void file_end_indicate_exec_stack_and_cet (void);
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet
+
+#if !defined USED_FOR_TARGET && !defined GENERATOR_FILE
+#include "input.h"
+
+extern void ix86_check_ucontext_function_reference (location_t, tree);
+
+#undef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+ do \
+ { \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ ix86_check_ucontext_function_reference (UNKNOWN_LOCATION,\
+ DECL); \
+ default_elf_asm_output_external (FILE, DECL, NAME); \
+ } \
+ while (0)
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-1.c b/gcc/testsuite/gcc.target/i386/pr81842-1.c
new file mode 100644
index 00000000000..bd6bf775625
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-1.c
@@ -0,0 +1,28 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet" } */
+
+#include <ucontext.h>
+
+int
+func1 (ucontext_t *ucp)
+{
+ return getcontext (ucp); /* { dg-error "'getcontext' cannot be used with -mshstk" } */
+}
+
+int
+func2 (const ucontext_t *ucp)
+{
+ return setcontext (ucp); /* { dg-error "'setcontext' cannot be used with -mshstk" } */
+}
+
+int
+func3 (ucontext_t *oucp, const ucontext_t *ucp)
+{
+ return swapcontext (oucp, ucp); /* { dg-error "'swapcontext' cannot be used with -mshstk" } */
+}
+
+void
+func4 (ucontext_t *ucp, void (*func) (void))
+{
+ makecontext (ucp, func, 0); /* { dg-error "'makecontext' cannot be used with -mshstk" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-2.c b/gcc/testsuite/gcc.target/i386/pr81842-2.c
new file mode 100644
index 00000000000..202b1aa1888
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */
+
+#include <ucontext.h>
+
+int
+func1 (ucontext_t *ucp)
+{
+ return getcontext (ucp);
+}
+
+int
+func2 (const ucontext_t *ucp)
+{
+ return setcontext (ucp);
+}
+
+int
+func3 (ucontext_t *oucp, const ucontext_t *ucp)
+{
+ return swapcontext (oucp, ucp);
+}
+
+void
+func4 (ucontext_t *ucp, void (*func) (void))
+{
+ makecontext (ucp, func, 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-3.c b/gcc/testsuite/gcc.target/i386/pr81842-3.c
new file mode 100644
index 00000000000..f98a8b56a71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-3.c
@@ -0,0 +1,32 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet" } */
+
+#include <ucontext.h>
+
+void *
+func1 (void)
+{
+ return getcontext;
+}
+
+void *
+func2 (void)
+{
+ return setcontext;
+}
+
+void *
+func3 (void)
+{
+ return swapcontext;
+}
+
+void *
+func4 (void)
+{
+ return makecontext;
+}
+/* { dg-error "'getcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'setcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'swapcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'makecontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-4.c b/gcc/testsuite/gcc.target/i386/pr81842-4.c
new file mode 100644
index 00000000000..d4d1dce1311
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-4.c
@@ -0,0 +1,28 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */
+
+#include <ucontext.h>
+
+void *
+func1 (void)
+{
+ return getcontext;
+}
+
+void *
+func2 (void)
+{
+ return setcontext;
+}
+
+void *
+func3 (void)
+{
+ return swapcontext;
+}
+
+void *
+func4 (void)
+{
+ return makecontext;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-5.c b/gcc/testsuite/gcc.target/i386/pr81842-5.c
new file mode 100644
index 00000000000..b9acf7a2e07
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-5.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet" } */
+
+#include <ucontext.h>
+
+void *p1 = getcontext;
+void *p2 = setcontext;
+void *p3 = swapcontext;
+void *p4 = makecontext;
+/* { dg-error "'getcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'setcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'swapcontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
+/* { dg-error "'makecontext' cannot be used with -mshstk" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81842-6.c b/gcc/testsuite/gcc.target/i386/pr81842-6.c
new file mode 100644
index 00000000000..01d5a3ddf8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81842-6.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection -mcet -mno-check-ucontext-functions" } */
+
+#include <ucontext.h>
+
+void *p1 = getcontext;
+void *p2 = setcontext;
+void *p3 = swapcontext;
+void *p4 = makecontext;