1 //===-- SanitizerCoverage.cpp - coverage instrumentation for sanitizers ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Coverage instrumentation done on LLVM IR level, works with Sanitizers. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" 14 #include "llvm/ADT/ArrayRef.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/Triple.h" 17 #include "llvm/Analysis/EHPersonalities.h" 18 #include "llvm/Analysis/PostDominators.h" 19 #include "llvm/IR/CFG.h" 20 #include "llvm/IR/Constant.h" 21 #include "llvm/IR/DataLayout.h" 22 #include "llvm/IR/DebugInfo.h" 23 #include "llvm/IR/Dominators.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/GlobalVariable.h" 26 #include "llvm/IR/IRBuilder.h" 27 #include "llvm/IR/InlineAsm.h" 28 #include "llvm/IR/IntrinsicInst.h" 29 #include "llvm/IR/Intrinsics.h" 30 #include "llvm/IR/LLVMContext.h" 31 #include "llvm/IR/MDBuilder.h" 32 #include "llvm/IR/Mangler.h" 33 #include "llvm/IR/Module.h" 34 #include "llvm/IR/Type.h" 35 #include "llvm/InitializePasses.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/Debug.h" 38 #include "llvm/Support/SpecialCaseList.h" 39 #include "llvm/Support/VirtualFileSystem.h" 40 #include "llvm/Support/raw_ostream.h" 41 #include "llvm/Transforms/Instrumentation.h" 42 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 43 #include "llvm/Transforms/Utils/ModuleUtils.h" 44 45 using namespace llvm; 46 47 #define DEBUG_TYPE "sancov" 48 49 const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir"; 50 const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc"; 51 const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1"; 52 const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2"; 53 const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4"; 54 const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8"; 55 const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; 56 const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; 57 const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; 58 const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; 59 const char SanCovLoad1[] = "__sanitizer_cov_load1"; 60 const char SanCovLoad2[] = "__sanitizer_cov_load2"; 61 const char SanCovLoad4[] = "__sanitizer_cov_load4"; 62 const char SanCovLoad8[] = "__sanitizer_cov_load8"; 63 const char SanCovLoad16[] = "__sanitizer_cov_load16"; 64 const char SanCovStore1[] = "__sanitizer_cov_store1"; 65 const char SanCovStore2[] = "__sanitizer_cov_store2"; 66 const char SanCovStore4[] = "__sanitizer_cov_store4"; 67 const char SanCovStore8[] = "__sanitizer_cov_store8"; 68 const char SanCovStore16[] = "__sanitizer_cov_store16"; 69 const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4"; 70 const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8"; 71 const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep"; 72 const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch"; 73 const char SanCovModuleCtorTracePcGuardName[] = 74 "sancov.module_ctor_trace_pc_guard"; 75 const char SanCovModuleCtor8bitCountersName[] = 76 "sancov.module_ctor_8bit_counters"; 77 const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag"; 78 static const uint64_t SanCtorAndDtorPriority = 2; 79 80 const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard"; 81 const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init"; 82 const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; 83 const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; 84 const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; 85 86 const char SanCovGuardsSectionName[] = "sancov_guards"; 87 const char SanCovCountersSectionName[] = "sancov_cntrs"; 88 const char SanCovBoolFlagSectionName[] = "sancov_bools"; 89 const char SanCovPCsSectionName[] = "sancov_pcs"; 90 91 const char SanCovLowestStackName[] = "__sancov_lowest_stack"; 92 93 static cl::opt<int> ClCoverageLevel( 94 "sanitizer-coverage-level", 95 cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, " 96 "3: all blocks and critical edges"), 97 cl::Hidden, cl::init(0)); 98 99 static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc", 100 cl::desc("Experimental pc tracing"), cl::Hidden, 101 cl::init(false)); 102 103 static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard", 104 cl::desc("pc tracing with a guard"), 105 cl::Hidden, cl::init(false)); 106 107 // If true, we create a global variable that contains PCs of all instrumented 108 // BBs, put this global into a named section, and pass this section's bounds 109 // to __sanitizer_cov_pcs_init. 110 // This way the coverage instrumentation does not need to acquire the PCs 111 // at run-time. Works with trace-pc-guard, inline-8bit-counters, and 112 // inline-bool-flag. 113 static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-pc-table", 114 cl::desc("create a static PC table"), 115 cl::Hidden, cl::init(false)); 116 117 static cl::opt<bool> 118 ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters", 119 cl::desc("increments 8-bit counter for every edge"), 120 cl::Hidden, cl::init(false)); 121 122 static cl::opt<bool> 123 ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag", 124 cl::desc("sets a boolean flag for every edge"), cl::Hidden, 125 cl::init(false)); 126 127 static cl::opt<bool> 128 ClCMPTracing("sanitizer-coverage-trace-compares", 129 cl::desc("Tracing of CMP and similar instructions"), 130 cl::Hidden, cl::init(false)); 131 132 static cl::opt<bool> ClDIVTracing("sanitizer-coverage-trace-divs", 133 cl::desc("Tracing of DIV instructions"), 134 cl::Hidden, cl::init(false)); 135 136 static cl::opt<bool> ClLoadTracing("sanitizer-coverage-trace-loads", 137 cl::desc("Tracing of load instructions"), 138 cl::Hidden, cl::init(false)); 139 140 static cl::opt<bool> ClStoreTracing("sanitizer-coverage-trace-stores", 141 cl::desc("Tracing of store instructions"), 142 cl::Hidden, cl::init(false)); 143 144 static cl::opt<bool> ClGEPTracing("sanitizer-coverage-trace-geps", 145 cl::desc("Tracing of GEP instructions"), 146 cl::Hidden, cl::init(false)); 147 148 static cl::opt<bool> 149 ClPruneBlocks("sanitizer-coverage-prune-blocks", 150 cl::desc("Reduce the number of instrumented blocks"), 151 cl::Hidden, cl::init(true)); 152 153 static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth", 154 cl::desc("max stack depth tracing"), 155 cl::Hidden, cl::init(false)); 156 157 namespace { 158 159 SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { 160 SanitizerCoverageOptions Res; 161 switch (LegacyCoverageLevel) { 162 case 0: 163 Res.CoverageType = SanitizerCoverageOptions::SCK_None; 164 break; 165 case 1: 166 Res.CoverageType = SanitizerCoverageOptions::SCK_Function; 167 break; 168 case 2: 169 Res.CoverageType = SanitizerCoverageOptions::SCK_BB; 170 break; 171 case 3: 172 Res.CoverageType = SanitizerCoverageOptions::SCK_Edge; 173 break; 174 case 4: 175 Res.CoverageType = SanitizerCoverageOptions::SCK_Edge; 176 Res.IndirectCalls = true; 177 break; 178 } 179 return Res; 180 } 181 182 SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { 183 // Sets CoverageType and IndirectCalls. 184 SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel); 185 Options.CoverageType = std::max(Options.CoverageType, CLOpts.CoverageType); 186 Options.IndirectCalls |= CLOpts.IndirectCalls; 187 Options.TraceCmp |= ClCMPTracing; 188 Options.TraceDiv |= ClDIVTracing; 189 Options.TraceGep |= ClGEPTracing; 190 Options.TracePC |= ClTracePC; 191 Options.TracePCGuard |= ClTracePCGuard; 192 Options.Inline8bitCounters |= ClInline8bitCounters; 193 Options.InlineBoolFlag |= ClInlineBoolFlag; 194 Options.PCTable |= ClCreatePCTable; 195 Options.NoPrune |= !ClPruneBlocks; 196 Options.StackDepth |= ClStackDepth; 197 Options.TraceLoads |= ClLoadTracing; 198 Options.TraceStores |= ClStoreTracing; 199 if (!Options.TracePCGuard && !Options.TracePC && 200 !Options.Inline8bitCounters && !Options.StackDepth && 201 !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores) 202 Options.TracePCGuard = true; // TracePCGuard is default. 203 return Options; 204 } 205 206 using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>; 207 using PostDomTreeCallback = 208 function_ref<const PostDominatorTree *(Function &F)>; 209 210 class ModuleSanitizerCoverage { 211 public: 212 ModuleSanitizerCoverage( 213 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), 214 const SpecialCaseList *Allowlist = nullptr, 215 const SpecialCaseList *Blocklist = nullptr) 216 : Options(OverrideFromCL(Options)), Allowlist(Allowlist), 217 Blocklist(Blocklist) {} 218 bool instrumentModule(Module &M, DomTreeCallback DTCallback, 219 PostDomTreeCallback PDTCallback); 220 221 private: 222 void instrumentFunction(Function &F, DomTreeCallback DTCallback, 223 PostDomTreeCallback PDTCallback); 224 void InjectCoverageForIndirectCalls(Function &F, 225 ArrayRef<Instruction *> IndirCalls); 226 void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets); 227 void InjectTraceForDiv(Function &F, 228 ArrayRef<BinaryOperator *> DivTraceTargets); 229 void InjectTraceForGep(Function &F, 230 ArrayRef<GetElementPtrInst *> GepTraceTargets); 231 void InjectTraceForLoadsAndStores(Function &F, ArrayRef<LoadInst *> Loads, 232 ArrayRef<StoreInst *> Stores); 233 void InjectTraceForSwitch(Function &F, 234 ArrayRef<Instruction *> SwitchTraceTargets); 235 bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks, 236 bool IsLeafFunc = true); 237 GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements, 238 Function &F, Type *Ty, 239 const char *Section); 240 GlobalVariable *CreatePCArray(Function &F, ArrayRef<BasicBlock *> AllBlocks); 241 void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks); 242 void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, 243 bool IsLeafFunc = true); 244 Function *CreateInitCallsForSections(Module &M, const char *CtorName, 245 const char *InitFunctionName, Type *Ty, 246 const char *Section); 247 std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section, 248 Type *Ty); 249 250 void SetNoSanitizeMetadata(Instruction *I) { 251 I->setMetadata(I->getModule()->getMDKindID("nosanitize"), 252 MDNode::get(*C, None)); 253 } 254 255 std::string getSectionName(const std::string &Section) const; 256 std::string getSectionStart(const std::string &Section) const; 257 std::string getSectionEnd(const std::string &Section) const; 258 FunctionCallee SanCovTracePCIndir; 259 FunctionCallee SanCovTracePC, SanCovTracePCGuard; 260 std::array<FunctionCallee, 4> SanCovTraceCmpFunction; 261 std::array<FunctionCallee, 4> SanCovTraceConstCmpFunction; 262 std::array<FunctionCallee, 5> SanCovLoadFunction; 263 std::array<FunctionCallee, 5> SanCovStoreFunction; 264 std::array<FunctionCallee, 2> SanCovTraceDivFunction; 265 FunctionCallee SanCovTraceGepFunction; 266 FunctionCallee SanCovTraceSwitchFunction; 267 GlobalVariable *SanCovLowestStack; 268 Type *Int128PtrTy, *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, 269 *Int32PtrTy, *Int16PtrTy, *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, 270 *Int1PtrTy; 271 Module *CurModule; 272 std::string CurModuleUniqueId; 273 Triple TargetTriple; 274 LLVMContext *C; 275 const DataLayout *DL; 276 277 GlobalVariable *FunctionGuardArray; // for trace-pc-guard. 278 GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. 279 GlobalVariable *FunctionBoolArray; // for inline-bool-flag. 280 GlobalVariable *FunctionPCsArray; // for pc-table. 281 SmallVector<GlobalValue *, 20> GlobalsToAppendToUsed; 282 SmallVector<GlobalValue *, 20> GlobalsToAppendToCompilerUsed; 283 284 SanitizerCoverageOptions Options; 285 286 const SpecialCaseList *Allowlist; 287 const SpecialCaseList *Blocklist; 288 }; 289 290 class ModuleSanitizerCoverageLegacyPass : public ModulePass { 291 public: 292 ModuleSanitizerCoverageLegacyPass( 293 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), 294 const std::vector<std::string> &AllowlistFiles = 295 std::vector<std::string>(), 296 const std::vector<std::string> &BlocklistFiles = 297 std::vector<std::string>()) 298 : ModulePass(ID), Options(Options) { 299 if (AllowlistFiles.size() > 0) 300 Allowlist = SpecialCaseList::createOrDie(AllowlistFiles, 301 *vfs::getRealFileSystem()); 302 if (BlocklistFiles.size() > 0) 303 Blocklist = SpecialCaseList::createOrDie(BlocklistFiles, 304 *vfs::getRealFileSystem()); 305 initializeModuleSanitizerCoverageLegacyPassPass( 306 *PassRegistry::getPassRegistry()); 307 } 308 bool runOnModule(Module &M) override { 309 ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), 310 Blocklist.get()); 311 auto DTCallback = [this](Function &F) -> const DominatorTree * { 312 return &this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(); 313 }; 314 auto PDTCallback = [this](Function &F) -> const PostDominatorTree * { 315 return &this->getAnalysis<PostDominatorTreeWrapperPass>(F) 316 .getPostDomTree(); 317 }; 318 return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback); 319 } 320 321 static char ID; // Pass identification, replacement for typeid 322 StringRef getPassName() const override { return "ModuleSanitizerCoverage"; } 323 324 void getAnalysisUsage(AnalysisUsage &AU) const override { 325 AU.addRequired<DominatorTreeWrapperPass>(); 326 AU.addRequired<PostDominatorTreeWrapperPass>(); 327 } 328 329 private: 330 SanitizerCoverageOptions Options; 331 332 std::unique_ptr<SpecialCaseList> Allowlist; 333 std::unique_ptr<SpecialCaseList> Blocklist; 334 }; 335 336 } // namespace 337 338 PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &M, 339 ModuleAnalysisManager &MAM) { 340 ModuleSanitizerCoverage ModuleSancov(Options, Allowlist.get(), 341 Blocklist.get()); 342 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 343 auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { 344 return &FAM.getResult<DominatorTreeAnalysis>(F); 345 }; 346 auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { 347 return &FAM.getResult<PostDominatorTreeAnalysis>(F); 348 }; 349 if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) 350 return PreservedAnalyses::none(); 351 return PreservedAnalyses::all(); 352 } 353 354 std::pair<Value *, Value *> 355 ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section, 356 Type *Ty) { 357 // Use ExternalWeak so that if all sections are discarded due to section 358 // garbage collection, the linker will not report undefined symbol errors. 359 // Windows defines the start/stop symbols in compiler-rt so no need for 360 // ExternalWeak. 361 GlobalValue::LinkageTypes Linkage = TargetTriple.isOSBinFormatCOFF() 362 ? GlobalVariable::ExternalLinkage 363 : GlobalVariable::ExternalWeakLinkage; 364 GlobalVariable *SecStart = 365 new GlobalVariable(M, Ty, false, Linkage, nullptr, 366 getSectionStart(Section)); 367 SecStart->setVisibility(GlobalValue::HiddenVisibility); 368 GlobalVariable *SecEnd = 369 new GlobalVariable(M, Ty, false, Linkage, nullptr, 370 getSectionEnd(Section)); 371 SecEnd->setVisibility(GlobalValue::HiddenVisibility); 372 IRBuilder<> IRB(M.getContext()); 373 if (!TargetTriple.isOSBinFormatCOFF()) 374 return std::make_pair(SecStart, SecEnd); 375 376 // Account for the fact that on windows-msvc __start_* symbols actually 377 // point to a uint64_t before the start of the array. 378 auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); 379 auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, 380 ConstantInt::get(IntptrTy, sizeof(uint64_t))); 381 return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)), 382 SecEnd); 383 } 384 385 Function *ModuleSanitizerCoverage::CreateInitCallsForSections( 386 Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, 387 const char *Section) { 388 auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); 389 auto SecStart = SecStartEnd.first; 390 auto SecEnd = SecStartEnd.second; 391 Function *CtorFunc; 392 Type *PtrTy = PointerType::getUnqual(Ty); 393 std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( 394 M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd}); 395 assert(CtorFunc->getName() == CtorName); 396 397 if (TargetTriple.supportsCOMDAT()) { 398 // Use comdat to dedup CtorFunc. 399 CtorFunc->setComdat(M.getOrInsertComdat(CtorName)); 400 appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); 401 } else { 402 appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); 403 } 404 405 if (TargetTriple.isOSBinFormatCOFF()) { 406 // In COFF files, if the contructors are set as COMDAT (they are because 407 // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced 408 // functions and data) is used, the constructors get stripped. To prevent 409 // this, give the constructors weak ODR linkage and ensure the linker knows 410 // to include the sancov constructor. This way the linker can deduplicate 411 // the constructors but always leave one copy. 412 CtorFunc->setLinkage(GlobalValue::WeakODRLinkage); 413 } 414 return CtorFunc; 415 } 416 417 bool ModuleSanitizerCoverage::instrumentModule( 418 Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { 419 if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) 420 return false; 421 if (Allowlist && 422 !Allowlist->inSection("coverage", "src", M.getSourceFileName())) 423 return false; 424 if (Blocklist && 425 Blocklist->inSection("coverage", "src", M.getSourceFileName())) 426 return false; 427 C = &(M.getContext()); 428 DL = &M.getDataLayout(); 429 CurModule = &M; 430 CurModuleUniqueId = getUniqueModuleId(CurModule); 431 TargetTriple = Triple(M.getTargetTriple()); 432 FunctionGuardArray = nullptr; 433 Function8bitCounterArray = nullptr; 434 FunctionBoolArray = nullptr; 435 FunctionPCsArray = nullptr; 436 IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); 437 IntptrPtrTy = PointerType::getUnqual(IntptrTy); 438 Type *VoidTy = Type::getVoidTy(*C); 439 IRBuilder<> IRB(*C); 440 Int128PtrTy = PointerType::getUnqual(IRB.getInt128Ty()); 441 Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); 442 Int16PtrTy = PointerType::getUnqual(IRB.getInt16Ty()); 443 Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); 444 Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); 445 Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty()); 446 Int64Ty = IRB.getInt64Ty(); 447 Int32Ty = IRB.getInt32Ty(); 448 Int16Ty = IRB.getInt16Ty(); 449 Int8Ty = IRB.getInt8Ty(); 450 Int1Ty = IRB.getInt1Ty(); 451 452 SanCovTracePCIndir = 453 M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy); 454 // Make sure smaller parameters are zero-extended to i64 if required by the 455 // target ABI. 456 AttributeList SanCovTraceCmpZeroExtAL; 457 SanCovTraceCmpZeroExtAL = 458 SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 0, Attribute::ZExt); 459 SanCovTraceCmpZeroExtAL = 460 SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 1, Attribute::ZExt); 461 462 SanCovTraceCmpFunction[0] = 463 M.getOrInsertFunction(SanCovTraceCmp1, SanCovTraceCmpZeroExtAL, VoidTy, 464 IRB.getInt8Ty(), IRB.getInt8Ty()); 465 SanCovTraceCmpFunction[1] = 466 M.getOrInsertFunction(SanCovTraceCmp2, SanCovTraceCmpZeroExtAL, VoidTy, 467 IRB.getInt16Ty(), IRB.getInt16Ty()); 468 SanCovTraceCmpFunction[2] = 469 M.getOrInsertFunction(SanCovTraceCmp4, SanCovTraceCmpZeroExtAL, VoidTy, 470 IRB.getInt32Ty(), IRB.getInt32Ty()); 471 SanCovTraceCmpFunction[3] = 472 M.getOrInsertFunction(SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty); 473 474 SanCovTraceConstCmpFunction[0] = M.getOrInsertFunction( 475 SanCovTraceConstCmp1, SanCovTraceCmpZeroExtAL, VoidTy, Int8Ty, Int8Ty); 476 SanCovTraceConstCmpFunction[1] = M.getOrInsertFunction( 477 SanCovTraceConstCmp2, SanCovTraceCmpZeroExtAL, VoidTy, Int16Ty, Int16Ty); 478 SanCovTraceConstCmpFunction[2] = M.getOrInsertFunction( 479 SanCovTraceConstCmp4, SanCovTraceCmpZeroExtAL, VoidTy, Int32Ty, Int32Ty); 480 SanCovTraceConstCmpFunction[3] = 481 M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); 482 483 // Loads. 484 SanCovLoadFunction[0] = M.getOrInsertFunction(SanCovLoad1, VoidTy, Int8PtrTy); 485 SanCovLoadFunction[1] = 486 M.getOrInsertFunction(SanCovLoad2, VoidTy, Int16PtrTy); 487 SanCovLoadFunction[2] = 488 M.getOrInsertFunction(SanCovLoad4, VoidTy, Int32PtrTy); 489 SanCovLoadFunction[3] = 490 M.getOrInsertFunction(SanCovLoad8, VoidTy, Int64PtrTy); 491 SanCovLoadFunction[4] = 492 M.getOrInsertFunction(SanCovLoad16, VoidTy, Int128PtrTy); 493 // Stores. 494 SanCovStoreFunction[0] = 495 M.getOrInsertFunction(SanCovStore1, VoidTy, Int8PtrTy); 496 SanCovStoreFunction[1] = 497 M.getOrInsertFunction(SanCovStore2, VoidTy, Int16PtrTy); 498 SanCovStoreFunction[2] = 499 M.getOrInsertFunction(SanCovStore4, VoidTy, Int32PtrTy); 500 SanCovStoreFunction[3] = 501 M.getOrInsertFunction(SanCovStore8, VoidTy, Int64PtrTy); 502 SanCovStoreFunction[4] = 503 M.getOrInsertFunction(SanCovStore16, VoidTy, Int128PtrTy); 504 505 { 506 AttributeList AL; 507 AL = AL.addParamAttribute(*C, 0, Attribute::ZExt); 508 SanCovTraceDivFunction[0] = 509 M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty()); 510 } 511 SanCovTraceDivFunction[1] = 512 M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty); 513 SanCovTraceGepFunction = 514 M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy); 515 SanCovTraceSwitchFunction = 516 M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy); 517 518 Constant *SanCovLowestStackConstant = 519 M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); 520 SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant); 521 if (!SanCovLowestStack || SanCovLowestStack->getValueType() != IntptrTy) { 522 C->emitError(StringRef("'") + SanCovLowestStackName + 523 "' should not be declared by the user"); 524 return true; 525 } 526 SanCovLowestStack->setThreadLocalMode( 527 GlobalValue::ThreadLocalMode::InitialExecTLSModel); 528 if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) 529 SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy)); 530 531 SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); 532 SanCovTracePCGuard = 533 M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); 534 535 for (auto &F : M) 536 instrumentFunction(F, DTCallback, PDTCallback); 537 538 Function *Ctor = nullptr; 539 540 if (FunctionGuardArray) 541 Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, 542 SanCovTracePCGuardInitName, Int32Ty, 543 SanCovGuardsSectionName); 544 if (Function8bitCounterArray) 545 Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, 546 SanCov8bitCountersInitName, Int8Ty, 547 SanCovCountersSectionName); 548 if (FunctionBoolArray) { 549 Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName, 550 SanCovBoolFlagInitName, Int1Ty, 551 SanCovBoolFlagSectionName); 552 } 553 if (Ctor && Options.PCTable) { 554 auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrTy); 555 FunctionCallee InitFunction = declareSanitizerInitFunction( 556 M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); 557 IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); 558 IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); 559 } 560 appendToUsed(M, GlobalsToAppendToUsed); 561 appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); 562 return true; 563 } 564 565 // True if block has successors and it dominates all of them. 566 static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { 567 if (succ_empty(BB)) 568 return false; 569 570 return llvm::all_of(successors(BB), [&](const BasicBlock *SUCC) { 571 return DT->dominates(BB, SUCC); 572 }); 573 } 574 575 // True if block has predecessors and it postdominates all of them. 576 static bool isFullPostDominator(const BasicBlock *BB, 577 const PostDominatorTree *PDT) { 578 if (pred_empty(BB)) 579 return false; 580 581 return llvm::all_of(predecessors(BB), [&](const BasicBlock *PRED) { 582 return PDT->dominates(BB, PRED); 583 }); 584 } 585 586 static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, 587 const DominatorTree *DT, 588 const PostDominatorTree *PDT, 589 const SanitizerCoverageOptions &Options) { 590 // Don't insert coverage for blocks containing nothing but unreachable: we 591 // will never call __sanitizer_cov() for them, so counting them in 592 // NumberOfInstrumentedBlocks() might complicate calculation of code coverage 593 // percentage. Also, unreachable instructions frequently have no debug 594 // locations. 595 if (isa<UnreachableInst>(BB->getFirstNonPHIOrDbgOrLifetime())) 596 return false; 597 598 // Don't insert coverage into blocks without a valid insertion point 599 // (catchswitch blocks). 600 if (BB->getFirstInsertionPt() == BB->end()) 601 return false; 602 603 if (Options.NoPrune || &F.getEntryBlock() == BB) 604 return true; 605 606 if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function && 607 &F.getEntryBlock() != BB) 608 return false; 609 610 // Do not instrument full dominators, or full post-dominators with multiple 611 // predecessors. 612 return !isFullDominator(BB, DT) 613 && !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor()); 614 } 615 616 617 // Returns true iff From->To is a backedge. 618 // A twist here is that we treat From->To as a backedge if 619 // * To dominates From or 620 // * To->UniqueSuccessor dominates From 621 static bool IsBackEdge(BasicBlock *From, BasicBlock *To, 622 const DominatorTree *DT) { 623 if (DT->dominates(To, From)) 624 return true; 625 if (auto Next = To->getUniqueSuccessor()) 626 if (DT->dominates(Next, From)) 627 return true; 628 return false; 629 } 630 631 // Prunes uninteresting Cmp instrumentation: 632 // * CMP instructions that feed into loop backedge branch. 633 // 634 // Note that Cmp pruning is controlled by the same flag as the 635 // BB pruning. 636 static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, 637 const SanitizerCoverageOptions &Options) { 638 if (!Options.NoPrune) 639 if (CMP->hasOneUse()) 640 if (auto BR = dyn_cast<BranchInst>(CMP->user_back())) 641 for (BasicBlock *B : BR->successors()) 642 if (IsBackEdge(BR->getParent(), B, DT)) 643 return false; 644 return true; 645 } 646 647 void ModuleSanitizerCoverage::instrumentFunction( 648 Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { 649 if (F.empty()) 650 return; 651 if (F.getName().find(".module_ctor") != std::string::npos) 652 return; // Should not instrument sanitizer init functions. 653 if (F.getName().startswith("__sanitizer_")) 654 return; // Don't instrument __sanitizer_* callbacks. 655 // Don't touch available_externally functions, their actual body is elewhere. 656 if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) 657 return; 658 // Don't instrument MSVC CRT configuration helpers. They may run before normal 659 // initialization. 660 if (F.getName() == "__local_stdio_printf_options" || 661 F.getName() == "__local_stdio_scanf_options") 662 return; 663 if (isa<UnreachableInst>(F.getEntryBlock().getTerminator())) 664 return; 665 // Don't instrument functions using SEH for now. Splitting basic blocks like 666 // we do for coverage breaks WinEHPrepare. 667 // FIXME: Remove this when SEH no longer uses landingpad pattern matching. 668 if (F.hasPersonalityFn() && 669 isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) 670 return; 671 if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName())) 672 return; 673 if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) 674 return; 675 if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) 676 return; 677 if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) 678 SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); 679 SmallVector<Instruction *, 8> IndirCalls; 680 SmallVector<BasicBlock *, 16> BlocksToInstrument; 681 SmallVector<Instruction *, 8> CmpTraceTargets; 682 SmallVector<Instruction *, 8> SwitchTraceTargets; 683 SmallVector<BinaryOperator *, 8> DivTraceTargets; 684 SmallVector<GetElementPtrInst *, 8> GepTraceTargets; 685 SmallVector<LoadInst *, 8> Loads; 686 SmallVector<StoreInst *, 8> Stores; 687 688 const DominatorTree *DT = DTCallback(F); 689 const PostDominatorTree *PDT = PDTCallback(F); 690 bool IsLeafFunc = true; 691 692 for (auto &BB : F) { 693 if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) 694 BlocksToInstrument.push_back(&BB); 695 for (auto &Inst : BB) { 696 if (Options.IndirectCalls) { 697 CallBase *CB = dyn_cast<CallBase>(&Inst); 698 if (CB && CB->isIndirectCall()) 699 IndirCalls.push_back(&Inst); 700 } 701 if (Options.TraceCmp) { 702 if (ICmpInst *CMP = dyn_cast<ICmpInst>(&Inst)) 703 if (IsInterestingCmp(CMP, DT, Options)) 704 CmpTraceTargets.push_back(&Inst); 705 if (isa<SwitchInst>(&Inst)) 706 SwitchTraceTargets.push_back(&Inst); 707 } 708 if (Options.TraceDiv) 709 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&Inst)) 710 if (BO->getOpcode() == Instruction::SDiv || 711 BO->getOpcode() == Instruction::UDiv) 712 DivTraceTargets.push_back(BO); 713 if (Options.TraceGep) 714 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&Inst)) 715 GepTraceTargets.push_back(GEP); 716 if (Options.TraceLoads) 717 if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) 718 Loads.push_back(LI); 719 if (Options.TraceStores) 720 if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) 721 Stores.push_back(SI); 722 if (Options.StackDepth) 723 if (isa<InvokeInst>(Inst) || 724 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst))) 725 IsLeafFunc = false; 726 } 727 } 728 729 InjectCoverage(F, BlocksToInstrument, IsLeafFunc); 730 InjectCoverageForIndirectCalls(F, IndirCalls); 731 InjectTraceForCmp(F, CmpTraceTargets); 732 InjectTraceForSwitch(F, SwitchTraceTargets); 733 InjectTraceForDiv(F, DivTraceTargets); 734 InjectTraceForGep(F, GepTraceTargets); 735 InjectTraceForLoadsAndStores(F, Loads, Stores); 736 } 737 738 GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( 739 size_t NumElements, Function &F, Type *Ty, const char *Section) { 740 ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); 741 auto Array = new GlobalVariable( 742 *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, 743 Constant::getNullValue(ArrayTy), "__sancov_gen_"); 744 745 if (TargetTriple.supportsCOMDAT() && 746 (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) 747 if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) 748 Array->setComdat(Comdat); 749 Array->setSection(getSectionName(Section)); 750 Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); 751 752 // sancov_pcs parallels the other metadata section(s). Optimizers (e.g. 753 // GlobalOpt/ConstantMerge) may not discard sancov_pcs and the other 754 // section(s) as a unit, so we conservatively retain all unconditionally in 755 // the compiler. 756 // 757 // With comdat (COFF/ELF), the linker can guarantee the associated sections 758 // will be retained or discarded as a unit, so llvm.compiler.used is 759 // sufficient. Otherwise, conservatively make all of them retained by the 760 // linker. 761 if (Array->hasComdat()) 762 GlobalsToAppendToCompilerUsed.push_back(Array); 763 else 764 GlobalsToAppendToUsed.push_back(Array); 765 766 return Array; 767 } 768 769 GlobalVariable * 770 ModuleSanitizerCoverage::CreatePCArray(Function &F, 771 ArrayRef<BasicBlock *> AllBlocks) { 772 size_t N = AllBlocks.size(); 773 assert(N); 774 SmallVector<Constant *, 32> PCs; 775 IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt()); 776 for (size_t i = 0; i < N; i++) { 777 if (&F.getEntryBlock() == AllBlocks[i]) { 778 PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); 779 PCs.push_back((Constant *)IRB.CreateIntToPtr( 780 ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); 781 } else { 782 PCs.push_back((Constant *)IRB.CreatePointerCast( 783 BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); 784 PCs.push_back((Constant *)IRB.CreateIntToPtr( 785 ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); 786 } 787 } 788 auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, 789 SanCovPCsSectionName); 790 PCArray->setInitializer( 791 ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); 792 PCArray->setConstant(true); 793 794 return PCArray; 795 } 796 797 void ModuleSanitizerCoverage::CreateFunctionLocalArrays( 798 Function &F, ArrayRef<BasicBlock *> AllBlocks) { 799 if (Options.TracePCGuard) 800 FunctionGuardArray = CreateFunctionLocalArrayInSection( 801 AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName); 802 803 if (Options.Inline8bitCounters) 804 Function8bitCounterArray = CreateFunctionLocalArrayInSection( 805 AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName); 806 if (Options.InlineBoolFlag) 807 FunctionBoolArray = CreateFunctionLocalArrayInSection( 808 AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName); 809 810 if (Options.PCTable) 811 FunctionPCsArray = CreatePCArray(F, AllBlocks); 812 } 813 814 bool ModuleSanitizerCoverage::InjectCoverage(Function &F, 815 ArrayRef<BasicBlock *> AllBlocks, 816 bool IsLeafFunc) { 817 if (AllBlocks.empty()) return false; 818 CreateFunctionLocalArrays(F, AllBlocks); 819 for (size_t i = 0, N = AllBlocks.size(); i < N; i++) 820 InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); 821 return true; 822 } 823 824 // On every indirect call we call a run-time function 825 // __sanitizer_cov_indir_call* with two parameters: 826 // - callee address, 827 // - global cache array that contains CacheSize pointers (zero-initialized). 828 // The cache is used to speed up recording the caller-callee pairs. 829 // The address of the caller is passed implicitly via caller PC. 830 // CacheSize is encoded in the name of the run-time function. 831 void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( 832 Function &F, ArrayRef<Instruction *> IndirCalls) { 833 if (IndirCalls.empty()) 834 return; 835 assert(Options.TracePC || Options.TracePCGuard || 836 Options.Inline8bitCounters || Options.InlineBoolFlag); 837 for (auto I : IndirCalls) { 838 IRBuilder<> IRB(I); 839 CallBase &CB = cast<CallBase>(*I); 840 Value *Callee = CB.getCalledOperand(); 841 if (isa<InlineAsm>(Callee)) 842 continue; 843 IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy)); 844 } 845 } 846 847 // For every switch statement we insert a call: 848 // __sanitizer_cov_trace_switch(CondValue, 849 // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) 850 851 void ModuleSanitizerCoverage::InjectTraceForSwitch( 852 Function &, ArrayRef<Instruction *> SwitchTraceTargets) { 853 for (auto I : SwitchTraceTargets) { 854 if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) { 855 IRBuilder<> IRB(I); 856 SmallVector<Constant *, 16> Initializers; 857 Value *Cond = SI->getCondition(); 858 if (Cond->getType()->getScalarSizeInBits() > 859 Int64Ty->getScalarSizeInBits()) 860 continue; 861 Initializers.push_back(ConstantInt::get(Int64Ty, SI->getNumCases())); 862 Initializers.push_back( 863 ConstantInt::get(Int64Ty, Cond->getType()->getScalarSizeInBits())); 864 if (Cond->getType()->getScalarSizeInBits() < 865 Int64Ty->getScalarSizeInBits()) 866 Cond = IRB.CreateIntCast(Cond, Int64Ty, false); 867 for (auto It : SI->cases()) { 868 Constant *C = It.getCaseValue(); 869 if (C->getType()->getScalarSizeInBits() < 870 Int64Ty->getScalarSizeInBits()) 871 C = ConstantExpr::getCast(CastInst::ZExt, It.getCaseValue(), Int64Ty); 872 Initializers.push_back(C); 873 } 874 llvm::sort(drop_begin(Initializers, 2), 875 [](const Constant *A, const Constant *B) { 876 return cast<ConstantInt>(A)->getLimitedValue() < 877 cast<ConstantInt>(B)->getLimitedValue(); 878 }); 879 ArrayType *ArrayOfInt64Ty = ArrayType::get(Int64Ty, Initializers.size()); 880 GlobalVariable *GV = new GlobalVariable( 881 *CurModule, ArrayOfInt64Ty, false, GlobalVariable::InternalLinkage, 882 ConstantArray::get(ArrayOfInt64Ty, Initializers), 883 "__sancov_gen_cov_switch_values"); 884 IRB.CreateCall(SanCovTraceSwitchFunction, 885 {Cond, IRB.CreatePointerCast(GV, Int64PtrTy)}); 886 } 887 } 888 } 889 890 void ModuleSanitizerCoverage::InjectTraceForDiv( 891 Function &, ArrayRef<BinaryOperator *> DivTraceTargets) { 892 for (auto BO : DivTraceTargets) { 893 IRBuilder<> IRB(BO); 894 Value *A1 = BO->getOperand(1); 895 if (isa<ConstantInt>(A1)) continue; 896 if (!A1->getType()->isIntegerTy()) 897 continue; 898 uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType()); 899 int CallbackIdx = TypeSize == 32 ? 0 : 900 TypeSize == 64 ? 1 : -1; 901 if (CallbackIdx < 0) continue; 902 auto Ty = Type::getIntNTy(*C, TypeSize); 903 IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx], 904 {IRB.CreateIntCast(A1, Ty, true)}); 905 } 906 } 907 908 void ModuleSanitizerCoverage::InjectTraceForGep( 909 Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) { 910 for (auto GEP : GepTraceTargets) { 911 IRBuilder<> IRB(GEP); 912 for (Use &Idx : GEP->indices()) 913 if (!isa<ConstantInt>(Idx) && Idx->getType()->isIntegerTy()) 914 IRB.CreateCall(SanCovTraceGepFunction, 915 {IRB.CreateIntCast(Idx, IntptrTy, true)}); 916 } 917 } 918 919 void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores( 920 Function &, ArrayRef<LoadInst *> Loads, ArrayRef<StoreInst *> Stores) { 921 auto CallbackIdx = [&](Type *ElementTy) -> int { 922 uint64_t TypeSize = DL->getTypeStoreSizeInBits(ElementTy); 923 return TypeSize == 8 ? 0 924 : TypeSize == 16 ? 1 925 : TypeSize == 32 ? 2 926 : TypeSize == 64 ? 3 927 : TypeSize == 128 ? 4 928 : -1; 929 }; 930 Type *PointerType[5] = {Int8PtrTy, Int16PtrTy, Int32PtrTy, Int64PtrTy, 931 Int128PtrTy}; 932 for (auto LI : Loads) { 933 IRBuilder<> IRB(LI); 934 auto Ptr = LI->getPointerOperand(); 935 int Idx = CallbackIdx(LI->getType()); 936 if (Idx < 0) 937 continue; 938 IRB.CreateCall(SanCovLoadFunction[Idx], 939 IRB.CreatePointerCast(Ptr, PointerType[Idx])); 940 } 941 for (auto SI : Stores) { 942 IRBuilder<> IRB(SI); 943 auto Ptr = SI->getPointerOperand(); 944 int Idx = CallbackIdx(SI->getValueOperand()->getType()); 945 if (Idx < 0) 946 continue; 947 IRB.CreateCall(SanCovStoreFunction[Idx], 948 IRB.CreatePointerCast(Ptr, PointerType[Idx])); 949 } 950 } 951 952 void ModuleSanitizerCoverage::InjectTraceForCmp( 953 Function &, ArrayRef<Instruction *> CmpTraceTargets) { 954 for (auto I : CmpTraceTargets) { 955 if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) { 956 IRBuilder<> IRB(ICMP); 957 Value *A0 = ICMP->getOperand(0); 958 Value *A1 = ICMP->getOperand(1); 959 if (!A0->getType()->isIntegerTy()) 960 continue; 961 uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); 962 int CallbackIdx = TypeSize == 8 ? 0 : 963 TypeSize == 16 ? 1 : 964 TypeSize == 32 ? 2 : 965 TypeSize == 64 ? 3 : -1; 966 if (CallbackIdx < 0) continue; 967 // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1); 968 auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx]; 969 bool FirstIsConst = isa<ConstantInt>(A0); 970 bool SecondIsConst = isa<ConstantInt>(A1); 971 // If both are const, then we don't need such a comparison. 972 if (FirstIsConst && SecondIsConst) continue; 973 // If only one is const, then make it the first callback argument. 974 if (FirstIsConst || SecondIsConst) { 975 CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx]; 976 if (SecondIsConst) 977 std::swap(A0, A1); 978 } 979 980 auto Ty = Type::getIntNTy(*C, TypeSize); 981 IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true), 982 IRB.CreateIntCast(A1, Ty, true)}); 983 } 984 } 985 } 986 987 void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, 988 size_t Idx, 989 bool IsLeafFunc) { 990 BasicBlock::iterator IP = BB.getFirstInsertionPt(); 991 bool IsEntryBB = &BB == &F.getEntryBlock(); 992 DebugLoc EntryLoc; 993 if (IsEntryBB) { 994 if (auto SP = F.getSubprogram()) 995 EntryLoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP); 996 // Keep static allocas and llvm.localescape calls in the entry block. Even 997 // if we aren't splitting the block, it's nice for allocas to be before 998 // calls. 999 IP = PrepareToSplitEntryBlock(BB, IP); 1000 } else { 1001 EntryLoc = IP->getDebugLoc(); 1002 if (!EntryLoc) 1003 if (auto *SP = F.getSubprogram()) 1004 EntryLoc = DILocation::get(SP->getContext(), 0, 0, SP); 1005 } 1006 1007 IRBuilder<> IRB(&*IP); 1008 IRB.SetCurrentDebugLocation(EntryLoc); 1009 if (Options.TracePC) { 1010 IRB.CreateCall(SanCovTracePC) 1011 ->setCannotMerge(); // gets the PC using GET_CALLER_PC. 1012 } 1013 if (Options.TracePCGuard) { 1014 auto GuardPtr = IRB.CreateIntToPtr( 1015 IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), 1016 ConstantInt::get(IntptrTy, Idx * 4)), 1017 Int32PtrTy); 1018 IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge(); 1019 } 1020 if (Options.Inline8bitCounters) { 1021 auto CounterPtr = IRB.CreateGEP( 1022 Function8bitCounterArray->getValueType(), Function8bitCounterArray, 1023 {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); 1024 auto Load = IRB.CreateLoad(Int8Ty, CounterPtr); 1025 auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1)); 1026 auto Store = IRB.CreateStore(Inc, CounterPtr); 1027 SetNoSanitizeMetadata(Load); 1028 SetNoSanitizeMetadata(Store); 1029 } 1030 if (Options.InlineBoolFlag) { 1031 auto FlagPtr = IRB.CreateGEP( 1032 FunctionBoolArray->getValueType(), FunctionBoolArray, 1033 {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); 1034 auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); 1035 auto ThenTerm = 1036 SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false); 1037 IRBuilder<> ThenIRB(ThenTerm); 1038 auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); 1039 SetNoSanitizeMetadata(Load); 1040 SetNoSanitizeMetadata(Store); 1041 } 1042 if (Options.StackDepth && IsEntryBB && !IsLeafFunc) { 1043 // Check stack depth. If it's the deepest so far, record it. 1044 Module *M = F.getParent(); 1045 Function *GetFrameAddr = Intrinsic::getDeclaration( 1046 M, Intrinsic::frameaddress, 1047 IRB.getInt8PtrTy(M->getDataLayout().getAllocaAddrSpace())); 1048 auto FrameAddrPtr = 1049 IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); 1050 auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); 1051 auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); 1052 auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); 1053 auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); 1054 IRBuilder<> ThenIRB(ThenTerm); 1055 auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); 1056 SetNoSanitizeMetadata(LowestStack); 1057 SetNoSanitizeMetadata(Store); 1058 } 1059 } 1060 1061 std::string 1062 ModuleSanitizerCoverage::getSectionName(const std::string &Section) const { 1063 if (TargetTriple.isOSBinFormatCOFF()) { 1064 if (Section == SanCovCountersSectionName) 1065 return ".SCOV$CM"; 1066 if (Section == SanCovBoolFlagSectionName) 1067 return ".SCOV$BM"; 1068 if (Section == SanCovPCsSectionName) 1069 return ".SCOVP$M"; 1070 return ".SCOV$GM"; // For SanCovGuardsSectionName. 1071 } 1072 if (TargetTriple.isOSBinFormatMachO()) 1073 return "__DATA,__" + Section; 1074 return "__" + Section; 1075 } 1076 1077 std::string 1078 ModuleSanitizerCoverage::getSectionStart(const std::string &Section) const { 1079 if (TargetTriple.isOSBinFormatMachO()) 1080 return "\1section$start$__DATA$__" + Section; 1081 return "__start___" + Section; 1082 } 1083 1084 std::string 1085 ModuleSanitizerCoverage::getSectionEnd(const std::string &Section) const { 1086 if (TargetTriple.isOSBinFormatMachO()) 1087 return "\1section$end$__DATA$__" + Section; 1088 return "__stop___" + Section; 1089 } 1090 1091 char ModuleSanitizerCoverageLegacyPass::ID = 0; 1092 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", 1093 "Pass for instrumenting coverage on functions", false, 1094 false) 1095 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 1096 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) 1097 INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", 1098 "Pass for instrumenting coverage on functions", false, 1099 false) 1100 ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( 1101 const SanitizerCoverageOptions &Options, 1102 const std::vector<std::string> &AllowlistFiles, 1103 const std::vector<std::string> &BlocklistFiles) { 1104 return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, 1105 BlocklistFiles); 1106 } 1107