[llvm] r282735 - [sanitizer-coverage/libFuzzer] make the guards for trace-pc 32-bit; create one array of guards per function, instead of one guard per BB. reorganize the code so that trace-pc-guard does not create unneeded globals
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 29 10:43:25 PDT 2016
Author: kcc
Date: Thu Sep 29 12:43:24 2016
New Revision: 282735
URL: http://llvm.org/viewvc/llvm-project?rev=282735&view=rev
Log:
[sanitizer-coverage/libFuzzer] make the guards for trace-pc 32-bit; create one array of guards per function, instead of one guard per BB. reorganize the code so that trace-pc-guard does not create unneeded globals
Modified:
llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll
llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing.ll
Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Thu Sep 29 12:43:24 2016
@@ -500,7 +500,8 @@ void Fuzzer::ExecuteCallback(const uint8
UnitStartTime = system_clock::now();
ResetCounters(); // Reset coverage right before the callback.
TPC.ResetMaps();
- TPC.ResetGuards();
+ if (Options.UseCounters)
+ TPC.ResetGuards();
int Res = CB(DataCopy, Size);
UnitStopTime = system_clock::now();
(void)Res;
Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp Thu Sep 29 12:43:24 2016
@@ -20,8 +20,8 @@ namespace fuzzer {
TracePC TPC;
-void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
- uintptr_t Idx = *Guard;
+void TracePC::HandleTrace(uint32_t *Guard, uintptr_t PC) {
+ uint32_t Idx = *Guard;
if (!Idx) return;
uint8_t *CounterPtr = &Counters[Idx % kNumCounters];
uint8_t Counter = *CounterPtr;
@@ -43,10 +43,10 @@ void TracePC::HandleTrace(uintptr_t *Gua
}
}
-void TracePC::HandleInit(uintptr_t *Start, uintptr_t *Stop) {
+void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
if (Start == Stop || *Start) return;
assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
- for (uintptr_t *P = Start; P < Stop; P++)
+ for (uint32_t *P = Start; P < Stop; P++)
*P = ++NumGuards;
Modules[NumModules].Start = Start;
Modules[NumModules].Stop = Stop;
@@ -61,9 +61,9 @@ void TracePC::PrintModuleInfo() {
}
void TracePC::ResetGuards() {
- uintptr_t N = 0;
+ uint32_t N = 0;
for (size_t M = 0; M < NumModules; M++)
- for (uintptr_t *X = Modules[M].Start; X < Modules[M].Stop; X++)
+ for (uint32_t *X = Modules[M].Start; X < Modules[M].Stop; X++)
*X = ++N;
assert(N == NumGuards);
}
@@ -138,13 +138,13 @@ void TracePC::PrintFeatureSet() {
extern "C" {
__attribute__((visibility("default")))
-void __sanitizer_cov_trace_pc_guard(uintptr_t *Guard) {
+void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
uintptr_t PC = (uintptr_t)__builtin_return_address(0);
fuzzer::TPC.HandleTrace(Guard, PC);
}
__attribute__((visibility("default")))
-void __sanitizer_cov_trace_pc_guard_init(uintptr_t *Start, uintptr_t *Stop) {
+void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
fuzzer::TPC.HandleInit(Start, Stop);
}
Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.h?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerTracePC.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.h Thu Sep 29 12:43:24 2016
@@ -19,8 +19,8 @@ namespace fuzzer {
class TracePC {
public:
- void HandleTrace(uintptr_t *guard, uintptr_t PC);
- void HandleInit(uintptr_t *start, uintptr_t *stop);
+ void HandleTrace(uint32_t *guard, uintptr_t PC);
+ void HandleInit(uint32_t *start, uint32_t *stop);
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); }
size_t GetTotalPCCoverage() { return TotalPCCoverage; }
@@ -71,7 +71,7 @@ private:
}
struct Module {
- uintptr_t *Start, *Stop;
+ uint32_t *Start, *Stop;
};
Module Modules[4096];
Modified: llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp Thu Sep 29 12:43:24 2016
@@ -207,8 +207,10 @@ private:
void InjectTraceForSwitch(Function &F,
ArrayRef<Instruction *> SwitchTraceTargets);
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks);
+ void CreateFunctionGuardArray(size_t NumGuards, Function &F);
void SetNoSanitizeMetadata(Instruction *I);
- void InjectCoverageAtBlock(Function &F, BasicBlock &BB, bool UseCalls);
+ void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx,
+ bool UseCalls);
unsigned NumberOfInstrumentedBlocks() {
return SanCovFunction->getNumUses() +
SanCovWithCheckFunction->getNumUses() + SanCovTraceBB->getNumUses() +
@@ -223,12 +225,13 @@ private:
Function *SanCovTraceGepFunction;
Function *SanCovTraceSwitchFunction;
InlineAsm *EmptyAsm;
- Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy;
+ Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy;
Module *CurModule;
LLVMContext *C;
const DataLayout *DL;
GlobalVariable *GuardArray;
+ GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
GlobalVariable *EightBitCounterArray;
bool HasSancovGuardsSection;
@@ -249,9 +252,10 @@ bool SanitizerCoverageModule::runOnModul
Type *VoidTy = Type::getVoidTy(*C);
IRBuilder<> IRB(*C);
Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
- Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
+ Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
Int64Ty = IRB.getInt64Ty();
+ Int32Ty = IRB.getInt32Ty();
SanCovFunction = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr));
@@ -296,7 +300,7 @@ bool SanitizerCoverageModule::runOnModul
SanCovTracePC = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- SanCovTracePCGuardName, VoidTy, IntptrPtrTy, nullptr));
+ SanCovTracePCGuardName, VoidTy, Int32PtrTy, nullptr));
SanCovTraceEnter = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
SanCovTraceBB = checkSanitizerInterfaceFunction(
@@ -307,9 +311,10 @@ bool SanitizerCoverageModule::runOnModul
Type *Int32Ty = IRB.getInt32Ty();
Type *Int8Ty = IRB.getInt8Ty();
- GuardArray =
- new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
- nullptr, "__sancov_gen_cov_tmp");
+ if (!Options.TracePCGuard)
+ GuardArray =
+ new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
+ nullptr, "__sancov_gen_cov_tmp");
if (Options.Use8bitCounters)
EightBitCounterArray =
new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage,
@@ -320,17 +325,20 @@ bool SanitizerCoverageModule::runOnModul
auto N = NumberOfInstrumentedBlocks();
- // Now we know how many elements we need. Create an array of guards
- // with one extra element at the beginning for the size.
- Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1);
- GlobalVariable *RealGuardArray = new GlobalVariable(
- M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage,
- Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov");
-
- // Replace the dummy array with the real one.
- GuardArray->replaceAllUsesWith(
- IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
- GuardArray->eraseFromParent();
+ GlobalVariable *RealGuardArray = nullptr;
+ if (!Options.TracePCGuard) {
+ // Now we know how many elements we need. Create an array of guards
+ // with one extra element at the beginning for the size.
+ Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1);
+ RealGuardArray = new GlobalVariable(
+ M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage,
+ Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov");
+
+ // Replace the dummy array with the real one.
+ GuardArray->replaceAllUsesWith(
+ IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
+ GuardArray->eraseFromParent();
+ }
GlobalVariable *RealEightBitCounterArray;
if (Options.Use8bitCounters) {
@@ -359,16 +367,16 @@ bool SanitizerCoverageModule::runOnModul
GlobalVariable *Bounds[2];
const char *Prefix[2] = {"__start_", "__stop_"};
for (int i = 0; i < 2; i++) {
- Bounds[i] = new GlobalVariable(M, IntptrPtrTy, false,
+ Bounds[i] = new GlobalVariable(M, Int32PtrTy, false,
GlobalVariable::ExternalLinkage, nullptr,
Prefix[i] + SectionName);
Bounds[i]->setVisibility(GlobalValue::HiddenVisibility);
}
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
M, SanCovModuleCtorName, SanCovTracePCGuardInitName,
- {IntptrPtrTy, IntptrPtrTy},
- {IRB.CreatePointerCast(Bounds[0], IntptrPtrTy),
- IRB.CreatePointerCast(Bounds[1], IntptrPtrTy)});
+ {Int32PtrTy, Int32PtrTy},
+ {IRB.CreatePointerCast(Bounds[0], Int32PtrTy),
+ IRB.CreatePointerCast(Bounds[1], Int32PtrTy)});
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
}
@@ -419,6 +427,14 @@ static bool isFullPostDominator(const Ba
static bool shouldInstrumentBlock(const Function& F, const BasicBlock *BB, const DominatorTree *DT,
const PostDominatorTree *PDT) {
+ // Don't insert coverage for unreachable blocks: we will never call
+ // __sanitizer_cov() for them, so counting them in
+ // NumberOfInstrumentedBlocks() might complicate calculation of code coverage
+ // percentage. Also, unreachable instructions frequently have no debug
+ // locations.
+ if (isa<UnreachableInst>(BB->getTerminator()))
+ return false;
+
if (!ClPruneBlocks || &F.getEntryBlock() == BB)
return true;
@@ -486,19 +502,34 @@ bool SanitizerCoverageModule::runOnFunct
InjectTraceForGep(F, GepTraceTargets);
return true;
}
+void SanitizerCoverageModule::CreateFunctionGuardArray(size_t NumGuards, Function &F) {
+ if (!Options.TracePCGuard) return;
+ HasSancovGuardsSection = true;
+ ArrayType *ArrayOfInt32Ty = ArrayType::get(Int32Ty, NumGuards);
+ FunctionGuardArray = new GlobalVariable(
+ *CurModule, ArrayOfInt32Ty, false, GlobalVariable::LinkOnceODRLinkage,
+ Constant::getNullValue(ArrayOfInt32Ty), "__sancov_guard." + F.getName());
+ if (auto Comdat = F.getComdat())
+ FunctionGuardArray->setComdat(Comdat);
+ FunctionGuardArray->setSection(SanCovTracePCGuardSection);
+ FunctionGuardArray->setVisibility(GlobalValue::HiddenVisibility);
+}
bool SanitizerCoverageModule::InjectCoverage(Function &F,
ArrayRef<BasicBlock *> AllBlocks) {
+ if (AllBlocks.empty()) return false;
switch (Options.CoverageType) {
case SanitizerCoverageOptions::SCK_None:
return false;
case SanitizerCoverageOptions::SCK_Function:
- InjectCoverageAtBlock(F, F.getEntryBlock(), false);
+ CreateFunctionGuardArray(1, F);
+ InjectCoverageAtBlock(F, F.getEntryBlock(), 0, false);
return true;
default: {
bool UseCalls = ClCoverageBlockThreshold < AllBlocks.size();
- for (auto BB : AllBlocks)
- InjectCoverageAtBlock(F, *BB, UseCalls);
+ CreateFunctionGuardArray(AllBlocks.size(), F);
+ for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
+ InjectCoverageAtBlock(F, *AllBlocks[i], i, UseCalls);
return true;
}
}
@@ -635,16 +666,8 @@ void SanitizerCoverageModule::SetNoSanit
}
void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
- bool UseCalls) {
- // Don't insert coverage for unreachable blocks: we will never call
- // __sanitizer_cov() for them, so counting them in
- // NumberOfInstrumentedBlocks() might complicate calculation of code coverage
- // percentage. Also, unreachable instructions frequently have no debug
- // locations.
- if (isa<UnreachableInst>(BB.getTerminator()))
- return;
+ size_t Idx, bool UseCalls) {
BasicBlock::iterator IP = BB.getFirstInsertionPt();
-
bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc;
if (IsEntryBB) {
@@ -660,24 +683,22 @@ void SanitizerCoverageModule::InjectCove
IRBuilder<> IRB(&*IP);
IRB.SetCurrentDebugLocation(EntryLoc);
- Value *GuardP = IRB.CreateAdd(
- IRB.CreatePointerCast(GuardArray, IntptrTy),
- ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4));
- Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
- GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
if (Options.TracePC) {
IRB.CreateCall(SanCovTracePC); // gets the PC using GET_CALLER_PC.
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
} else if (Options.TracePCGuard) {
- auto GuardVar = new GlobalVariable(
- *F.getParent(), Int64Ty, false, GlobalVariable::LinkOnceODRLinkage,
- Constant::getNullValue(Int64Ty), "__sancov_guard." + F.getName());
- if (auto Comdat = F.getComdat())
- GuardVar->setComdat(Comdat);
+ //auto GuardVar = new GlobalVariable(
+ // *F.getParent(), Int64Ty, false, GlobalVariable::LinkOnceODRLinkage,
+ // Constant::getNullValue(Int64Ty), "__sancov_guard." + F.getName());
+ // if (auto Comdat = F.getComdat())
+ // GuardVar->setComdat(Comdat);
// TODO: add debug into to GuardVar.
- GuardVar->setSection(SanCovTracePCGuardSection);
- HasSancovGuardsSection = true;
- auto GuardPtr = IRB.CreatePointerCast(GuardVar, IntptrPtrTy);
+ // GuardVar->setSection(SanCovTracePCGuardSection);
+ // auto GuardPtr = IRB.CreatePointerCast(GuardVar, IntptrPtrTy);
+ auto GuardPtr = IRB.CreateIntToPtr(
+ IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
+ ConstantInt::get(IntptrTy, Idx * 4)),
+ Int32PtrTy);
if (!UseCalls) {
auto GuardLoad = IRB.CreateLoad(GuardPtr);
GuardLoad->setAtomic(AtomicOrdering::Monotonic);
@@ -692,24 +713,30 @@ void SanitizerCoverageModule::InjectCove
}
IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
- } else if (Options.TraceBB) {
- IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
- } else if (UseCalls) {
- IRB.CreateCall(SanCovWithCheckFunction, GuardP);
} else {
- LoadInst *Load = IRB.CreateLoad(GuardP);
- Load->setAtomic(AtomicOrdering::Monotonic);
- Load->setAlignment(4);
- SetNoSanitizeMetadata(Load);
- Value *Cmp =
- IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load);
- Instruction *Ins = SplitBlockAndInsertIfThen(
- Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
- IRB.SetInsertPoint(Ins);
- IRB.SetCurrentDebugLocation(EntryLoc);
- // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
- IRB.CreateCall(SanCovFunction, GuardP);
- IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
+ Value *GuardP = IRB.CreateAdd(
+ IRB.CreatePointerCast(GuardArray, IntptrTy),
+ ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4));
+ GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
+ if (Options.TraceBB) {
+ IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
+ } else if (UseCalls) {
+ IRB.CreateCall(SanCovWithCheckFunction, GuardP);
+ } else {
+ LoadInst *Load = IRB.CreateLoad(GuardP);
+ Load->setAtomic(AtomicOrdering::Monotonic);
+ Load->setAlignment(4);
+ SetNoSanitizeMetadata(Load);
+ Value *Cmp =
+ IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load);
+ Instruction *Ins = SplitBlockAndInsertIfThen(
+ Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
+ IRB.SetInsertPoint(Ins);
+ IRB.SetCurrentDebugLocation(EntryLoc);
+ // __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
+ IRB.CreateCall(SanCovFunction, GuardP);
+ IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
+ }
}
if (Options.Use8bitCounters) {
Modified: llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll (original)
+++ llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing-comdat.ll Thu Sep 29 12:43:24 2016
@@ -9,5 +9,4 @@ entry:
ret void
}
-; CHECK: @__sancov_guard.Foo = linkonce_odr global i64 0, section "__sancov_guards", comdat($Foo)
-
+; CHECK: @__sancov_guard.Foo = linkonce_odr hidden global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($Foo)
Modified: llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing.ll?rev=282735&r1=282734&r2=282735&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing.ll (original)
+++ llvm/trunk/test/Instrumentation/SanitizerCoverage/tracing.ll Thu Sep 29 12:43:24 2016
@@ -46,4 +46,4 @@ entry:
; 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(i64* bitcast (i64** @__start___sancov_guards to i64*), i64* bitcast (i64** @__stop___sancov_guards to i64*))
+; CHECK_PC_GUARD: call void @__sanitizer_cov_trace_pc_guard_init(i32* bitcast (i32** @__start___sancov_guards to i32*), i32* bitcast (i32** @__stop___sancov_guards to i32*))
More information about the llvm-commits
mailing list