From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18143 invoked by alias); 13 Jul 2017 10:41:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 17513 invoked by uid 89); 13 Jul 2017 10:41:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-12.0 required=5.0 tests=AWL,BAYES_00,BODY_8BITS,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GARBLED_BODY,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_LOW,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy= X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-qt0-f178.google.com Received: from mail-qt0-f178.google.com (HELO mail-qt0-f178.google.com) (209.85.216.178) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 13 Jul 2017 10:41:25 +0000 Received: by mail-qt0-f178.google.com with SMTP id b40so34212043qtb.2; Thu, 13 Jul 2017 03:41:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=DRlIstpZorzxnRfvRvZzTMxoWMWcqH7JZapJ4i8Zo34=; b=Nn5NwGEsyha6LxSkuE6dzBuF4dXoLsTPp3pYre6j6YaUN9tHICxTWDyBD6MlD81sS9 DjiK7khlq+6t+dB29KcgEgTsFgD31qWHD1FzgP0oikuhr47dqNmgU8RuleRlIGdU7RPM C2bRcUt6aTcuSTN5SwCtHm6KnV7+Pf1IOKfoKKUyTXPzE1uu9BOhk8Txc/j8MGostPTk xjhWQN5eaMIXkrlgwRlI7PQfS0tTg27WtP7OJDZwIHzKN1LjLyLxMAccfJwKp/XQ6qkr ypBasleMExGQzNFTnjiz+we/Vc0g+TSqhoyQu5LnUCOqOXbUKUqGJ1yNC1DC1ozhZJ8p W4fg== X-Gm-Message-State: AIVw113CHAObSFQuzP1qKT3OtJr7BfDrEWVRNeg513Eq2xGAudCOeIu/ 3J0zo4GjK5fyn/eMAEg0E5DHAWvVXg== X-Received: by 10.200.47.176 with SMTP id l45mr4099040qta.153.1499942483212; Thu, 13 Jul 2017 03:41:23 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.30.163 with HTTP; Thu, 13 Jul 2017 03:41:22 -0700 (PDT) In-Reply-To: References: <234840fd-a06a-4dfd-a1c5-254e26144754.weixi.wwx@antfin.com> From: Wish Wu Date: Thu, 13 Jul 2017 10:41:00 -0000 Message-ID: Subject: Re: Add support to trace comparison instructions and switch statements To: Dmitry Vyukov Cc: gcc , gcc-patches , weixi.wwx@antfin.com, Kostya Serebryany , Alexander Potapenko , andreyknvl , Victor Chibotaru , Yuri Gribov Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-SW-Source: 2017-07/txt/msg00724.txt.bz2 Hi In fact, under linux with "return address" and file "/proc/self/maps", we can give unique id for every comparison. For fuzzing, we may give 3 bits for every comparison as marker of if "<", "=3D=3D" or ">" is showed. :D With Regards Wish Wu of Ant-financial Light-Year Security Lab On Thu, Jul 13, 2017 at 6:04 PM, Wish Wu wrote: > Hi > > In my perspective: > > 1. Do we need to assign unique id for every comparison ? > Yes, I suggest to implement it like -fsanitize-coverage=3Dtrace-pc-gu= ard . > Because some fuzzing targets may invoke dlopen() like functions to > load libraries(modules) after fork(), while these libraries are > compiled with trace-cmp as well. > With ALSR enabled by linker and/or kernel, return address can't be > a unique id for every comparison. > > 2. Should we merge cmp1(),cmp2(),cmp4(),cmp8(),cmpf(),cmpd() into one cmp= () ? > No, It may reduce the performance of fuzzing. It may wastes > registers. But the number "switch" statements are much less than "if", > I forgive "switch"'s wasting behaviors. > > 3.Should we record operands(<,>,=3D=3D,<=3D ......) ? > Probably no. As comparison,"<" , "=3D=3D" and ">" all of them are > meaningful, because programmers must have some reasons to do that. As > practice , "=3D=3D" is more meaningful. > > 4.Should we record comparisons for counting loop checks ? > Not sure. > > With Regards > Wish Wu of Ant-financial Light-Year Security Lab > > On Thu, Jul 13, 2017 at 4:09 PM, Dmitry Vyukov wrote: >> On Tue, Jul 11, 2017 at 1:59 PM, Wish Wu wrote: >>> Hi >>> >>> I wrote a test for "-fsanitize-coverage=3Dtrace-cmp" . >>> >>> Is there anybody tells me if these codes could be merged into gcc ? >> >> >> Nice! >> >> We are currently working on Linux kernel fuzzing that use the >> comparison tracing. We use clang at the moment, but having this >> support in gcc would be great for kernel land. >> >> One concern I have: do we want to do some final refinements to the API >> before we implement this in both compilers? >> >> 2 things we considered from our perspective: >> - communicating to the runtime which operands are constants >> - communicating to the runtime which comparisons are counting loop chec= ks >> >> First is useful if you do "find one operand in input and replace with >> the other one" thing. Second is useful because counting loop checks >> are usually not useful (at least all but one). >> In the original Go implementation I also conveyed signedness of >> operands, exact comparison operation (<, >, etc): >> https://github.com/dvyukov/go-fuzz/blob/master/go-fuzz-defs/defs.go#L13 >> But I did not find any use for that. >> I also gave all comparisons unique IDs: >> https://github.com/dvyukov/go-fuzz/blob/master/go-fuzz-dep/sonar.go#L24 >> That turned out to be useful. And there are chances we will want this >> for C/C++ as well. >> >> Kostya, did anything like this pop up in your work on libfuzzer? >> Can we still change the clang API? At least add an additional argument >> to the callbacks? >> >> At the very least I would suggest that we add an additional arg that >> contains some flags (1/2 arg is a const, this is counting loop check, >> etc). If we do that we can also have just 1 callback that accepts >> uint64's for args because we can pass operand size in the flags: >> >> void __sanitizer_cov_trace_cmp(uint64 arg1, uint64 arg2, uint64 flags); >> >> But I wonder if 3 uint64 args will be too inefficient for 32 bit archs?.= .. >> >> If we create a global per comparison then we could put the flags into >> the global: >> >> void __sanitizer_cov_trace_cmp(uint64 arg1, uint64 arg2, something_t *gl= obal); >> >> Thoughts? >> >> >> >> >>> Index: gcc/testsuite/gcc.dg/sancov/basic3.c >>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>> --- gcc/testsuite/gcc.dg/sancov/basic3.c (nonexistent) >>> +++ gcc/testsuite/gcc.dg/sancov/basic3.c (working copy) >>> @@ -0,0 +1,42 @@ >>> +/* Basic test on number of inserted callbacks. */ >>> +/* { dg-do compile } */ >>> +/* { dg-options "-fsanitize-coverage=3Dtrace-cmp -fdump-tree-optimized= " } */ >>> + >>> +void foo(char *a, short *b, int *c, long long *d, float *e, double *f) >>> +{ >>> + if (*a) >>> + *a +=3D 1; >>> + if (*b) >>> + *b =3D *a; >>> + if (*c) >>> + *c +=3D 1; >>> + if(*d) >>> + *d =3D *c; >>> + if(*e =3D=3D *c) >>> + *e =3D *c; >>> + if(*f =3D=3D *e) >>> + *f =3D *e; >>> + switch(*a) >>> + { >>> + case 2: >>> + *b +=3D 2; >>> + break; >>> + default: >>> + break; >>> + } >>> + switch(*d) >>> + { >>> + case 3: >>> + *d +=3D 3; >>> + case -4: >>> + *d -=3D 4; >>> + } >>> +} >>> + >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmp1 \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmp2 \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmp4 \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmp8 \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmpf \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_cmpd \\(" 1 "optimized" } } */ >>> +/* { dg-final { scan-tree-dump-times >>> "__builtin___sanitizer_cov_trace_switch \\(" 2 "optimized" } } */ >>> >>> >>> With Regards >>> Wish Wu >>> >>> On Mon, Jul 10, 2017 at 8:07 PM, =E5=90=B4=E6=BD=8D=E6=B5=A0(=E6=AD=A4= =E5=BD=BC) wrote: >>>> Hi >>>> >>>> I write some codes to make gcc support comparison-guided fuzzing. >>>> It is very like http://clang.llvm.org/docs/SanitizerCoverage.html#trac= ing-data-flow . >>>> With -fsanitize-coverage=3Dtrace-cmp the compiler will insert extra in= strumentation 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 >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- 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 >>>> =3D build_function_type_list (size_type_node, const_ptr_type_node, >>>> integer_type_node, NULL_TREE); >>>> + >>>> + tree BT_FN_VOID_UINT8_UINT8 >>>> + =3D build_function_type_list (void_type_node, unsigned_char_type_= node, >>>> + unsigned_char_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_UINT16_UINT16 >>>> + =3D build_function_type_list (void_type_node, uint16_type_node, >>>> + uint16_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_UINT32_UINT32 >>>> + =3D build_function_type_list (void_type_node, uint32_type_node, >>>> + uint32_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_UINT64_UINT64 >>>> + =3D build_function_type_list (void_type_node, uint64_type_node, >>>> + uint64_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_FLOAT_FLOAT >>>> + =3D build_function_type_list (void_type_node, float_type_node, >>>> + float_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_DOUBLE_DOUBLE >>>> + =3D build_function_type_list (void_type_node, double_type_node, >>>> + double_type_node, NULL_TREE); >>>> + tree BT_FN_VOID_UINT64_PTR >>>> + =3D 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 >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- 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 >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- gcc/common.opt (revision 250082) >>>> +++ gcc/common.opt (working copy) >>>> @@ -226,10 +226,9 @@ unsigned int flag_sanitize >>>> Variable >>>> unsigned int flag_sanitize_recover =3D (SANITIZE_UNDEFINED | SANITIZE= _UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS) & ~(SANITIZE_UNREACHABLE |= SANITIZE_RETURN) >>>> >>>> -fsanitize-coverage=3Dtrace-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=3D >>>> Common Driver Report Joined >>>> Select what to sanitize. >>>> >>>> +fsanitize-coverage=3D >>>> +Common Driver Report Joined >>>> +Select what to coverage sanitize. >>>> + >>>> fasan-shadow-offset=3D >>>> Common Joined RejectNegative Var(common_deferred_options) Defer >>>> -fasan-shadow-offset=3D Use custom shadow memory offset. >>>> Index: gcc/flag-types.h >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- 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 =3D 1UL << 0, >>>> + /* Trace Compare */ >>>> + SANITIZE_COV_TRACE_CMP =3D 1UL << 1 >>>> +}; >>>> + >>>> /* flag_vtable_verify initialization levels. */ >>>> enum vtv_priority { >>>> VTV_NO_PRIORITY =3D 0, /* i.E. Do NOT do vtable verification= . */ >>>> Index: gcc/opts.c >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- gcc/opts.c (revision 250082) >>>> +++ gcc/opts.c (working copy) >>>> @@ -1518,6 +1518,17 @@ const struct sanitizer_opts_s sanitizer_opts[] = =3D >>>> { NULL, 0U, 0UL, false } >>>> }; >>>> >>>> +/* -f{,no-}sanitize-coverage=3D suboptions. */ >>>> +const struct sanitizer_opts_s coverage_sanitizer_opts[] =3D >>>> +{ >>>> +#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, locatio= n_t >>>> return flags; >>>> } >>>> >>>> +/* Given ARG, an unrecognized coverage sanitizer option, return the b= est >>>> + 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=3D"). */ >>>> + >>>> +static const char * >>>> +get_closest_coverage_sanitizer_option (const string_fragment &arg, in= t value) >>>> +{ >>>> + best_match bm (arg); >>>> + for (int i =3D 0; coverage_sanitizer_opts[i].name !=3D 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 !=3D 0) >>>> + { >>>> + size_t len, i; >>>> + bool found =3D false; >>>> + const char *comma =3D strchr (p, ','); >>>> + >>>> + if (comma =3D=3D NULL) >>>> + len =3D strlen (p); >>>> + else >>>> + len =3D comma - p; >>>> + if (len =3D=3D 0) >>>> + { >>>> + p =3D comma + 1; >>>> + continue; >>>> + } >>>> + >>>> + /* Check to see if the string matches an option class name. */ >>>> + for (i =3D 0; coverage_sanitizer_opts[i].name !=3D NULL; ++i) >>>> + if (len =3D=3D coverage_sanitizer_opts[i].len >>>> + && memcmp (p, coverage_sanitizer_opts[i].name, len) =3D=3D= 0) >>>> + { >>>> + if (value) >>>> + flags |=3D coverage_sanitizer_opts[i].flag; >>>> + else >>>> + flags &=3D ~coverage_sanitizer_opts[i].flag; >>>> + found =3D true; >>>> + break; >>>> + } >>>> + >>>> + if (! found && complain) >>>> + { >>>> + const char *hint >>>> + =3D get_closest_coverage_sanitizer_option (string_fragment= (p, len), >>>> + value); >>>> + >>>> + if (hint) >>>> + error_at (loc, >>>> + "unrecognized argument to -f%ssanitize-coverage= =3D option: %q.*s;" >>>> + " did you mean %qs?", >>>> + value ? "" : "no-", >>>> + (int) len, p, hint); >>>> + else >>>> + error_at (loc, >>>> + "unrecognized argument to -f%ssanitize-coverage= =3D option: %q.*s", >>>> + value ? "" : "no-", >>>> + (int) len, p); >>>> + } >>>> + >>>> + if (comma =3D=3D NULL) >>>> + break; >>>> + p =3D 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, >>>> &=3D ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); >>>> break; >>>> >>>> + case OPT_fsanitize_coverage_: >>>> + opts->x_flag_sanitize_coverage >>>> + =3D parse_coverage_sanitizer_options (arg, loc, >>>> + opts->x_flag_sanitize_coverage, val= ue, true); >>>> + break; >>>> + >>>> case OPT_O: >>>> case OPT_Os: >>>> case OPT_Ofast: >>>> Index: gcc/sancov.c >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- 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 =3D gimple_cond_lhs (stmt); >>>> + tree rhs =3D gimple_cond_rhs (stmt); >>>> + unsigned int bitno =3D TYPE_PRECISION (TREE_TYPE (lhs)) > TYPE_PREC= ISION (TREE_TYPE (rhs)) ? >>>> + TYPE_PRECISION (TREE_TYPE (lhs)) : TYPE_PRECISI= ON (TREE_TYPE (rhs)); >>>> + if (TREE_CODE (TREE_TYPE (lhs)) =3D=3D INTEGER_TYPE) >>>> + { >>>> + enum built_in_function fncode; >>>> + switch (bitno) >>>> + { >>>> + case 8: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMP1; >>>> + break; >>>> + >>>> + case 16: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMP2; >>>> + break; >>>> + >>>> + case 32: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMP4; >>>> + break; >>>> + >>>> + case 64: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMP8; >>>> + break; >>>> + >>>> + default: >>>> + return; >>>> + break; >>>> + } >>>> + tree fndecl =3D builtin_decl_implicit (fncode); >>>> + gimple *gcall =3D 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)) =3D=3D REAL_TYPE) >>>> + { >>>> + enum built_in_function fncode; >>>> + switch (bitno) >>>> + { >>>> + case 32: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMPF; >>>> + break; >>>> + >>>> + case 64: >>>> + fncode =3D BUILT_IN_SANITIZER_COV_TRACE_CMPD; >>>> + break; >>>> + >>>> + default: >>>> + return; >>>> + break; >>>> + } >>>> + tree fndecl =3D builtin_decl_implicit (fncode); >>>> + gimple *gcall =3D 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 =3D as_a (stmt); >>>> + tree index =3D gimple_switch_index (switch_stmt); >>>> + unsigned bitno =3D TYPE_PRECISION (TREE_TYPE (index)); >>>> + unsigned i, n =3D gimple_switch_num_labels (switch_stmt), num =3D 0; >>>> + for (i =3D 0; i < n; ++i) >>>> + { >>>> + tree label =3D gimple_switch_label (switch_stmt, i); >>>> + tree low_case =3D CASE_LOW (label); >>>> + if (low_case !=3D NULL_TREE) >>>> + num++; >>>> + tree high_case =3D CASE_HIGH (label); >>>> + if (high_case !=3D NULL_TREE) >>>> + num++; >>>> + } >>>> + >>>> + tree case_array_elem_type =3D build_type_variant (uint64_type_node,= 1, 0); >>>> + tree case_array_type =3D build_array_type (case_array_elem_type, >>>> + build_index_type (size_int = (num + 2 - 1))); >>>> + char name[64]; >>>> + static size_t case_array_count =3D 0; >>>> + snprintf(name, sizeof(name) - 1, "__sanitizer_cov_trace_switch_arra= y%lu", case_array_count++); >>>> + tree case_array_var =3D build_decl (UNKNOWN_LOCATION, VAR_DECL, >>>> + get_identifier (name), case_array_= type); >>>> + TREE_STATIC (case_array_var) =3D 1; >>>> + TREE_PUBLIC (case_array_var) =3D 0; >>>> + TREE_CONSTANT (case_array_var) =3D 1; >>>> + TREE_READONLY (case_array_var) =3D 1; >>>> + DECL_EXTERNAL (case_array_var) =3D 0; >>>> + DECL_ARTIFICIAL (case_array_var) =3D 1; >>>> + DECL_IGNORED_P (case_array_var) =3D 1; >>>> + >>>> + vec *v =3D NULL; >>>> + vec_alloc (v, num + 2); >>>> + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (uint64_type_no= de, num)); >>>> + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (uint64_type_no= de, bitno)); >>>> + for (i =3D 0; i < n; ++i) >>>> + { >>>> + tree label =3D gimple_switch_label (switch_stmt, i); >>>> + >>>> + tree low_case =3D CASE_LOW (label); >>>> + if (low_case !=3D NULL_TREE) >>>> + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, >>>> + build_int_cst (uint64_type_node, TREE_= INT_CST_LOW (low_case))); >>>> + >>>> + tree high_case =3D CASE_HIGH (label); >>>> + if (high_case !=3D NULL_TREE) >>>> + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, >>>> + build_int_cst (uint64_type_node, TREE_= INT_CST_LOW (high_case))); >>>> + } >>>> + tree ctor =3D build_constructor (case_array_type, v); >>>> + TREE_STATIC (ctor) =3D 1; >>>> + TREE_PUBLIC (ctor) =3D 0; >>>> + TREE_CONSTANT (ctor) =3D 1; >>>> + TREE_READONLY (ctor) =3D 1; >>>> + DECL_EXTERNAL (ctor) =3D 0; >>>> + DECL_INITIAL (case_array_var) =3D ctor; >>>> + varpool_node::finalize_decl (case_array_var); >>>> + >>>> + tree case_array_var_ref =3D build_fold_addr_expr (case_array_var); >>>> + add_local_decl (fun, case_array_var); >>>> + tree fndecl =3D builtin_decl_implicit (BUILT_IN_SANITIZER_COV_TRACE= _SWITCH); >>>> + gimple *gcall =3D gimple_build_call (fndecl, 2, index, case_array_v= ar_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 =3D 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 =3D gsi_start_nondebug_after_labels_bb= (bb); >>>> - if (gsi_end_p (gsi)) >>>> - continue; >>>> - gimple *stmt =3D gsi_stmt (gsi); >>>> - gimple *gcall =3D gimple_build_call (fndecl, 0); >>>> - gimple_set_location (gcall, gimple_location (stmt)); >>>> - gsi_insert_before (&gsi, gcall, GSI_SAME_STMT); >>>> + tree fndecl =3D builtin_decl_implicit (BUILT_IN_SANITIZER_COV_T= RACE_PC); >>>> + FOR_EACH_BB_FN (bb, fun) >>>> + { >>>> + gimple_stmt_iterator gsi =3D gsi_start_nondebug_after_label= s_bb (bb); >>>> + if (gsi_end_p (gsi)) >>>> + continue; >>>> + gimple *stmt =3D gsi_stmt (gsi); >>>> + gimple *gcall =3D 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 =3D gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next = (&gsi)) >>>> + { >>>> + gimple *stmt =3D 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 >>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>> --- 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)