mirror of
https://github.com/intel/llvm.git
synced 2026-02-09 01:34:21 +08:00
[sanitizer-coverage] one more flavor of coverage: -fsanitize-coverage=inline-8bit-counters. Experimental so far, not documenting yet. Reapplying revisions 304630, 304631, 304632, 304673, see PR33308
llvm-svn: 305026
This commit is contained in:
@@ -293,6 +293,9 @@ def fsanitize_coverage_trace_gep
|
||||
def fsanitize_coverage_8bit_counters
|
||||
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
|
||||
HelpText<"Enable frequency counters in sanitizer coverage">;
|
||||
def fsanitize_coverage_inline_8bit_counters
|
||||
: Flag<["-"], "fsanitize-coverage-inline-8bit-counters">,
|
||||
HelpText<"Enable inline 8-bit counters in sanitizer coverage">;
|
||||
def fsanitize_coverage_trace_pc
|
||||
: Flag<["-"], "fsanitize-coverage-trace-pc">,
|
||||
HelpText<"Enable PC tracing in sanitizer coverage">;
|
||||
|
||||
@@ -163,6 +163,7 @@ CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters.
|
||||
CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning.
|
||||
CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
|
||||
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
|
||||
|
||||
@@ -187,6 +187,7 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
|
||||
Opts.TracePC = CGOpts.SanitizeCoverageTracePC;
|
||||
Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
|
||||
Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;
|
||||
Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
|
||||
PM.add(createSanitizerCoverageModulePass(Opts));
|
||||
}
|
||||
|
||||
|
||||
@@ -48,13 +48,14 @@ enum CoverageFeature {
|
||||
CoverageBB = 1 << 1,
|
||||
CoverageEdge = 1 << 2,
|
||||
CoverageIndirCall = 1 << 3,
|
||||
CoverageTraceBB = 1 << 4,
|
||||
CoverageTraceBB = 1 << 4, // Deprecated.
|
||||
CoverageTraceCmp = 1 << 5,
|
||||
CoverageTraceDiv = 1 << 6,
|
||||
CoverageTraceGep = 1 << 7,
|
||||
Coverage8bitCounters = 1 << 8,
|
||||
Coverage8bitCounters = 1 << 8, // Deprecated.
|
||||
CoverageTracePC = 1 << 9,
|
||||
CoverageTracePCGuard = 1 << 10,
|
||||
CoverageInline8bitCounters = 1 << 12,
|
||||
CoverageNoPrune = 1 << 11,
|
||||
};
|
||||
|
||||
@@ -530,7 +531,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
||||
}
|
||||
|
||||
// trace-pc w/o func/bb/edge implies edge.
|
||||
if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) &&
|
||||
if ((CoverageFeatures &
|
||||
(CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters)) &&
|
||||
!(CoverageFeatures & InsertionPointTypes))
|
||||
CoverageFeatures |= CoverageEdge;
|
||||
|
||||
@@ -637,6 +639,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
|
||||
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(CoverageNoPrune, "-fsanitize-coverage-no-prune")};
|
||||
for (auto F : CoverageFlags) {
|
||||
if (CoverageFeatures & F.first)
|
||||
@@ -798,6 +801,7 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
|
||||
.Case("trace-pc", CoverageTracePC)
|
||||
.Case("trace-pc-guard", CoverageTracePCGuard)
|
||||
.Case("no-prune", CoverageNoPrune)
|
||||
.Case("inline-8bit-counters", CoverageInline8bitCounters)
|
||||
.Default(0);
|
||||
if (F == 0)
|
||||
D.Diag(clang::diag::err_drv_unsupported_option_argument)
|
||||
|
||||
@@ -768,6 +768,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
||||
Opts.SanitizeCoverageTracePCGuard =
|
||||
Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard);
|
||||
Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune);
|
||||
Opts.SanitizeCoverageInline8bitCounters =
|
||||
Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters);
|
||||
Opts.SanitizeMemoryTrackOrigins =
|
||||
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
|
||||
Opts.SanitizeMemoryUseAfterDtor =
|
||||
|
||||
@@ -85,6 +85,9 @@
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=no-prune,func,trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_NOPRUNE
|
||||
// CHECK_NOPRUNE: -fsanitize-coverage-no-prune
|
||||
|
||||
// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=inline-8bit-counters %s -### 2>&1 | FileCheck %s --check-prefix=CHECK_INLINE8BIT
|
||||
// CHECK_INLINE8BIT: -fsanitize-coverage-inline-8bit-counters
|
||||
|
||||
// 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:
|
||||
// CLANG-CL-COVERAGE-NOT: warning:
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Tests -fsanitize-coverage=inline-8bit-counters
|
||||
//
|
||||
// REQUIRES: has_sancovcc,stable-runtime
|
||||
// UNSUPPORTED: i386-darwin, x86_64-darwin
|
||||
//
|
||||
// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters 2>&1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char *first_counter;
|
||||
|
||||
extern "C"
|
||||
void __sanitizer_cov_8bit_counters_init(const char *start, const char *end) {
|
||||
printf("INIT: %p %p\n", start, end);
|
||||
assert(end - start > 1);
|
||||
first_counter = start;
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(first_counter);
|
||||
assert(*first_counter == 1);
|
||||
}
|
||||
@@ -177,6 +177,7 @@ struct SanitizerCoverageOptions {
|
||||
bool Use8bitCounters = false;
|
||||
bool TracePC = false;
|
||||
bool TracePCGuard = false;
|
||||
bool Inline8bitCounters = false;
|
||||
bool NoPrune = false;
|
||||
|
||||
SanitizerCoverageOptions() = default;
|
||||
|
||||
@@ -57,8 +57,11 @@ static const char *const SanCovTracePCGuardName =
|
||||
"__sanitizer_cov_trace_pc_guard";
|
||||
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 SanCovGuardsSectionName = "sancov_guards";
|
||||
static const char *const SanCovCountersSectionName = "sancov_counters";
|
||||
|
||||
static cl::opt<int> ClCoverageLevel(
|
||||
"sanitizer-coverage-level",
|
||||
@@ -66,14 +69,18 @@ static cl::opt<int> ClCoverageLevel(
|
||||
"3: all blocks and critical edges"),
|
||||
cl::Hidden, cl::init(0));
|
||||
|
||||
static cl::opt<bool> ClExperimentalTracePC("sanitizer-coverage-trace-pc",
|
||||
cl::desc("Experimental pc tracing"),
|
||||
cl::Hidden, cl::init(false));
|
||||
static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc",
|
||||
cl::desc("Experimental pc tracing"), cl::Hidden,
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",
|
||||
cl::desc("pc tracing with a guard"),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
static cl::opt<bool> ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters",
|
||||
cl::desc("increments 8-bit counter 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"),
|
||||
@@ -125,9 +132,10 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
||||
Options.TraceCmp |= ClCMPTracing;
|
||||
Options.TraceDiv |= ClDIVTracing;
|
||||
Options.TraceGep |= ClGEPTracing;
|
||||
Options.TracePC |= ClExperimentalTracePC;
|
||||
Options.TracePC |= ClTracePC;
|
||||
Options.TracePCGuard |= ClTracePCGuard;
|
||||
if (!Options.TracePCGuard && !Options.TracePC)
|
||||
Options.Inline8bitCounters |= ClInline8bitCounters;
|
||||
if (!Options.TracePCGuard && !Options.TracePC && !Options.Inline8bitCounters)
|
||||
Options.TracePCGuard = true; // TracePCGuard is default.
|
||||
Options.NoPrune |= !ClPruneBlocks;
|
||||
return Options;
|
||||
@@ -169,6 +177,11 @@ private:
|
||||
void CreateInitCallForSection(Module &M, const char *InitFunctionName,
|
||||
Type *Ty, const std::string &Section);
|
||||
|
||||
void SetNoSanitizeMetadata(Instruction *I) {
|
||||
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
|
||||
MDNode::get(*C, None));
|
||||
}
|
||||
|
||||
std::string getSectionName(const std::string &Section) const;
|
||||
std::string getSectionStart(const std::string &Section) const;
|
||||
std::string getSectionEnd(const std::string &Section) const;
|
||||
@@ -179,13 +192,15 @@ private:
|
||||
Function *SanCovTraceGepFunction;
|
||||
Function *SanCovTraceSwitchFunction;
|
||||
InlineAsm *EmptyAsm;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
|
||||
*Int8Ty, *Int8PtrTy;
|
||||
Module *CurModule;
|
||||
Triple TargetTriple;
|
||||
LLVMContext *C;
|
||||
const DataLayout *DL;
|
||||
|
||||
GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
|
||||
GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters.
|
||||
|
||||
SanitizerCoverageOptions Options;
|
||||
};
|
||||
@@ -227,14 +242,17 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||
CurModule = &M;
|
||||
TargetTriple = Triple(M.getTargetTriple());
|
||||
FunctionGuardArray = nullptr;
|
||||
Function8bitCounterArray = nullptr;
|
||||
IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
|
||||
IntptrPtrTy = PointerType::getUnqual(IntptrTy);
|
||||
Type *VoidTy = Type::getVoidTy(*C);
|
||||
IRBuilder<> IRB(*C);
|
||||
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
|
||||
Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
||||
Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
|
||||
Int64Ty = IRB.getInt64Ty();
|
||||
Int32Ty = IRB.getInt32Ty();
|
||||
Int8Ty = IRB.getInt8Ty();
|
||||
|
||||
SanCovTracePCIndir = checkSanitizerInterfaceFunction(
|
||||
M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy));
|
||||
@@ -280,6 +298,9 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||
if (FunctionGuardArray)
|
||||
CreateInitCallForSection(M, SanCovTracePCGuardInitName, Int32PtrTy,
|
||||
SanCovGuardsSectionName);
|
||||
if (Function8bitCounterArray)
|
||||
CreateInitCallForSection(M, SanCov8bitCountersInitName, Int8PtrTy,
|
||||
SanCovCountersSectionName);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -420,6 +441,9 @@ void SanitizerCoverageModule::CreateFunctionLocalArrays(size_t NumGuards,
|
||||
if (Options.TracePCGuard)
|
||||
FunctionGuardArray = CreateFunctionLocalArrayInSection(
|
||||
NumGuards, F, Int32Ty, SanCovGuardsSectionName);
|
||||
if (Options.Inline8bitCounters)
|
||||
Function8bitCounterArray = CreateFunctionLocalArrayInSection(
|
||||
NumGuards, F, Int8Ty, SanCovCountersSectionName);
|
||||
}
|
||||
|
||||
bool SanitizerCoverageModule::InjectCoverage(Function &F,
|
||||
@@ -452,7 +476,7 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
|
||||
Function &F, ArrayRef<Instruction *> IndirCalls) {
|
||||
if (IndirCalls.empty())
|
||||
return;
|
||||
assert(Options.TracePC || Options.TracePCGuard);
|
||||
assert(Options.TracePC || Options.TracePCGuard || Options.Inline8bitCounters);
|
||||
for (auto I : IndirCalls) {
|
||||
IRBuilder<> IRB(I);
|
||||
CallSite CS(I);
|
||||
@@ -580,8 +604,8 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
if (Options.TracePC) {
|
||||
IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC.
|
||||
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
||||
} else {
|
||||
assert(Options.TracePCGuard);
|
||||
}
|
||||
if (Options.TracePCGuard) {
|
||||
auto GuardPtr = IRB.CreateIntToPtr(
|
||||
IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||
ConstantInt::get(IntptrTy, Idx * 4)),
|
||||
@@ -589,6 +613,16 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
|
||||
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
||||
}
|
||||
if (Options.Inline8bitCounters) {
|
||||
auto CounterPtr = IRB.CreateGEP(
|
||||
Function8bitCounterArray,
|
||||
{ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
|
||||
auto Load = IRB.CreateLoad(CounterPtr);
|
||||
auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1));
|
||||
auto Store = IRB.CreateStore(Inc, CounterPtr);
|
||||
SetNoSanitizeMetadata(Load);
|
||||
SetNoSanitizeMetadata(Store);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
; Test -sanitizer-coverage-inline-8bit-counters=1
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=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: %0 = load i8, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @__sancov_gen_, i64 0, i64 0), !nosanitize
|
||||
; CHECK: %1 = add i8 %0, 1
|
||||
; CHECK: store i8 %1, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @__sancov_gen_, i64 0, i64 0), !nosanitize
|
||||
ret void
|
||||
}
|
||||
; CHECK: call void @__sanitizer_cov_8bit_counters_init(i8* bitcast (i8** @__start___sancov_counters to i8*), i8* bitcast (i8** @__stop___sancov_counters to i8*))
|
||||
Reference in New Issue
Block a user