From patchwork Mon Jul 10 12:07:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?UTF-8?B?5ZC05r2N5rWgKOatpOW9vCk=?= X-Patchwork-Id: 786124 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3x5kWZ1xFDz9s2s for ; Mon, 10 Jul 2017 22:08:22 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="quSD7YBe"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:reply-to:message-id:subject:mime-version :content-type:content-transfer-encoding; q=dns; s=default; b=N6u 25afgYGnmFomV0q72MDX9pl2oBE9et1UZIsJkcWPqvLfd8/G7SUamM5K8PF89S9b R1SPWmaWXG/sphWhFCnzDy7jG9ws5Vc1/+R8p7eyoQnFgBu2wu7U6TKByuW8vUFH nKKcfGwdQKvyYsvaZ9RmDMtGXXrv0VSaNpkmf20A= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:reply-to:message-id:subject:mime-version :content-type:content-transfer-encoding; s=default; bh=X/yAHGti2 zf4wynIHUcLa4HbMYc=; b=quSD7YBeaY2do/Sv84CWg7yPq2a13WGyok7MhbGU+ y+8pAlAdAlENGl6UEfyz3f8h2VDUpTltPpwFCje/Up/i1Dn3yGiyhM0HzAOuDr63 XkooP2Kj49HEnILOuRGG0TFkOwnDJqm3DJpKTra8ak67ZXEZRDKHZrGRcCBELXhH 7w= Received: (qmail 20352 invoked by alias); 10 Jul 2017 12:08:11 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 17708 invoked by uid 89); 10 Jul 2017 12:08:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-16.1 required=5.0 tests=BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, MIME_BASE64_BLANKS, SPF_PASS autolearn=ham version=3.3.2 spammy=H*x:Chrome, H*UA:Chrome, Wish, Different X-Spam-User: qpsmtpd, 2 recipients X-HELO: out0-237.mail.aliyun.com Received: from out0-237.mail.aliyun.com (HELO out0-237.mail.aliyun.com) (140.205.0.237) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jul 2017 12:08:03 +0000 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R151e4; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e02c03309; MF=weixi.wwx@antfin.com; NM=1; PH=DW; RN=3; SR=0; TI=W4_4993099_0A930E47_1499687288052_o7001c295f; Received: from WS-web (weixi.wwx@antfin.com[121.0.29.221]) by e02c03268.eu6 at Mon, 10 Jul 2017 20:07:58 +0800 Date: Mon, 10 Jul 2017 20:07:58 +0800 From: "=?UTF-8?B?5ZC05r2N5rWgKOatpOW9vCk=?=" To: "gcc" , "gcc-patches" Cc: "wishwu007" Reply-To: "=?UTF-8?B?5ZC05r2N5rWgKOatpOW9vCk=?=" Message-ID: <234840fd-a06a-4dfd-a1c5-254e26144754.weixi.wwx@antfin.com> Subject: =?UTF-8?B?QWRkIHN1cHBvcnQgdG8gdHJhY2UgY29tcGFyaXNvbiBpbnN0cnVjdGlvbnMgYW5kIHN3aXRj?= =?UTF-8?B?aCBzdGF0ZW1lbnRz?= MIME-Version: 1.0 x-aliyun-mail-creator: W4_4993099_null_M3LTW96aWxsYS81LjAgKE1hY2ludG9zaDsgSW50ZWwgTWFjIE9TIFggMTBfMTFfNikgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzU5LjAuMzA3MS4xMTUgU2FmYXJpLzUzNy4zNg==vN Hi I write some codes to make gcc support comparison-guided fuzzing. It is very like http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow . With -fsanitize-coverage=trace-cmp the compiler will insert extra instrumentation around comparison instructions and switch statements. I think it is useful for fuzzing. :D Patch is below, I may supply test cases later. With Regards Wish Wu Index: gcc/asan.c =================================================================== --- gcc/asan.c (revision 250082) +++ gcc/asan.c (working copy) @@ -2705,6 +2705,29 @@ initialize_sanitizer_builtins (void) tree BT_FN_SIZE_CONST_PTR_INT = build_function_type_list (size_type_node, const_ptr_type_node, integer_type_node, NULL_TREE); + + tree BT_FN_VOID_UINT8_UINT8 + = build_function_type_list (void_type_node, unsigned_char_type_node, + unsigned_char_type_node, NULL_TREE); + tree BT_FN_VOID_UINT16_UINT16 + = build_function_type_list (void_type_node, uint16_type_node, + uint16_type_node, NULL_TREE); + tree BT_FN_VOID_UINT32_UINT32 + = build_function_type_list (void_type_node, uint32_type_node, + uint32_type_node, NULL_TREE); + tree BT_FN_VOID_UINT64_UINT64 + = build_function_type_list (void_type_node, uint64_type_node, + uint64_type_node, NULL_TREE); + tree BT_FN_VOID_FLOAT_FLOAT + = build_function_type_list (void_type_node, float_type_node, + float_type_node, NULL_TREE); + tree BT_FN_VOID_DOUBLE_DOUBLE + = build_function_type_list (void_type_node, double_type_node, + double_type_node, NULL_TREE); + tree BT_FN_VOID_UINT64_PTR + = build_function_type_list (void_type_node, uint64_type_node, + ptr_type_node, NULL_TREE); + tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5]; tree BT_FN_IX_CONST_VPTR_INT[5]; tree BT_FN_IX_VPTR_IX_INT[5]; Index: gcc/builtin-types.def =================================================================== --- gcc/builtin-types.def (revision 250082) +++ gcc/builtin-types.def (working copy) @@ -338,8 +338,20 @@ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRMODE_PTR, BT_VOID, BT_PTRMODE, BT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE, BT_VOID, BT_PTR, BT_PTRMODE) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT8_UINT8, + BT_VOID, BT_UINT8, BT_UINT8) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT16_UINT16, + BT_VOID, BT_UINT16, BT_UINT16) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT32_UINT32, + BT_VOID, BT_UINT32, BT_UINT32) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT64_UINT64, BT_VOID, BT_UINT64, BT_UINT64) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_FLOAT_FLOAT, + BT_VOID, BT_FLOAT, BT_FLOAT) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_DOUBLE_DOUBLE, + BT_VOID, BT_DOUBLE, BT_DOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT64_PTR, + BT_VOID, BT_UINT64, BT_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG, BT_VOID, BT_VALIST_REF, BT_VALIST_ARG) DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG, Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 250082) +++ gcc/common.opt (working copy) @@ -226,10 +226,9 @@ unsigned int flag_sanitize Variable unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN) -fsanitize-coverage=trace-pc -Common Report Var(flag_sanitize_coverage) -Enable coverage-guided fuzzing code instrumentation. -Inserts call to __sanitizer_cov_trace_pc into every basic block. +; What the coverage sanitizers should instrument +Variable +unsigned int flag_sanitize_coverage ; Flag whether a prefix has been added to dump_base_name Variable @@ -975,6 +974,10 @@ fsanitize= Common Driver Report Joined Select what to sanitize. +fsanitize-coverage= +Common Driver Report Joined +Select what to coverage sanitize. + fasan-shadow-offset= Common Joined RejectNegative Var(common_deferred_options) Defer -fasan-shadow-offset= Use custom shadow memory offset. Index: gcc/flag-types.h =================================================================== --- gcc/flag-types.h (revision 250082) +++ gcc/flag-types.h (working copy) @@ -250,6 +250,14 @@ enum sanitize_code { | SANITIZE_BOUNDS_STRICT }; +/* Different trace modes */ +enum sanitize_coverage_code { + /* Trace PC */ + SANITIZE_COV_TRACE_PC = 1UL << 0, + /* Trace Compare */ + SANITIZE_COV_TRACE_CMP = 1UL << 1 +}; + /* flag_vtable_verify initialization levels. */ enum vtv_priority { VTV_NO_PRIORITY = 0, /* i.E. Do NOT do vtable verification. */ Index: gcc/opts.c =================================================================== --- gcc/opts.c (revision 250082) +++ gcc/opts.c (working copy) @@ -1518,6 +1518,17 @@ const struct sanitizer_opts_s sanitizer_opts[] = { NULL, 0U, 0UL, false } }; +/* -f{,no-}sanitize-coverage= suboptions. */ +const struct sanitizer_opts_s coverage_sanitizer_opts[] = +{ +#define SANITIZER_OPT(name, flags, recover) \ + { #name, flags, sizeof #name - 1, recover } + SANITIZER_OPT (trace-pc, SANITIZE_COV_TRACE_PC, false), + SANITIZER_OPT (trace-cmp, SANITIZE_COV_TRACE_CMP, false), +#undef SANITIZER_OPT + { NULL, 0U, 0UL, false } +}; + /* A struct for describing a run of chars within a string. */ struct string_fragment @@ -1665,6 +1676,85 @@ parse_sanitizer_options (const char *p, location_t return flags; } +/* Given ARG, an unrecognized coverage sanitizer option, return the best + matching coverage sanitizer option, or NULL if there isn't one. + VALUE is non-zero for the regular form of the option, zero + for the "no-" form (e.g. "-fno-sanitize-coverage="). */ + +static const char * +get_closest_coverage_sanitizer_option (const string_fragment &arg, int value) +{ + best_match bm (arg); + for (int i = 0; coverage_sanitizer_opts[i].name != NULL; ++i) + { + bm.consider (coverage_sanitizer_opts[i].name); + } + return bm.get_best_meaningful_candidate (); +} + +/* Parse comma separated sanitizer suboptions from P for option SCODE, + adjust previous FLAGS and return new ones. If COMPLAIN is false, + don't issue diagnostics. */ + +unsigned int +parse_coverage_sanitizer_options (const char *p, location_t loc, + unsigned int flags, int value, bool complain) +{ + while (*p != 0) + { + size_t len, i; + bool found = false; + const char *comma = strchr (p, ','); + + if (comma == NULL) + len = strlen (p); + else + len = comma - p; + if (len == 0) + { + p = comma + 1; + continue; + } + + /* Check to see if the string matches an option class name. */ + for (i = 0; coverage_sanitizer_opts[i].name != NULL; ++i) + if (len == coverage_sanitizer_opts[i].len + && memcmp (p, coverage_sanitizer_opts[i].name, len) == 0) + { + if (value) + flags |= coverage_sanitizer_opts[i].flag; + else + flags &= ~coverage_sanitizer_opts[i].flag; + found = true; + break; + } + + if (! found && complain) + { + const char *hint + = get_closest_coverage_sanitizer_option (string_fragment (p, len), + value); + + if (hint) + error_at (loc, + "unrecognized argument to -f%ssanitize-coverage= option: %q.*s;" + " did you mean %qs?", + value ? "" : "no-", + (int) len, p, hint); + else + error_at (loc, + "unrecognized argument to -f%ssanitize-coverage= option: %q.*s", + value ? "" : "no-", + (int) len, p); + } + + if (comma == NULL) + break; + p = comma + 1; + } + return flags; +} + /* Parse string values of no_sanitize attribute passed in VALUE. Values are separated with comma. Wrong argument is stored to WRONG_ARGUMENT variable. */ @@ -1942,6 +2032,12 @@ common_handle_option (struct gcc_options *opts, &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); break; + case OPT_fsanitize_coverage_: + opts->x_flag_sanitize_coverage + = parse_coverage_sanitizer_options (arg, loc, + opts->x_flag_sanitize_coverage, value, true); + break; + case OPT_O: case OPT_Os: case OPT_Ofast: Index: gcc/sancov.c =================================================================== --- gcc/sancov.c (revision 250082) +++ gcc/sancov.c (working copy) @@ -29,31 +29,194 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "stmt.h" #include "gimple-iterator.h" +#include "tree-core.h" #include "tree-cfg.h" #include "tree-pass.h" #include "tree-iterator.h" +#include "fold-const.h" +#include "stringpool.h" +#include "output.h" +#include "cgraph.h" #include "asan.h" namespace { +static void +instrument_cond (gimple_stmt_iterator *gsi, gimple *stmt) +{ + tree lhs = gimple_cond_lhs (stmt); + tree rhs = gimple_cond_rhs (stmt); + unsigned int bitno = TYPE_PRECISION (TREE_TYPE (lhs)) > TYPE_PRECISION (TREE_TYPE (rhs)) ? + TYPE_PRECISION (TREE_TYPE (lhs)) : TYPE_PRECISION (TREE_TYPE (rhs)); + if (TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE) + { + enum built_in_function fncode; + switch (bitno) + { + case 8: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMP1; + break; + + case 16: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMP2; + break; + + case 32: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMP4; + break; + + case 64: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMP8; + break; + + default: + return; + break; + } + tree fndecl = builtin_decl_implicit (fncode); + gimple *gcall = gimple_build_call (fndecl, 2, lhs, rhs); + gimple_set_location (gcall, gimple_location (stmt)); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + } + else if (TREE_CODE (TREE_TYPE (lhs)) == REAL_TYPE) + { + enum built_in_function fncode; + switch (bitno) + { + case 32: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMPF; + break; + + case 64: + fncode = BUILT_IN_SANITIZER_COV_TRACE_CMPD; + break; + + default: + return; + break; + } + tree fndecl = builtin_decl_implicit (fncode); + gimple *gcall = gimple_build_call (fndecl, 2, lhs, rhs); + gimple_set_location (gcall, gimple_location (stmt)); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + } +} + +static void +instrument_switch (gimple_stmt_iterator *gsi, gimple *stmt, function *fun) +{ + gswitch *switch_stmt = as_a (stmt); + tree index = gimple_switch_index (switch_stmt); + unsigned bitno = TYPE_PRECISION (TREE_TYPE (index)); + unsigned i, n = gimple_switch_num_labels (switch_stmt), num = 0; + for (i = 0; i < n; ++i) + { + tree label = gimple_switch_label (switch_stmt, i); + tree low_case = CASE_LOW (label); + if (low_case != NULL_TREE) + num++; + tree high_case = CASE_HIGH (label); + if (high_case != NULL_TREE) + num++; + } + + tree case_array_elem_type = build_type_variant (uint64_type_node, 1, 0); + tree case_array_type = build_array_type (case_array_elem_type, + build_index_type (size_int (num + 2 - 1))); + char name[64]; + static size_t case_array_count = 0; + snprintf(name, sizeof(name) - 1, "__sanitizer_cov_trace_switch_array%lu", case_array_count++); + tree case_array_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, + get_identifier (name), case_array_type); + TREE_STATIC (case_array_var) = 1; + TREE_PUBLIC (case_array_var) = 0; + TREE_CONSTANT (case_array_var) = 1; + TREE_READONLY (case_array_var) = 1; + DECL_EXTERNAL (case_array_var) = 0; + DECL_ARTIFICIAL (case_array_var) = 1; + DECL_IGNORED_P (case_array_var) = 1; + + vec *v = NULL; + vec_alloc (v, num + 2); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (uint64_type_node, num)); + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (uint64_type_node, bitno)); + for (i = 0; i < n; ++i) + { + tree label = gimple_switch_label (switch_stmt, i); + + tree low_case = CASE_LOW (label); + if (low_case != NULL_TREE) + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + build_int_cst (uint64_type_node, TREE_INT_CST_LOW (low_case))); + + tree high_case = CASE_HIGH (label); + if (high_case != NULL_TREE) + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + build_int_cst (uint64_type_node, TREE_INT_CST_LOW (high_case))); + } + tree ctor = build_constructor (case_array_type, v); + TREE_STATIC (ctor) = 1; + TREE_PUBLIC (ctor) = 0; + TREE_CONSTANT (ctor) = 1; + TREE_READONLY (ctor) = 1; + DECL_EXTERNAL (ctor) = 0; + DECL_INITIAL (case_array_var) = ctor; + varpool_node::finalize_decl (case_array_var); + + tree case_array_var_ref = build_fold_addr_expr (case_array_var); + add_local_decl (fun, case_array_var); + tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_SWITCH); + gimple *gcall = gimple_build_call (fndecl, 2, index, case_array_var_ref); + gimple_set_location (gcall, gimple_location (stmt)); + gsi_insert_before(gsi, gcall, GSI_SAME_STMT); +} + unsigned sancov_pass (function *fun) { initialize_sanitizer_builtins (); + basic_block bb; + /* Insert callback into beginning of every BB. */ - tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_PC); - basic_block bb; - FOR_EACH_BB_FN (bb, fun) + if (flag_sanitize_coverage & SANITIZE_COV_TRACE_PC) { - gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb); - if (gsi_end_p (gsi)) - continue; - gimple *stmt = gsi_stmt (gsi); - gimple *gcall = gimple_build_call (fndecl, 0); - gimple_set_location (gcall, gimple_location (stmt)); - gsi_insert_before (&gsi, gcall, GSI_SAME_STMT); + tree fndecl = builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE_PC); + FOR_EACH_BB_FN (bb, fun) + { + gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb); + if (gsi_end_p (gsi)) + continue; + gimple *stmt = gsi_stmt (gsi); + gimple *gcall = gimple_build_call (fndecl, 0); + gimple_set_location (gcall, gimple_location (stmt)); + gsi_insert_before (&gsi, gcall, GSI_SAME_STMT); + } } + + /* Insert callback to every compare statments. */ + if (flag_sanitize_coverage & SANITIZE_COV_TRACE_CMP) + { + FOR_EACH_BB_FN (bb, fun) + { + gimple_stmt_iterator gsi; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + switch (gimple_code (stmt)) + { + case GIMPLE_COND: + instrument_cond (&gsi, stmt); + break; + case GIMPLE_SWITCH: + instrument_switch (&gsi, stmt, fun); + break; + default: + break; + } + } + } + } return 0; } Index: gcc/sanitizer.def =================================================================== --- gcc/sanitizer.def (revision 250082) +++ gcc/sanitizer.def (working copy) @@ -529,6 +529,27 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DYNAMI DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_PC, "__sanitizer_cov_trace_pc", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP1, + "__sanitizer_cov_trace_cmp1", + BT_FN_VOID_UINT8_UINT8, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP2, + "__sanitizer_cov_trace_cmp2", + BT_FN_VOID_UINT16_UINT16, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP4, + "__sanitizer_cov_trace_cmp4", + BT_FN_VOID_UINT32_UINT32, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP8, + "__sanitizer_cov_trace_cmp8", + BT_FN_VOID_UINT64_UINT64, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMPF, + "__sanitizer_cov_trace_cmpf", + BT_FN_VOID_FLOAT_FLOAT, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMPD, + "__sanitizer_cov_trace_cmpd", + BT_FN_VOID_DOUBLE_DOUBLE, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_SWITCH, + "__sanitizer_cov_trace_switch", + BT_FN_VOID_UINT64_PTR, ATTR_NOTHROW_LEAF_LIST) /* This has to come after all the sanitizer builtins. */ DEF_BUILTIN_STUB(END_SANITIZER_BUILTINS, (const char *)0)