[llvm] e8d1c65 - [SanitizerCoverage] sancov/inline-bool-flag instrumentation.
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 8 22:44:05 PDT 2020
Author: Pratyai Mazumder
Date: 2020-04-08T22:43:52-07:00
New Revision: e8d1c6529b951131fe9c2636d672ed8073919820
URL: https://github.com/llvm/llvm-project/commit/e8d1c6529b951131fe9c2636d672ed8073919820
DIFF: https://github.com/llvm/llvm-project/commit/e8d1c6529b951131fe9c2636d672ed8073919820.diff
LOG: [SanitizerCoverage] sancov/inline-bool-flag instrumentation.
Summary:
New SanitizerCoverage feature `inline-bool-flag` which inserts an
atomic store of `1` to a boolean (which is an 8bit integer in
practice) flag on every instrumented edge.
Implementation-wise it's very similar to `inline-8bit-counters`
features. So, much of wiring and test just follows the same pattern.
Reviewers: kcc, vitalybuka
Reviewed By: vitalybuka
Subscribers: llvm-commits, hiraditya, jfb, cfe-commits, #sanitizers
Tags: #clang, #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D77244
Added:
llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-bool-flag.ll
llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll
llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-bool-flag.ll
Modified:
llvm/include/llvm/Transforms/Instrumentation.h
llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h
index fcad1e11895f..99cafba4f0a8 100644
--- a/llvm/include/llvm/Transforms/Instrumentation.h
+++ b/llvm/include/llvm/Transforms/Instrumentation.h
@@ -174,6 +174,7 @@ struct SanitizerCoverageOptions {
bool TracePC = false;
bool TracePCGuard = false;
bool Inline8bitCounters = false;
+ bool InlineBoolFlag = false;
bool PCTable = false;
bool NoPrune = false;
bool StackDepth = false;
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 98a0e0892786..6ab8ef1caa54 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -67,6 +67,8 @@ static const char *const SanCovModuleCtorTracePcGuardName =
"sancov.module_ctor_trace_pc_guard";
static const char *const SanCovModuleCtor8bitCountersName =
"sancov.module_ctor_8bit_counters";
+static const char *const SanCovModuleCtorBoolFlagName =
+ "sancov.module_ctor_bool_flag";
static const uint64_t SanCtorAndDtorPriority = 2;
static const char *const SanCovTracePCGuardName =
@@ -75,10 +77,13 @@ static const char *const SanCovTracePCGuardInitName =
"__sanitizer_cov_trace_pc_guard_init";
static const char *const SanCov8bitCountersInitName =
"__sanitizer_cov_8bit_counters_init";
+static const char *const SanCovBoolFlagInitName =
+ "__sanitizer_cov_bool_flag_init";
static const char *const SanCovPCsInitName = "__sanitizer_cov_pcs_init";
static const char *const SanCovGuardsSectionName = "sancov_guards";
static const char *const SanCovCountersSectionName = "sancov_cntrs";
+static const char *const SanCovBoolFlagSectionName = "sancov_bool_flag";
static const char *const SanCovPCsSectionName = "sancov_pcs";
static const char *const SanCovLowestStackName = "__sancov_lowest_stack";
@@ -101,7 +106,8 @@ static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",
// BBs, put this global into a named section, and pass this section's bounds
// to __sanitizer_cov_pcs_init.
// This way the coverage instrumentation does not need to acquire the PCs
-// at run-time. Works with trace-pc-guard and inline-8bit-counters.
+// at run-time. Works with trace-pc-guard, inline-8bit-counters, and
+// inline-bool-flag.
static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-pc-table",
cl::desc("create a static PC table"),
cl::Hidden, cl::init(false));
@@ -111,6 +117,11 @@ static cl::opt<bool>
cl::desc("increments 8-bit counter for every edge"),
cl::Hidden, cl::init(false));
+static cl::opt<bool>
+ ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag",
+ cl::desc("sets a boolean flag for every edge"), cl::Hidden,
+ cl::init(false));
+
static cl::opt<bool>
ClCMPTracing("sanitizer-coverage-trace-compares",
cl::desc("Tracing of CMP and similar instructions"),
@@ -169,11 +180,13 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
Options.TracePC |= ClTracePC;
Options.TracePCGuard |= ClTracePCGuard;
Options.Inline8bitCounters |= ClInline8bitCounters;
+ Options.InlineBoolFlag |= ClInlineBoolFlag;
Options.PCTable |= ClCreatePCTable;
Options.NoPrune |= !ClPruneBlocks;
Options.StackDepth |= ClStackDepth;
if (!Options.TracePCGuard && !Options.TracePC &&
- !Options.Inline8bitCounters && !Options.StackDepth)
+ !Options.Inline8bitCounters && !Options.StackDepth &&
+ !Options.InlineBoolFlag)
Options.TracePCGuard = true; // TracePCGuard is default.
return Options;
}
@@ -235,7 +248,7 @@ class ModuleSanitizerCoverage {
GlobalVariable *SanCovLowestStack;
InlineAsm *EmptyAsm;
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
- *Int16Ty, *Int8Ty, *Int8PtrTy;
+ *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
Module *CurModule;
std::string CurModuleUniqueId;
Triple TargetTriple;
@@ -244,6 +257,7 @@ class ModuleSanitizerCoverage {
GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters.
+ GlobalVariable *FunctionBoolArray; // for inline-bool-flag.
GlobalVariable *FunctionPCsArray; // for pc-table.
SmallVector<GlobalValue *, 20> GlobalsToAppendToUsed;
SmallVector<GlobalValue *, 20> GlobalsToAppendToCompilerUsed;
@@ -367,6 +381,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
TargetTriple = Triple(M.getTargetTriple());
FunctionGuardArray = nullptr;
Function8bitCounterArray = nullptr;
+ FunctionBoolArray = nullptr;
FunctionPCsArray = nullptr;
IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
IntptrPtrTy = PointerType::getUnqual(IntptrTy);
@@ -375,10 +390,12 @@ bool ModuleSanitizerCoverage::instrumentModule(
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
+ Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty());
Int64Ty = IRB.getInt64Ty();
Int32Ty = IRB.getInt32Ty();
Int16Ty = IRB.getInt16Ty();
Int8Ty = IRB.getInt8Ty();
+ Int1Ty = IRB.getInt1Ty();
SanCovTracePCIndir =
M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy);
@@ -462,6 +479,11 @@ bool ModuleSanitizerCoverage::instrumentModule(
Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
SanCov8bitCountersInitName, Int8PtrTy,
SanCovCountersSectionName);
+ if (FunctionBoolArray) {
+ Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName,
+ SanCovBoolFlagInitName, Int1PtrTy,
+ SanCovBoolFlagSectionName);
+ }
if (Ctor && Options.PCTable) {
auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
FunctionCallee InitFunction = declareSanitizerInitFunction(
@@ -699,6 +721,9 @@ void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
if (Options.Inline8bitCounters)
Function8bitCounterArray = CreateFunctionLocalArrayInSection(
AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName);
+ if (Options.InlineBoolFlag)
+ FunctionBoolArray = CreateFunctionLocalArrayInSection(
+ AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName);
if (Options.PCTable)
FunctionPCsArray = CreatePCArray(F, AllBlocks);
@@ -725,7 +750,8 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) {
if (IndirCalls.empty())
return;
- assert(Options.TracePC || Options.TracePCGuard || Options.Inline8bitCounters);
+ assert(Options.TracePC || Options.TracePCGuard ||
+ Options.Inline8bitCounters || Options.InlineBoolFlag);
for (auto I : IndirCalls) {
IRBuilder<> IRB(I);
CallSite CS(I);
@@ -884,6 +910,13 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
SetNoSanitizeMetadata(Load);
SetNoSanitizeMetadata(Store);
}
+ if (Options.InlineBoolFlag) {
+ auto FlagPtr = IRB.CreateGEP(
+ FunctionBoolArray->getValueType(), FunctionBoolArray,
+ {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
+ auto Store = IRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
+ SetNoSanitizeMetadata(Store);
+ }
if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {
// Check stack depth. If it's the deepest so far, record it.
Module *M = F.getParent();
@@ -908,6 +941,8 @@ ModuleSanitizerCoverage::getSectionName(const std::string &Section) const {
if (TargetTriple.isOSBinFormatCOFF()) {
if (Section == SanCovCountersSectionName)
return ".SCOV$CM";
+ if (Section == SanCovBoolFlagSectionName)
+ return ".SCOV$BM";
if (Section == SanCovPCsSectionName)
return ".SCOVP$M";
return ".SCOV$GM"; // For SanCovGuardsSectionName.
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-bool-flag.ll b/llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-bool-flag.ll
new file mode 100644
index 000000000000..9fcafa9a8b9a
--- /dev/null
+++ b/llvm/test/Instrumentation/SanitizerCoverage/coff-pc-table-inline-bool-flag.ll
@@ -0,0 +1,13 @@
+; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries.
+; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.14.26433"
+
+define void @foo() {
+entry:
+ ret void
+}
+
+; CHECK-DAG: section ".SCOV{{\$}}BM",
+; CHECK-DAG: section ".SCOVP{{\$}}M",
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll
new file mode 100644
index 000000000000..b7f8e83894cb
--- /dev/null
+++ b/llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll
@@ -0,0 +1,13 @@
+; Test -sanitizer-coverage-inline-bool-flag=1
+; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -S | FileCheck %s
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo() {
+entry:
+; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bool_flag", comdat($foo), align 1, !associated !0
+; CHECK: store i1 true, i1* getelementptr inbounds ([1 x i1], [1 x i1]* @__sancov_gen_, i64 0, i64 0), !nosanitize !1
+ ret void
+}
+; CHECK: call void @__sanitizer_cov_bool_flag_init(i1* bitcast (i1** @__start___sancov_bool_flag to i1*), i1* bitcast (i1** @__stop___sancov_bool_flag to i1*))
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll b/llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll
index dfed75610881..509abab59187 100644
--- a/llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll
+++ b/llvm/test/Instrumentation/SanitizerCoverage/pc-table.ll
@@ -1,8 +1,10 @@
; Test -sanitizer-coverage-pc-table=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s
+; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-bool-flag -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-bool-flag -sanitizer-coverage-pc-table=1 -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-bool-flag.ll b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-bool-flag.ll
new file mode 100644
index 000000000000..76f9dc9c1ccb
--- /dev/null
+++ b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard-inline-bool-flag.ll
@@ -0,0 +1,14 @@
+; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-bool-flag -S | FileCheck %s
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-bool-flag -S | FileCheck %s
+
+; Module ctors should have stable names across modules, not something like
+; @sancov.module_ctor.3 that may cause duplicate ctors after linked together.
+
+; CHECK: define internal void @sancov.module_ctor_trace_pc_guard() comdat {
+; CHECK: define internal void @sancov.module_ctor_bool_flag() comdat {
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo() {
+ ret void
+}
More information about the llvm-commits
mailing list