40 #define DEBUG_TYPE "sancov"
67 "sancov.module_ctor_trace_pc_guard";
69 "sancov.module_ctor_8bit_counters";
87 "sanitizer-coverage-level",
88 cl::desc(
"Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
89 "3: all blocks and critical edges"),
107 cl::desc(
"create a static PC table"),
112 cl::desc(
"increments 8-bit counter for every edge"),
122 cl::desc(
"Tracing of CMP and similar instructions"),
126 cl::desc(
"Tracing of DIV instructions"),
130 cl::desc(
"Tracing of load instructions"),
134 cl::desc(
"Tracing of store instructions"),
138 cl::desc(
"Tracing of GEP instructions"),
143 cl::desc(
"Reduce the number of instrumented blocks"),
147 cl::desc(
"max stack depth tracing"),
154 switch (LegacyCoverageLevel) {
200 using PostDomTreeCallback =
203 class ModuleSanitizerCoverage {
205 ModuleSanitizerCoverage(
210 Blocklist(Blocklist) {}
211 bool instrumentModule(
Module &M, DomTreeCallback DTCallback,
212 PostDomTreeCallback PDTCallback);
215 void instrumentFunction(
Function &
F, DomTreeCallback DTCallback,
216 PostDomTreeCallback PDTCallback);
217 void InjectCoverageForIndirectCalls(
Function &
F,
229 bool IsLeafFunc =
true);
230 GlobalVariable *CreateFunctionLocalArrayInSection(
size_t NumElements,
232 const char *Section);
236 bool IsLeafFunc =
true);
237 Function *CreateInitCallsForSections(
Module &M,
const char *CtorName,
238 const char *InitFunctionName,
Type *Ty,
239 const char *Section);
240 std::pair<Value *, Value *> CreateSecStartEnd(
Module &M,
const char *Section,
244 I->setMetadata(
I->getModule()->getMDKindID(
"nosanitize"),
248 std::string getSectionName(
const std::string &Section)
const;
249 std::string getSectionStart(
const std::string &Section)
const;
250 std::string getSectionEnd(
const std::string &Section)
const;
253 std::array<FunctionCallee, 4> SanCovTraceCmpFunction;
254 std::array<FunctionCallee, 4> SanCovTraceConstCmpFunction;
255 std::array<FunctionCallee, 5> SanCovLoadFunction;
256 std::array<FunctionCallee, 5> SanCovStoreFunction;
257 std::array<FunctionCallee, 2> SanCovTraceDivFunction;
261 Type *Int128PtrTy, *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *
Int32Ty,
262 *Int32PtrTy, *Int16PtrTy, *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty,
265 std::string CurModuleUniqueId;
283 class ModuleSanitizerCoverageLegacyPass :
public ModulePass {
285 ModuleSanitizerCoverageLegacyPass(
287 const std::vector<std::string> &AllowlistFiles =
288 std::vector<std::string>(),
289 const std::vector<std::string> &BlocklistFiles =
290 std::vector<std::string>())
292 if (AllowlistFiles.size() > 0)
295 if (BlocklistFiles.size() > 0)
301 bool runOnModule(
Module &M)
override {
302 ModuleSanitizerCoverage ModuleSancov(
Options, Allowlist.get(),
305 return &this->getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
308 return &this->getAnalysis<PostDominatorTreeWrapperPass>(
F)
311 return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
315 StringRef getPassName()
const override {
return "ModuleSanitizerCoverage"; }
325 std::unique_ptr<SpecialCaseList> Allowlist;
326 std::unique_ptr<SpecialCaseList> Blocklist;
333 ModuleSanitizerCoverage ModuleSancov(
Options, Allowlist.get(),
342 if (ModuleSancov.instrumentModule(
M, DTCallback, PDTCallback))
347 std::pair<Value *, Value *>
348 ModuleSanitizerCoverage::CreateSecStartEnd(
Module &M,
const char *Section,
359 getSectionStart(Section));
363 getSectionEnd(Section));
366 if (!TargetTriple.isOSBinFormatCOFF())
367 return std::make_pair(SecStart, SecEnd);
371 auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
372 auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
378 Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
379 Module &M,
const char *CtorName,
const char *InitFunctionName,
Type *Ty,
380 const char *Section) {
381 auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
382 auto SecStart = SecStartEnd.first;
383 auto SecEnd = SecStartEnd.second;
387 M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd});
390 if (TargetTriple.supportsCOMDAT()) {
392 CtorFunc->
setComdat(
M.getOrInsertComdat(CtorName));
398 if (TargetTriple.isOSBinFormatCOFF()) {
410 bool ModuleSanitizerCoverage::instrumentModule(
411 Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
415 !Allowlist->inSection(
"coverage",
"src",
M.getSourceFileName()))
418 Blocklist->inSection(
"coverage",
"src",
M.getSourceFileName()))
420 C = &(
M.getContext());
421 DL = &
M.getDataLayout();
424 TargetTriple =
Triple(
M.getTargetTriple());
425 FunctionGuardArray =
nullptr;
426 Function8bitCounterArray =
nullptr;
427 FunctionBoolArray =
nullptr;
428 FunctionPCsArray =
nullptr;
439 Int64Ty = IRB.getInt64Ty();
450 SanCovTraceCmpZeroExtAL =
452 SanCovTraceCmpZeroExtAL =
455 SanCovTraceCmpFunction[0] =
457 IRB.getInt8Ty(), IRB.getInt8Ty());
458 SanCovTraceCmpFunction[1] =
460 IRB.getInt16Ty(), IRB.getInt16Ty());
461 SanCovTraceCmpFunction[2] =
463 IRB.getInt32Ty(), IRB.getInt32Ty());
464 SanCovTraceCmpFunction[3] =
467 SanCovTraceConstCmpFunction[0] =
M.getOrInsertFunction(
469 SanCovTraceConstCmpFunction[1] =
M.getOrInsertFunction(
471 SanCovTraceConstCmpFunction[2] =
M.getOrInsertFunction(
473 SanCovTraceConstCmpFunction[3] =
477 SanCovLoadFunction[0] =
M.getOrInsertFunction(
SanCovLoad1, VoidTy, Int8PtrTy);
478 SanCovLoadFunction[1] =
480 SanCovLoadFunction[2] =
482 SanCovLoadFunction[3] =
484 SanCovLoadFunction[4] =
487 SanCovStoreFunction[0] =
489 SanCovStoreFunction[1] =
491 SanCovStoreFunction[2] =
493 SanCovStoreFunction[3] =
495 SanCovStoreFunction[4] =
500 AL =
AL.addParamAttribute(*
C, 0, Attribute::ZExt);
501 SanCovTraceDivFunction[0] =
504 SanCovTraceDivFunction[1] =
506 SanCovTraceGepFunction =
508 SanCovTraceSwitchFunction =
511 Constant *SanCovLowestStackConstant =
513 SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant);
514 if (!SanCovLowestStack || SanCovLowestStack->getValueType() != IntptrTy) {
516 "' should not be declared by the user");
519 SanCovLowestStack->setThreadLocalMode(
520 GlobalValue::ThreadLocalMode::InitialExecTLSModel);
521 if (
Options.StackDepth && !SanCovLowestStack->isDeclaration())
529 instrumentFunction(
F, DTCallback, PDTCallback);
533 if (FunctionGuardArray)
537 if (Function8bitCounterArray)
541 if (FunctionBoolArray) {
551 IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
588 if (isa<UnreachableInst>(
BB->getFirstNonPHIOrDbgOrLifetime()))
593 if (
BB->getFirstInsertionPt() ==
BB->end())
596 if (
Options.NoPrune || &
F.getEntryBlock() ==
BB)
600 &
F.getEntryBlock() !=
BB)
632 if (
CMP->hasOneUse())
633 if (
auto BR = dyn_cast<BranchInst>(
CMP->user_back()))
640 void ModuleSanitizerCoverage::instrumentFunction(
641 Function &
F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
644 if (
F.getName().find(
".module_ctor") != std::string::npos)
646 if (
F.getName().startswith(
"__sanitizer_"))
653 if (
F.getName() ==
"__local_stdio_printf_options" ||
654 F.getName() ==
"__local_stdio_scanf_options")
656 if (isa<UnreachableInst>(
F.getEntryBlock().getTerminator()))
661 if (
F.hasPersonalityFn() &&
664 if (Allowlist && !Allowlist->inSection(
"coverage",
"fun",
F.getName()))
666 if (Blocklist && Blocklist->inSection(
"coverage",
"fun",
F.getName()))
668 if (
F.hasFnAttribute(Attribute::NoSanitizeCoverage))
683 bool IsLeafFunc =
true;
687 BlocksToInstrument.push_back(&
BB);
688 for (
auto &Inst :
BB) {
690 CallBase *CB = dyn_cast<CallBase>(&Inst);
692 IndirCalls.push_back(&Inst);
697 CmpTraceTargets.push_back(&Inst);
698 if (isa<SwitchInst>(&Inst))
699 SwitchTraceTargets.push_back(&Inst);
703 if (BO->getOpcode() == Instruction::SDiv ||
704 BO->getOpcode() == Instruction::UDiv)
705 DivTraceTargets.push_back(BO);
708 GepTraceTargets.push_back(
GEP);
710 if (
LoadInst *LI = dyn_cast<LoadInst>(&Inst))
714 Stores.push_back(
SI);
716 if (isa<InvokeInst>(Inst) ||
717 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst)))
722 InjectCoverage(
F, BlocksToInstrument, IsLeafFunc);
723 InjectCoverageForIndirectCalls(
F, IndirCalls);
724 InjectTraceForCmp(
F, CmpTraceTargets);
725 InjectTraceForSwitch(
F, SwitchTraceTargets);
726 InjectTraceForDiv(
F, DivTraceTargets);
727 InjectTraceForGep(
F, GepTraceTargets);
728 InjectTraceForLoadsAndStores(
F, Loads, Stores);
731 GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
732 size_t NumElements,
Function &
F,
Type *Ty,
const char *Section) {
738 if (TargetTriple.supportsCOMDAT() &&
739 (TargetTriple.isOSBinFormatELF() || !
F.isInterposable()))
742 Array->setSection(getSectionName(Section));
743 Array->setAlignment(
Align(
DL->getTypeStoreSize(Ty).getFixedSize()));
754 if (
Array->hasComdat())
755 GlobalsToAppendToCompilerUsed.push_back(Array);
757 GlobalsToAppendToUsed.push_back(Array);
763 ModuleSanitizerCoverage::CreatePCArray(
Function &
F,
765 size_t N = AllBlocks.
size();
768 IRBuilder<> IRB(&*
F.getEntryBlock().getFirstInsertionPt());
769 for (
size_t i = 0;
i <
N;
i++) {
770 if (&
F.getEntryBlock() == AllBlocks[
i]) {
771 PCs.push_back((
Constant *)IRB.CreatePointerCast(&
F, IntptrPtrTy));
772 PCs.push_back((
Constant *)IRB.CreateIntToPtr(
775 PCs.push_back((
Constant *)IRB.CreatePointerCast(
777 PCs.push_back((
Constant *)IRB.CreateIntToPtr(
781 auto *PCArray = CreateFunctionLocalArrayInSection(
N * 2,
F, IntptrPtrTy,
783 PCArray->setInitializer(
785 PCArray->setConstant(
true);
790 void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
793 FunctionGuardArray = CreateFunctionLocalArrayInSection(
796 if (
Options.Inline8bitCounters)
797 Function8bitCounterArray = CreateFunctionLocalArrayInSection(
800 FunctionBoolArray = CreateFunctionLocalArrayInSection(
804 FunctionPCsArray = CreatePCArray(
F, AllBlocks);
807 bool ModuleSanitizerCoverage::InjectCoverage(
Function &
F,
810 if (AllBlocks.
empty())
return false;
811 CreateFunctionLocalArrays(
F, AllBlocks);
812 for (
size_t i = 0,
N = AllBlocks.
size();
i <
N;
i++)
813 InjectCoverageAtBlock(
F, *AllBlocks[
i],
i, IsLeafFunc);
824 void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
826 if (IndirCalls.
empty())
830 for (
auto I : IndirCalls) {
834 if (isa<InlineAsm>(Callee))
836 IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy));
844 void ModuleSanitizerCoverage::InjectTraceForSwitch(
846 for (
auto I : SwitchTraceTargets) {
851 if (
Cond->getType()->getScalarSizeInBits() >
852 Int64Ty->getScalarSizeInBits())
855 Initializers.push_back(
857 if (
Cond->getType()->getScalarSizeInBits() <
858 Int64Ty->getScalarSizeInBits())
859 Cond = IRB.CreateIntCast(
Cond, Int64Ty,
false);
860 for (
auto It :
SI->cases()) {
862 if (
C->getType()->getScalarSizeInBits() <
863 Int64Ty->getScalarSizeInBits())
865 Initializers.push_back(
C);
869 return cast<ConstantInt>(A)->getLimitedValue() <
870 cast<ConstantInt>(
B)->getLimitedValue();
876 "__sancov_gen_cov_switch_values");
877 IRB.CreateCall(SanCovTraceSwitchFunction,
878 {
Cond, IRB.CreatePointerCast(GV, Int64PtrTy)});
883 void ModuleSanitizerCoverage::InjectTraceForDiv(
885 for (
auto BO : DivTraceTargets) {
887 Value *A1 = BO->getOperand(1);
888 if (isa<ConstantInt>(A1))
continue;
892 int CallbackIdx =
TypeSize == 32 ? 0 :
894 if (CallbackIdx < 0)
continue;
896 IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx],
897 {IRB.CreateIntCast(A1, Ty,
true)});
901 void ModuleSanitizerCoverage::InjectTraceForGep(
903 for (
auto GEP : GepTraceTargets) {
905 for (
Use &Idx :
GEP->indices())
906 if (!isa<ConstantInt>(Idx) && Idx->getType()->isIntegerTy())
907 IRB.CreateCall(SanCovTraceGepFunction,
908 {IRB.CreateIntCast(Idx, IntptrTy,
true)});
912 void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores(
914 auto CallbackIdx = [&](
Type *ElementTy) ->
int {
925 for (
auto LI : Loads) {
927 auto Ptr = LI->getPointerOperand();
928 int Idx = CallbackIdx(LI->getType());
931 IRB.CreateCall(SanCovLoadFunction[Idx],
934 for (
auto SI : Stores) {
936 auto Ptr =
SI->getPointerOperand();
937 int Idx = CallbackIdx(
SI->getValueOperand()->getType());
940 IRB.CreateCall(SanCovStoreFunction[Idx],
945 void ModuleSanitizerCoverage::InjectTraceForCmp(
947 for (
auto I : CmpTraceTargets) {
955 int CallbackIdx =
TypeSize == 8 ? 0 :
959 if (CallbackIdx < 0)
continue;
961 auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];
962 bool FirstIsConst = isa<ConstantInt>(A0);
963 bool SecondIsConst = isa<ConstantInt>(A1);
965 if (FirstIsConst && SecondIsConst)
continue;
967 if (FirstIsConst || SecondIsConst) {
968 CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx];
974 IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty,
true),
975 IRB.CreateIntCast(A1, Ty,
true)});
984 bool IsEntryBB = &
BB == &
F.getEntryBlock();
987 if (
auto SP =
F.getSubprogram())
988 EntryLoc =
DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
997 IRB.SetCurrentDebugLocation(EntryLoc);
999 IRB.CreateCall(SanCovTracePC)
1003 auto GuardPtr = IRB.CreateIntToPtr(
1004 IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
1007 IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge();
1009 if (
Options.Inline8bitCounters) {
1010 auto CounterPtr = IRB.CreateGEP(
1011 Function8bitCounterArray->getValueType(), Function8bitCounterArray,
1012 {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
1013 auto Load = IRB.CreateLoad(Int8Ty, CounterPtr);
1015 auto Store = IRB.CreateStore(Inc, CounterPtr);
1016 SetNoSanitizeMetadata(
Load);
1017 SetNoSanitizeMetadata(
Store);
1020 auto FlagPtr = IRB.CreateGEP(
1021 FunctionBoolArray->getValueType(), FunctionBoolArray,
1022 {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
1023 auto Load = IRB.CreateLoad(Int1Ty, FlagPtr);
1028 SetNoSanitizeMetadata(
Load);
1029 SetNoSanitizeMetadata(
Store);
1031 if (
Options.StackDepth && IsEntryBB && !IsLeafFunc) {
1035 M, Intrinsic::frameaddress,
1036 IRB.getInt8PtrTy(
M->getDataLayout().getAllocaAddrSpace()));
1039 auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy);
1040 auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack);
1041 auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack);
1044 auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
1045 SetNoSanitizeMetadata(LowestStack);
1046 SetNoSanitizeMetadata(
Store);
1051 ModuleSanitizerCoverage::getSectionName(
const std::string &Section)
const {
1052 if (TargetTriple.isOSBinFormatCOFF()) {
1061 if (TargetTriple.isOSBinFormatMachO())
1067 ModuleSanitizerCoverage::getSectionStart(
const std::string &Section)
const {
1068 if (TargetTriple.isOSBinFormatMachO())
1069 return "\1section$start$__DATA$__" +
Section;
1070 return "__start___" +
Section;
1074 ModuleSanitizerCoverage::getSectionEnd(
const std::string &Section)
const {
1075 if (TargetTriple.isOSBinFormatMachO())
1076 return "\1section$end$__DATA$__" +
Section;
1082 "Pass for instrumenting coverage on functions",
false,
1093 return new ModuleSanitizerCoverageLegacyPass(
Options, AllowlistFiles,