return result_flags;
}
+/* Return true when coverage sanitization should happend for FN function. */
+
+static inline bool
+sanitize_coverage_p (const_tree fn = current_function_decl)
+{
+ return (flag_sanitize_coverage
+ && lookup_attribute ("no_sanitize_coverage",
+ DECL_ATTRIBUTES (fn)) == NULL_TREE);
+}
+
#endif /* TREE_ASAN */
int, bool *);
static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
bool *);
+static tree handle_no_sanitize_coverage_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
handle_no_sanitize_thread_attribute, NULL },
{ "no_sanitize_undefined", 0, 0, true, false, false, false,
handle_no_sanitize_undefined_attribute, NULL },
+ { "no_sanitize_coverage", 0, 0, true, false, false, false,
+ handle_no_sanitize_coverage_attribute, NULL },
{ "asan odr indicator", 0, 0, true, false, false, false,
handle_asan_odr_indicator_attribute, NULL },
{ "warning", 1, 1, true, false, false, false,
return NULL_TREE;
}
+/* Handle a "no_sanitize_coverage" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_sanitize_coverage_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle an "asan odr indicator" attribute; arguments as in
struct attribute_spec.handler. */
to inform the compiler that it should not check for undefined behavior
in the function when compiling with the @option{-fsanitize=undefined} option.
+@item no_sanitize_coverage
+@cindex @code{no_sanitize_coverage} function attribute
+The @code{no_sanitize_coverage} attribute on functions is used
+to inform the compiler that it should not do coverage-guided
+fuzzing code instrumentation (@option{-fsanitize-coverage}).
+
@item no_split_stack
@cindex @code{no_split_stack} function attribute
@opindex fsplit-stack
logical_op_non_short_circuit
= param_logical_op_non_short_circuit;
if (logical_op_non_short_circuit
- && !flag_sanitize_coverage
+ && !sanitize_coverage_p ()
&& lhs != 0 && rhs != 0
&& (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
&& operand_equal_p (lhs, rhs, 0))
logical_op_non_short_circuit
= param_logical_op_non_short_circuit;
if (logical_op_non_short_circuit
- && !flag_sanitize_coverage
+ && !sanitize_coverage_p ()
&& (code == TRUTH_AND_EXPR
|| code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR
!= sanitize_flags_p (codes[i], callee))
return false;
+ if (sanitize_coverage_p (caller) != sanitize_coverage_p (callee))
+ return false;
+
return true;
}
return new pass_sancov<O0> (m_ctxt);
}
virtual bool
- gate (function *)
+ gate (function *fun)
{
- return flag_sanitize_coverage && (!O0 || !optimize);
+ return sanitize_coverage_p (fun->decl) && (!O0 || !optimize);
}
virtual unsigned int
execute (function *fun)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */
+
+void foo(void)
+{
+}
+
+void
+__attribute__((no_sanitize_coverage))
+bar(void)
+{
+}
+
+static void inline
+__attribute__((always_inline))
+inline_fn(void)
+{
+}
+
+void
+__attribute__((no_sanitize_coverage))
+baz(void)
+{
+ inline_fn();
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin___sanitizer_cov_trace_pc \\(\\)" 1 "optimized" } } */
#include "gimplify-me.h"
#include "tree-cfg.h"
#include "tree-ssa.h"
+#include "attribs.h"
+#include "asan.h"
#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
#define LOGICAL_OP_NON_SHORT_CIRCUIT \
if (param_logical_op_non_short_circuit != -1)
logical_op_non_short_circuit
= param_logical_op_non_short_circuit;
- if (!logical_op_non_short_circuit || flag_sanitize_coverage)
+ if (!logical_op_non_short_circuit || sanitize_coverage_p ())
return false;
/* Only do this optimization if the inner bb contains only the conditional. */
if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb)))