* [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839)
@ 2014-11-13 22:04 Marek Polacek
2014-11-14 8:45 ` Richard Biener
0 siblings, 1 reply; 3+ messages in thread
From: Marek Polacek @ 2014-11-13 22:04 UTC (permalink / raw)
To: GCC Patches, Jakub Jelinek, Richard Biener
As Richi pointed in the pr audit trail, instrumenting via folding is
bad. In this case we changed __builtin_unreachable, created by the
inliner, into BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE which requires
VOPS, which is a no-no in folding. So this patch:
- marks BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE as const to match
BUILT_IN_UNREACHABLE,
- moves the __builtin_unreachable instrumentation into sanopt pass,
- disables optimize_unreachable when doing the __builtin_unreachable
instrumentation,
- marks BUILT_IN_UNREACHABLE as "cold" (I don't see how this could
make a difference?). Now, BUILT_IN_TRAP should probably be also
marked as const+cold; I'm happy to do that as a follow-up.
Bootstrapped/regtested on power8-linux, ok for trunk?
2014-11-13 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.
* builtins.def (BUILT_IN_UNREACHABLE): Make cold.
* 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.
testsuite/
* c-c++-common/ubsan/pr63839.c: New test.
* c-c++-common/ubsan/unreachable-2.c: New test.
diff --git gcc/asan.c gcc/asan.c
index 79dede7..2961b44 100644
--- gcc/asan.c
+++ 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 gcc/builtin-attrs.def gcc/builtin-attrs.def
index 9c05a94..c707367 100644
--- gcc/builtin-attrs.def
+++ 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 gcc/builtins.c gcc/builtins.c
index 1cd65ed..311c0e3 100644
--- gcc/builtins.c
+++ 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 gcc/builtins.def gcc/builtins.def
index 0406016..8699a41 100644
--- gcc/builtins.def
+++ gcc/builtins.def
@@ -803,7 +803,7 @@ DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NOTHROW_L
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_LIST)
-DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL)
DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR_INT, ATTR_NULL)
DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NOTHROW_LEAF_LIST)
diff --git gcc/sanitizer.def gcc/sanitizer.def
index cddc5ea..3fc8c83 100644
--- gcc/sanitizer.def
+++ 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 gcc/sanopt.c gcc/sanopt.c
index 0fc032a..fe2e42d 100644
--- gcc/sanopt.c
+++ 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 gcc/testsuite/c-c++-common/ubsan/pr63839.c gcc/testsuite/c-c++-common/ubsan/pr63839.c
index e69de29..e3933f7 100644
--- gcc/testsuite/c-c++-common/ubsan/pr63839.c
+++ 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 gcc/testsuite/c-c++-common/ubsan/unreachable-2.c gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
index e69de29..783ebc2 100644
--- gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
+++ 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 gcc/tree-ssa-ccp.c gcc/tree-ssa-ccp.c
index 52d8503..31ca0e1 100644
--- gcc/tree-ssa-ccp.c
+++ 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 gcc/ubsan.c gcc/ubsan.c
index 41cf546..b5b1b92 100644
--- gcc/ubsan.c
+++ 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 gcc/ubsan.h gcc/ubsan.h
index 27c18eb..dcdbb4f 100644
--- gcc/ubsan.h
+++ 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);
Marek
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839)
2014-11-13 22:04 [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839) Marek Polacek
@ 2014-11-14 8:45 ` Richard Biener
2014-11-14 11:12 ` Marek Polacek
0 siblings, 1 reply; 3+ messages in thread
From: Richard Biener @ 2014-11-14 8:45 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches, Jakub Jelinek
On Thu, 13 Nov 2014, Marek Polacek wrote:
> As Richi pointed in the pr audit trail, instrumenting via folding is
> bad. In this case we changed __builtin_unreachable, created by the
> inliner, into BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE which requires
> VOPS, which is a no-no in folding. So this patch:
> - marks BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE as const to match
> BUILT_IN_UNREACHABLE,
> - moves the __builtin_unreachable instrumentation into sanopt pass,
> - disables optimize_unreachable when doing the __builtin_unreachable
> instrumentation,
> - marks BUILT_IN_UNREACHABLE as "cold" (I don't see how this could
> make a difference?). Now, BUILT_IN_TRAP should probably be also
> marked as const+cold; I'm happy to do that as a follow-up.
It's not necessary to mark any of them as cold as seen from predict.c:
if (is_gimple_call (stmt))
{
if ((gimple_call_flags (stmt) & ECF_NORETURN)
&& has_return_edges)
predict_paths_leading_to (bb, PRED_NORETURN,
NOT_TAKEN);
decl = gimple_call_fndecl (stmt);
if (decl
&& lookup_attribute ("cold",
DECL_ATTRIBUTES (decl)))
predict_paths_leading_to (bb, PRED_COLD_FUNCTION,
NOT_TAKEN);
so anything with a noreturn attribute behaves exactly the same as cold.
So please leave existing non-cold things as non-cold.
> Bootstrapped/regtested on power8-linux, ok for trunk?
Ok with that change.
Thanks,
Richard.
> 2014-11-13 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.
> * builtins.def (BUILT_IN_UNREACHABLE): Make cold.
> * 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.
> testsuite/
> * c-c++-common/ubsan/pr63839.c: New test.
> * c-c++-common/ubsan/unreachable-2.c: New test.
>
> diff --git gcc/asan.c gcc/asan.c
> index 79dede7..2961b44 100644
> --- gcc/asan.c
> +++ 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 gcc/builtin-attrs.def gcc/builtin-attrs.def
> index 9c05a94..c707367 100644
> --- gcc/builtin-attrs.def
> +++ 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 gcc/builtins.c gcc/builtins.c
> index 1cd65ed..311c0e3 100644
> --- gcc/builtins.c
> +++ 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 gcc/builtins.def gcc/builtins.def
> index 0406016..8699a41 100644
> --- gcc/builtins.def
> +++ gcc/builtins.def
> @@ -803,7 +803,7 @@ DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NOTHROW_L
> DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
> DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
> DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_LIST)
> -DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST)
> +DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST)
> DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL)
> DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR_INT, ATTR_NULL)
> DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NOTHROW_LEAF_LIST)
> diff --git gcc/sanitizer.def gcc/sanitizer.def
> index cddc5ea..3fc8c83 100644
> --- gcc/sanitizer.def
> +++ 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 gcc/sanopt.c gcc/sanopt.c
> index 0fc032a..fe2e42d 100644
> --- gcc/sanopt.c
> +++ 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 gcc/testsuite/c-c++-common/ubsan/pr63839.c gcc/testsuite/c-c++-common/ubsan/pr63839.c
> index e69de29..e3933f7 100644
> --- gcc/testsuite/c-c++-common/ubsan/pr63839.c
> +++ 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 gcc/testsuite/c-c++-common/ubsan/unreachable-2.c gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
> index e69de29..783ebc2 100644
> --- gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
> +++ 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 gcc/tree-ssa-ccp.c gcc/tree-ssa-ccp.c
> index 52d8503..31ca0e1 100644
> --- gcc/tree-ssa-ccp.c
> +++ 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 gcc/ubsan.c gcc/ubsan.c
> index 41cf546..b5b1b92 100644
> --- gcc/ubsan.c
> +++ 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 gcc/ubsan.h gcc/ubsan.h
> index 27c18eb..dcdbb4f 100644
> --- gcc/ubsan.h
> +++ 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);
>
> Marek
>
>
--
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284
(AG Nuernberg)
Maxfeldstrasse 5, 90409 Nuernberg, Germany
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839)
2014-11-14 8:45 ` Richard Biener
@ 2014-11-14 11:12 ` Marek Polacek
0 siblings, 0 replies; 3+ messages in thread
From: Marek Polacek @ 2014-11-14 11:12 UTC (permalink / raw)
To: Richard Biener; +Cc: GCC Patches, Jakub Jelinek
On Fri, Nov 14, 2014 at 09:36:40AM +0100, Richard Biener wrote:
> So please leave existing non-cold things as non-cold.
>
> > Bootstrapped/regtested on power8-linux, ok for trunk?
>
> Ok with that change.
Thanks, this is the version with the builtins.def hunk dropped.
Applying to trunk.
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.
testsuite/
* c-c++-common/ubsan/pr63839.c: New test.
* c-c++-common/ubsan/unreachable-2.c: New test.
diff --git gcc/asan.c gcc/asan.c
index 79dede7..2961b44 100644
--- gcc/asan.c
+++ 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 gcc/builtin-attrs.def gcc/builtin-attrs.def
index 9c05a94..c707367 100644
--- gcc/builtin-attrs.def
+++ 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 gcc/builtins.c gcc/builtins.c
index 1cd65ed..311c0e3 100644
--- gcc/builtins.c
+++ 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 gcc/sanitizer.def gcc/sanitizer.def
index cddc5ea..3fc8c83 100644
--- gcc/sanitizer.def
+++ 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 gcc/sanopt.c gcc/sanopt.c
index 0fc032a..fe2e42d 100644
--- gcc/sanopt.c
+++ 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 gcc/testsuite/c-c++-common/ubsan/pr63839.c gcc/testsuite/c-c++-common/ubsan/pr63839.c
index e69de29..e3933f7 100644
--- gcc/testsuite/c-c++-common/ubsan/pr63839.c
+++ 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 gcc/testsuite/c-c++-common/ubsan/unreachable-2.c gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
index e69de29..783ebc2 100644
--- gcc/testsuite/c-c++-common/ubsan/unreachable-2.c
+++ 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 gcc/tree-ssa-ccp.c gcc/tree-ssa-ccp.c
index 52d8503..31ca0e1 100644
--- gcc/tree-ssa-ccp.c
+++ 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 gcc/ubsan.c gcc/ubsan.c
index 41cf546..b5b1b92 100644
--- gcc/ubsan.c
+++ 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 gcc/ubsan.h gcc/ubsan.h
index 27c18eb..dcdbb4f 100644
--- gcc/ubsan.h
+++ 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);
Marek
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-11-14 11:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-13 22:04 [PATCH] -fsanitize=unreachable overhaul (PR sanitizer/63839) Marek Polacek
2014-11-14 8:45 ` Richard Biener
2014-11-14 11:12 ` Marek Polacek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).