#define DEBUG_TYPE "sancov"
-static const char *const kSanCovModuleInitName = "__sanitizer_cov_module_init";
-static const char *const kSanCovName = "__sanitizer_cov";
-static const char *const kSanCovWithCheckName = "__sanitizer_cov_with_check";
-static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16";
-static const char *const kSanCovTracePCIndir = "__sanitizer_cov_trace_pc_indir";
-static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter";
-static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block";
-static const char *const kSanCovTracePC = "__sanitizer_cov_trace_pc";
-static const char *const kSanCovTraceCmp = "__sanitizer_cov_trace_cmp";
-static const char *const kSanCovTraceSwitch = "__sanitizer_cov_trace_switch";
-static const char *const kSanCovModuleCtorName = "sancov.module_ctor";
-static const uint64_t kSanCtorAndDtorPriority = 2;
-
-static cl::opt<int> ClCoverageLevel("sanitizer-coverage-level",
- cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
- "3: all blocks and critical edges, "
- "4: above plus indirect calls"),
- cl::Hidden, cl::init(0));
+static const char *const SanCovModuleInitName = "__sanitizer_cov_module_init";
+static const char *const SanCovName = "__sanitizer_cov";
+static const char *const SanCovWithCheckName = "__sanitizer_cov_with_check";
+static const char *const SanCovIndirCallName = "__sanitizer_cov_indir_call16";
+static const char *const SanCovTracePCIndirName =
+ "__sanitizer_cov_trace_pc_indir";
+static const char *const SanCovTraceEnterName =
+ "__sanitizer_cov_trace_func_enter";
+static const char *const SanCovTraceBBName =
+ "__sanitizer_cov_trace_basic_block";
+static const char *const SanCovTracePCName = "__sanitizer_cov_trace_pc";
+static const char *const SanCovTraceCmpName = "__sanitizer_cov_trace_cmp";
+static const char *const SanCovTraceSwitchName = "__sanitizer_cov_trace_switch";
+static const char *const SanCovModuleCtorName = "sancov.module_ctor";
+static const uint64_t SanCtorAndDtorPriority = 2;
+
+static cl::opt<int> ClCoverageLevel(
+ "sanitizer-coverage-level",
+ cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
+ "3: all blocks and critical edges, "
+ "4: above plus indirect calls"),
+ cl::Hidden, cl::init(0));
static cl::opt<unsigned> ClCoverageBlockThreshold(
"sanitizer-coverage-block-threshold",
}
class SanitizerCoverageModule : public ModulePass {
- public:
+public:
SanitizerCoverageModule(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
: ModulePass(ID), Options(OverrideFromCL(Options)) {
}
bool runOnModule(Module &M) override;
bool runOnFunction(Function &F);
- static char ID; // Pass identification, replacement for typeid
- const char *getPassName() const override {
- return "SanitizerCoverageModule";
- }
+ static char ID; // Pass identification, replacement for typeid
+ const char *getPassName() const override { return "SanitizerCoverageModule"; }
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<DominatorTreeWrapperPass>();
SanitizerCoverageOptions Options;
};
-} // namespace
+} // namespace
bool SanitizerCoverageModule::runOnModule(Module &M) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
Int64Ty = IRB.getInt64Ty();
SanCovFunction = checkSanitizerInterfaceFunction(
- M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr));
+ M.getOrInsertFunction(SanCovName, VoidTy, Int32PtrTy, nullptr));
SanCovWithCheckFunction = checkSanitizerInterfaceFunction(
- M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr));
- SanCovTracePCIndir =
- checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kSanCovTracePCIndir, VoidTy, IntptrTy, nullptr));
+ M.getOrInsertFunction(SanCovWithCheckName, VoidTy, Int32PtrTy, nullptr));
+ SanCovTracePCIndir = checkSanitizerInterfaceFunction(
+ M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy, nullptr));
SanCovIndirCallFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
+ SanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
SanCovTraceCmpFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr));
+ SanCovTraceCmpName, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr));
SanCovTraceSwitchFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kSanCovTraceSwitch, VoidTy, Int64Ty, Int64PtrTy, nullptr));
+ SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy, nullptr));
// We insert an empty inline asm after cov callbacks to avoid callback merge.
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
/*hasSideEffects=*/true);
SanCovTracePC = checkSanitizerInterfaceFunction(
- M.getOrInsertFunction(kSanCovTracePC, VoidTy, nullptr));
+ M.getOrInsertFunction(SanCovTracePCName, VoidTy, nullptr));
SanCovTraceEnter = checkSanitizerInterfaceFunction(
- M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr));
+ M.getOrInsertFunction(SanCovTraceEnterName, VoidTy, Int32PtrTy, nullptr));
SanCovTraceBB = checkSanitizerInterfaceFunction(
- M.getOrInsertFunction(kSanCovTraceBB, VoidTy, Int32PtrTy, nullptr));
+ M.getOrInsertFunction(SanCovTraceBBName, VoidTy, Int32PtrTy, nullptr));
// At this point we create a dummy array of guards because we don't
// know how many elements we will need.
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));
GlobalVariable *RealEightBitCounterArray;
if (Options.Use8bitCounters) {
// Make sure the array is 16-aligned.
- static const int kCounterAlignment = 16;
- Type *Int8ArrayNTy = ArrayType::get(Int8Ty, alignTo(N, kCounterAlignment));
+ static const int CounterAlignment = 16;
+ Type *Int8ArrayNTy = ArrayType::get(Int8Ty, alignTo(N, CounterAlignment));
RealEightBitCounterArray = new GlobalVariable(
M, Int8ArrayNTy, false, GlobalValue::PrivateLinkage,
Constant::getNullValue(Int8ArrayNTy), "__sancov_gen_cov_counter");
- RealEightBitCounterArray->setAlignment(kCounterAlignment);
+ RealEightBitCounterArray->setAlignment(CounterAlignment);
EightBitCounterArray->replaceAllUsesWith(
IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy));
EightBitCounterArray->eraseFromParent();
if (!Options.TracePC) {
Function *CtorFunc;
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
- M, kSanCovModuleCtorName, kSanCovModuleInitName,
+ M, SanCovModuleCtorName, SanCovModuleInitName,
{Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy},
{IRB.CreatePointerCast(RealGuardArray, Int32PtrTy),
- ConstantInt::get(IntptrTy, N),
- Options.Use8bitCounters
- ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)
- : Constant::getNullValue(Int8PtrTy),
- IRB.CreatePointerCast(ModuleName, Int8PtrTy)});
+ ConstantInt::get(IntptrTy, N),
+ Options.Use8bitCounters
+ ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)
+ : Constant::getNullValue(Int8PtrTy),
+ IRB.CreatePointerCast(ModuleName, Int8PtrTy)});
- appendToGlobalCtors(M, CtorFunc, kSanCtorAndDtorPriority);
+ appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);
}
return true;
}
bool SanitizerCoverageModule::runOnFunction(Function &F) {
- if (F.empty()) return false;
+ if (F.empty())
+ return false;
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.
// Don't instrument functions using SEH for now. Splitting basic blocks like
// we do for coverage breaks WinEHPrepare.
// FIXME: Remove this when SEH no longer uses landingpad pattern matching.
return false;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(F);
- SmallVector<Instruction*, 8> IndirCalls;
+ SmallVector<Instruction *, 8> IndirCalls;
SmallVector<BasicBlock *, 16> BlocksToInstrument;
- SmallVector<Instruction*, 8> CmpTraceTargets;
- SmallVector<Instruction*, 8> SwitchTraceTargets;
+ SmallVector<Instruction *, 8> CmpTraceTargets;
+ SmallVector<Instruction *, 8> SwitchTraceTargets;
DominatorTree DT;
DT.recalculate(F);
// On every indirect call we call a run-time function
// __sanitizer_cov_indir_call* with two parameters:
// - callee address,
-// - global cache array that contains kCacheSize pointers (zero-initialized).
+// - global cache array that contains CacheSize pointers (zero-initialized).
// The cache is used to speed up recording the caller-callee pairs.
// The address of the caller is passed implicitly via caller PC.
-// kCacheSize is encoded in the name of the run-time function.
+// CacheSize is encoded in the name of the run-time function.
void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) {
- if (IndirCalls.empty()) return;
- const int kCacheSize = 16;
- const int kCacheAlignment = 64; // Align for better performance.
- Type *Ty = ArrayType::get(IntptrTy, kCacheSize);
+ if (IndirCalls.empty())
+ return;
+ const int CacheSize = 16;
+ const int CacheAlignment = 64; // Align for better performance.
+ Type *Ty = ArrayType::get(IntptrTy, CacheSize);
for (auto I : IndirCalls) {
IRBuilder<> IRB(I);
CallSite CS(I);
Value *Callee = CS.getCalledValue();
- if (isa<InlineAsm>(Callee)) continue;
+ if (isa<InlineAsm>(Callee))
+ continue;
GlobalVariable *CalleeCache = new GlobalVariable(
*F.getParent(), Ty, false, GlobalValue::PrivateLinkage,
Constant::getNullValue(Ty), "__sancov_gen_callee_cache");
- CalleeCache->setAlignment(kCacheAlignment);
+ CalleeCache->setAlignment(CacheAlignment);
if (Options.TracePC)
IRB.CreateCall(SanCovTracePCIndir,
IRB.CreatePointerCast(Callee, IntptrTy));
else
IRB.CreateCall(SanCovIndirCallFunction,
{IRB.CreatePointerCast(Callee, IntptrTy),
- IRB.CreatePointerCast(CalleeCache, IntptrTy)});
+ IRB.CreatePointerCast(CalleeCache, IntptrTy)});
}
}
// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
void SanitizerCoverageModule::InjectTraceForSwitch(
- Function &F, ArrayRef<Instruction *> SwitchTraceTargets) {
+ Function &, ArrayRef<Instruction *> SwitchTraceTargets) {
for (auto I : SwitchTraceTargets) {
if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
IRBuilder<> IRB(I);
if (Cond->getType()->getScalarSizeInBits() <
Int64Ty->getScalarSizeInBits())
Cond = IRB.CreateIntCast(Cond, Int64Ty, false);
- for (auto It: SI->cases()) {
+ for (auto It : SI->cases()) {
Constant *C = It.getCaseValue();
if (C->getType()->getScalarSizeInBits() <
Int64Ty->getScalarSizeInBits())
}
}
-
void SanitizerCoverageModule::InjectTraceForCmp(
- Function &F, ArrayRef<Instruction *> CmpTraceTargets) {
+ Function &, ArrayRef<Instruction *> CmpTraceTargets) {
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;
+ if (!A0->getType()->isIntegerTy())
+ continue;
uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());
// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
IRB.CreateCall(
}
void SanitizerCoverageModule::SetNoSanitizeMetadata(Instruction *I) {
- I->setMetadata(
- I->getModule()->getMDKindID("nosanitize"), MDNode::get(*C, None));
+ I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
+ MDNode::get(*C, None));
}
void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
Load->setAtomic(Monotonic);
Load->setAlignment(4);
SetNoSanitizeMetadata(Load);
- Value *Cmp = IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load);
+ Value *Cmp =
+ IRB.CreateICmpSGE(Constant::getNullValue(Load->getType()), Load);
Instruction *Ins = SplitBlockAndInsertIfThen(
Cmp, &*IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
IRB.SetInsertPoint(Ins);
char SanitizerCoverageModule::ID = 0;
INITIALIZE_PASS_BEGIN(SanitizerCoverageModule, "sancov",
- "SanitizerCoverage: TODO."
- "ModulePass", false, false)
+ "SanitizerCoverage: TODO."
+ "ModulePass",
+ false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_END(SanitizerCoverageModule, "sancov",
- "SanitizerCoverage: TODO."
- "ModulePass", false, false)
+ "SanitizerCoverage: TODO."
+ "ModulePass",
+ false, false)
ModulePass *llvm::createSanitizerCoverageModulePass(
const SanitizerCoverageOptions &Options) {
return new SanitizerCoverageModule(Options);