Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
35266 views
//===-- SanitizerCoverage.cpp - coverage instrumentation for sanitizers ---===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Coverage instrumentation done on LLVM IR level, works with Sanitizers.9//10//===----------------------------------------------------------------------===//1112#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"13#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/Analysis/GlobalsModRef.h"16#include "llvm/Analysis/PostDominators.h"17#include "llvm/IR/Constant.h"18#include "llvm/IR/DataLayout.h"19#include "llvm/IR/Dominators.h"20#include "llvm/IR/EHPersonalities.h"21#include "llvm/IR/Function.h"22#include "llvm/IR/GlobalVariable.h"23#include "llvm/IR/IRBuilder.h"24#include "llvm/IR/IntrinsicInst.h"25#include "llvm/IR/Intrinsics.h"26#include "llvm/IR/LLVMContext.h"27#include "llvm/IR/MDBuilder.h"28#include "llvm/IR/Module.h"29#include "llvm/IR/Type.h"30#include "llvm/Support/CommandLine.h"31#include "llvm/Support/SpecialCaseList.h"32#include "llvm/Support/VirtualFileSystem.h"33#include "llvm/TargetParser/Triple.h"34#include "llvm/Transforms/Utils/BasicBlockUtils.h"35#include "llvm/Transforms/Utils/ModuleUtils.h"3637using namespace llvm;3839#define DEBUG_TYPE "sancov"4041const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir";42const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc";43const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1";44const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2";45const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4";46const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8";47const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1";48const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2";49const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4";50const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8";51const char SanCovLoad1[] = "__sanitizer_cov_load1";52const char SanCovLoad2[] = "__sanitizer_cov_load2";53const char SanCovLoad4[] = "__sanitizer_cov_load4";54const char SanCovLoad8[] = "__sanitizer_cov_load8";55const char SanCovLoad16[] = "__sanitizer_cov_load16";56const char SanCovStore1[] = "__sanitizer_cov_store1";57const char SanCovStore2[] = "__sanitizer_cov_store2";58const char SanCovStore4[] = "__sanitizer_cov_store4";59const char SanCovStore8[] = "__sanitizer_cov_store8";60const char SanCovStore16[] = "__sanitizer_cov_store16";61const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4";62const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8";63const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep";64const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch";65const char SanCovModuleCtorTracePcGuardName[] =66"sancov.module_ctor_trace_pc_guard";67const char SanCovModuleCtor8bitCountersName[] =68"sancov.module_ctor_8bit_counters";69const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag";70static const uint64_t SanCtorAndDtorPriority = 2;7172const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard";73const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init";74const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init";75const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init";76const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init";77const char SanCovCFsInitName[] = "__sanitizer_cov_cfs_init";7879const char SanCovGuardsSectionName[] = "sancov_guards";80const char SanCovCountersSectionName[] = "sancov_cntrs";81const char SanCovBoolFlagSectionName[] = "sancov_bools";82const char SanCovPCsSectionName[] = "sancov_pcs";83const char SanCovCFsSectionName[] = "sancov_cfs";8485const char SanCovLowestStackName[] = "__sancov_lowest_stack";8687static cl::opt<int> ClCoverageLevel(88"sanitizer-coverage-level",89cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "90"3: all blocks and critical edges"),91cl::Hidden);9293static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc",94cl::desc("Experimental pc tracing"), cl::Hidden);9596static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",97cl::desc("pc tracing with a guard"),98cl::Hidden);99100// If true, we create a global variable that contains PCs of all instrumented101// BBs, put this global into a named section, and pass this section's bounds102// to __sanitizer_cov_pcs_init.103// This way the coverage instrumentation does not need to acquire the PCs104// at run-time. Works with trace-pc-guard, inline-8bit-counters, and105// inline-bool-flag.106static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-pc-table",107cl::desc("create a static PC table"),108cl::Hidden);109110static cl::opt<bool>111ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters",112cl::desc("increments 8-bit counter for every edge"),113cl::Hidden);114115static cl::opt<bool>116ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag",117cl::desc("sets a boolean flag for every edge"),118cl::Hidden);119120static cl::opt<bool>121ClCMPTracing("sanitizer-coverage-trace-compares",122cl::desc("Tracing of CMP and similar instructions"),123cl::Hidden);124125static cl::opt<bool> ClDIVTracing("sanitizer-coverage-trace-divs",126cl::desc("Tracing of DIV instructions"),127cl::Hidden);128129static cl::opt<bool> ClLoadTracing("sanitizer-coverage-trace-loads",130cl::desc("Tracing of load instructions"),131cl::Hidden);132133static cl::opt<bool> ClStoreTracing("sanitizer-coverage-trace-stores",134cl::desc("Tracing of store instructions"),135cl::Hidden);136137static cl::opt<bool> ClGEPTracing("sanitizer-coverage-trace-geps",138cl::desc("Tracing of GEP instructions"),139cl::Hidden);140141static cl::opt<bool>142ClPruneBlocks("sanitizer-coverage-prune-blocks",143cl::desc("Reduce the number of instrumented blocks"),144cl::Hidden, cl::init(true));145146static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth",147cl::desc("max stack depth tracing"),148cl::Hidden);149150static cl::opt<bool>151ClCollectCF("sanitizer-coverage-control-flow",152cl::desc("collect control flow for each function"), cl::Hidden);153154namespace {155156SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) {157SanitizerCoverageOptions Res;158switch (LegacyCoverageLevel) {159case 0:160Res.CoverageType = SanitizerCoverageOptions::SCK_None;161break;162case 1:163Res.CoverageType = SanitizerCoverageOptions::SCK_Function;164break;165case 2:166Res.CoverageType = SanitizerCoverageOptions::SCK_BB;167break;168case 3:169Res.CoverageType = SanitizerCoverageOptions::SCK_Edge;170break;171case 4:172Res.CoverageType = SanitizerCoverageOptions::SCK_Edge;173Res.IndirectCalls = true;174break;175}176return Res;177}178179SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {180// Sets CoverageType and IndirectCalls.181SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel);182Options.CoverageType = std::max(Options.CoverageType, CLOpts.CoverageType);183Options.IndirectCalls |= CLOpts.IndirectCalls;184Options.TraceCmp |= ClCMPTracing;185Options.TraceDiv |= ClDIVTracing;186Options.TraceGep |= ClGEPTracing;187Options.TracePC |= ClTracePC;188Options.TracePCGuard |= ClTracePCGuard;189Options.Inline8bitCounters |= ClInline8bitCounters;190Options.InlineBoolFlag |= ClInlineBoolFlag;191Options.PCTable |= ClCreatePCTable;192Options.NoPrune |= !ClPruneBlocks;193Options.StackDepth |= ClStackDepth;194Options.TraceLoads |= ClLoadTracing;195Options.TraceStores |= ClStoreTracing;196if (!Options.TracePCGuard && !Options.TracePC &&197!Options.Inline8bitCounters && !Options.StackDepth &&198!Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores)199Options.TracePCGuard = true; // TracePCGuard is default.200Options.CollectControlFlow |= ClCollectCF;201return Options;202}203204class ModuleSanitizerCoverage {205public:206using DomTreeCallback = function_ref<const DominatorTree &(Function &F)>;207using PostDomTreeCallback =208function_ref<const PostDominatorTree &(Function &F)>;209210ModuleSanitizerCoverage(Module &M, DomTreeCallback DTCallback,211PostDomTreeCallback PDTCallback,212const SanitizerCoverageOptions &Options,213const SpecialCaseList *Allowlist,214const SpecialCaseList *Blocklist)215: M(M), DTCallback(DTCallback), PDTCallback(PDTCallback),216Options(Options), Allowlist(Allowlist), Blocklist(Blocklist) {}217218bool instrumentModule();219220private:221void createFunctionControlFlow(Function &F);222void instrumentFunction(Function &F);223void InjectCoverageForIndirectCalls(Function &F,224ArrayRef<Instruction *> IndirCalls);225void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);226void InjectTraceForDiv(Function &F,227ArrayRef<BinaryOperator *> DivTraceTargets);228void InjectTraceForGep(Function &F,229ArrayRef<GetElementPtrInst *> GepTraceTargets);230void InjectTraceForLoadsAndStores(Function &F, ArrayRef<LoadInst *> Loads,231ArrayRef<StoreInst *> Stores);232void InjectTraceForSwitch(Function &F,233ArrayRef<Instruction *> SwitchTraceTargets);234bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,235bool IsLeafFunc = true);236GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements,237Function &F, Type *Ty,238const char *Section);239GlobalVariable *CreatePCArray(Function &F, ArrayRef<BasicBlock *> AllBlocks);240void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks);241void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx,242bool IsLeafFunc = true);243Function *CreateInitCallsForSections(Module &M, const char *CtorName,244const char *InitFunctionName, Type *Ty,245const char *Section);246std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section,247Type *Ty);248249std::string getSectionName(const std::string &Section) const;250std::string getSectionStart(const std::string &Section) const;251std::string getSectionEnd(const std::string &Section) const;252253Module &M;254DomTreeCallback DTCallback;255PostDomTreeCallback PDTCallback;256257FunctionCallee SanCovTracePCIndir;258FunctionCallee SanCovTracePC, SanCovTracePCGuard;259std::array<FunctionCallee, 4> SanCovTraceCmpFunction;260std::array<FunctionCallee, 4> SanCovTraceConstCmpFunction;261std::array<FunctionCallee, 5> SanCovLoadFunction;262std::array<FunctionCallee, 5> SanCovStoreFunction;263std::array<FunctionCallee, 2> SanCovTraceDivFunction;264FunctionCallee SanCovTraceGepFunction;265FunctionCallee SanCovTraceSwitchFunction;266GlobalVariable *SanCovLowestStack;267Type *PtrTy, *IntptrTy, *Int64Ty, *Int32Ty, *Int16Ty, *Int8Ty, *Int1Ty;268Module *CurModule;269std::string CurModuleUniqueId;270Triple TargetTriple;271LLVMContext *C;272const DataLayout *DL;273274GlobalVariable *FunctionGuardArray; // for trace-pc-guard.275GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters.276GlobalVariable *FunctionBoolArray; // for inline-bool-flag.277GlobalVariable *FunctionPCsArray; // for pc-table.278GlobalVariable *FunctionCFsArray; // for control flow table279SmallVector<GlobalValue *, 20> GlobalsToAppendToUsed;280SmallVector<GlobalValue *, 20> GlobalsToAppendToCompilerUsed;281282SanitizerCoverageOptions Options;283284const SpecialCaseList *Allowlist;285const SpecialCaseList *Blocklist;286};287} // namespace288289PreservedAnalyses SanitizerCoveragePass::run(Module &M,290ModuleAnalysisManager &MAM) {291auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();292auto DTCallback = [&FAM](Function &F) -> const DominatorTree & {293return FAM.getResult<DominatorTreeAnalysis>(F);294};295auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree & {296return FAM.getResult<PostDominatorTreeAnalysis>(F);297};298ModuleSanitizerCoverage ModuleSancov(M, DTCallback, PDTCallback,299OverrideFromCL(Options), Allowlist.get(),300Blocklist.get());301if (!ModuleSancov.instrumentModule())302return PreservedAnalyses::all();303304PreservedAnalyses PA = PreservedAnalyses::none();305// GlobalsAA is considered stateless and does not get invalidated unless306// explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers307// make changes that require GlobalsAA to be invalidated.308PA.abandon<GlobalsAA>();309return PA;310}311312std::pair<Value *, Value *>313ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,314Type *Ty) {315// Use ExternalWeak so that if all sections are discarded due to section316// garbage collection, the linker will not report undefined symbol errors.317// Windows defines the start/stop symbols in compiler-rt so no need for318// ExternalWeak.319GlobalValue::LinkageTypes Linkage = TargetTriple.isOSBinFormatCOFF()320? GlobalVariable::ExternalLinkage321: GlobalVariable::ExternalWeakLinkage;322GlobalVariable *SecStart =323new GlobalVariable(M, Ty, false, Linkage, nullptr,324getSectionStart(Section));325SecStart->setVisibility(GlobalValue::HiddenVisibility);326GlobalVariable *SecEnd =327new GlobalVariable(M, Ty, false, Linkage, nullptr,328getSectionEnd(Section));329SecEnd->setVisibility(GlobalValue::HiddenVisibility);330IRBuilder<> IRB(M.getContext());331if (!TargetTriple.isOSBinFormatCOFF())332return std::make_pair(SecStart, SecEnd);333334// Account for the fact that on windows-msvc __start_* symbols actually335// point to a uint64_t before the start of the array.336auto GEP =337IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));338return std::make_pair(GEP, SecEnd);339}340341Function *ModuleSanitizerCoverage::CreateInitCallsForSections(342Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty,343const char *Section) {344auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);345auto SecStart = SecStartEnd.first;346auto SecEnd = SecStartEnd.second;347Function *CtorFunc;348std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(349M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd});350assert(CtorFunc->getName() == CtorName);351352if (TargetTriple.supportsCOMDAT()) {353// Use comdat to dedup CtorFunc.354CtorFunc->setComdat(M.getOrInsertComdat(CtorName));355appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc);356} else {357appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority);358}359360if (TargetTriple.isOSBinFormatCOFF()) {361// In COFF files, if the contructors are set as COMDAT (they are because362// COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced363// functions and data) is used, the constructors get stripped. To prevent364// this, give the constructors weak ODR linkage and ensure the linker knows365// to include the sancov constructor. This way the linker can deduplicate366// the constructors but always leave one copy.367CtorFunc->setLinkage(GlobalValue::WeakODRLinkage);368}369return CtorFunc;370}371372bool ModuleSanitizerCoverage::instrumentModule() {373if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)374return false;375if (Allowlist &&376!Allowlist->inSection("coverage", "src", M.getSourceFileName()))377return false;378if (Blocklist &&379Blocklist->inSection("coverage", "src", M.getSourceFileName()))380return false;381C = &(M.getContext());382DL = &M.getDataLayout();383CurModule = &M;384CurModuleUniqueId = getUniqueModuleId(CurModule);385TargetTriple = Triple(M.getTargetTriple());386FunctionGuardArray = nullptr;387Function8bitCounterArray = nullptr;388FunctionBoolArray = nullptr;389FunctionPCsArray = nullptr;390FunctionCFsArray = nullptr;391IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());392PtrTy = PointerType::getUnqual(*C);393Type *VoidTy = Type::getVoidTy(*C);394IRBuilder<> IRB(*C);395Int64Ty = IRB.getInt64Ty();396Int32Ty = IRB.getInt32Ty();397Int16Ty = IRB.getInt16Ty();398Int8Ty = IRB.getInt8Ty();399Int1Ty = IRB.getInt1Ty();400401SanCovTracePCIndir =402M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy);403// Make sure smaller parameters are zero-extended to i64 if required by the404// target ABI.405AttributeList SanCovTraceCmpZeroExtAL;406SanCovTraceCmpZeroExtAL =407SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 0, Attribute::ZExt);408SanCovTraceCmpZeroExtAL =409SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 1, Attribute::ZExt);410411SanCovTraceCmpFunction[0] =412M.getOrInsertFunction(SanCovTraceCmp1, SanCovTraceCmpZeroExtAL, VoidTy,413IRB.getInt8Ty(), IRB.getInt8Ty());414SanCovTraceCmpFunction[1] =415M.getOrInsertFunction(SanCovTraceCmp2, SanCovTraceCmpZeroExtAL, VoidTy,416IRB.getInt16Ty(), IRB.getInt16Ty());417SanCovTraceCmpFunction[2] =418M.getOrInsertFunction(SanCovTraceCmp4, SanCovTraceCmpZeroExtAL, VoidTy,419IRB.getInt32Ty(), IRB.getInt32Ty());420SanCovTraceCmpFunction[3] =421M.getOrInsertFunction(SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty);422423SanCovTraceConstCmpFunction[0] = M.getOrInsertFunction(424SanCovTraceConstCmp1, SanCovTraceCmpZeroExtAL, VoidTy, Int8Ty, Int8Ty);425SanCovTraceConstCmpFunction[1] = M.getOrInsertFunction(426SanCovTraceConstCmp2, SanCovTraceCmpZeroExtAL, VoidTy, Int16Ty, Int16Ty);427SanCovTraceConstCmpFunction[2] = M.getOrInsertFunction(428SanCovTraceConstCmp4, SanCovTraceCmpZeroExtAL, VoidTy, Int32Ty, Int32Ty);429SanCovTraceConstCmpFunction[3] =430M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty);431432// Loads.433SanCovLoadFunction[0] = M.getOrInsertFunction(SanCovLoad1, VoidTy, PtrTy);434SanCovLoadFunction[1] =435M.getOrInsertFunction(SanCovLoad2, VoidTy, PtrTy);436SanCovLoadFunction[2] =437M.getOrInsertFunction(SanCovLoad4, VoidTy, PtrTy);438SanCovLoadFunction[3] =439M.getOrInsertFunction(SanCovLoad8, VoidTy, PtrTy);440SanCovLoadFunction[4] =441M.getOrInsertFunction(SanCovLoad16, VoidTy, PtrTy);442// Stores.443SanCovStoreFunction[0] =444M.getOrInsertFunction(SanCovStore1, VoidTy, PtrTy);445SanCovStoreFunction[1] =446M.getOrInsertFunction(SanCovStore2, VoidTy, PtrTy);447SanCovStoreFunction[2] =448M.getOrInsertFunction(SanCovStore4, VoidTy, PtrTy);449SanCovStoreFunction[3] =450M.getOrInsertFunction(SanCovStore8, VoidTy, PtrTy);451SanCovStoreFunction[4] =452M.getOrInsertFunction(SanCovStore16, VoidTy, PtrTy);453454{455AttributeList AL;456AL = AL.addParamAttribute(*C, 0, Attribute::ZExt);457SanCovTraceDivFunction[0] =458M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty());459}460SanCovTraceDivFunction[1] =461M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty);462SanCovTraceGepFunction =463M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy);464SanCovTraceSwitchFunction =465M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, PtrTy);466467Constant *SanCovLowestStackConstant =468M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);469SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant);470if (!SanCovLowestStack || SanCovLowestStack->getValueType() != IntptrTy) {471C->emitError(StringRef("'") + SanCovLowestStackName +472"' should not be declared by the user");473return true;474}475SanCovLowestStack->setThreadLocalMode(476GlobalValue::ThreadLocalMode::InitialExecTLSModel);477if (Options.StackDepth && !SanCovLowestStack->isDeclaration())478SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy));479480SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy);481SanCovTracePCGuard =482M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, PtrTy);483484for (auto &F : M)485instrumentFunction(F);486487Function *Ctor = nullptr;488489if (FunctionGuardArray)490Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,491SanCovTracePCGuardInitName, Int32Ty,492SanCovGuardsSectionName);493if (Function8bitCounterArray)494Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,495SanCov8bitCountersInitName, Int8Ty,496SanCovCountersSectionName);497if (FunctionBoolArray) {498Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName,499SanCovBoolFlagInitName, Int1Ty,500SanCovBoolFlagSectionName);501}502if (Ctor && Options.PCTable) {503auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrTy);504FunctionCallee InitFunction = declareSanitizerInitFunction(505M, SanCovPCsInitName, {PtrTy, PtrTy});506IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());507IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});508}509510if (Ctor && Options.CollectControlFlow) {511auto SecStartEnd = CreateSecStartEnd(M, SanCovCFsSectionName, IntptrTy);512FunctionCallee InitFunction = declareSanitizerInitFunction(513M, SanCovCFsInitName, {PtrTy, PtrTy});514IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());515IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});516}517518appendToUsed(M, GlobalsToAppendToUsed);519appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed);520return true;521}522523// True if block has successors and it dominates all of them.524static bool isFullDominator(const BasicBlock *BB, const DominatorTree &DT) {525if (succ_empty(BB))526return false;527528return llvm::all_of(successors(BB), [&](const BasicBlock *SUCC) {529return DT.dominates(BB, SUCC);530});531}532533// True if block has predecessors and it postdominates all of them.534static bool isFullPostDominator(const BasicBlock *BB,535const PostDominatorTree &PDT) {536if (pred_empty(BB))537return false;538539return llvm::all_of(predecessors(BB), [&](const BasicBlock *PRED) {540return PDT.dominates(BB, PRED);541});542}543544static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,545const DominatorTree &DT,546const PostDominatorTree &PDT,547const SanitizerCoverageOptions &Options) {548// Don't insert coverage for blocks containing nothing but unreachable: we549// will never call __sanitizer_cov() for them, so counting them in550// NumberOfInstrumentedBlocks() might complicate calculation of code coverage551// percentage. Also, unreachable instructions frequently have no debug552// locations.553if (isa<UnreachableInst>(BB->getFirstNonPHIOrDbgOrLifetime()))554return false;555556// Don't insert coverage into blocks without a valid insertion point557// (catchswitch blocks).558if (BB->getFirstInsertionPt() == BB->end())559return false;560561if (Options.NoPrune || &F.getEntryBlock() == BB)562return true;563564if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function &&565&F.getEntryBlock() != BB)566return false;567568// Do not instrument full dominators, or full post-dominators with multiple569// predecessors.570return !isFullDominator(BB, DT)571&& !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor());572}573574// Returns true iff From->To is a backedge.575// A twist here is that we treat From->To as a backedge if576// * To dominates From or577// * To->UniqueSuccessor dominates From578static bool IsBackEdge(BasicBlock *From, BasicBlock *To,579const DominatorTree &DT) {580if (DT.dominates(To, From))581return true;582if (auto Next = To->getUniqueSuccessor())583if (DT.dominates(Next, From))584return true;585return false;586}587588// Prunes uninteresting Cmp instrumentation:589// * CMP instructions that feed into loop backedge branch.590//591// Note that Cmp pruning is controlled by the same flag as the592// BB pruning.593static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree &DT,594const SanitizerCoverageOptions &Options) {595if (!Options.NoPrune)596if (CMP->hasOneUse())597if (auto BR = dyn_cast<BranchInst>(CMP->user_back()))598for (BasicBlock *B : BR->successors())599if (IsBackEdge(BR->getParent(), B, DT))600return false;601return true;602}603604void ModuleSanitizerCoverage::instrumentFunction(Function &F) {605if (F.empty())606return;607if (F.getName().contains(".module_ctor"))608return; // Should not instrument sanitizer init functions.609if (F.getName().starts_with("__sanitizer_"))610return; // Don't instrument __sanitizer_* callbacks.611// Don't touch available_externally functions, their actual body is elewhere.612if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)613return;614// Don't instrument MSVC CRT configuration helpers. They may run before normal615// initialization.616if (F.getName() == "__local_stdio_printf_options" ||617F.getName() == "__local_stdio_scanf_options")618return;619if (isa<UnreachableInst>(F.getEntryBlock().getTerminator()))620return;621// Don't instrument functions using SEH for now. Splitting basic blocks like622// we do for coverage breaks WinEHPrepare.623// FIXME: Remove this when SEH no longer uses landingpad pattern matching.624if (F.hasPersonalityFn() &&625isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))626return;627if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))628return;629if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))630return;631if (F.hasFnAttribute(Attribute::NoSanitizeCoverage))632return;633if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))634return;635if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) {636SplitAllCriticalEdges(637F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());638}639SmallVector<Instruction *, 8> IndirCalls;640SmallVector<BasicBlock *, 16> BlocksToInstrument;641SmallVector<Instruction *, 8> CmpTraceTargets;642SmallVector<Instruction *, 8> SwitchTraceTargets;643SmallVector<BinaryOperator *, 8> DivTraceTargets;644SmallVector<GetElementPtrInst *, 8> GepTraceTargets;645SmallVector<LoadInst *, 8> Loads;646SmallVector<StoreInst *, 8> Stores;647648const DominatorTree &DT = DTCallback(F);649const PostDominatorTree &PDT = PDTCallback(F);650bool IsLeafFunc = true;651652for (auto &BB : F) {653if (shouldInstrumentBlock(F, &BB, DT, PDT, Options))654BlocksToInstrument.push_back(&BB);655for (auto &Inst : BB) {656if (Options.IndirectCalls) {657CallBase *CB = dyn_cast<CallBase>(&Inst);658if (CB && CB->isIndirectCall())659IndirCalls.push_back(&Inst);660}661if (Options.TraceCmp) {662if (ICmpInst *CMP = dyn_cast<ICmpInst>(&Inst))663if (IsInterestingCmp(CMP, DT, Options))664CmpTraceTargets.push_back(&Inst);665if (isa<SwitchInst>(&Inst))666SwitchTraceTargets.push_back(&Inst);667}668if (Options.TraceDiv)669if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&Inst))670if (BO->getOpcode() == Instruction::SDiv ||671BO->getOpcode() == Instruction::UDiv)672DivTraceTargets.push_back(BO);673if (Options.TraceGep)674if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&Inst))675GepTraceTargets.push_back(GEP);676if (Options.TraceLoads)677if (LoadInst *LI = dyn_cast<LoadInst>(&Inst))678Loads.push_back(LI);679if (Options.TraceStores)680if (StoreInst *SI = dyn_cast<StoreInst>(&Inst))681Stores.push_back(SI);682if (Options.StackDepth)683if (isa<InvokeInst>(Inst) ||684(isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst)))685IsLeafFunc = false;686}687}688689if (Options.CollectControlFlow)690createFunctionControlFlow(F);691692InjectCoverage(F, BlocksToInstrument, IsLeafFunc);693InjectCoverageForIndirectCalls(F, IndirCalls);694InjectTraceForCmp(F, CmpTraceTargets);695InjectTraceForSwitch(F, SwitchTraceTargets);696InjectTraceForDiv(F, DivTraceTargets);697InjectTraceForGep(F, GepTraceTargets);698InjectTraceForLoadsAndStores(F, Loads, Stores);699}700701GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(702size_t NumElements, Function &F, Type *Ty, const char *Section) {703ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);704auto Array = new GlobalVariable(705*CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage,706Constant::getNullValue(ArrayTy), "__sancov_gen_");707708if (TargetTriple.supportsCOMDAT() &&709(TargetTriple.isOSBinFormatELF() || !F.isInterposable()))710if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple))711Array->setComdat(Comdat);712Array->setSection(getSectionName(Section));713Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue()));714715// sancov_pcs parallels the other metadata section(s). Optimizers (e.g.716// GlobalOpt/ConstantMerge) may not discard sancov_pcs and the other717// section(s) as a unit, so we conservatively retain all unconditionally in718// the compiler.719//720// With comdat (COFF/ELF), the linker can guarantee the associated sections721// will be retained or discarded as a unit, so llvm.compiler.used is722// sufficient. Otherwise, conservatively make all of them retained by the723// linker.724if (Array->hasComdat())725GlobalsToAppendToCompilerUsed.push_back(Array);726else727GlobalsToAppendToUsed.push_back(Array);728729return Array;730}731732GlobalVariable *733ModuleSanitizerCoverage::CreatePCArray(Function &F,734ArrayRef<BasicBlock *> AllBlocks) {735size_t N = AllBlocks.size();736assert(N);737SmallVector<Constant *, 32> PCs;738IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt());739for (size_t i = 0; i < N; i++) {740if (&F.getEntryBlock() == AllBlocks[i]) {741PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));742PCs.push_back((Constant *)IRB.CreateIntToPtr(743ConstantInt::get(IntptrTy, 1), PtrTy));744} else {745PCs.push_back((Constant *)IRB.CreatePointerCast(746BlockAddress::get(AllBlocks[i]), PtrTy));747PCs.push_back(Constant::getNullValue(PtrTy));748}749}750auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, PtrTy,751SanCovPCsSectionName);752PCArray->setInitializer(753ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));754PCArray->setConstant(true);755756return PCArray;757}758759void ModuleSanitizerCoverage::CreateFunctionLocalArrays(760Function &F, ArrayRef<BasicBlock *> AllBlocks) {761if (Options.TracePCGuard)762FunctionGuardArray = CreateFunctionLocalArrayInSection(763AllBlocks.size(), F, Int32Ty, SanCovGuardsSectionName);764765if (Options.Inline8bitCounters)766Function8bitCounterArray = CreateFunctionLocalArrayInSection(767AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName);768if (Options.InlineBoolFlag)769FunctionBoolArray = CreateFunctionLocalArrayInSection(770AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName);771772if (Options.PCTable)773FunctionPCsArray = CreatePCArray(F, AllBlocks);774}775776bool ModuleSanitizerCoverage::InjectCoverage(Function &F,777ArrayRef<BasicBlock *> AllBlocks,778bool IsLeafFunc) {779if (AllBlocks.empty()) return false;780CreateFunctionLocalArrays(F, AllBlocks);781for (size_t i = 0, N = AllBlocks.size(); i < N; i++)782InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);783return true;784}785786// On every indirect call we call a run-time function787// __sanitizer_cov_indir_call* with two parameters:788// - callee address,789// - global cache array that contains CacheSize pointers (zero-initialized).790// The cache is used to speed up recording the caller-callee pairs.791// The address of the caller is passed implicitly via caller PC.792// CacheSize is encoded in the name of the run-time function.793void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(794Function &F, ArrayRef<Instruction *> IndirCalls) {795if (IndirCalls.empty())796return;797assert(Options.TracePC || Options.TracePCGuard ||798Options.Inline8bitCounters || Options.InlineBoolFlag);799for (auto *I : IndirCalls) {800InstrumentationIRBuilder IRB(I);801CallBase &CB = cast<CallBase>(*I);802Value *Callee = CB.getCalledOperand();803if (isa<InlineAsm>(Callee))804continue;805IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy));806}807}808809// For every switch statement we insert a call:810// __sanitizer_cov_trace_switch(CondValue,811// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })812813void ModuleSanitizerCoverage::InjectTraceForSwitch(814Function &, ArrayRef<Instruction *> SwitchTraceTargets) {815for (auto *I : SwitchTraceTargets) {816if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {817InstrumentationIRBuilder IRB(I);818SmallVector<Constant *, 16> Initializers;819Value *Cond = SI->getCondition();820if (Cond->getType()->getScalarSizeInBits() >821Int64Ty->getScalarSizeInBits())822continue;823Initializers.push_back(ConstantInt::get(Int64Ty, SI->getNumCases()));824Initializers.push_back(825ConstantInt::get(Int64Ty, Cond->getType()->getScalarSizeInBits()));826if (Cond->getType()->getScalarSizeInBits() <827Int64Ty->getScalarSizeInBits())828Cond = IRB.CreateIntCast(Cond, Int64Ty, false);829for (auto It : SI->cases()) {830ConstantInt *C = It.getCaseValue();831if (C->getType()->getScalarSizeInBits() < 64)832C = ConstantInt::get(C->getContext(), C->getValue().zext(64));833Initializers.push_back(C);834}835llvm::sort(drop_begin(Initializers, 2),836[](const Constant *A, const Constant *B) {837return cast<ConstantInt>(A)->getLimitedValue() <838cast<ConstantInt>(B)->getLimitedValue();839});840ArrayType *ArrayOfInt64Ty = ArrayType::get(Int64Ty, Initializers.size());841GlobalVariable *GV = new GlobalVariable(842*CurModule, ArrayOfInt64Ty, false, GlobalVariable::InternalLinkage,843ConstantArray::get(ArrayOfInt64Ty, Initializers),844"__sancov_gen_cov_switch_values");845IRB.CreateCall(SanCovTraceSwitchFunction, {Cond, GV});846}847}848}849850void ModuleSanitizerCoverage::InjectTraceForDiv(851Function &, ArrayRef<BinaryOperator *> DivTraceTargets) {852for (auto *BO : DivTraceTargets) {853InstrumentationIRBuilder IRB(BO);854Value *A1 = BO->getOperand(1);855if (isa<ConstantInt>(A1)) continue;856if (!A1->getType()->isIntegerTy())857continue;858uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType());859int CallbackIdx = TypeSize == 32 ? 0 :860TypeSize == 64 ? 1 : -1;861if (CallbackIdx < 0) continue;862auto Ty = Type::getIntNTy(*C, TypeSize);863IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx],864{IRB.CreateIntCast(A1, Ty, true)});865}866}867868void ModuleSanitizerCoverage::InjectTraceForGep(869Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) {870for (auto *GEP : GepTraceTargets) {871InstrumentationIRBuilder IRB(GEP);872for (Use &Idx : GEP->indices())873if (!isa<ConstantInt>(Idx) && Idx->getType()->isIntegerTy())874IRB.CreateCall(SanCovTraceGepFunction,875{IRB.CreateIntCast(Idx, IntptrTy, true)});876}877}878879void ModuleSanitizerCoverage::InjectTraceForLoadsAndStores(880Function &, ArrayRef<LoadInst *> Loads, ArrayRef<StoreInst *> Stores) {881auto CallbackIdx = [&](Type *ElementTy) -> int {882uint64_t TypeSize = DL->getTypeStoreSizeInBits(ElementTy);883return TypeSize == 8 ? 0884: TypeSize == 16 ? 1885: TypeSize == 32 ? 2886: TypeSize == 64 ? 3887: TypeSize == 128 ? 4888: -1;889};890for (auto *LI : Loads) {891InstrumentationIRBuilder IRB(LI);892auto Ptr = LI->getPointerOperand();893int Idx = CallbackIdx(LI->getType());894if (Idx < 0)895continue;896IRB.CreateCall(SanCovLoadFunction[Idx], Ptr);897}898for (auto *SI : Stores) {899InstrumentationIRBuilder IRB(SI);900auto Ptr = SI->getPointerOperand();901int Idx = CallbackIdx(SI->getValueOperand()->getType());902if (Idx < 0)903continue;904IRB.CreateCall(SanCovStoreFunction[Idx], Ptr);905}906}907908void ModuleSanitizerCoverage::InjectTraceForCmp(909Function &, ArrayRef<Instruction *> CmpTraceTargets) {910for (auto *I : CmpTraceTargets) {911if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) {912InstrumentationIRBuilder IRB(ICMP);913Value *A0 = ICMP->getOperand(0);914Value *A1 = ICMP->getOperand(1);915if (!A0->getType()->isIntegerTy())916continue;917uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType());918int CallbackIdx = TypeSize == 8 ? 0 :919TypeSize == 16 ? 1 :920TypeSize == 32 ? 2 :921TypeSize == 64 ? 3 : -1;922if (CallbackIdx < 0) continue;923// __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);924auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx];925bool FirstIsConst = isa<ConstantInt>(A0);926bool SecondIsConst = isa<ConstantInt>(A1);927// If both are const, then we don't need such a comparison.928if (FirstIsConst && SecondIsConst) continue;929// If only one is const, then make it the first callback argument.930if (FirstIsConst || SecondIsConst) {931CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx];932if (SecondIsConst)933std::swap(A0, A1);934}935936auto Ty = Type::getIntNTy(*C, TypeSize);937IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true),938IRB.CreateIntCast(A1, Ty, true)});939}940}941}942943void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,944size_t Idx,945bool IsLeafFunc) {946BasicBlock::iterator IP = BB.getFirstInsertionPt();947bool IsEntryBB = &BB == &F.getEntryBlock();948DebugLoc EntryLoc;949if (IsEntryBB) {950if (auto SP = F.getSubprogram())951EntryLoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);952// Keep static allocas and llvm.localescape calls in the entry block. Even953// if we aren't splitting the block, it's nice for allocas to be before954// calls.955IP = PrepareToSplitEntryBlock(BB, IP);956}957958InstrumentationIRBuilder IRB(&*IP);959if (EntryLoc)960IRB.SetCurrentDebugLocation(EntryLoc);961if (Options.TracePC) {962IRB.CreateCall(SanCovTracePC)963->setCannotMerge(); // gets the PC using GET_CALLER_PC.964}965if (Options.TracePCGuard) {966auto GuardPtr = IRB.CreateIntToPtr(967IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),968ConstantInt::get(IntptrTy, Idx * 4)),969PtrTy);970IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge();971}972if (Options.Inline8bitCounters) {973auto CounterPtr = IRB.CreateGEP(974Function8bitCounterArray->getValueType(), Function8bitCounterArray,975{ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});976auto Load = IRB.CreateLoad(Int8Ty, CounterPtr);977auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1));978auto Store = IRB.CreateStore(Inc, CounterPtr);979Load->setNoSanitizeMetadata();980Store->setNoSanitizeMetadata();981}982if (Options.InlineBoolFlag) {983auto FlagPtr = IRB.CreateGEP(984FunctionBoolArray->getValueType(), FunctionBoolArray,985{ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});986auto Load = IRB.CreateLoad(Int1Ty, FlagPtr);987auto ThenTerm = SplitBlockAndInsertIfThen(988IRB.CreateIsNull(Load), &*IP, false,989MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());990IRBuilder<> ThenIRB(ThenTerm);991auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);992Load->setNoSanitizeMetadata();993Store->setNoSanitizeMetadata();994}995if (Options.StackDepth && IsEntryBB && !IsLeafFunc) {996// Check stack depth. If it's the deepest so far, record it.997Module *M = F.getParent();998Function *GetFrameAddr = Intrinsic::getDeclaration(999M, Intrinsic::frameaddress,1000IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace()));1001auto FrameAddrPtr =1002IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)});1003auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy);1004auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack);1005auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack);1006auto ThenTerm = SplitBlockAndInsertIfThen(1007IsStackLower, &*IP, false,1008MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());1009IRBuilder<> ThenIRB(ThenTerm);1010auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);1011LowestStack->setNoSanitizeMetadata();1012Store->setNoSanitizeMetadata();1013}1014}10151016std::string1017ModuleSanitizerCoverage::getSectionName(const std::string &Section) const {1018if (TargetTriple.isOSBinFormatCOFF()) {1019if (Section == SanCovCountersSectionName)1020return ".SCOV$CM";1021if (Section == SanCovBoolFlagSectionName)1022return ".SCOV$BM";1023if (Section == SanCovPCsSectionName)1024return ".SCOVP$M";1025return ".SCOV$GM"; // For SanCovGuardsSectionName.1026}1027if (TargetTriple.isOSBinFormatMachO())1028return "__DATA,__" + Section;1029return "__" + Section;1030}10311032std::string1033ModuleSanitizerCoverage::getSectionStart(const std::string &Section) const {1034if (TargetTriple.isOSBinFormatMachO())1035return "\1section$start$__DATA$__" + Section;1036return "__start___" + Section;1037}10381039std::string1040ModuleSanitizerCoverage::getSectionEnd(const std::string &Section) const {1041if (TargetTriple.isOSBinFormatMachO())1042return "\1section$end$__DATA$__" + Section;1043return "__stop___" + Section;1044}10451046void ModuleSanitizerCoverage::createFunctionControlFlow(Function &F) {1047SmallVector<Constant *, 32> CFs;1048IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt());10491050for (auto &BB : F) {1051// blockaddress can not be used on function's entry block.1052if (&BB == &F.getEntryBlock())1053CFs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));1054else1055CFs.push_back((Constant *)IRB.CreatePointerCast(BlockAddress::get(&BB),1056PtrTy));10571058for (auto SuccBB : successors(&BB)) {1059assert(SuccBB != &F.getEntryBlock());1060CFs.push_back((Constant *)IRB.CreatePointerCast(BlockAddress::get(SuccBB),1061PtrTy));1062}10631064CFs.push_back((Constant *)Constant::getNullValue(PtrTy));10651066for (auto &Inst : BB) {1067if (CallBase *CB = dyn_cast<CallBase>(&Inst)) {1068if (CB->isIndirectCall()) {1069// TODO(navidem): handle indirect calls, for now mark its existence.1070CFs.push_back((Constant *)IRB.CreateIntToPtr(1071ConstantInt::get(IntptrTy, -1), PtrTy));1072} else {1073auto CalledF = CB->getCalledFunction();1074if (CalledF && !CalledF->isIntrinsic())1075CFs.push_back(1076(Constant *)IRB.CreatePointerCast(CalledF, PtrTy));1077}1078}1079}10801081CFs.push_back((Constant *)Constant::getNullValue(PtrTy));1082}10831084FunctionCFsArray = CreateFunctionLocalArrayInSection(1085CFs.size(), F, PtrTy, SanCovCFsSectionName);1086FunctionCFsArray->setInitializer(1087ConstantArray::get(ArrayType::get(PtrTy, CFs.size()), CFs));1088FunctionCFsArray->setConstant(true);1089}109010911092