forked from OSchip/llvm-project
[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
llvm-svn: 282735
This commit is contained in:
parent
ba72b95f7b
commit
a9b0dd0e51
|
@ -334,7 +334,7 @@ on every edge:
|
||||||
if (guard_variable)
|
if (guard_variable)
|
||||||
__sanitizer_cov_trace_pc_guard(&guard_variable)
|
__sanitizer_cov_trace_pc_guard(&guard_variable)
|
||||||
|
|
||||||
Every edge will have its own `guard_variable` (uintptr_t).
|
Every edge will have its own `guard_variable` (uint32_t).
|
||||||
|
|
||||||
The compler will also insert a module constructor that will call
|
The compler will also insert a module constructor that will call
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ The compler will also insert a module constructor that will call
|
||||||
|
|
||||||
// The guards are [start, stop).
|
// The guards are [start, stop).
|
||||||
// This function may be called multiple times with the same values of start/stop.
|
// This function may be called multiple times with the same values of start/stop.
|
||||||
__sanitizer_cov_trace_pc_guard_init(uintptr_t *start, uintptr_t *stop);
|
__sanitizer_cov_trace_pc_guard_init(uint32_t_t *start, uint32_t *stop);
|
||||||
|
|
||||||
Similarly to `trace-pc,indirect-calls`, with `trace-pc-guards,indirect-calls`
|
Similarly to `trace-pc,indirect-calls`, with `trace-pc-guards,indirect-calls`
|
||||||
``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
|
``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
|
||||||
|
|
|
@ -500,7 +500,8 @@ void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
|
||||||
UnitStartTime = system_clock::now();
|
UnitStartTime = system_clock::now();
|
||||||
ResetCounters(); // Reset coverage right before the callback.
|
ResetCounters(); // Reset coverage right before the callback.
|
||||||
TPC.ResetMaps();
|
TPC.ResetMaps();
|
||||||
TPC.ResetGuards();
|
if (Options.UseCounters)
|
||||||
|
TPC.ResetGuards();
|
||||||
int Res = CB(DataCopy, Size);
|
int Res = CB(DataCopy, Size);
|
||||||
UnitStopTime = system_clock::now();
|
UnitStopTime = system_clock::now();
|
||||||
(void)Res;
|
(void)Res;
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace fuzzer {
|
||||||
|
|
||||||
TracePC TPC;
|
TracePC TPC;
|
||||||
|
|
||||||
void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
void TracePC::HandleTrace(uint32_t *Guard, uintptr_t PC) {
|
||||||
uintptr_t Idx = *Guard;
|
uint32_t Idx = *Guard;
|
||||||
if (!Idx) return;
|
if (!Idx) return;
|
||||||
uint8_t *CounterPtr = &Counters[Idx % kNumCounters];
|
uint8_t *CounterPtr = &Counters[Idx % kNumCounters];
|
||||||
uint8_t Counter = *CounterPtr;
|
uint8_t Counter = *CounterPtr;
|
||||||
|
@ -43,10 +43,10 @@ void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracePC::HandleInit(uintptr_t *Start, uintptr_t *Stop) {
|
void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
|
||||||
if (Start == Stop || *Start) return;
|
if (Start == Stop || *Start) return;
|
||||||
assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
|
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;
|
*P = ++NumGuards;
|
||||||
Modules[NumModules].Start = Start;
|
Modules[NumModules].Start = Start;
|
||||||
Modules[NumModules].Stop = Stop;
|
Modules[NumModules].Stop = Stop;
|
||||||
|
@ -61,9 +61,9 @@ void TracePC::PrintModuleInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TracePC::ResetGuards() {
|
void TracePC::ResetGuards() {
|
||||||
uintptr_t N = 0;
|
uint32_t N = 0;
|
||||||
for (size_t M = 0; M < NumModules; M++)
|
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;
|
*X = ++N;
|
||||||
assert(N == NumGuards);
|
assert(N == NumGuards);
|
||||||
}
|
}
|
||||||
|
@ -138,13 +138,13 @@ void TracePC::PrintFeatureSet() {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__attribute__((visibility("default")))
|
__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);
|
uintptr_t PC = (uintptr_t)__builtin_return_address(0);
|
||||||
fuzzer::TPC.HandleTrace(Guard, PC);
|
fuzzer::TPC.HandleTrace(Guard, PC);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((visibility("default")))
|
__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);
|
fuzzer::TPC.HandleInit(Start, Stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ namespace fuzzer {
|
||||||
|
|
||||||
class TracePC {
|
class TracePC {
|
||||||
public:
|
public:
|
||||||
void HandleTrace(uintptr_t *guard, uintptr_t PC);
|
void HandleTrace(uint32_t *guard, uintptr_t PC);
|
||||||
void HandleInit(uintptr_t *start, uintptr_t *stop);
|
void HandleInit(uint32_t *start, uint32_t *stop);
|
||||||
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
|
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
|
||||||
void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); }
|
void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); }
|
||||||
size_t GetTotalPCCoverage() { return TotalPCCoverage; }
|
size_t GetTotalPCCoverage() { return TotalPCCoverage; }
|
||||||
|
@ -71,7 +71,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Module {
|
struct Module {
|
||||||
uintptr_t *Start, *Stop;
|
uint32_t *Start, *Stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
Module Modules[4096];
|
Module Modules[4096];
|
||||||
|
|
|
@ -207,8 +207,10 @@ private:
|
||||||
void InjectTraceForSwitch(Function &F,
|
void InjectTraceForSwitch(Function &F,
|
||||||
ArrayRef<Instruction *> SwitchTraceTargets);
|
ArrayRef<Instruction *> SwitchTraceTargets);
|
||||||
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks);
|
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks);
|
||||||
|
void CreateFunctionGuardArray(size_t NumGuards, Function &F);
|
||||||
void SetNoSanitizeMetadata(Instruction *I);
|
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() {
|
unsigned NumberOfInstrumentedBlocks() {
|
||||||
return SanCovFunction->getNumUses() +
|
return SanCovFunction->getNumUses() +
|
||||||
SanCovWithCheckFunction->getNumUses() + SanCovTraceBB->getNumUses() +
|
SanCovWithCheckFunction->getNumUses() + SanCovTraceBB->getNumUses() +
|
||||||
|
@ -223,12 +225,13 @@ private:
|
||||||
Function *SanCovTraceGepFunction;
|
Function *SanCovTraceGepFunction;
|
||||||
Function *SanCovTraceSwitchFunction;
|
Function *SanCovTraceSwitchFunction;
|
||||||
InlineAsm *EmptyAsm;
|
InlineAsm *EmptyAsm;
|
||||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy;
|
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy;
|
||||||
Module *CurModule;
|
Module *CurModule;
|
||||||
LLVMContext *C;
|
LLVMContext *C;
|
||||||
const DataLayout *DL;
|
const DataLayout *DL;
|
||||||
|
|
||||||
GlobalVariable *GuardArray;
|
GlobalVariable *GuardArray;
|
||||||
|
GlobalVariable *FunctionGuardArray; // for trace-pc-guard.
|
||||||
GlobalVariable *EightBitCounterArray;
|
GlobalVariable *EightBitCounterArray;
|
||||||
bool HasSancovGuardsSection;
|
bool HasSancovGuardsSection;
|
||||||
|
|
||||||
|
@ -249,9 +252,10 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||||
Type *VoidTy = Type::getVoidTy(*C);
|
Type *VoidTy = Type::getVoidTy(*C);
|
||||||
IRBuilder<> IRB(*C);
|
IRBuilder<> IRB(*C);
|
||||||
Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
|
Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
|
||||||
Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
|
||||||
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
|
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
|
||||||
|
Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
|
||||||
Int64Ty = IRB.getInt64Ty();
|
Int64Ty = IRB.getInt64Ty();
|
||||||
|
Int32Ty = IRB.getInt32Ty();
|
||||||
|
|
||||||
SanCovFunction = checkSanitizerInterfaceFunction(
|
SanCovFunction = checkSanitizerInterfaceFunction(
|
||||||
M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr));
|
M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr));
|
||||||
|
@ -296,7 +300,7 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||||
SanCovTracePC = checkSanitizerInterfaceFunction(
|
SanCovTracePC = checkSanitizerInterfaceFunction(
|
||||||
M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
|
M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
|
||||||
SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
|
SanCovTracePCGuard = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
|
||||||
SanCovTracePCGuardName, VoidTy, IntptrPtrTy, nullptr));
|
SanCovTracePCGuardName, VoidTy, Int32PtrTy, nullptr));
|
||||||
SanCovTraceEnter = checkSanitizerInterfaceFunction(
|
SanCovTraceEnter = checkSanitizerInterfaceFunction(
|
||||||
M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
|
M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
|
||||||
SanCovTraceBB = checkSanitizerInterfaceFunction(
|
SanCovTraceBB = checkSanitizerInterfaceFunction(
|
||||||
|
@ -307,9 +311,10 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||||
Type *Int32Ty = IRB.getInt32Ty();
|
Type *Int32Ty = IRB.getInt32Ty();
|
||||||
Type *Int8Ty = IRB.getInt8Ty();
|
Type *Int8Ty = IRB.getInt8Ty();
|
||||||
|
|
||||||
GuardArray =
|
if (!Options.TracePCGuard)
|
||||||
new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
|
GuardArray =
|
||||||
nullptr, "__sancov_gen_cov_tmp");
|
new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
|
||||||
|
nullptr, "__sancov_gen_cov_tmp");
|
||||||
if (Options.Use8bitCounters)
|
if (Options.Use8bitCounters)
|
||||||
EightBitCounterArray =
|
EightBitCounterArray =
|
||||||
new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage,
|
new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage,
|
||||||
|
@ -320,17 +325,20 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||||
|
|
||||||
auto N = NumberOfInstrumentedBlocks();
|
auto N = NumberOfInstrumentedBlocks();
|
||||||
|
|
||||||
// Now we know how many elements we need. Create an array of guards
|
GlobalVariable *RealGuardArray = nullptr;
|
||||||
// with one extra element at the beginning for the size.
|
if (!Options.TracePCGuard) {
|
||||||
Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1);
|
// Now we know how many elements we need. Create an array of guards
|
||||||
GlobalVariable *RealGuardArray = new GlobalVariable(
|
// with one extra element at the beginning for the size.
|
||||||
M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage,
|
Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1);
|
||||||
Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov");
|
RealGuardArray = new GlobalVariable(
|
||||||
|
M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage,
|
||||||
|
Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov");
|
||||||
|
|
||||||
// Replace the dummy array with the real one.
|
// Replace the dummy array with the real one.
|
||||||
GuardArray->replaceAllUsesWith(
|
GuardArray->replaceAllUsesWith(
|
||||||
IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
|
IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
|
||||||
GuardArray->eraseFromParent();
|
GuardArray->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
GlobalVariable *RealEightBitCounterArray;
|
GlobalVariable *RealEightBitCounterArray;
|
||||||
if (Options.Use8bitCounters) {
|
if (Options.Use8bitCounters) {
|
||||||
|
@ -359,16 +367,16 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||||
GlobalVariable *Bounds[2];
|
GlobalVariable *Bounds[2];
|
||||||
const char *Prefix[2] = {"__start_", "__stop_"};
|
const char *Prefix[2] = {"__start_", "__stop_"};
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
Bounds[i] = new GlobalVariable(M, IntptrPtrTy, false,
|
Bounds[i] = new GlobalVariable(M, Int32PtrTy, false,
|
||||||
GlobalVariable::ExternalLinkage, nullptr,
|
GlobalVariable::ExternalLinkage, nullptr,
|
||||||
Prefix[i] + SectionName);
|
Prefix[i] + SectionName);
|
||||||
Bounds[i]->setVisibility(GlobalValue::HiddenVisibility);
|
Bounds[i]->setVisibility(GlobalValue::HiddenVisibility);
|
||||||
}
|
}
|
||||||
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
|
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
|
||||||
M, SanCovModuleCtorName, SanCovTracePCGuardInitName,
|
M, SanCovModuleCtorName, SanCovTracePCGuardInitName,
|
||||||
{IntptrPtrTy, IntptrPtrTy},
|
{Int32PtrTy, Int32PtrTy},
|
||||||
{IRB.CreatePointerCast(Bounds[0], IntptrPtrTy),
|
{IRB.CreatePointerCast(Bounds[0], Int32PtrTy),
|
||||||
IRB.CreatePointerCast(Bounds[1], IntptrPtrTy)});
|
IRB.CreatePointerCast(Bounds[1], Int32PtrTy)});
|
||||||
|
|
||||||
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
|
appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
|
||||||
}
|
}
|
||||||
|
@ -419,6 +427,14 @@ static bool isFullPostDominator(const BasicBlock *BB,
|
||||||
|
|
||||||
static bool shouldInstrumentBlock(const Function& F, const BasicBlock *BB, const DominatorTree *DT,
|
static bool shouldInstrumentBlock(const Function& F, const BasicBlock *BB, const DominatorTree *DT,
|
||||||
const PostDominatorTree *PDT) {
|
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)
|
if (!ClPruneBlocks || &F.getEntryBlock() == BB)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -486,19 +502,34 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
||||||
InjectTraceForGep(F, GepTraceTargets);
|
InjectTraceForGep(F, GepTraceTargets);
|
||||||
return true;
|
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,
|
bool SanitizerCoverageModule::InjectCoverage(Function &F,
|
||||||
ArrayRef<BasicBlock *> AllBlocks) {
|
ArrayRef<BasicBlock *> AllBlocks) {
|
||||||
|
if (AllBlocks.empty()) return false;
|
||||||
switch (Options.CoverageType) {
|
switch (Options.CoverageType) {
|
||||||
case SanitizerCoverageOptions::SCK_None:
|
case SanitizerCoverageOptions::SCK_None:
|
||||||
return false;
|
return false;
|
||||||
case SanitizerCoverageOptions::SCK_Function:
|
case SanitizerCoverageOptions::SCK_Function:
|
||||||
InjectCoverageAtBlock(F, F.getEntryBlock(), false);
|
CreateFunctionGuardArray(1, F);
|
||||||
|
InjectCoverageAtBlock(F, F.getEntryBlock(), 0, false);
|
||||||
return true;
|
return true;
|
||||||
default: {
|
default: {
|
||||||
bool UseCalls = ClCoverageBlockThreshold < AllBlocks.size();
|
bool UseCalls = ClCoverageBlockThreshold < AllBlocks.size();
|
||||||
for (auto BB : AllBlocks)
|
CreateFunctionGuardArray(AllBlocks.size(), F);
|
||||||
InjectCoverageAtBlock(F, *BB, UseCalls);
|
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
|
||||||
|
InjectCoverageAtBlock(F, *AllBlocks[i], i, UseCalls);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,16 +666,8 @@ void SanitizerCoverageModule::SetNoSanitizeMetadata(Instruction *I) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||||
bool UseCalls) {
|
size_t Idx, 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;
|
|
||||||
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
||||||
|
|
||||||
bool IsEntryBB = &BB == &F.getEntryBlock();
|
bool IsEntryBB = &BB == &F.getEntryBlock();
|
||||||
DebugLoc EntryLoc;
|
DebugLoc EntryLoc;
|
||||||
if (IsEntryBB) {
|
if (IsEntryBB) {
|
||||||
|
@ -660,24 +683,22 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||||
|
|
||||||
IRBuilder<> IRB(&*IP);
|
IRBuilder<> IRB(&*IP);
|
||||||
IRB.SetCurrentDebugLocation(EntryLoc);
|
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) {
|
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) {
|
} else if (Options.TracePCGuard) {
|
||||||
auto GuardVar = new GlobalVariable(
|
//auto GuardVar = new GlobalVariable(
|
||||||
*F.getParent(), Int64Ty, false, GlobalVariable::LinkOnceODRLinkage,
|
// *F.getParent(), Int64Ty, false, GlobalVariable::LinkOnceODRLinkage,
|
||||||
Constant::getNullValue(Int64Ty), "__sancov_guard." + F.getName());
|
// Constant::getNullValue(Int64Ty), "__sancov_guard." + F.getName());
|
||||||
if (auto Comdat = F.getComdat())
|
// if (auto Comdat = F.getComdat())
|
||||||
GuardVar->setComdat(Comdat);
|
// GuardVar->setComdat(Comdat);
|
||||||
// TODO: add debug into to GuardVar.
|
// TODO: add debug into to GuardVar.
|
||||||
GuardVar->setSection(SanCovTracePCGuardSection);
|
// GuardVar->setSection(SanCovTracePCGuardSection);
|
||||||
HasSancovGuardsSection = true;
|
// auto GuardPtr = IRB.CreatePointerCast(GuardVar, IntptrPtrTy);
|
||||||
auto GuardPtr = IRB.CreatePointerCast(GuardVar, IntptrPtrTy);
|
auto GuardPtr = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(IntptrTy, Idx * 4)),
|
||||||
|
Int32PtrTy);
|
||||||
if (!UseCalls) {
|
if (!UseCalls) {
|
||||||
auto GuardLoad = IRB.CreateLoad(GuardPtr);
|
auto GuardLoad = IRB.CreateLoad(GuardPtr);
|
||||||
GuardLoad->setAtomic(AtomicOrdering::Monotonic);
|
GuardLoad->setAtomic(AtomicOrdering::Monotonic);
|
||||||
|
@ -692,24 +713,30 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||||
}
|
}
|
||||||
IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
|
IRB.CreateCall(SanCovTracePCGuard, GuardPtr);
|
||||||
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
||||||
} else if (Options.TraceBB) {
|
|
||||||
IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
|
|
||||||
} else if (UseCalls) {
|
|
||||||
IRB.CreateCall(SanCovWithCheckFunction, GuardP);
|
|
||||||
} else {
|
} else {
|
||||||
LoadInst *Load = IRB.CreateLoad(GuardP);
|
Value *GuardP = IRB.CreateAdd(
|
||||||
Load->setAtomic(AtomicOrdering::Monotonic);
|
IRB.CreatePointerCast(GuardArray, IntptrTy),
|
||||||
Load->setAlignment(4);
|
ConstantInt::get(IntptrTy, (1 + NumberOfInstrumentedBlocks()) * 4));
|
||||||
SetNoSanitizeMetadata(Load);
|
GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
|
||||||
Value *Cmp =
|
if (Options.TraceBB) {
|
||||||
IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load);
|
IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
|
||||||
Instruction *Ins = SplitBlockAndInsertIfThen(
|
} else if (UseCalls) {
|
||||||
Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
|
IRB.CreateCall(SanCovWithCheckFunction, GuardP);
|
||||||
IRB.SetInsertPoint(Ins);
|
} else {
|
||||||
IRB.SetCurrentDebugLocation(EntryLoc);
|
LoadInst *Load = IRB.CreateLoad(GuardP);
|
||||||
// __sanitizer_cov gets the PC of the instruction using GET_CALLER_PC.
|
Load->setAtomic(AtomicOrdering::Monotonic);
|
||||||
IRB.CreateCall(SanCovFunction, GuardP);
|
Load->setAlignment(4);
|
||||||
IRB.CreateCall(EmptyAsm, {}); // Avoids callback merge.
|
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) {
|
if (Options.Use8bitCounters) {
|
||||||
|
|
|
@ -9,5 +9,4 @@ entry:
|
||||||
ret void
|
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)
|
||||||
|
|
||||||
|
|
|
@ -46,4 +46,4 @@ entry:
|
||||||
; 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-NOT: call void @__sanitizer_cov_trace_pc
|
||||||
; CHECK_PC_GUARD: ret void
|
; 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*))
|
||||||
|
|
Loading…
Reference in New Issue