llvm.org GIT mirror llvm / 3f54675
[NewPM] Port Sancov This patch contains a port of SanitizerCoverage to the new pass manager. This one's a bit hefty. Changes: - Split SanitizerCoverageModule into 2 SanitizerCoverage for passing over functions and ModuleSanitizerCoverage for passing over modules. - ModuleSanitizerCoverage exists for adding 2 module level calls to initialization functions but only if there's a function that was instrumented by sancov. - Added legacy and new PM wrapper classes that own instances of the 2 new classes. - Update llvm tests and add clang tests. Differential Revision: https://reviews.llvm.org/D62888 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365838 91177308-0d34-0410-b5e6-96231b3b80d8 Leonard Chan 3 months ago
38 changed file(s) with 411 addition(s) and 152 deletion(s). Raw diff Collapse all Expand all
359359 void initializeSafeStackLegacyPassPass(PassRegistry&);
360360 void initializeSafepointIRVerifierPass(PassRegistry&);
361361 void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&);
362 void initializeSanitizerCoverageModulePass(PassRegistry&);
362 void initializeSanitizerCoverageFunctionCheckLegacyPassPass(PassRegistry &);
363 void initializeSanitizerCoverageLegacyPassPass(PassRegistry &);
364 void initializeModuleSanitizerCoverageLegacyPassPass(PassRegistry &);
363365 void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
364366 void initializeScalarizeMaskedMemIntrinPass(PassRegistry&);
365367 void initializeScalarizerLegacyPassPass(PassRegistry&);
0 //===--------- Definition of the SanitizerCoverage class --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares the SanitizerCoverage class which is a port of the legacy
11 // SanitizerCoverage pass to use the new PassManager infrastructure.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H
16 #define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H
17
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/PassManager.h"
21 #include "llvm/Transforms/Instrumentation.h"
22
23 namespace llvm {
24
25 /// This is the SanitizerCoverage pass used in the new pass manager. The
26 /// pass instruments functions for coverage.
27 class SanitizerCoveragePass : public PassInfoMixin {
28 public:
29 explicit SanitizerCoveragePass(
30 SanitizerCoverageOptions Options = SanitizerCoverageOptions())
31 : Options(Options) {}
32 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
33
34 private:
35 SanitizerCoverageOptions Options;
36 };
37
38 /// This is the ModuleSanitizerCoverage pass used in the new pass manager. This
39 /// adds initialization calls to the module for trace PC guards and 8bit
40 /// counters if they are requested.
41 class ModuleSanitizerCoveragePass
42 : public PassInfoMixin {
43 public:
44 explicit ModuleSanitizerCoveragePass(
45 SanitizerCoverageOptions Options = SanitizerCoverageOptions())
46 : Options(Options) {}
47 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
48
49 private:
50 SanitizerCoverageOptions Options;
51 };
52
53 // Insert SanitizerCoverage instrumentation.
54 FunctionPass *createSanitizerCoverageLegacyPassPass(
55 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
56 ModulePass *createModuleSanitizerCoverageLegacyPassPass(
57 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
58
59 } // namespace llvm
60
61 #endif
180180 SanitizerCoverageOptions() = default;
181181 };
182182
183 // Insert SanitizerCoverage instrumentation.
184 ModulePass *createSanitizerCoverageModulePass(
185 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
186
187183 /// Calculate what to divide by to scale counts.
188184 ///
189185 /// Given the maximum count, calculate a divisor that will scale all the
100100 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
101101 #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
102102 #include "llvm/Transforms/Instrumentation/PoisonChecking.h"
103 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
103104 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
104105 #include "llvm/Transforms/Scalar/ADCE.h"
105106 #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
142143 #include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
143144 #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"
144145 #include "llvm/Transforms/Scalar/MemCpyOptimizer.h"
146 #include "llvm/Transforms/Scalar/MergeICmps.h"
145147 #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"
146 #include "llvm/Transforms/Scalar/MergeICmps.h"
147148 #include "llvm/Transforms/Scalar/NaryReassociate.h"
148149 #include "llvm/Transforms/Scalar/NewGVN.h"
149150 #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
8585 MODULE_PASS("verify", VerifierPass())
8686 MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false))
8787 MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false))
88 MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
8889 MODULE_PASS("poison-checking", PoisonCheckingPass())
8990 #undef MODULE_PASS
9091
244245 FUNCTION_PASS("msan", MemorySanitizerPass({}))
245246 FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
246247 FUNCTION_PASS("tsan", ThreadSanitizerPass())
248 FUNCTION_PASS("sancov-func", SanitizerCoveragePass())
247249 #undef FUNCTION_PASS
248250
249251 #ifndef FUNCTION_PASS_WITH_PARAMS
115115 initializeMemorySanitizerLegacyPassPass(Registry);
116116 initializeHWAddressSanitizerLegacyPassPass(Registry);
117117 initializeThreadSanitizerLegacyPassPass(Registry);
118 initializeSanitizerCoverageModulePass(Registry);
118 initializeSanitizerCoverageLegacyPassPass(Registry);
119119 initializeDataFlowSanitizerPass(Registry);
120120 }
121121
99 //
1010 //===----------------------------------------------------------------------===//
1111
12 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
1213 #include "llvm/ADT/ArrayRef.h"
1314 #include "llvm/ADT/SmallVector.h"
1415 #include "llvm/Analysis/EHPersonalities.h"
175176 return Options;
176177 }
177178
178 class SanitizerCoverageModule : public ModulePass {
179 bool canInstrumentWithSancov(const Function &F) {
180 if (F.empty())
181 return false;
182 if (F.getName().find(".module_ctor") != std::string::npos)
183 return false; // Should not instrument sanitizer init functions.
184 if (F.getName().startswith("__sanitizer_"))
185 return false; // Don't instrument __sanitizer_* callbacks.
186 // Don't touch available_externally functions, their actual body is elewhere.
187 if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
188 return false;
189 // Don't instrument MSVC CRT configuration helpers. They may run before normal
190 // initialization.
191 if (F.getName() == "__local_stdio_printf_options" ||
192 F.getName() == "__local_stdio_scanf_options")
193 return false;
194 if (isa(F.getEntryBlock().getTerminator()))
195 return false;
196 // Don't instrument functions using SEH for now. Splitting basic blocks like
197 // we do for coverage breaks WinEHPrepare.
198 // FIXME: Remove this when SEH no longer uses landingpad pattern matching.
199 if (F.hasPersonalityFn() &&
200 isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
201 return false;
202 return true;
203 }
204
205 std::string getSectionStartImpl(const Triple &TargetTriple,
206 const std::string &Section) {
207 if (TargetTriple.isOSBinFormatMachO())
208 return "\1section$start$__DATA$__" + Section;
209 return "__start___" + Section;
210 }
211
212 std::string getSectionEndImpl(const Triple &TargetTriple,
213 const std::string &Section) {
214 if (TargetTriple.isOSBinFormatMachO())
215 return "\1section$end$__DATA$__" + Section;
216 return "__stop___" + Section;
217 }
218
219 /// This is a class for instrumenting the module to add calls to initializing
220 /// the trace PC guards and 8bit counter globals. This should only be done
221 /// though if there is at least one function that can be instrumented with
222 /// Sancov.
223 class ModuleSanitizerCoverage {
179224 public:
180 SanitizerCoverageModule(
181 const SanitizerCoverageOptions &Options = SanitizerCoverageOptions())
182 : ModulePass(ID), Options(OverrideFromCL(Options)) {
183 initializeSanitizerCoverageModulePass(*PassRegistry::getPassRegistry());
184 }
185 bool runOnModule(Module &M) override;
186 bool runOnFunction(Function &F);
187 static char ID; // Pass identification, replacement for typeid
188 StringRef getPassName() const override { return "SanitizerCoverageModule"; }
189
190 void getAnalysisUsage(AnalysisUsage &AU) const override {
191 AU.addRequired();
192 AU.addRequired();
225 ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options)
226 : Options(OverrideFromCL(Options)) {}
227
228 bool instrumentModule(Module &M) {
229 if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
230 return false;
231
232 Function *Ctor = nullptr;
233 LLVMContext *C = &(M.getContext());
234 const DataLayout *DL = &M.getDataLayout();
235 TargetTriple = Triple(M.getTargetTriple());
236 IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
237 Type *IntptrPtrTy = PointerType::getUnqual(IntptrTy);
238 IRBuilder<> IRB(*C);
239 Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
240 Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
241 Int8Ty = IRB.getInt8Ty();
242
243 // Check that the __sancov_lowest_stack marker does not already exist.
244 Constant *SanCovLowestStackConstant =
245 M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
246 GlobalVariable *SanCovLowestStack =
247 dyn_cast(SanCovLowestStackConstant);
248 if (!SanCovLowestStack) {
249 C->emitError(StringRef("'") + SanCovLowestStackName +
250 "' should not be declared by the user");
251 return true;
252 }
253
254 // We want to emit guard init calls if the module contains a function that
255 // we can instrument with SanitizerCoverage. We ignore any functions that
256 // were inserted by SanitizerCoverage and get the result from the analysis
257 // that checks for a valid function that the analysis may have run over.
258 if (!llvm::any_of(
259 M, [](const Function &F) { return canInstrumentWithSancov(F); }))
260 return false;
261
262 // Emit the init calls.
263 if (Options.TracePCGuard)
264 Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,
265 SanCovTracePCGuardInitName, Int32PtrTy,
266 SanCovGuardsSectionName);
267 if (Options.Inline8bitCounters)
268 Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
269 SanCov8bitCountersInitName, Int8PtrTy,
270 SanCovCountersSectionName);
271 if (Ctor && Options.PCTable) {
272 auto SecStartEnd =
273 CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
274 FunctionCallee InitFunction = declareSanitizerInitFunction(
275 M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
276 IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
277 IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
278 }
279 return Ctor;
193280 }
194281
195282 private:
283 Function *CreateInitCallsForSections(Module &M, const char *CtorName,
284 const char *InitFunctionName, Type *Ty,
285 const char *Section);
286 std::pair CreateSecStartEnd(Module &M, const char *Section,
287 Type *Ty);
288 std::string getSectionStart(const std::string &Section) const {
289 return getSectionStartImpl(TargetTriple, Section);
290 }
291 std::string getSectionEnd(const std::string &Section) const {
292 return getSectionEndImpl(TargetTriple, Section);
293 }
294
295 SanitizerCoverageOptions Options;
296 Triple TargetTriple;
297 Type *IntptrTy, *Int8PtrTy, *Int8Ty;
298 };
299
300 class ModuleSanitizerCoverageLegacyPass : public ModulePass {
301 public:
302 static char ID;
303
304 ModuleSanitizerCoverageLegacyPass(
305 SanitizerCoverageOptions Options = SanitizerCoverageOptions())
306 : ModulePass(ID), Options(Options) {
307 initializeModuleSanitizerCoverageLegacyPassPass(
308 *PassRegistry::getPassRegistry());
309 }
310
311 bool runOnModule(Module &M) override {
312 ModuleSanitizerCoverage ModuleSancov(Options);
313 return ModuleSancov.instrumentModule(M);
314 };
315
316 StringRef getPassName() const override {
317 return "ModuleSanitizerCoverageLegacyPass";
318 }
319
320 private:
321 SanitizerCoverageOptions Options;
322 };
323
324 char ModuleSanitizerCoverageLegacyPass::ID = 0;
325
326 class SanitizerCoverage {
327 public:
328 SanitizerCoverage(Function &F, const SanitizerCoverageOptions &Options)
329 : CurModule(F.getParent()), Options(OverrideFromCL(Options)) {
330 initializeModule(*F.getParent());
331 }
332
333 ~SanitizerCoverage() { finalizeModule(*CurModule); }
334
335 bool instrumentFunction(Function &F, const DominatorTree *DT,
336 const PostDominatorTree *PDT);
337
338 private:
339 void initializeModule(Module &M);
340 void finalizeModule(Module &M);
196341 void InjectCoverageForIndirectCalls(Function &F,
197342 ArrayRef IndirCalls);
198343 void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets);
211356 void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks);
212357 void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx,
213358 bool IsLeafFunc = true);
214 Function *CreateInitCallsForSections(Module &M, const char *CtorName,
215 const char *InitFunctionName, Type *Ty,
216 const char *Section);
217 std::pair CreateSecStartEnd(Module &M, const char *Section,
218 Type *Ty);
219359
220360 void SetNoSanitizeMetadata(Instruction *I) {
221361 I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
251391 SanitizerCoverageOptions Options;
252392 };
253393
394 class SanitizerCoverageLegacyPass : public FunctionPass {
395 public:
396 static char ID; // Pass identification, replacement for typeid
397
398 SanitizerCoverageLegacyPass(
399 SanitizerCoverageOptions Options = SanitizerCoverageOptions())
400 : FunctionPass(ID), Options(Options) {
401 initializeSanitizerCoverageLegacyPassPass(*PassRegistry::getPassRegistry());
402 }
403
404 bool runOnFunction(Function &F) override {
405 const DominatorTree *DT =
406 &getAnalysis().getDomTree();
407 const PostDominatorTree *PDT =
408 &getAnalysis().getPostDomTree();
409 SanitizerCoverage Sancov(F, Options);
410 return Sancov.instrumentFunction(F, DT, PDT);
411 }
412
413 StringRef getPassName() const override {
414 return "SanitizerCoverageLegacyPass";
415 }
416
417 void getAnalysisUsage(AnalysisUsage &AU) const override {
418 // Make the module sancov pass required by this pass so that it runs when
419 // -sancov is passed.
420 AU.addRequired();
421 AU.addRequired();
422 AU.addRequired();
423 }
424
425 private:
426 SanitizerCoverageOptions Options;
427 };
428
254429 } // namespace
255430
431 PreservedAnalyses SanitizerCoveragePass::run(Function &F,
432 FunctionAnalysisManager &AM) {
433 const DominatorTree *DT = &AM.getResult(F);
434 const PostDominatorTree *PDT = &AM.getResult(F);
435 SanitizerCoverage Sancov(F, Options);
436 if (Sancov.instrumentFunction(F, DT, PDT))
437 return PreservedAnalyses::none();
438 return PreservedAnalyses::all();
439 }
440
441 PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &M,
442 ModuleAnalysisManager &AM) {
443 ModuleSanitizerCoverage ModuleSancov(Options);
444 if (ModuleSancov.instrumentModule(M))
445 return PreservedAnalyses::none();
446 return PreservedAnalyses::all();
447 }
448
256449 std::pair
257 SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
450 ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,
258451 Type *Ty) {
259452 GlobalVariable *SecStart =
260453 new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr,
264457 new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
265458 nullptr, getSectionEnd(Section));
266459 SecEnd->setVisibility(GlobalValue::HiddenVisibility);
460
267461 IRBuilder<> IRB(M.getContext());
268462 Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty);
269463 if (!TargetTriple.isOSBinFormatCOFF())
277471 return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr);
278472 }
279473
280 Function *SanitizerCoverageModule::CreateInitCallsForSections(
474 Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
281475 Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty,
282476 const char *Section) {
283477 auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
309503 return CtorFunc;
310504 }
311505
312 bool SanitizerCoverageModule::runOnModule(Module &M) {
506 void SanitizerCoverage::initializeModule(Module &M) {
313507 if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
314 return false;
508 return;
315509 C = &(M.getContext());
316510 DL = &M.getDataLayout();
317 CurModule = &M;
318511 CurModuleUniqueId = getUniqueModuleId(CurModule);
319512 TargetTriple = Triple(M.getTargetTriple());
320513 FunctionGuardArray = nullptr;
382575 Constant *SanCovLowestStackConstant =
383576 M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
384577 SanCovLowestStack = dyn_cast(SanCovLowestStackConstant);
385 if (!SanCovLowestStack) {
386 C->emitError(StringRef("'") + SanCovLowestStackName +
387 "' should not be declared by the user");
388 return true;
389 }
390578 SanCovLowestStack->setThreadLocalMode(
391579 GlobalValue::ThreadLocalMode::InitialExecTLSModel);
392580 if (Options.StackDepth && !SanCovLowestStack->isDeclaration())
400588 SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy);
401589 SanCovTracePCGuard =
402590 M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
403
404 for (auto &F : M)
405 runOnFunction(F);
406
407 Function *Ctor = nullptr;
408
409 if (FunctionGuardArray)
410 Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,
411 SanCovTracePCGuardInitName, Int32PtrTy,
412 SanCovGuardsSectionName);
413 if (Function8bitCounterArray)
414 Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
415 SanCov8bitCountersInitName, Int8PtrTy,
416 SanCovCountersSectionName);
417 if (Ctor && Options.PCTable) {
418 auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
419 FunctionCallee InitFunction = declareSanitizerInitFunction(
420 M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
421 IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
422 IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
423 }
591 }
592
593 void SanitizerCoverage::finalizeModule(Module &M) {
424594 // We don't reference these arrays directly in any of our runtime functions,
425595 // so we need to prevent them from being dead stripped.
426596 if (TargetTriple.isOSBinFormatMachO())
427597 appendToUsed(M, GlobalsToAppendToUsed);
428598 appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed);
429 return true;
430599 }
431600
432601 // True if block has successors and it dominates all of them.
517686 return true;
518687 }
519688
520 bool SanitizerCoverageModule::runOnFunction(Function &F) {
521 if (F.empty())
522 return false;
523 if (F.getName().find(".module_ctor") != std::string::npos)
524 return false; // Should not instrument sanitizer init functions.
525 if (F.getName().startswith("__sanitizer_"))
526 return false; // Don't instrument __sanitizer_* callbacks.
527 // Don't touch available_externally functions, their actual body is elewhere.
528 if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
529 return false;
530 // Don't instrument MSVC CRT configuration helpers. They may run before normal
531 // initialization.
532 if (F.getName() == "__local_stdio_printf_options" ||
533 F.getName() == "__local_stdio_scanf_options")
534 return false;
535 if (isa(F.getEntryBlock().getTerminator()))
536 return false;
537 // Don't instrument functions using SEH for now. Splitting basic blocks like
538 // we do for coverage breaks WinEHPrepare.
539 // FIXME: Remove this when SEH no longer uses landingpad pattern matching.
540 if (F.hasPersonalityFn() &&
541 isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
689 bool SanitizerCoverage::instrumentFunction(Function &F, const DominatorTree *DT,
690 const PostDominatorTree *PDT) {
691 if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
692 return false;
693 if (!canInstrumentWithSancov(F))
542694 return false;
543695 if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
544696 SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
549701 SmallVector DivTraceTargets;
550702 SmallVector GepTraceTargets;
551703
552 const DominatorTree *DT =
553 &getAnalysis(F).getDomTree();
554 const PostDominatorTree *PDT =
555 &getAnalysis(F).getPostDomTree();
556704 bool IsLeafFunc = true;
557705
558706 for (auto &BB : F) {
595743 return true;
596744 }
597745
598 GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection(
746 GlobalVariable *SanitizerCoverage::CreateFunctionLocalArrayInSection(
599747 size_t NumElements, Function &F, Type *Ty, const char *Section) {
600748 ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
601749 auto Array = new GlobalVariable(
618766 }
619767
620768 GlobalVariable *
621 SanitizerCoverageModule::CreatePCArray(Function &F,
622 ArrayRef AllBlocks) {
769 SanitizerCoverage::CreatePCArray(Function &F,
770 ArrayRef AllBlocks) {
623771 size_t N = AllBlocks.size();
624772 assert(N);
625773 SmallVector PCs;
645793 return PCArray;
646794 }
647795
648 void SanitizerCoverageModule::CreateFunctionLocalArrays(
796 void SanitizerCoverage::CreateFunctionLocalArrays(
649797 Function &F, ArrayRef AllBlocks) {
650798 if (Options.TracePCGuard)
651799 FunctionGuardArray = CreateFunctionLocalArrayInSection(
659807 FunctionPCsArray = CreatePCArray(F, AllBlocks);
660808 }
661809
662 bool SanitizerCoverageModule::InjectCoverage(Function &F,
663 ArrayRef AllBlocks,
664 bool IsLeafFunc) {
810 bool SanitizerCoverage::InjectCoverage(Function &F,
811 ArrayRef AllBlocks,
812 bool IsLeafFunc) {
665813 if (AllBlocks.empty()) return false;
666814 CreateFunctionLocalArrays(F, AllBlocks);
667815 for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
676824 // The cache is used to speed up recording the caller-callee pairs.
677825 // The address of the caller is passed implicitly via caller PC.
678826 // CacheSize is encoded in the name of the run-time function.
679 void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
827 void SanitizerCoverage::InjectCoverageForIndirectCalls(
680828 Function &F, ArrayRef IndirCalls) {
681829 if (IndirCalls.empty())
682830 return;
695843 // __sanitizer_cov_trace_switch(CondValue,
696844 // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
697845
698 void SanitizerCoverageModule::InjectTraceForSwitch(
846 void SanitizerCoverage::InjectTraceForSwitch(
699847 Function &, ArrayRef SwitchTraceTargets) {
700848 for (auto I : SwitchTraceTargets) {
701849 if (SwitchInst *SI = dyn_cast(I)) {
734882 }
735883 }
736884
737 void SanitizerCoverageModule::InjectTraceForDiv(
885 void SanitizerCoverage::InjectTraceForDiv(
738886 Function &, ArrayRef DivTraceTargets) {
739887 for (auto BO : DivTraceTargets) {
740888 IRBuilder<> IRB(BO);
752900 }
753901 }
754902
755 void SanitizerCoverageModule::InjectTraceForGep(
903 void SanitizerCoverage::InjectTraceForGep(
756904 Function &, ArrayRef GepTraceTargets) {
757905 for (auto GEP : GepTraceTargets) {
758906 IRBuilder<> IRB(GEP);
763911 }
764912 }
765913
766 void SanitizerCoverageModule::InjectTraceForCmp(
914 void SanitizerCoverage::InjectTraceForCmp(
767915 Function &, ArrayRef CmpTraceTargets) {
768916 for (auto I : CmpTraceTargets) {
769917 if (ICmpInst *ICMP = dyn_cast(I)) {
798946 }
799947 }
800948
801 void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
802 size_t Idx,
803 bool IsLeafFunc) {
949 void SanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
950 size_t Idx, bool IsLeafFunc) {
804951 BasicBlock::iterator IP = BB.getFirstInsertionPt();
805952 bool IsEntryBB = &BB == &F.getEntryBlock();
806953 DebugLoc EntryLoc;
8571004 }
8581005
8591006 std::string
860 SanitizerCoverageModule::getSectionName(const std::string &Section) const {
1007 SanitizerCoverage::getSectionName(const std::string &Section) const {
8611008 if (TargetTriple.isOSBinFormatCOFF()) {
8621009 if (Section == SanCovCountersSectionName)
8631010 return ".SCOV$CM";
8711018 }
8721019
8731020 std::string
874 SanitizerCoverageModule::getSectionStart(const std::string &Section) const {
875 if (TargetTriple.isOSBinFormatMachO())
876 return "\1section$start$__DATA$__" + Section;
877 return "__start___" + Section;
878 }
879
880 std::string
881 SanitizerCoverageModule::getSectionEnd(const std::string &Section) const {
882 if (TargetTriple.isOSBinFormatMachO())
883 return "\1section$end$__DATA$__" + Section;
884 return "__stop___" + Section;
885 }
886
887
888 char SanitizerCoverageModule::ID = 0;
889 INITIALIZE_PASS_BEGIN(SanitizerCoverageModule, "sancov",
890 "SanitizerCoverage: TODO."
891 "ModulePass",
892 false, false)
1021 SanitizerCoverage::getSectionStart(const std::string &Section) const {
1022 return getSectionStartImpl(TargetTriple, Section);
1023 }
1024
1025 std::string SanitizerCoverage::getSectionEnd(const std::string &Section) const {
1026 return getSectionEndImpl(TargetTriple, Section);
1027 }
1028
1029 INITIALIZE_PASS(ModuleSanitizerCoverageLegacyPass, "module-sancov",
1030 "Pass for inserting sancov top-level initialization calls",
1031 false, false)
1032
1033 char SanitizerCoverageLegacyPass::ID = 0;
1034 INITIALIZE_PASS_BEGIN(SanitizerCoverageLegacyPass, "sancov",
1035 "Pass for instrumenting coverage on functions", false,
1036 false)
1037 INITIALIZE_PASS_DEPENDENCY(ModuleSanitizerCoverageLegacyPass)
8931038 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
8941039 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
895 INITIALIZE_PASS_END(SanitizerCoverageModule, "sancov",
896 "SanitizerCoverage: TODO."
897 "ModulePass",
898 false, false)
899 ModulePass *llvm::createSanitizerCoverageModulePass(
1040 INITIALIZE_PASS_END(SanitizerCoverageLegacyPass, "sancov",
1041 "Pass for instrumenting coverage on functions", false,
1042 false)
1043 FunctionPass *llvm::createSanitizerCoverageLegacyPassPass(
9001044 const SanitizerCoverageOptions &Options) {
901 return new SanitizerCoverageModule(Options);
902 }
1045 return new SanitizerCoverageLegacyPass(Options);
1046 }
1047 ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
1048 const SanitizerCoverageOptions &Options) {
1049 return new ModuleSanitizerCoverageLegacyPass(Options);
1050 }
0 ; Checks that a function with no-return in the entry block is not instrumented.
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
23 ; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard
34
45 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
0 ; Test -sanitizer-coverage-trace-compares=1 and how it prunes backedge compares.
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE
4 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE
35
46 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
57 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
12
23 define i32 @blah(i32) #0 {
34 %2 = icmp sgt i32 %0, 1
0 ; Test -sanitizer-coverage-trace-compares=1 API declarations on a non-x86_64 arch
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
23
34 target triple = "i386-unknown-linux-gnu"
45 define i32 @foo() #0 {
67 ret i32 0
78 }
89
9 ; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64)
10 ; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8, i8)
11 ; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16, i16)
12 ; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32, i32)
13 ; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
14 ; CHECK: declare void @__sanitizer_cov_trace_div4(i32)
15 ; CHECK: declare void @__sanitizer_cov_trace_div8(i64)
16 ; CHECK: declare void @__sanitizer_cov_trace_gep(i64)
17 ; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*)
18 ; CHECK: declare void @__sanitizer_cov_trace_pc()
19 ; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*)
20 ; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
10 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64)
11 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8, i8)
12 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16, i16)
13 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32, i32)
14 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
15 ; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32)
16 ; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64)
17 ; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64)
18 ; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*)
19 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc()
20 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*)
21 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
2122 ; CHECK-NOT: declare
0 ; Test -sanitizer-coverage-trace-compares=1 API declarations on x86_64
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
23
34 target triple = "x86_64-unknown-linux-gnu"
45 define i32 @foo() #0 {
67 ret i32 0
78 }
89
9 ; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64)
10 ; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext)
11 ; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext)
12 ; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext)
13 ; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
14 ; CHECK: declare void @__sanitizer_cov_trace_div4(i32 zeroext)
15 ; CHECK: declare void @__sanitizer_cov_trace_div8(i64)
16 ; CHECK: declare void @__sanitizer_cov_trace_gep(i64)
17 ; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*)
18 ; CHECK: declare void @__sanitizer_cov_trace_pc()
19 ; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*)
20 ; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
10 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64)
11 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext)
12 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext)
13 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext)
14 ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
15 ; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext)
16 ; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64)
17 ; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64)
18 ; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*)
19 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc()
20 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*)
21 ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
2122 ; CHECK-NOT: declare
0 ; Test -sanitizer-coverage-trace-compares=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
23
34 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
12
23 ; Make sure we use the right comdat groups for COFF to avoid relocations
34 ; against discarded sections. Internal linkage functions are also different from
0 ; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries.
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
23 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
34 target triple = "x86_64-pc-windows-msvc19.14.26433"
45
0 ; Checks that sancov.module_ctor is marked used.
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
23 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
34 target triple = "x86_64-pc-windows-msvc19.14.26433"
45
78 ret void
89 }
910
10 ; CHECK: @llvm.used = appending global {{.*}} @sancov.module_ctor
11 ; CHECK: @llvm.used = appending global {{.*}} @sancov.module_ctor
0 ; Test -sanitizer-coverage-trace-compares=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
23
34 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; Test that coverage instrumentation does not lose debug location.
11
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s
34
45 ; C++ source:
56 ; 1: struct A {
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC
1 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE
12
2 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC
4 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE
35
46 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
57 target triple = "x86_64-unknown-linux-gnu"
0 ; Test that coverage instrumentation does not lose debug location.
11
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s
34
45 ; C++ source:
56 ; 1: void foo(int *a) {
0 ; Test -sanitizer-coverage-trace-divs=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s
23
34 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; Test -sanitizer-coverage-trace-geps=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s
23
34 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; Test -sanitizer-coverage-inline-8bit-counters=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s
23
34 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; Test that interposable symbols do not get put in comdats.
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s
4 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s
35
46 define void @Vanilla() {
57 entry:
0 ; Tests that we don't insert __sanitizer_cov_trace_pc_guard_init or some such
11 ; when there is no instrumentation.
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
34 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
45 target triple = "x86_64-unknown-linux-gnu"
56
0 ; Test -sanitizer-coverage-pc-table=1
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s
4 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s
35
46 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
57 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=CHECK_NO_PRUNE
24
35 define i32 @foo(i32) #0 {
46 %2 = icmp sgt i32 %0, 0
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=0 -S | FileCheck %s
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s
3 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=0 -S | FileCheck %s
4 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s
5 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s
36
47 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
58 target triple = "i686-pc-windows-msvc18.0.0"
0 ; Ensure that we terminate with a useful error message (instead of crash) if the
11 ; user declares `__sancov_lowest_stack` with an unexpected type.
22 ; RUN: not opt < %s -sancov -sanitizer-coverage-level=1 \
3 ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s
4 ; RUN: not opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \
35 ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s
46
57 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 \
22 ; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s
33 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \
4 ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
5 ; RUN: -S | FileCheck %s
6 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \
7 ; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s
8 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 \
49 ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
510 ; RUN: -S | FileCheck %s
611
0 ; Test -sanitizer-coverage-trace-compares=1 (instrumenting a switch)
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
2 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
23
34 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
45 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
12
23 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
34 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s
12
23 ; Module ctors should have stable names across modules, not something like
34 ; @sancov.module_ctor.3 that may cause duplicate ctors after linked together.
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
12
23 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
34 target triple = "x86_64-apple-darwin10.0.0"
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
22 ; Make sure asan does not instrument __sancov_gen_
33 ; RUN: opt < %s -sancov -asan -asan-module -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
4
5 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
6 ; RUN: opt < %s -passes='module(require,sancov-module,asan-module),function(sancov-func,asan)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
47 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
58 target triple = "x86_64-unknown-linux-gnu"
69 $Foo = comdat any
11 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC
22 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD
33 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN
4
5 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_PC
6 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD
7 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S -mtriple=x86_64-apple-macosx | FileCheck %s --check-prefix=CHECK_PC_GUARD_DARWIN
48
59 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
610 target triple = "x86_64-unknown-linux-gnu"
0 ; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s
1 ; RUN: opt < %s -S -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 | FileCheck %s
12
23 ; The critical edges to unreachable_bb should not be split.
34 define i32 @foo(i32 %c, i32 %d) {
0 ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK
1 ; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK
12
23 ; Generated from this C++ source:
34 ; $ clang -O2 t.cpp -S -emit-llvm