diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e4a6686dd6387d38753f551a09c02d7979f8e5c..58efc772d66dea789038b008eee710abad617b95 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2014-11-14 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63839 + * asan.c (ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST, + ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST): Define. + * builtin-attrs.def (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST): + Define. + * builtins.c (fold_builtin_0): Don't include ubsan.h. Don't + instrument BUILT_IN_UNREACHABLE here. + * sanitizer.def (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE): Make + const. + * sanopt.c (pass_sanopt::execute): Instrument BUILT_IN_UNREACHABLE. + * tree-ssa-ccp.c (optimize_unreachable): Bail out if + SANITIZE_UNREACHABLE. + * ubsan.c (ubsan_instrument_unreachable): Rewrite for GIMPLE. + * ubsan.h (ubsan_instrument_unreachable): Adjust declaration. + 2014-11-14 Alan Lawrence <alan.lawrence@arm.com> * config/rs6000/vector.md (vec_shl_<mode>): Remove. diff --git a/gcc/asan.c b/gcc/asan.c index 79dede714181611f7cb4913c6a6c1563a644d401..2961b4460dee50e671a30993838f711449ecf607 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -2346,6 +2346,9 @@ initialize_sanitizer_builtins (void) #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST #undef ATTR_NORETURN_NOTHROW_LEAF_LIST #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST +#undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST +#define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \ + ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \ ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST @@ -2355,6 +2358,9 @@ initialize_sanitizer_builtins (void) #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \ /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST +#undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST +#define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \ + /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST #undef DEF_SANITIZER_BUILTIN #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \ diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index 9c05a949039a6baf6207e4b2b677f2c164600a3f..c707367d4e7dafc3f64f47e1465c0c126d4b1071 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -145,6 +145,8 @@ DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL, \ ATTR_NULL, ATTR_NOTHROW_LIST) DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LEAF_LIST, ATTR_SENTINEL, \ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) +DEF_ATTR_TREE_LIST (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_CONST,\ + ATTR_NULL, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) /* Functions whose pointer parameter(s) are all nonnull. */ DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, ATTR_NONNULL, ATTR_NULL, ATTR_NULL) diff --git a/gcc/builtins.c b/gcc/builtins.c index 1cd65edb194198f17e1c5005dbe4444140694086..311c0e382797807fd04cd78a86570a3dfde74fc2 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -64,7 +64,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "builtins.h" #include "asan.h" -#include "ubsan.h" #include "cilk.h" #include "ipa-ref.h" #include "lto-streamer.h" @@ -9803,14 +9802,6 @@ fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED) case BUILT_IN_CLASSIFY_TYPE: return fold_builtin_classify_type (NULL_TREE); - case BUILT_IN_UNREACHABLE: - if (flag_sanitize & SANITIZE_UNREACHABLE - && (current_function_decl == NULL - || !lookup_attribute ("no_sanitize_undefined", - DECL_ATTRIBUTES (current_function_decl)))) - return ubsan_instrument_unreachable (loc); - break; - default: break; } diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index cddc5ea4935e065e0c718bf91946cb99eee3a372..3fc8c8396be66efc1946abe6fb7cf5cc949875be 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -394,7 +394,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS, DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE, "__ubsan_handle_builtin_unreachable", BT_FN_VOID_PTR, - ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) + ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MISSING_RETURN, "__ubsan_handle_missing_return", BT_FN_VOID_PTR, diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 0fc032a7a3057d7003f192f1ff38a35cf5e3e43d..fe2e42d121ccf1176477f40e094681dd89d2c206 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -312,6 +312,21 @@ pass_sanopt::execute (function *fun) break; } } + else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + { + tree callee = gimple_call_fndecl (stmt); + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_UNREACHABLE: + if (flag_sanitize & SANITIZE_UNREACHABLE + && !lookup_attribute ("no_sanitize_undefined", + DECL_ATTRIBUTES (fun->decl))) + no_next = ubsan_instrument_unreachable (&gsi); + break; + default: + break; + } + } if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5ffb5d445b4069aeb0ffaa1d7f55b992d1a42221..1d3ef947bf24f90c053b4b2b42efcc86bebab9a4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2014-11-14 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63839 + * c-c++-common/ubsan/pr63839.c: New test. + * c-c++-common/ubsan/unreachable-2.c: New test. + 2014-11-14 Richard Biener <rguenther@suse.de> * gcc.c-torture/execute/shiftopt-1.c: XFAIL invalid parts. diff --git a/gcc/testsuite/c-c++-common/ubsan/pr63839.c b/gcc/testsuite/c-c++-common/ubsan/pr63839.c new file mode 100644 index 0000000000000000000000000000000000000000..e3933f7fe6629092ab740d4884d2559190343351 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr63839.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=unreachable" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-shouldfail "ubsan" } */ + +static void __attribute__ ((noreturn)) +bar () +{ +} /* { dg-warning "function does return" } */ + +void +foo () +{ + bar (); +} + +int +main (void) +{ + foo (); +} + +/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c b/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c new file mode 100644 index 0000000000000000000000000000000000000000..783ebc249136bb35971d810d580acb03b811fe08 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/unreachable-2.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=unreachable" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-shouldfail "ubsan" } */ + +int e; + +int +main (void) +{ + return e ? 0 : (__builtin_unreachable (), 1); +} + +/* { dg-output "execution reached a __builtin_unreachable\\(\\) call" } */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 52d85036e1ff20afb701ae0d9a90e06537658747..31ca0e120e3e70f0f9e7e3b3ec15f4866b2a066a 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -2568,6 +2568,9 @@ optimize_unreachable (gimple_stmt_iterator i) edge e; bool ret; + if (flag_sanitize & SANITIZE_UNREACHABLE) + return false; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { stmt = gsi_stmt (gsi); diff --git a/gcc/ubsan.c b/gcc/ubsan.c index 41cf546cde3e00ea566b0dda48097a3bf0a909ae..b5b1b924c67561d1f88407eb7436d5c4d47e4811 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -588,17 +588,26 @@ ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...) /* Instrument the __builtin_unreachable call. We just call the libubsan routine instead. */ -tree -ubsan_instrument_unreachable (location_t loc) +bool +ubsan_instrument_unreachable (gimple_stmt_iterator *gsi) { - if (flag_sanitize_undefined_trap_on_error) - return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); + gimple g; + location_t loc = gimple_location (gsi_stmt (*gsi)); - initialize_sanitizer_builtins (); - tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, NULL_TREE, - NULL_TREE); - tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); - return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data)); + if (flag_sanitize_undefined_trap_on_error) + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0); + else + { + tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc, + NULL_TREE, NULL_TREE); + data = build_fold_addr_expr_loc (loc, data); + tree fn + = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE); + g = gimple_build_call (fn, 1, data); + } + gimple_set_location (g, loc); + gsi_replace (gsi, g, false); + return false; } /* Return true if T is a call to a libubsan routine. */ diff --git a/gcc/ubsan.h b/gcc/ubsan.h index 27c18eb00f8af3a2d49caae0733757e3f936a10d..dcdbb4fa4c98e0a9075b71711d8403571275f16a 100644 --- a/gcc/ubsan.h +++ b/gcc/ubsan.h @@ -41,7 +41,7 @@ enum ubsan_print_style { extern bool ubsan_expand_bounds_ifn (gimple_stmt_iterator *); extern bool ubsan_expand_null_ifn (gimple_stmt_iterator *); extern bool ubsan_expand_objsize_ifn (gimple_stmt_iterator *); -extern tree ubsan_instrument_unreachable (location_t); +extern bool ubsan_instrument_unreachable (gimple_stmt_iterator *); extern tree ubsan_create_data (const char *, int, const location_t *, ...); extern tree ubsan_type_descriptor (tree, enum ubsan_print_style = UBSAN_PRINT_NORMAL); extern tree ubsan_encode_value (tree, bool = false);