1 //===-- SanitizerCoverage.cpp - coverage instrumentation for sanitizers ---===//
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
7 //===----------------------------------------------------------------------===//
9 // Coverage instrumentation done on LLVM IR level, works with Sanitizers.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/Analysis/EHPersonalities.h"
17 #include "llvm/Analysis/PostDominators.h"
18 #include "llvm/IR/CFG.h"
19 #include "llvm/IR/Constant.h"
20 #include "llvm/IR/DataLayout.h"
21 #include "llvm/IR/DebugInfo.h"
22 #include "llvm/IR/Dominators.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/GlobalVariable.h"
25 #include "llvm/IR/IRBuilder.h"
26 #include "llvm/IR/InlineAsm.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/MDBuilder.h"
31 #include "llvm/IR/Mangler.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/IR/Type.h"
34 #include "llvm/InitializePasses.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/Debug.h"
37 #include "llvm/Support/SpecialCaseList.h"
38 #include "llvm/Support/VirtualFileSystem.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Transforms/Instrumentation.h"
41 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
42 #include "llvm/Transforms/Utils/ModuleUtils.h"
46 #define DEBUG_TYPE "sancov"
48 const char SanCovTracePCIndirName
[] = "__sanitizer_cov_trace_pc_indir";
49 const char SanCovTracePCName
[] = "__sanitizer_cov_trace_pc";
50 const char SanCovTraceCmp1
[] = "__sanitizer_cov_trace_cmp1";
51 const char SanCovTraceCmp2
[] = "__sanitizer_cov_trace_cmp2";
52 const char SanCovTraceCmp4
[] = "__sanitizer_cov_trace_cmp4";
53 const char SanCovTraceCmp8
[] = "__sanitizer_cov_trace_cmp8";
54 const char SanCovTraceConstCmp1
[] = "__sanitizer_cov_trace_const_cmp1";
55 const char SanCovTraceConstCmp2
[] = "__sanitizer_cov_trace_const_cmp2";
56 const char SanCovTraceConstCmp4
[] = "__sanitizer_cov_trace_const_cmp4";
57 const char SanCovTraceConstCmp8
[] = "__sanitizer_cov_trace_const_cmp8";
58 const char SanCovTraceDiv4
[] = "__sanitizer_cov_trace_div4";
59 const char SanCovTraceDiv8
[] = "__sanitizer_cov_trace_div8";
60 const char SanCovTraceGep
[] = "__sanitizer_cov_trace_gep";
61 const char SanCovTraceSwitchName
[] = "__sanitizer_cov_trace_switch";
62 const char SanCovModuleCtorTracePcGuardName
[] =
63 "sancov.module_ctor_trace_pc_guard";
64 const char SanCovModuleCtor8bitCountersName
[] =
65 "sancov.module_ctor_8bit_counters";
66 const char SanCovModuleCtorBoolFlagName
[] = "sancov.module_ctor_bool_flag";
67 static const uint64_t SanCtorAndDtorPriority
= 2;
69 const char SanCovTracePCGuardName
[] = "__sanitizer_cov_trace_pc_guard";
70 const char SanCovTracePCGuardInitName
[] = "__sanitizer_cov_trace_pc_guard_init";
71 const char SanCov8bitCountersInitName
[] = "__sanitizer_cov_8bit_counters_init";
72 const char SanCovBoolFlagInitName
[] = "__sanitizer_cov_bool_flag_init";
73 const char SanCovPCsInitName
[] = "__sanitizer_cov_pcs_init";
75 const char SanCovGuardsSectionName
[] = "sancov_guards";
76 const char SanCovCountersSectionName
[] = "sancov_cntrs";
77 const char SanCovBoolFlagSectionName
[] = "sancov_bools";
78 const char SanCovPCsSectionName
[] = "sancov_pcs";
80 const char SanCovLowestStackName
[] = "__sancov_lowest_stack";
82 static cl::opt
<int> ClCoverageLevel(
83 "sanitizer-coverage-level",
84 cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
85 "3: all blocks and critical edges"),
86 cl::Hidden
, cl::init(0));
88 static cl::opt
<bool> ClTracePC("sanitizer-coverage-trace-pc",
89 cl::desc("Experimental pc tracing"), cl::Hidden
,
92 static cl::opt
<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",
93 cl::desc("pc tracing with a guard"),
94 cl::Hidden
, cl::init(false));
96 // If true, we create a global variable that contains PCs of all instrumented
97 // BBs, put this global into a named section, and pass this section's bounds
98 // to __sanitizer_cov_pcs_init.
99 // This way the coverage instrumentation does not need to acquire the PCs
100 // at run-time. Works with trace-pc-guard, inline-8bit-counters, and
102 static cl::opt
<bool> ClCreatePCTable("sanitizer-coverage-pc-table",
103 cl::desc("create a static PC table"),
104 cl::Hidden
, cl::init(false));
107 ClInline8bitCounters("sanitizer-coverage-inline-8bit-counters",
108 cl::desc("increments 8-bit counter for every edge"),
109 cl::Hidden
, cl::init(false));
112 ClInlineBoolFlag("sanitizer-coverage-inline-bool-flag",
113 cl::desc("sets a boolean flag for every edge"), cl::Hidden
,
117 ClCMPTracing("sanitizer-coverage-trace-compares",
118 cl::desc("Tracing of CMP and similar instructions"),
119 cl::Hidden
, cl::init(false));
121 static cl::opt
<bool> ClDIVTracing("sanitizer-coverage-trace-divs",
122 cl::desc("Tracing of DIV instructions"),
123 cl::Hidden
, cl::init(false));
125 static cl::opt
<bool> ClGEPTracing("sanitizer-coverage-trace-geps",
126 cl::desc("Tracing of GEP instructions"),
127 cl::Hidden
, cl::init(false));
130 ClPruneBlocks("sanitizer-coverage-prune-blocks",
131 cl::desc("Reduce the number of instrumented blocks"),
132 cl::Hidden
, cl::init(true));
134 static cl::opt
<bool> ClStackDepth("sanitizer-coverage-stack-depth",
135 cl::desc("max stack depth tracing"),
136 cl::Hidden
, cl::init(false));
140 SanitizerCoverageOptions
getOptions(int LegacyCoverageLevel
) {
141 SanitizerCoverageOptions Res
;
142 switch (LegacyCoverageLevel
) {
144 Res
.CoverageType
= SanitizerCoverageOptions::SCK_None
;
147 Res
.CoverageType
= SanitizerCoverageOptions::SCK_Function
;
150 Res
.CoverageType
= SanitizerCoverageOptions::SCK_BB
;
153 Res
.CoverageType
= SanitizerCoverageOptions::SCK_Edge
;
156 Res
.CoverageType
= SanitizerCoverageOptions::SCK_Edge
;
157 Res
.IndirectCalls
= true;
163 SanitizerCoverageOptions
OverrideFromCL(SanitizerCoverageOptions Options
) {
164 // Sets CoverageType and IndirectCalls.
165 SanitizerCoverageOptions CLOpts
= getOptions(ClCoverageLevel
);
166 Options
.CoverageType
= std::max(Options
.CoverageType
, CLOpts
.CoverageType
);
167 Options
.IndirectCalls
|= CLOpts
.IndirectCalls
;
168 Options
.TraceCmp
|= ClCMPTracing
;
169 Options
.TraceDiv
|= ClDIVTracing
;
170 Options
.TraceGep
|= ClGEPTracing
;
171 Options
.TracePC
|= ClTracePC
;
172 Options
.TracePCGuard
|= ClTracePCGuard
;
173 Options
.Inline8bitCounters
|= ClInline8bitCounters
;
174 Options
.InlineBoolFlag
|= ClInlineBoolFlag
;
175 Options
.PCTable
|= ClCreatePCTable
;
176 Options
.NoPrune
|= !ClPruneBlocks
;
177 Options
.StackDepth
|= ClStackDepth
;
178 if (!Options
.TracePCGuard
&& !Options
.TracePC
&&
179 !Options
.Inline8bitCounters
&& !Options
.StackDepth
&&
180 !Options
.InlineBoolFlag
)
181 Options
.TracePCGuard
= true; // TracePCGuard is default.
185 using DomTreeCallback
= function_ref
<const DominatorTree
*(Function
&F
)>;
186 using PostDomTreeCallback
=
187 function_ref
<const PostDominatorTree
*(Function
&F
)>;
189 class ModuleSanitizerCoverage
{
191 ModuleSanitizerCoverage(
192 const SanitizerCoverageOptions
&Options
= SanitizerCoverageOptions(),
193 const SpecialCaseList
*Allowlist
= nullptr,
194 const SpecialCaseList
*Blocklist
= nullptr)
195 : Options(OverrideFromCL(Options
)), Allowlist(Allowlist
),
196 Blocklist(Blocklist
) {}
197 bool instrumentModule(Module
&M
, DomTreeCallback DTCallback
,
198 PostDomTreeCallback PDTCallback
);
201 void instrumentFunction(Function
&F
, DomTreeCallback DTCallback
,
202 PostDomTreeCallback PDTCallback
);
203 void InjectCoverageForIndirectCalls(Function
&F
,
204 ArrayRef
<Instruction
*> IndirCalls
);
205 void InjectTraceForCmp(Function
&F
, ArrayRef
<Instruction
*> CmpTraceTargets
);
206 void InjectTraceForDiv(Function
&F
,
207 ArrayRef
<BinaryOperator
*> DivTraceTargets
);
208 void InjectTraceForGep(Function
&F
,
209 ArrayRef
<GetElementPtrInst
*> GepTraceTargets
);
210 void InjectTraceForSwitch(Function
&F
,
211 ArrayRef
<Instruction
*> SwitchTraceTargets
);
212 bool InjectCoverage(Function
&F
, ArrayRef
<BasicBlock
*> AllBlocks
,
213 bool IsLeafFunc
= true);
214 GlobalVariable
*CreateFunctionLocalArrayInSection(size_t NumElements
,
215 Function
&F
, Type
*Ty
,
216 const char *Section
);
217 GlobalVariable
*CreatePCArray(Function
&F
, ArrayRef
<BasicBlock
*> AllBlocks
);
218 void CreateFunctionLocalArrays(Function
&F
, ArrayRef
<BasicBlock
*> AllBlocks
);
219 void InjectCoverageAtBlock(Function
&F
, BasicBlock
&BB
, size_t Idx
,
220 bool IsLeafFunc
= true);
221 Function
*CreateInitCallsForSections(Module
&M
, const char *CtorName
,
222 const char *InitFunctionName
, Type
*Ty
,
223 const char *Section
);
224 std::pair
<Value
*, Value
*> CreateSecStartEnd(Module
&M
, const char *Section
,
227 void SetNoSanitizeMetadata(Instruction
*I
) {
228 I
->setMetadata(I
->getModule()->getMDKindID("nosanitize"),
229 MDNode::get(*C
, None
));
232 std::string
getSectionName(const std::string
&Section
) const;
233 std::string
getSectionStart(const std::string
&Section
) const;
234 std::string
getSectionEnd(const std::string
&Section
) const;
235 FunctionCallee SanCovTracePCIndir
;
236 FunctionCallee SanCovTracePC
, SanCovTracePCGuard
;
237 FunctionCallee SanCovTraceCmpFunction
[4];
238 FunctionCallee SanCovTraceConstCmpFunction
[4];
239 FunctionCallee SanCovTraceDivFunction
[2];
240 FunctionCallee SanCovTraceGepFunction
;
241 FunctionCallee SanCovTraceSwitchFunction
;
242 GlobalVariable
*SanCovLowestStack
;
243 Type
*IntptrTy
, *IntptrPtrTy
, *Int64Ty
, *Int64PtrTy
, *Int32Ty
, *Int32PtrTy
,
244 *Int16Ty
, *Int8Ty
, *Int8PtrTy
, *Int1Ty
, *Int1PtrTy
;
246 std::string CurModuleUniqueId
;
249 const DataLayout
*DL
;
251 GlobalVariable
*FunctionGuardArray
; // for trace-pc-guard.
252 GlobalVariable
*Function8bitCounterArray
; // for inline-8bit-counters.
253 GlobalVariable
*FunctionBoolArray
; // for inline-bool-flag.
254 GlobalVariable
*FunctionPCsArray
; // for pc-table.
255 SmallVector
<GlobalValue
*, 20> GlobalsToAppendToUsed
;
256 SmallVector
<GlobalValue
*, 20> GlobalsToAppendToCompilerUsed
;
258 SanitizerCoverageOptions Options
;
260 const SpecialCaseList
*Allowlist
;
261 const SpecialCaseList
*Blocklist
;
264 class ModuleSanitizerCoverageLegacyPass
: public ModulePass
{
266 ModuleSanitizerCoverageLegacyPass(
267 const SanitizerCoverageOptions
&Options
= SanitizerCoverageOptions(),
268 const std::vector
<std::string
> &AllowlistFiles
=
269 std::vector
<std::string
>(),
270 const std::vector
<std::string
> &BlocklistFiles
=
271 std::vector
<std::string
>())
272 : ModulePass(ID
), Options(Options
) {
273 if (AllowlistFiles
.size() > 0)
274 Allowlist
= SpecialCaseList::createOrDie(AllowlistFiles
,
275 *vfs::getRealFileSystem());
276 if (BlocklistFiles
.size() > 0)
277 Blocklist
= SpecialCaseList::createOrDie(BlocklistFiles
,
278 *vfs::getRealFileSystem());
279 initializeModuleSanitizerCoverageLegacyPassPass(
280 *PassRegistry::getPassRegistry());
282 bool runOnModule(Module
&M
) override
{
283 ModuleSanitizerCoverage
ModuleSancov(Options
, Allowlist
.get(),
285 auto DTCallback
= [this](Function
&F
) -> const DominatorTree
* {
286 return &this->getAnalysis
<DominatorTreeWrapperPass
>(F
).getDomTree();
288 auto PDTCallback
= [this](Function
&F
) -> const PostDominatorTree
* {
289 return &this->getAnalysis
<PostDominatorTreeWrapperPass
>(F
)
292 return ModuleSancov
.instrumentModule(M
, DTCallback
, PDTCallback
);
295 static char ID
; // Pass identification, replacement for typeid
296 StringRef
getPassName() const override
{ return "ModuleSanitizerCoverage"; }
298 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
299 AU
.addRequired
<DominatorTreeWrapperPass
>();
300 AU
.addRequired
<PostDominatorTreeWrapperPass
>();
304 SanitizerCoverageOptions Options
;
306 std::unique_ptr
<SpecialCaseList
> Allowlist
;
307 std::unique_ptr
<SpecialCaseList
> Blocklist
;
312 PreservedAnalyses
ModuleSanitizerCoveragePass::run(Module
&M
,
313 ModuleAnalysisManager
&MAM
) {
314 ModuleSanitizerCoverage
ModuleSancov(Options
, Allowlist
.get(),
316 auto &FAM
= MAM
.getResult
<FunctionAnalysisManagerModuleProxy
>(M
).getManager();
317 auto DTCallback
= [&FAM
](Function
&F
) -> const DominatorTree
* {
318 return &FAM
.getResult
<DominatorTreeAnalysis
>(F
);
320 auto PDTCallback
= [&FAM
](Function
&F
) -> const PostDominatorTree
* {
321 return &FAM
.getResult
<PostDominatorTreeAnalysis
>(F
);
323 if (ModuleSancov
.instrumentModule(M
, DTCallback
, PDTCallback
))
324 return PreservedAnalyses::none();
325 return PreservedAnalyses::all();
328 std::pair
<Value
*, Value
*>
329 ModuleSanitizerCoverage::CreateSecStartEnd(Module
&M
, const char *Section
,
331 // Use ExternalWeak so that if all sections are discarded due to section
332 // garbage collection, the linker will not report undefined symbol errors.
333 // Windows defines the start/stop symbols in compiler-rt so no need for
335 GlobalValue::LinkageTypes Linkage
= TargetTriple
.isOSBinFormatCOFF()
336 ? GlobalVariable::ExternalLinkage
337 : GlobalVariable::ExternalWeakLinkage
;
338 GlobalVariable
*SecStart
=
339 new GlobalVariable(M
, Ty
, false, Linkage
, nullptr,
340 getSectionStart(Section
));
341 SecStart
->setVisibility(GlobalValue::HiddenVisibility
);
342 GlobalVariable
*SecEnd
=
343 new GlobalVariable(M
, Ty
, false, Linkage
, nullptr,
344 getSectionEnd(Section
));
345 SecEnd
->setVisibility(GlobalValue::HiddenVisibility
);
346 IRBuilder
<> IRB(M
.getContext());
347 if (!TargetTriple
.isOSBinFormatCOFF())
348 return std::make_pair(SecStart
, SecEnd
);
350 // Account for the fact that on windows-msvc __start_* symbols actually
351 // point to a uint64_t before the start of the array.
352 auto SecStartI8Ptr
= IRB
.CreatePointerCast(SecStart
, Int8PtrTy
);
353 auto GEP
= IRB
.CreateGEP(Int8Ty
, SecStartI8Ptr
,
354 ConstantInt::get(IntptrTy
, sizeof(uint64_t)));
355 return std::make_pair(IRB
.CreatePointerCast(GEP
, PointerType::getUnqual(Ty
)),
359 Function
*ModuleSanitizerCoverage::CreateInitCallsForSections(
360 Module
&M
, const char *CtorName
, const char *InitFunctionName
, Type
*Ty
,
361 const char *Section
) {
362 auto SecStartEnd
= CreateSecStartEnd(M
, Section
, Ty
);
363 auto SecStart
= SecStartEnd
.first
;
364 auto SecEnd
= SecStartEnd
.second
;
366 Type
*PtrTy
= PointerType::getUnqual(Ty
);
367 std::tie(CtorFunc
, std::ignore
) = createSanitizerCtorAndInitFunctions(
368 M
, CtorName
, InitFunctionName
, {PtrTy
, PtrTy
}, {SecStart
, SecEnd
});
369 assert(CtorFunc
->getName() == CtorName
);
371 if (TargetTriple
.supportsCOMDAT()) {
372 // Use comdat to dedup CtorFunc.
373 CtorFunc
->setComdat(M
.getOrInsertComdat(CtorName
));
374 appendToGlobalCtors(M
, CtorFunc
, SanCtorAndDtorPriority
, CtorFunc
);
376 appendToGlobalCtors(M
, CtorFunc
, SanCtorAndDtorPriority
);
379 if (TargetTriple
.isOSBinFormatCOFF()) {
380 // In COFF files, if the contructors are set as COMDAT (they are because
381 // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced
382 // functions and data) is used, the constructors get stripped. To prevent
383 // this, give the constructors weak ODR linkage and ensure the linker knows
384 // to include the sancov constructor. This way the linker can deduplicate
385 // the constructors but always leave one copy.
386 CtorFunc
->setLinkage(GlobalValue::WeakODRLinkage
);
391 bool ModuleSanitizerCoverage::instrumentModule(
392 Module
&M
, DomTreeCallback DTCallback
, PostDomTreeCallback PDTCallback
) {
393 if (Options
.CoverageType
== SanitizerCoverageOptions::SCK_None
)
396 !Allowlist
->inSection("coverage", "src", M
.getSourceFileName()))
399 Blocklist
->inSection("coverage", "src", M
.getSourceFileName()))
401 C
= &(M
.getContext());
402 DL
= &M
.getDataLayout();
404 CurModuleUniqueId
= getUniqueModuleId(CurModule
);
405 TargetTriple
= Triple(M
.getTargetTriple());
406 FunctionGuardArray
= nullptr;
407 Function8bitCounterArray
= nullptr;
408 FunctionBoolArray
= nullptr;
409 FunctionPCsArray
= nullptr;
410 IntptrTy
= Type::getIntNTy(*C
, DL
->getPointerSizeInBits());
411 IntptrPtrTy
= PointerType::getUnqual(IntptrTy
);
412 Type
*VoidTy
= Type::getVoidTy(*C
);
414 Int64PtrTy
= PointerType::getUnqual(IRB
.getInt64Ty());
415 Int32PtrTy
= PointerType::getUnqual(IRB
.getInt32Ty());
416 Int8PtrTy
= PointerType::getUnqual(IRB
.getInt8Ty());
417 Int1PtrTy
= PointerType::getUnqual(IRB
.getInt1Ty());
418 Int64Ty
= IRB
.getInt64Ty();
419 Int32Ty
= IRB
.getInt32Ty();
420 Int16Ty
= IRB
.getInt16Ty();
421 Int8Ty
= IRB
.getInt8Ty();
422 Int1Ty
= IRB
.getInt1Ty();
425 M
.getOrInsertFunction(SanCovTracePCIndirName
, VoidTy
, IntptrTy
);
426 // Make sure smaller parameters are zero-extended to i64 if required by the
428 AttributeList SanCovTraceCmpZeroExtAL
;
429 SanCovTraceCmpZeroExtAL
=
430 SanCovTraceCmpZeroExtAL
.addParamAttribute(*C
, 0, Attribute::ZExt
);
431 SanCovTraceCmpZeroExtAL
=
432 SanCovTraceCmpZeroExtAL
.addParamAttribute(*C
, 1, Attribute::ZExt
);
434 SanCovTraceCmpFunction
[0] =
435 M
.getOrInsertFunction(SanCovTraceCmp1
, SanCovTraceCmpZeroExtAL
, VoidTy
,
436 IRB
.getInt8Ty(), IRB
.getInt8Ty());
437 SanCovTraceCmpFunction
[1] =
438 M
.getOrInsertFunction(SanCovTraceCmp2
, SanCovTraceCmpZeroExtAL
, VoidTy
,
439 IRB
.getInt16Ty(), IRB
.getInt16Ty());
440 SanCovTraceCmpFunction
[2] =
441 M
.getOrInsertFunction(SanCovTraceCmp4
, SanCovTraceCmpZeroExtAL
, VoidTy
,
442 IRB
.getInt32Ty(), IRB
.getInt32Ty());
443 SanCovTraceCmpFunction
[3] =
444 M
.getOrInsertFunction(SanCovTraceCmp8
, VoidTy
, Int64Ty
, Int64Ty
);
446 SanCovTraceConstCmpFunction
[0] = M
.getOrInsertFunction(
447 SanCovTraceConstCmp1
, SanCovTraceCmpZeroExtAL
, VoidTy
, Int8Ty
, Int8Ty
);
448 SanCovTraceConstCmpFunction
[1] = M
.getOrInsertFunction(
449 SanCovTraceConstCmp2
, SanCovTraceCmpZeroExtAL
, VoidTy
, Int16Ty
, Int16Ty
);
450 SanCovTraceConstCmpFunction
[2] = M
.getOrInsertFunction(
451 SanCovTraceConstCmp4
, SanCovTraceCmpZeroExtAL
, VoidTy
, Int32Ty
, Int32Ty
);
452 SanCovTraceConstCmpFunction
[3] =
453 M
.getOrInsertFunction(SanCovTraceConstCmp8
, VoidTy
, Int64Ty
, Int64Ty
);
457 AL
= AL
.addParamAttribute(*C
, 0, Attribute::ZExt
);
458 SanCovTraceDivFunction
[0] =
459 M
.getOrInsertFunction(SanCovTraceDiv4
, AL
, VoidTy
, IRB
.getInt32Ty());
461 SanCovTraceDivFunction
[1] =
462 M
.getOrInsertFunction(SanCovTraceDiv8
, VoidTy
, Int64Ty
);
463 SanCovTraceGepFunction
=
464 M
.getOrInsertFunction(SanCovTraceGep
, VoidTy
, IntptrTy
);
465 SanCovTraceSwitchFunction
=
466 M
.getOrInsertFunction(SanCovTraceSwitchName
, VoidTy
, Int64Ty
, Int64PtrTy
);
468 Constant
*SanCovLowestStackConstant
=
469 M
.getOrInsertGlobal(SanCovLowestStackName
, IntptrTy
);
470 SanCovLowestStack
= dyn_cast
<GlobalVariable
>(SanCovLowestStackConstant
);
471 if (!SanCovLowestStack
|| SanCovLowestStack
->getValueType() != IntptrTy
) {
472 C
->emitError(StringRef("'") + SanCovLowestStackName
+
473 "' should not be declared by the user");
476 SanCovLowestStack
->setThreadLocalMode(
477 GlobalValue::ThreadLocalMode::InitialExecTLSModel
);
478 if (Options
.StackDepth
&& !SanCovLowestStack
->isDeclaration())
479 SanCovLowestStack
->setInitializer(Constant::getAllOnesValue(IntptrTy
));
481 SanCovTracePC
= M
.getOrInsertFunction(SanCovTracePCName
, VoidTy
);
483 M
.getOrInsertFunction(SanCovTracePCGuardName
, VoidTy
, Int32PtrTy
);
486 instrumentFunction(F
, DTCallback
, PDTCallback
);
488 Function
*Ctor
= nullptr;
490 if (FunctionGuardArray
)
491 Ctor
= CreateInitCallsForSections(M
, SanCovModuleCtorTracePcGuardName
,
492 SanCovTracePCGuardInitName
, Int32Ty
,
493 SanCovGuardsSectionName
);
494 if (Function8bitCounterArray
)
495 Ctor
= CreateInitCallsForSections(M
, SanCovModuleCtor8bitCountersName
,
496 SanCov8bitCountersInitName
, Int8Ty
,
497 SanCovCountersSectionName
);
498 if (FunctionBoolArray
) {
499 Ctor
= CreateInitCallsForSections(M
, SanCovModuleCtorBoolFlagName
,
500 SanCovBoolFlagInitName
, Int1Ty
,
501 SanCovBoolFlagSectionName
);
503 if (Ctor
&& Options
.PCTable
) {
504 auto SecStartEnd
= CreateSecStartEnd(M
, SanCovPCsSectionName
, IntptrTy
);
505 FunctionCallee InitFunction
= declareSanitizerInitFunction(
506 M
, SanCovPCsInitName
, {IntptrPtrTy
, IntptrPtrTy
});
507 IRBuilder
<> IRBCtor(Ctor
->getEntryBlock().getTerminator());
508 IRBCtor
.CreateCall(InitFunction
, {SecStartEnd
.first
, SecStartEnd
.second
});
510 appendToUsed(M
, GlobalsToAppendToUsed
);
511 appendToCompilerUsed(M
, GlobalsToAppendToCompilerUsed
);
515 // True if block has successors and it dominates all of them.
516 static bool isFullDominator(const BasicBlock
*BB
, const DominatorTree
*DT
) {
520 return llvm::all_of(successors(BB
), [&](const BasicBlock
*SUCC
) {
521 return DT
->dominates(BB
, SUCC
);
525 // True if block has predecessors and it postdominates all of them.
526 static bool isFullPostDominator(const BasicBlock
*BB
,
527 const PostDominatorTree
*PDT
) {
531 return llvm::all_of(predecessors(BB
), [&](const BasicBlock
*PRED
) {
532 return PDT
->dominates(BB
, PRED
);
536 static bool shouldInstrumentBlock(const Function
&F
, const BasicBlock
*BB
,
537 const DominatorTree
*DT
,
538 const PostDominatorTree
*PDT
,
539 const SanitizerCoverageOptions
&Options
) {
540 // Don't insert coverage for blocks containing nothing but unreachable: we
541 // will never call __sanitizer_cov() for them, so counting them in
542 // NumberOfInstrumentedBlocks() might complicate calculation of code coverage
543 // percentage. Also, unreachable instructions frequently have no debug
545 if (isa
<UnreachableInst
>(BB
->getFirstNonPHIOrDbgOrLifetime()))
548 // Don't insert coverage into blocks without a valid insertion point
549 // (catchswitch blocks).
550 if (BB
->getFirstInsertionPt() == BB
->end())
553 if (Options
.NoPrune
|| &F
.getEntryBlock() == BB
)
556 if (Options
.CoverageType
== SanitizerCoverageOptions::SCK_Function
&&
557 &F
.getEntryBlock() != BB
)
560 // Do not instrument full dominators, or full post-dominators with multiple
562 return !isFullDominator(BB
, DT
)
563 && !(isFullPostDominator(BB
, PDT
) && !BB
->getSinglePredecessor());
567 // Returns true iff From->To is a backedge.
568 // A twist here is that we treat From->To as a backedge if
569 // * To dominates From or
570 // * To->UniqueSuccessor dominates From
571 static bool IsBackEdge(BasicBlock
*From
, BasicBlock
*To
,
572 const DominatorTree
*DT
) {
573 if (DT
->dominates(To
, From
))
575 if (auto Next
= To
->getUniqueSuccessor())
576 if (DT
->dominates(Next
, From
))
581 // Prunes uninteresting Cmp instrumentation:
582 // * CMP instructions that feed into loop backedge branch.
584 // Note that Cmp pruning is controlled by the same flag as the
586 static bool IsInterestingCmp(ICmpInst
*CMP
, const DominatorTree
*DT
,
587 const SanitizerCoverageOptions
&Options
) {
588 if (!Options
.NoPrune
)
589 if (CMP
->hasOneUse())
590 if (auto BR
= dyn_cast
<BranchInst
>(CMP
->user_back()))
591 for (BasicBlock
*B
: BR
->successors())
592 if (IsBackEdge(BR
->getParent(), B
, DT
))
597 void ModuleSanitizerCoverage::instrumentFunction(
598 Function
&F
, DomTreeCallback DTCallback
, PostDomTreeCallback PDTCallback
) {
601 if (F
.getName().find(".module_ctor") != std::string::npos
)
602 return; // Should not instrument sanitizer init functions.
603 if (F
.getName().startswith("__sanitizer_"))
604 return; // Don't instrument __sanitizer_* callbacks.
605 // Don't touch available_externally functions, their actual body is elewhere.
606 if (F
.getLinkage() == GlobalValue::AvailableExternallyLinkage
)
608 // Don't instrument MSVC CRT configuration helpers. They may run before normal
610 if (F
.getName() == "__local_stdio_printf_options" ||
611 F
.getName() == "__local_stdio_scanf_options")
613 if (isa
<UnreachableInst
>(F
.getEntryBlock().getTerminator()))
615 // Don't instrument functions using SEH for now. Splitting basic blocks like
616 // we do for coverage breaks WinEHPrepare.
617 // FIXME: Remove this when SEH no longer uses landingpad pattern matching.
618 if (F
.hasPersonalityFn() &&
619 isAsynchronousEHPersonality(classifyEHPersonality(F
.getPersonalityFn())))
621 if (Allowlist
&& !Allowlist
->inSection("coverage", "fun", F
.getName()))
623 if (Blocklist
&& Blocklist
->inSection("coverage", "fun", F
.getName()))
625 if (F
.hasFnAttribute(Attribute::NoSanitizeCoverage
))
627 if (Options
.CoverageType
>= SanitizerCoverageOptions::SCK_Edge
)
628 SplitAllCriticalEdges(F
, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
629 SmallVector
<Instruction
*, 8> IndirCalls
;
630 SmallVector
<BasicBlock
*, 16> BlocksToInstrument
;
631 SmallVector
<Instruction
*, 8> CmpTraceTargets
;
632 SmallVector
<Instruction
*, 8> SwitchTraceTargets
;
633 SmallVector
<BinaryOperator
*, 8> DivTraceTargets
;
634 SmallVector
<GetElementPtrInst
*, 8> GepTraceTargets
;
636 const DominatorTree
*DT
= DTCallback(F
);
637 const PostDominatorTree
*PDT
= PDTCallback(F
);
638 bool IsLeafFunc
= true;
641 if (shouldInstrumentBlock(F
, &BB
, DT
, PDT
, Options
))
642 BlocksToInstrument
.push_back(&BB
);
643 for (auto &Inst
: BB
) {
644 if (Options
.IndirectCalls
) {
645 CallBase
*CB
= dyn_cast
<CallBase
>(&Inst
);
646 if (CB
&& !CB
->getCalledFunction())
647 IndirCalls
.push_back(&Inst
);
649 if (Options
.TraceCmp
) {
650 if (ICmpInst
*CMP
= dyn_cast
<ICmpInst
>(&Inst
))
651 if (IsInterestingCmp(CMP
, DT
, Options
))
652 CmpTraceTargets
.push_back(&Inst
);
653 if (isa
<SwitchInst
>(&Inst
))
654 SwitchTraceTargets
.push_back(&Inst
);
656 if (Options
.TraceDiv
)
657 if (BinaryOperator
*BO
= dyn_cast
<BinaryOperator
>(&Inst
))
658 if (BO
->getOpcode() == Instruction::SDiv
||
659 BO
->getOpcode() == Instruction::UDiv
)
660 DivTraceTargets
.push_back(BO
);
661 if (Options
.TraceGep
)
662 if (GetElementPtrInst
*GEP
= dyn_cast
<GetElementPtrInst
>(&Inst
))
663 GepTraceTargets
.push_back(GEP
);
664 if (Options
.StackDepth
)
665 if (isa
<InvokeInst
>(Inst
) ||
666 (isa
<CallInst
>(Inst
) && !isa
<IntrinsicInst
>(Inst
)))
671 InjectCoverage(F
, BlocksToInstrument
, IsLeafFunc
);
672 InjectCoverageForIndirectCalls(F
, IndirCalls
);
673 InjectTraceForCmp(F
, CmpTraceTargets
);
674 InjectTraceForSwitch(F
, SwitchTraceTargets
);
675 InjectTraceForDiv(F
, DivTraceTargets
);
676 InjectTraceForGep(F
, GepTraceTargets
);
679 GlobalVariable
*ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
680 size_t NumElements
, Function
&F
, Type
*Ty
, const char *Section
) {
681 ArrayType
*ArrayTy
= ArrayType::get(Ty
, NumElements
);
682 auto Array
= new GlobalVariable(
683 *CurModule
, ArrayTy
, false, GlobalVariable::PrivateLinkage
,
684 Constant::getNullValue(ArrayTy
), "__sancov_gen_");
686 if (TargetTriple
.supportsCOMDAT() &&
687 (TargetTriple
.isOSBinFormatELF() || !F
.isInterposable()))
688 if (auto Comdat
= getOrCreateFunctionComdat(F
, TargetTriple
))
689 Array
->setComdat(Comdat
);
690 Array
->setSection(getSectionName(Section
));
691 Array
->setAlignment(Align(DL
->getTypeStoreSize(Ty
).getFixedSize()));
693 // sancov_pcs parallels the other metadata section(s). Optimizers (e.g.
694 // GlobalOpt/ConstantMerge) may not discard sancov_pcs and the other
695 // section(s) as a unit, so we conservatively retain all unconditionally in
698 // With comdat (COFF/ELF), the linker can guarantee the associated sections
699 // will be retained or discarded as a unit, so llvm.compiler.used is
700 // sufficient. Otherwise, conservatively make all of them retained by the
702 if (Array
->hasComdat())
703 GlobalsToAppendToCompilerUsed
.push_back(Array
);
705 GlobalsToAppendToUsed
.push_back(Array
);
711 ModuleSanitizerCoverage::CreatePCArray(Function
&F
,
712 ArrayRef
<BasicBlock
*> AllBlocks
) {
713 size_t N
= AllBlocks
.size();
715 SmallVector
<Constant
*, 32> PCs
;
716 IRBuilder
<> IRB(&*F
.getEntryBlock().getFirstInsertionPt());
717 for (size_t i
= 0; i
< N
; i
++) {
718 if (&F
.getEntryBlock() == AllBlocks
[i
]) {
719 PCs
.push_back((Constant
*)IRB
.CreatePointerCast(&F
, IntptrPtrTy
));
720 PCs
.push_back((Constant
*)IRB
.CreateIntToPtr(
721 ConstantInt::get(IntptrTy
, 1), IntptrPtrTy
));
723 PCs
.push_back((Constant
*)IRB
.CreatePointerCast(
724 BlockAddress::get(AllBlocks
[i
]), IntptrPtrTy
));
725 PCs
.push_back((Constant
*)IRB
.CreateIntToPtr(
726 ConstantInt::get(IntptrTy
, 0), IntptrPtrTy
));
729 auto *PCArray
= CreateFunctionLocalArrayInSection(N
* 2, F
, IntptrPtrTy
,
730 SanCovPCsSectionName
);
731 PCArray
->setInitializer(
732 ConstantArray::get(ArrayType::get(IntptrPtrTy
, N
* 2), PCs
));
733 PCArray
->setConstant(true);
738 void ModuleSanitizerCoverage::CreateFunctionLocalArrays(
739 Function
&F
, ArrayRef
<BasicBlock
*> AllBlocks
) {
740 if (Options
.TracePCGuard
)
741 FunctionGuardArray
= CreateFunctionLocalArrayInSection(
742 AllBlocks
.size(), F
, Int32Ty
, SanCovGuardsSectionName
);
744 if (Options
.Inline8bitCounters
)
745 Function8bitCounterArray
= CreateFunctionLocalArrayInSection(
746 AllBlocks
.size(), F
, Int8Ty
, SanCovCountersSectionName
);
747 if (Options
.InlineBoolFlag
)
748 FunctionBoolArray
= CreateFunctionLocalArrayInSection(
749 AllBlocks
.size(), F
, Int1Ty
, SanCovBoolFlagSectionName
);
752 FunctionPCsArray
= CreatePCArray(F
, AllBlocks
);
755 bool ModuleSanitizerCoverage::InjectCoverage(Function
&F
,
756 ArrayRef
<BasicBlock
*> AllBlocks
,
758 if (AllBlocks
.empty()) return false;
759 CreateFunctionLocalArrays(F
, AllBlocks
);
760 for (size_t i
= 0, N
= AllBlocks
.size(); i
< N
; i
++)
761 InjectCoverageAtBlock(F
, *AllBlocks
[i
], i
, IsLeafFunc
);
765 // On every indirect call we call a run-time function
766 // __sanitizer_cov_indir_call* with two parameters:
768 // - global cache array that contains CacheSize pointers (zero-initialized).
769 // The cache is used to speed up recording the caller-callee pairs.
770 // The address of the caller is passed implicitly via caller PC.
771 // CacheSize is encoded in the name of the run-time function.
772 void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
773 Function
&F
, ArrayRef
<Instruction
*> IndirCalls
) {
774 if (IndirCalls
.empty())
776 assert(Options
.TracePC
|| Options
.TracePCGuard
||
777 Options
.Inline8bitCounters
|| Options
.InlineBoolFlag
);
778 for (auto I
: IndirCalls
) {
780 CallBase
&CB
= cast
<CallBase
>(*I
);
781 Value
*Callee
= CB
.getCalledOperand();
782 if (isa
<InlineAsm
>(Callee
))
784 IRB
.CreateCall(SanCovTracePCIndir
, IRB
.CreatePointerCast(Callee
, IntptrTy
));
788 // For every switch statement we insert a call:
789 // __sanitizer_cov_trace_switch(CondValue,
790 // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
792 void ModuleSanitizerCoverage::InjectTraceForSwitch(
793 Function
&, ArrayRef
<Instruction
*> SwitchTraceTargets
) {
794 for (auto I
: SwitchTraceTargets
) {
795 if (SwitchInst
*SI
= dyn_cast
<SwitchInst
>(I
)) {
797 SmallVector
<Constant
*, 16> Initializers
;
798 Value
*Cond
= SI
->getCondition();
799 if (Cond
->getType()->getScalarSizeInBits() >
800 Int64Ty
->getScalarSizeInBits())
802 Initializers
.push_back(ConstantInt::get(Int64Ty
, SI
->getNumCases()));
803 Initializers
.push_back(
804 ConstantInt::get(Int64Ty
, Cond
->getType()->getScalarSizeInBits()));
805 if (Cond
->getType()->getScalarSizeInBits() <
806 Int64Ty
->getScalarSizeInBits())
807 Cond
= IRB
.CreateIntCast(Cond
, Int64Ty
, false);
808 for (auto It
: SI
->cases()) {
809 Constant
*C
= It
.getCaseValue();
810 if (C
->getType()->getScalarSizeInBits() <
811 Int64Ty
->getScalarSizeInBits())
812 C
= ConstantExpr::getCast(CastInst::ZExt
, It
.getCaseValue(), Int64Ty
);
813 Initializers
.push_back(C
);
815 llvm::sort(drop_begin(Initializers
, 2),
816 [](const Constant
*A
, const Constant
*B
) {
817 return cast
<ConstantInt
>(A
)->getLimitedValue() <
818 cast
<ConstantInt
>(B
)->getLimitedValue();
820 ArrayType
*ArrayOfInt64Ty
= ArrayType::get(Int64Ty
, Initializers
.size());
821 GlobalVariable
*GV
= new GlobalVariable(
822 *CurModule
, ArrayOfInt64Ty
, false, GlobalVariable::InternalLinkage
,
823 ConstantArray::get(ArrayOfInt64Ty
, Initializers
),
824 "__sancov_gen_cov_switch_values");
825 IRB
.CreateCall(SanCovTraceSwitchFunction
,
826 {Cond
, IRB
.CreatePointerCast(GV
, Int64PtrTy
)});
831 void ModuleSanitizerCoverage::InjectTraceForDiv(
832 Function
&, ArrayRef
<BinaryOperator
*> DivTraceTargets
) {
833 for (auto BO
: DivTraceTargets
) {
835 Value
*A1
= BO
->getOperand(1);
836 if (isa
<ConstantInt
>(A1
)) continue;
837 if (!A1
->getType()->isIntegerTy())
839 uint64_t TypeSize
= DL
->getTypeStoreSizeInBits(A1
->getType());
840 int CallbackIdx
= TypeSize
== 32 ? 0 :
841 TypeSize
== 64 ? 1 : -1;
842 if (CallbackIdx
< 0) continue;
843 auto Ty
= Type::getIntNTy(*C
, TypeSize
);
844 IRB
.CreateCall(SanCovTraceDivFunction
[CallbackIdx
],
845 {IRB
.CreateIntCast(A1
, Ty
, true)});
849 void ModuleSanitizerCoverage::InjectTraceForGep(
850 Function
&, ArrayRef
<GetElementPtrInst
*> GepTraceTargets
) {
851 for (auto GEP
: GepTraceTargets
) {
852 IRBuilder
<> IRB(GEP
);
853 for (Use
&Idx
: GEP
->indices())
854 if (!isa
<ConstantInt
>(Idx
) && Idx
->getType()->isIntegerTy())
855 IRB
.CreateCall(SanCovTraceGepFunction
,
856 {IRB
.CreateIntCast(Idx
, IntptrTy
, true)});
860 void ModuleSanitizerCoverage::InjectTraceForCmp(
861 Function
&, ArrayRef
<Instruction
*> CmpTraceTargets
) {
862 for (auto I
: CmpTraceTargets
) {
863 if (ICmpInst
*ICMP
= dyn_cast
<ICmpInst
>(I
)) {
864 IRBuilder
<> IRB(ICMP
);
865 Value
*A0
= ICMP
->getOperand(0);
866 Value
*A1
= ICMP
->getOperand(1);
867 if (!A0
->getType()->isIntegerTy())
869 uint64_t TypeSize
= DL
->getTypeStoreSizeInBits(A0
->getType());
870 int CallbackIdx
= TypeSize
== 8 ? 0 :
873 TypeSize
== 64 ? 3 : -1;
874 if (CallbackIdx
< 0) continue;
875 // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1);
876 auto CallbackFunc
= SanCovTraceCmpFunction
[CallbackIdx
];
877 bool FirstIsConst
= isa
<ConstantInt
>(A0
);
878 bool SecondIsConst
= isa
<ConstantInt
>(A1
);
879 // If both are const, then we don't need such a comparison.
880 if (FirstIsConst
&& SecondIsConst
) continue;
881 // If only one is const, then make it the first callback argument.
882 if (FirstIsConst
|| SecondIsConst
) {
883 CallbackFunc
= SanCovTraceConstCmpFunction
[CallbackIdx
];
888 auto Ty
= Type::getIntNTy(*C
, TypeSize
);
889 IRB
.CreateCall(CallbackFunc
, {IRB
.CreateIntCast(A0
, Ty
, true),
890 IRB
.CreateIntCast(A1
, Ty
, true)});
895 void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function
&F
, BasicBlock
&BB
,
898 BasicBlock::iterator IP
= BB
.getFirstInsertionPt();
899 bool IsEntryBB
= &BB
== &F
.getEntryBlock();
902 if (auto SP
= F
.getSubprogram())
903 EntryLoc
= DILocation::get(SP
->getContext(), SP
->getScopeLine(), 0, SP
);
904 // Keep static allocas and llvm.localescape calls in the entry block. Even
905 // if we aren't splitting the block, it's nice for allocas to be before
907 IP
= PrepareToSplitEntryBlock(BB
, IP
);
909 EntryLoc
= IP
->getDebugLoc();
911 if (auto *SP
= F
.getSubprogram())
912 EntryLoc
= DILocation::get(SP
->getContext(), 0, 0, SP
);
915 IRBuilder
<> IRB(&*IP
);
916 IRB
.SetCurrentDebugLocation(EntryLoc
);
917 if (Options
.TracePC
) {
918 IRB
.CreateCall(SanCovTracePC
)
919 ->setCannotMerge(); // gets the PC using GET_CALLER_PC.
921 if (Options
.TracePCGuard
) {
922 auto GuardPtr
= IRB
.CreateIntToPtr(
923 IRB
.CreateAdd(IRB
.CreatePointerCast(FunctionGuardArray
, IntptrTy
),
924 ConstantInt::get(IntptrTy
, Idx
* 4)),
926 IRB
.CreateCall(SanCovTracePCGuard
, GuardPtr
)->setCannotMerge();
928 if (Options
.Inline8bitCounters
) {
929 auto CounterPtr
= IRB
.CreateGEP(
930 Function8bitCounterArray
->getValueType(), Function8bitCounterArray
,
931 {ConstantInt::get(IntptrTy
, 0), ConstantInt::get(IntptrTy
, Idx
)});
932 auto Load
= IRB
.CreateLoad(Int8Ty
, CounterPtr
);
933 auto Inc
= IRB
.CreateAdd(Load
, ConstantInt::get(Int8Ty
, 1));
934 auto Store
= IRB
.CreateStore(Inc
, CounterPtr
);
935 SetNoSanitizeMetadata(Load
);
936 SetNoSanitizeMetadata(Store
);
938 if (Options
.InlineBoolFlag
) {
939 auto FlagPtr
= IRB
.CreateGEP(
940 FunctionBoolArray
->getValueType(), FunctionBoolArray
,
941 {ConstantInt::get(IntptrTy
, 0), ConstantInt::get(IntptrTy
, Idx
)});
942 auto Load
= IRB
.CreateLoad(Int1Ty
, FlagPtr
);
944 SplitBlockAndInsertIfThen(IRB
.CreateIsNull(Load
), &*IP
, false);
945 IRBuilder
<> ThenIRB(ThenTerm
);
946 auto Store
= ThenIRB
.CreateStore(ConstantInt::getTrue(Int1Ty
), FlagPtr
);
947 SetNoSanitizeMetadata(Load
);
948 SetNoSanitizeMetadata(Store
);
950 if (Options
.StackDepth
&& IsEntryBB
&& !IsLeafFunc
) {
951 // Check stack depth. If it's the deepest so far, record it.
952 Module
*M
= F
.getParent();
953 Function
*GetFrameAddr
= Intrinsic::getDeclaration(
954 M
, Intrinsic::frameaddress
,
955 IRB
.getInt8PtrTy(M
->getDataLayout().getAllocaAddrSpace()));
957 IRB
.CreateCall(GetFrameAddr
, {Constant::getNullValue(Int32Ty
)});
958 auto FrameAddrInt
= IRB
.CreatePtrToInt(FrameAddrPtr
, IntptrTy
);
959 auto LowestStack
= IRB
.CreateLoad(IntptrTy
, SanCovLowestStack
);
960 auto IsStackLower
= IRB
.CreateICmpULT(FrameAddrInt
, LowestStack
);
961 auto ThenTerm
= SplitBlockAndInsertIfThen(IsStackLower
, &*IP
, false);
962 IRBuilder
<> ThenIRB(ThenTerm
);
963 auto Store
= ThenIRB
.CreateStore(FrameAddrInt
, SanCovLowestStack
);
964 SetNoSanitizeMetadata(LowestStack
);
965 SetNoSanitizeMetadata(Store
);
970 ModuleSanitizerCoverage::getSectionName(const std::string
&Section
) const {
971 if (TargetTriple
.isOSBinFormatCOFF()) {
972 if (Section
== SanCovCountersSectionName
)
974 if (Section
== SanCovBoolFlagSectionName
)
976 if (Section
== SanCovPCsSectionName
)
978 return ".SCOV$GM"; // For SanCovGuardsSectionName.
980 if (TargetTriple
.isOSBinFormatMachO())
981 return "__DATA,__" + Section
;
982 return "__" + Section
;
986 ModuleSanitizerCoverage::getSectionStart(const std::string
&Section
) const {
987 if (TargetTriple
.isOSBinFormatMachO())
988 return "\1section$start$__DATA$__" + Section
;
989 return "__start___" + Section
;
993 ModuleSanitizerCoverage::getSectionEnd(const std::string
&Section
) const {
994 if (TargetTriple
.isOSBinFormatMachO())
995 return "\1section$end$__DATA$__" + Section
;
996 return "__stop___" + Section
;
999 char ModuleSanitizerCoverageLegacyPass::ID
= 0;
1000 INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass
, "sancov",
1001 "Pass for instrumenting coverage on functions", false,
1003 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass
)
1004 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass
)
1005 INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass
, "sancov",
1006 "Pass for instrumenting coverage on functions", false,
1008 ModulePass
*llvm::createModuleSanitizerCoverageLegacyPassPass(
1009 const SanitizerCoverageOptions
&Options
,
1010 const std::vector
<std::string
> &AllowlistFiles
,
1011 const std::vector
<std::string
> &BlocklistFiles
) {
1012 return new ModuleSanitizerCoverageLegacyPass(Options
, AllowlistFiles
,