mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[sanitizer-coverage] add yet another flavour of coverage instrumentation: trace-pc-guard. The intent is to eventually replace all of {bool coverage, 8bit-counters, trace-pc} with just this one. LLVM part
llvm-svn: 281431
This commit is contained in:
parent
6613b97f48
commit
562a9d7d62
@ -137,7 +137,7 @@ struct SanitizerCoverageOptions {
|
|||||||
SanitizerCoverageOptions()
|
SanitizerCoverageOptions()
|
||||||
: CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
|
: CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
|
||||||
TraceCmp(false), TraceDiv(false), TraceGep(false),
|
TraceCmp(false), TraceDiv(false), TraceGep(false),
|
||||||
Use8bitCounters(false), TracePC(false) {}
|
Use8bitCounters(false), TracePC(false), TracePCGuard(false) {}
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
SCK_None = 0,
|
SCK_None = 0,
|
||||||
@ -152,6 +152,7 @@ struct SanitizerCoverageOptions {
|
|||||||
bool TraceGep;
|
bool TraceGep;
|
||||||
bool Use8bitCounters;
|
bool Use8bitCounters;
|
||||||
bool TracePC;
|
bool TracePC;
|
||||||
|
bool TracePCGuard;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Insert SanitizerCoverage instrumentation.
|
// Insert SanitizerCoverage instrumentation.
|
||||||
|
@ -78,6 +78,12 @@ static const char *const SanCovTraceSwitchName = "__sanitizer_cov_trace_switch";
|
|||||||
static const char *const SanCovModuleCtorName = "sancov.module_ctor";
|
static const char *const SanCovModuleCtorName = "sancov.module_ctor";
|
||||||
static const uint64_t SanCtorAndDtorPriority = 2;
|
static const uint64_t SanCtorAndDtorPriority = 2;
|
||||||
|
|
||||||
|
static const char *const SanCovTracePCGuardSection = "__sancov_guards";
|
||||||
|
static const char *const SanCovTracePCGuardName =
|
||||||
|
"__sanitizer_cov_trace_pc_guard";
|
||||||
|
static const char *const SanCovTracePCGuardInitName =
|
||||||
|
"__sanitizer_cov_trace_pc_guard_init";
|
||||||
|
|
||||||
static cl::opt<int> ClCoverageLevel(
|
static cl::opt<int> ClCoverageLevel(
|
||||||
"sanitizer-coverage-level",
|
"sanitizer-coverage-level",
|
||||||
cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
|
cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
|
||||||
@ -101,6 +107,10 @@ static cl::opt<bool> ClExperimentalTracePC("sanitizer-coverage-trace-pc",
|
|||||||
cl::desc("Experimental pc tracing"),
|
cl::desc("Experimental pc tracing"),
|
||||||
cl::Hidden, cl::init(false));
|
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>
|
static cl::opt<bool>
|
||||||
ClCMPTracing("sanitizer-coverage-trace-compares",
|
ClCMPTracing("sanitizer-coverage-trace-compares",
|
||||||
cl::desc("Tracing of CMP and similar instructions"),
|
cl::desc("Tracing of CMP and similar instructions"),
|
||||||
@ -165,6 +175,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
|||||||
Options.TraceGep |= ClGEPTracing;
|
Options.TraceGep |= ClGEPTracing;
|
||||||
Options.Use8bitCounters |= ClUse8bitCounters;
|
Options.Use8bitCounters |= ClUse8bitCounters;
|
||||||
Options.TracePC |= ClExperimentalTracePC;
|
Options.TracePC |= ClExperimentalTracePC;
|
||||||
|
Options.TracePCGuard |= ClTracePCGuard;
|
||||||
return Options;
|
return Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +217,7 @@ private:
|
|||||||
Function *SanCovFunction;
|
Function *SanCovFunction;
|
||||||
Function *SanCovWithCheckFunction;
|
Function *SanCovWithCheckFunction;
|
||||||
Function *SanCovIndirCallFunction, *SanCovTracePCIndir;
|
Function *SanCovIndirCallFunction, *SanCovTracePCIndir;
|
||||||
Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC;
|
Function *SanCovTraceEnter, *SanCovTraceBB, *SanCovTracePC, *SanCovTracePCGuard;
|
||||||
Function *SanCovTraceCmpFunction[4];
|
Function *SanCovTraceCmpFunction[4];
|
||||||
Function *SanCovTraceDivFunction[2];
|
Function *SanCovTraceDivFunction[2];
|
||||||
Function *SanCovTraceGepFunction;
|
Function *SanCovTraceGepFunction;
|
||||||
@ -281,6 +292,8 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||||||
|
|
||||||
SanCovTracePC = checkSanitizerInterfaceFunction(
|
SanCovTracePC = checkSanitizerInterfaceFunction(
|
||||||
M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
|
M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
|
||||||
|
SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
|
||||||
|
SanCovTracePCGuardName, VoidTy, IRB.getInt8PtrTy(), nullptr));
|
||||||
SanCovTraceEnter = checkSanitizerInterfaceFunction(
|
SanCovTraceEnter = checkSanitizerInterfaceFunction(
|
||||||
M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
|
M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
|
||||||
SanCovTraceBB = checkSanitizerInterfaceFunction(
|
SanCovTraceBB = checkSanitizerInterfaceFunction(
|
||||||
@ -336,8 +349,23 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||||||
GlobalVariable *ModuleName =
|
GlobalVariable *ModuleName =
|
||||||
new GlobalVariable(M, ModNameStrConst->getType(), true,
|
new GlobalVariable(M, ModNameStrConst->getType(), true,
|
||||||
GlobalValue::PrivateLinkage, ModNameStrConst);
|
GlobalValue::PrivateLinkage, ModNameStrConst);
|
||||||
|
if (Options.TracePCGuard) {
|
||||||
|
Function *CtorFunc;
|
||||||
|
std::string SectionName(SanCovTracePCGuardSection);
|
||||||
|
auto Start =
|
||||||
|
new GlobalVariable(M, Int8PtrTy, false, GlobalVariable::ExternalLinkage,
|
||||||
|
nullptr, "__start_" + SectionName);
|
||||||
|
auto Stop =
|
||||||
|
new GlobalVariable(M, Int8PtrTy, false, GlobalVariable::ExternalLinkage,
|
||||||
|
nullptr, "__stop_" + SectionName);
|
||||||
|
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
|
||||||
|
M, SanCovModuleCtorName, SanCovTracePCGuardInitName,
|
||||||
|
{Int8PtrTy, Int8PtrTy}, {IRB.CreatePointerCast(Start, Int8PtrTy),
|
||||||
|
IRB.CreatePointerCast(Stop, Int8PtrTy)});
|
||||||
|
|
||||||
if (!Options.TracePC) {
|
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
|
||||||
|
|
||||||
|
} else if (!Options.TracePC) {
|
||||||
Function *CtorFunc;
|
Function *CtorFunc;
|
||||||
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
|
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
|
||||||
M, SanCovModuleCtorName, SanCovModuleInitName,
|
M, SanCovModuleCtorName, SanCovModuleInitName,
|
||||||
@ -395,6 +423,8 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
|||||||
return false;
|
return false;
|
||||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||||
return false; // Should not instrument sanitizer init functions.
|
return false; // Should not instrument sanitizer init functions.
|
||||||
|
if (F.getName().startswith("__sanitizer_"))
|
||||||
|
return false; // Don't instrument __sanitizer_* callbacks.
|
||||||
// Don't instrument functions using SEH for now. Splitting basic blocks like
|
// Don't instrument functions using SEH for now. Splitting basic blocks like
|
||||||
// we do for coverage breaks WinEHPrepare.
|
// we do for coverage breaks WinEHPrepare.
|
||||||
// FIXME: Remove this when SEH no longer uses landingpad pattern matching.
|
// FIXME: Remove this when SEH no longer uses landingpad pattern matching.
|
||||||
@ -631,6 +661,26 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
if (Options.TracePC) {
|
if (Options.TracePC) {
|
||||||
IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC.
|
IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC.
|
||||||
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
||||||
|
} else if (Options.TracePCGuard) {
|
||||||
|
auto GuardVar = new GlobalVariable(*F.getParent(), IRB.getInt8Ty(), false,
|
||||||
|
GlobalVariable::LinkOnceODRLinkage,
|
||||||
|
Constant::getNullValue(IRB.getInt8Ty()),
|
||||||
|
"__sancov_guard." + F.getName());
|
||||||
|
// TODO: add debug into to GuardVar.
|
||||||
|
GuardVar->setSection(SanCovTracePCGuardSection);
|
||||||
|
auto GuardPtr = IRB.CreatePointerCast(GuardVar, IRB.getInt8PtrTy());
|
||||||
|
auto GuardLoad = IRB.CreateLoad(GuardPtr);
|
||||||
|
GuardLoad->setAtomic(AtomicOrdering::Monotonic);
|
||||||
|
GuardLoad->setAlignment(1);
|
||||||
|
SetNoSanitizeMetadata(GuardLoad); // Don't instrument with e.g. asan.
|
||||||
|
auto Cmp = IRB.CreateICmpNE(
|
||||||
|
Constant::getAllOnesValue(GuardLoad->getType()), GuardLoad);
|
||||||
|
auto Ins = SplitBlockAndInsertIfThen(
|
||||||
|
Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
|
||||||
|
IRB.SetCurrentDebugLocation(EntryLoc);
|
||||||
|
IRB.SetInsertPoint(Ins);
|
||||||
|
IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
|
||||||
|
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
||||||
} else if (Options.TraceBB) {
|
} else if (Options.TraceBB) {
|
||||||
IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
|
IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
|
||||||
} else if (UseCalls) {
|
} else if (UseCalls) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK1
|
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK1
|
||||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK3
|
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK3
|
||||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC
|
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC
|
||||||
|
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD
|
||||||
|
|
||||||
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 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"
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
@ -38,3 +39,11 @@ entry:
|
|||||||
; CHECK_PC-NOT: call void @__sanitizer_cov_trace_pc
|
; CHECK_PC-NOT: call void @__sanitizer_cov_trace_pc
|
||||||
; CHECK_PC: ret void
|
; CHECK_PC: ret void
|
||||||
; CHECK_PC-NOT: call void @__sanitizer_cov_module_init
|
; CHECK_PC-NOT: call void @__sanitizer_cov_module_init
|
||||||
|
|
||||||
|
; CHECK_PC_GUARD-LABEL: define void @foo
|
||||||
|
; CHECK_PC_GUARD: call void @__sanitizer_cov_trace_pc_guard
|
||||||
|
; CHECK_PC_GUARD: call void @__sanitizer_cov_trace_pc_guard
|
||||||
|
; CHECK_PC_GUARD: call void @__sanitizer_cov_trace_pc_guard
|
||||||
|
; CHECK_PC_GUARD-NOT: call void @__sanitizer_cov_trace_pc
|
||||||
|
; CHECK_PC_GUARD: ret void
|
||||||
|
; CHECK_PC_GUARD: call void @__sanitizer_cov_trace_pc_guard_init(i8* bitcast (i8** @__start___sancov_guards to i8*), i8* bitcast (i8** @__stop___sancov_guards to i8*))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user