forked from OSchip/llvm-project
[sanitizer] experimental tracing for cmp instructions
llvm-svn: 232873
This commit is contained in:
parent
7173b669b4
commit
f4e35cc47d
|
@ -59,6 +59,7 @@ static const char *const kSanCovWithCheckName = "__sanitizer_cov_with_check";
|
|||
static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16";
|
||||
static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter";
|
||||
static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block";
|
||||
static const char *const kSanCovTraceCmp = "__sanitizer_cov_trace_cmp";
|
||||
static const char *const kSanCovModuleCtorName = "sancov.module_ctor";
|
||||
static const uint64_t kSanCtorAndDtorPriority = 2;
|
||||
|
||||
|
@ -80,6 +81,12 @@ static cl::opt<bool>
|
|||
"callbacks at every basic block"),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
static cl::opt<bool>
|
||||
ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares",
|
||||
cl::desc("Experimental tracing of CMP and similar "
|
||||
"instructions"),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
// Experimental 8-bit counters used as an additional search heuristic during
|
||||
// coverage-guided fuzzing.
|
||||
// The counters are not thread-friendly:
|
||||
|
@ -107,8 +114,8 @@ class SanitizerCoverageModule : public ModulePass {
|
|||
private:
|
||||
void InjectCoverageForIndirectCalls(Function &F,
|
||||
ArrayRef<Instruction *> IndirCalls);
|
||||
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
|
||||
ArrayRef<Instruction *> IndirCalls);
|
||||
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
|
||||
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks);
|
||||
void SetNoSanitizeMetada(Instruction *I);
|
||||
void InjectCoverageAtBlock(Function &F, BasicBlock &BB, bool UseCalls);
|
||||
unsigned NumberOfInstrumentedBlocks() {
|
||||
|
@ -119,9 +126,11 @@ class SanitizerCoverageModule : public ModulePass {
|
|||
Function *SanCovIndirCallFunction;
|
||||
Function *SanCovModuleInit;
|
||||
Function *SanCovTraceEnter, *SanCovTraceBB;
|
||||
Function *SanCovTraceCmpFunction;
|
||||
InlineAsm *EmptyAsm;
|
||||
Type *IntptrTy;
|
||||
Type *IntptrTy, *Int64Ty;
|
||||
LLVMContext *C;
|
||||
const DataLayout *DL;
|
||||
|
||||
GlobalVariable *GuardArray;
|
||||
GlobalVariable *EightBitCounterArray;
|
||||
|
@ -144,12 +153,13 @@ static Function *checkInterfaceFunction(Constant *FuncOrBitcast) {
|
|||
bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||
if (!CoverageLevel) return false;
|
||||
C = &(M.getContext());
|
||||
auto &DL = M.getDataLayout();
|
||||
IntptrTy = Type::getIntNTy(*C, DL.getPointerSizeInBits());
|
||||
DL = &M.getDataLayout();
|
||||
IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
|
||||
Type *VoidTy = Type::getVoidTy(*C);
|
||||
IRBuilder<> IRB(*C);
|
||||
Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
|
||||
Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
||||
Int64Ty = IRB.getInt64Ty();
|
||||
|
||||
Function *CtorFunc =
|
||||
Function::Create(FunctionType::get(VoidTy, false),
|
||||
|
@ -163,6 +173,9 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||
M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr));
|
||||
SanCovIndirCallFunction = checkInterfaceFunction(M.getOrInsertFunction(
|
||||
kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
|
||||
SanCovTraceCmpFunction = checkInterfaceFunction(M.getOrInsertFunction(
|
||||
kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr));
|
||||
|
||||
SanCovModuleInit = checkInterfaceFunction(M.getOrInsertFunction(
|
||||
kSanCovModuleInitName, Type::getVoidTy(*C), Int32PtrTy, IntptrTy,
|
||||
Int8PtrTy, Int8PtrTy, nullptr));
|
||||
|
@ -252,23 +265,28 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
|||
SplitAllCriticalEdges(F);
|
||||
SmallVector<Instruction*, 8> IndirCalls;
|
||||
SmallVector<BasicBlock*, 16> AllBlocks;
|
||||
SmallVector<Instruction*, 8> CmpTraceTargets;
|
||||
for (auto &BB : F) {
|
||||
AllBlocks.push_back(&BB);
|
||||
if (CoverageLevel >= 4)
|
||||
for (auto &Inst : BB) {
|
||||
for (auto &Inst : BB) {
|
||||
if (CoverageLevel >= 4) {
|
||||
CallSite CS(&Inst);
|
||||
if (CS && !CS.getCalledFunction())
|
||||
IndirCalls.push_back(&Inst);
|
||||
}
|
||||
if (ClExperimentalCMPTracing)
|
||||
if (isa<ICmpInst>(&Inst))
|
||||
CmpTraceTargets.push_back(&Inst);
|
||||
}
|
||||
}
|
||||
InjectCoverage(F, AllBlocks, IndirCalls);
|
||||
InjectCoverage(F, AllBlocks);
|
||||
InjectCoverageForIndirectCalls(F, IndirCalls);
|
||||
InjectTraceForCmp(F, CmpTraceTargets);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SanitizerCoverageModule::InjectCoverage(Function &F,
|
||||
ArrayRef<BasicBlock *> AllBlocks,
|
||||
ArrayRef<Instruction *> IndirCalls) {
|
||||
bool SanitizerCoverageModule::InjectCoverage(Function &F,
|
||||
ArrayRef<BasicBlock *> AllBlocks) {
|
||||
if (!CoverageLevel) return false;
|
||||
|
||||
if (CoverageLevel == 1) {
|
||||
|
@ -278,7 +296,6 @@ SanitizerCoverageModule::InjectCoverage(Function &F,
|
|||
InjectCoverageAtBlock(F, *BB,
|
||||
ClCoverageBlockThreshold < AllBlocks.size());
|
||||
}
|
||||
InjectCoverageForIndirectCalls(F, IndirCalls);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -310,6 +327,26 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
|
|||
}
|
||||
}
|
||||
|
||||
void SanitizerCoverageModule::InjectTraceForCmp(
|
||||
Function &F, ArrayRef<Instruction *> CmpTraceTargets) {
|
||||
if (!ClExperimentalCMPTracing) return;
|
||||
for (auto I : CmpTraceTargets) {
|
||||
if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) {
|
||||
IRBuilder<> IRB(ICMP);
|
||||
Value *A0 = ICMP->getOperand(0);
|
||||
Value *A1 = ICMP->getOperand(1);
|
||||
if (!A0->getType()->isIntegerTy()) continue;
|
||||
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
|
||||
// __sanitizer_cov_indir_call((type_size << 32) | predicate, A0, A1);
|
||||
IRB.CreateCall3(
|
||||
SanCovTraceCmpFunction,
|
||||
ConstantInt::get(Int64Ty, (TypeSize << 32) | ICMP->getPredicate()),
|
||||
IRB.CreateIntCast(A0, Int64Ty, true),
|
||||
IRB.CreateIntCast(A1, Int64Ty, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SanitizerCoverageModule::SetNoSanitizeMetada(Instruction *I) {
|
||||
I->setMetadata(
|
||||
I->getParent()->getParent()->getParent()->getMDKindID("nosanitize"),
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
; Test -sanitizer-coverage-experimental-trace-compares=1
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-experimental-trace-compares=1 -S | FileCheck %s --check-prefix=CHECK
|
||||
|
||||
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 i32 @foo(i32 %a, i32 %b) #0 {
|
||||
entry:
|
||||
%cmp = icmp slt i32 %a, %b
|
||||
; CHECK: call void @__sanitizer_cov_trace_cmp
|
||||
; CHECK-NEXT: icmp slt i32 %a, %b
|
||||
%conv = zext i1 %cmp to i32
|
||||
ret i32 %conv
|
||||
}
|
Loading…
Reference in New Issue