diff --git a/clang/docs/SanitizerCoverage.rst b/clang/docs/SanitizerCoverage.rst --- a/clang/docs/SanitizerCoverage.rst +++ b/clang/docs/SanitizerCoverage.rst @@ -139,6 +139,28 @@ // Capture this array in order to read/modify the counters. } + +Inline bool-flag +================ + +**Experimental, may change or disappear in future** + +With ``-fsanitize-coverage=inline-bool-flag`` the compiler will insert +setting an inline boolean to true on every edge. +This is similar to ``-fsanitize-coverage=inline-8bit-counter`` but instead of +an increment of a counter, it just sets a boolean to true. + +Users need to implement a single function to capture the flags at startup. + +.. code-block:: c++ + + extern "C" + void __sanitizer_cov_bool_flag_init(bool *start, bool *end) { + // [start,end) is the array of boolean flags created for the current DSO. + // Capture this array in order to read/modify the flags. + } + + PC-Table ======== @@ -150,8 +172,8 @@ `Bug 34636 `_. With ``-fsanitize-coverage=pc-table`` the compiler will create a table of -instrumented PCs. Requires either ``-fsanitize-coverage=inline-8bit-counters`` or -``-fsanitize-coverage=trace-pc-guard``. +instrumented PCs. Requires either ``-fsanitize-coverage=inline-8bit-counters``, +or ``-fsanitize-coverage=inline-bool-flag``, or ``-fsanitize-coverage=trace-pc-guard``. Users need to implement a single function to capture the PC table at startup: @@ -164,8 +186,9 @@ // pairs [PC,PCFlags] for every instrumented block in the current DSO. // Capture this array in order to read the PCs and their Flags. // The number of PCs and PCFlags for a given DSO is the same as the number - // of 8-bit counters (-fsanitize-coverage=inline-8bit-counters) or - // trace_pc_guard callbacks (-fsanitize-coverage=trace-pc-guard) + // of 8-bit counters (-fsanitize-coverage=inline-8bit-counters), or + // boolean flags (-fsanitize-coverage=inline=bool-flags), or trace_pc_guard + // callbacks (-fsanitize-coverage=trace-pc-guard). // A PCFlags describes the basic block: // * bit0: 1 if the block is the function entry block, 0 otherwise. } diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -232,6 +232,7 @@ CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. +CODEGENOPT(SanitizeCoverageInlineBoolFlag, 1, 0) ///< Use inline bool flag. CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table. CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -355,6 +355,9 @@ def fsanitize_coverage_inline_8bit_counters : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">, HelpText<"Enable inline 8-bit counters in sanitizer coverage">; +def fsanitize_coverage_inline_bool_flag + : Flag<["-"], "fsanitize-coverage-inline-bool-flag">, + HelpText<"Enable inline bool flag in sanitizer coverage">; def fsanitize_coverage_pc_table : Flag<["-"], "fsanitize-coverage-pc-table">, HelpText<"Create a table of coverage-instrumented PCs">; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -901,7 +901,7 @@ def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group, HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">, - Group, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">; + Group, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">; def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group; def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group; def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">, @@ -1019,7 +1019,7 @@ : CommaJoined<["-"], "fno-sanitize-coverage=">, Group, Flags<[CoreOption, DriverOption]>, HelpText<"Disable specified features of coverage instrumentation for " - "Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters">; + "Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters,inline-bool-flag">; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group, HelpText<"Enable origins tracking in MemorySanitizer">; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -222,6 +222,7 @@ Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard; Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune; Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; + Opts.InlineBoolFlag = CGOpts.SanitizeCoverageInlineBoolFlag; Opts.PCTable = CGOpts.SanitizeCoveragePCTable; Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; return Opts; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -77,17 +77,18 @@ CoverageBB = 1 << 1, CoverageEdge = 1 << 2, CoverageIndirCall = 1 << 3, - CoverageTraceBB = 1 << 4, // Deprecated. + CoverageTraceBB = 1 << 4, // Deprecated. CoverageTraceCmp = 1 << 5, CoverageTraceDiv = 1 << 6, CoverageTraceGep = 1 << 7, - Coverage8bitCounters = 1 << 8, // Deprecated. + Coverage8bitCounters = 1 << 8, // Deprecated. CoverageTracePC = 1 << 9, CoverageTracePCGuard = 1 << 10, CoverageNoPrune = 1 << 11, CoverageInline8bitCounters = 1 << 12, CoveragePCTable = 1 << 13, CoverageStackDepth = 1 << 14, + CoverageInlineBoolFlag = 1 << 15, }; /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any @@ -723,8 +724,9 @@ << "-fsanitize-coverage=trace-pc-guard"; int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge; - int InstrumentationTypes = - CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters; + int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard | + CoverageInline8bitCounters | + CoverageInlineBoolFlag; if ((CoverageFeatures & InsertionPointTypes) && !(CoverageFeatures & InstrumentationTypes)) { D.Diag(clang::diag::warn_drv_deprecated_arg) @@ -735,7 +737,8 @@ // trace-pc w/o func/bb/edge implies edge. if (!(CoverageFeatures & InsertionPointTypes)) { if (CoverageFeatures & - (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) + (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters | + CoverageInlineBoolFlag)) CoverageFeatures |= CoverageEdge; if (CoverageFeatures & CoverageStackDepth) @@ -907,21 +910,25 @@ // Do it even if Sanitizers.empty() since some forms of coverage don't require // sanitizers. std::pair CoverageFlags[] = { - std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"), - std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"), - std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"), - std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"), - std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"), - std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"), - std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"), - std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"), - std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), - std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), - std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"), - std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"), - std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"), - std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"), - std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")}; + std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"), + std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"), + std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"), + std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"), + std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"), + std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"), + std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"), + std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"), + std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"), + std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"), + std::make_pair(CoverageTracePCGuard, + "-fsanitize-coverage-trace-pc-guard"), + std::make_pair(CoverageInline8bitCounters, + "-fsanitize-coverage-inline-8bit-counters"), + std::make_pair(CoverageInlineBoolFlag, + "-fsanitize-coverage-inline-bool-flag"), + std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"), + std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"), + std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")}; for (auto F : CoverageFlags) { if (CoverageFeatures & F.first) CmdArgs.push_back(F.second); @@ -1105,22 +1112,23 @@ for (int i = 0, n = A->getNumValues(); i != n; ++i) { const char *Value = A->getValue(i); int F = llvm::StringSwitch(Value) - .Case("func", CoverageFunc) - .Case("bb", CoverageBB) - .Case("edge", CoverageEdge) - .Case("indirect-calls", CoverageIndirCall) - .Case("trace-bb", CoverageTraceBB) - .Case("trace-cmp", CoverageTraceCmp) - .Case("trace-div", CoverageTraceDiv) - .Case("trace-gep", CoverageTraceGep) - .Case("8bit-counters", Coverage8bitCounters) - .Case("trace-pc", CoverageTracePC) - .Case("trace-pc-guard", CoverageTracePCGuard) - .Case("no-prune", CoverageNoPrune) - .Case("inline-8bit-counters", CoverageInline8bitCounters) - .Case("pc-table", CoveragePCTable) - .Case("stack-depth", CoverageStackDepth) - .Default(0); + .Case("func", CoverageFunc) + .Case("bb", CoverageBB) + .Case("edge", CoverageEdge) + .Case("indirect-calls", CoverageIndirCall) + .Case("trace-bb", CoverageTraceBB) + .Case("trace-cmp", CoverageTraceCmp) + .Case("trace-div", CoverageTraceDiv) + .Case("trace-gep", CoverageTraceGep) + .Case("8bit-counters", Coverage8bitCounters) + .Case("trace-pc", CoverageTracePC) + .Case("trace-pc-guard", CoverageTracePCGuard) + .Case("no-prune", CoverageNoPrune) + .Case("inline-8bit-counters", CoverageInline8bitCounters) + .Case("inline-bool-flag", CoverageInlineBoolFlag) + .Case("pc-table", CoveragePCTable) + .Case("stack-depth", CoverageStackDepth) + .Default(0); if (F == 0) D.Diag(clang::diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1176,6 +1176,8 @@ Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); Opts.SanitizeCoverageInline8bitCounters = Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); + Opts.SanitizeCoverageInlineBoolFlag = + Args.hasArg(OPT_fsanitize_coverage_inline_bool_flag); Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table); Opts.SanitizeCoverageStackDepth = Args.hasArg(OPT_fsanitize_coverage_stack_depth); diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c --- a/clang/test/Driver/autocomplete.c +++ b/clang/test/Driver/autocomplete.c @@ -54,6 +54,7 @@ // FNOSANICOVERALL-NEXT: func // FNOSANICOVERALL-NEXT: indirect-calls // FNOSANICOVERALL-NEXT: inline-8bit-counters +// FNOSANICOVERALL-NEXT: inline-bool-flag // FNOSANICOVERALL-NEXT: no-prune // FNOSANICOVERALL-NEXT: trace-bb // FNOSANICOVERALL-NEXT: trace-cmp diff --git a/clang/test/Driver/fsanitize-coverage.c b/clang/test/Driver/fsanitize-coverage.c --- a/clang/test/Driver/fsanitize-coverage.c +++ b/clang/test/Driver/fsanitize-coverage.c @@ -105,9 +105,18 @@ // CHECK_INLINE8BIT-NOT: warning // CHECK_INLINE8BIT: -fsanitize-coverage-inline-8bit-counters -// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-8bit-counters,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE -// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=trace-pc-guard,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE -// CHECK_PC_TABLE: -fsanitize-coverage-pc-table +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-8bit-counters,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE_FOR_INLINE8BIT +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=trace-pc-guard,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE_FOR_INLINE8BIT +// CHECK_PC_TABLE_FOR_INLINE8BIT: -fsanitize-coverage-pc-table + +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-bool-flag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_INLINE_BOOL_FLAG +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=bb,inline-bool-flag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_INLINE_BOOL_FLAG +// CHECK_INLINE_BOOL_FLAG-NOT: warning +// CHECK_INLINE_BOOL_FLAG: -fsanitize-coverage-inline-bool-flag + +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-bool-flag,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE_FOR_INLINEBOOL +// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=trace-pc-guard,pc-table %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_PC_TABLE_FOR_INLINEBOOL +// CHECK_PC_TABLE_FOR_INLINEBOOL: -fsanitize-coverage-pc-table // RUN: %clang_cl --target=i386-pc-win32 -fsanitize=address -fsanitize-coverage=func,trace-pc-guard -c -### -- %s 2>&1 | FileCheck %s -check-prefix=CLANG-CL-COVERAGE // CLANG-CL-COVERAGE-NOT: error: