Reland the "[NewPM] Port Sancov" patch from rL365838. No functional

changes were made to the patch since then.

--------

[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.

llvm-svn: 367053
This commit is contained in:
Leonard Chan 2019-07-25 20:53:15 +00:00
parent 9294c87282
commit 007f674c6a
40 changed files with 484 additions and 151 deletions

View File

@ -60,6 +60,7 @@
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar.h"
@ -195,11 +196,8 @@ static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
PM.add(createBoundsCheckingLegacyPass()); PM.add(createBoundsCheckingLegacyPass());
} }
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, static SanitizerCoverageOptions
legacy::PassManagerBase &PM) { getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
SanitizerCoverageOptions Opts; SanitizerCoverageOptions Opts;
Opts.CoverageType = Opts.CoverageType =
static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType); static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType);
@ -215,7 +213,17 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
Opts.PCTable = CGOpts.SanitizeCoveragePCTable; Opts.PCTable = CGOpts.SanitizeCoveragePCTable;
Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth;
PM.add(createSanitizerCoverageModulePass(Opts)); return Opts;
}
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper &>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
auto Opts = getSancovOptsFromCGOpts(CGOpts);
PM.add(createModuleSanitizerCoverageLegacyPassPass(Opts));
PM.add(createSanitizerCoverageLegacyPassPass(Opts));
} }
// Check if ASan should use GC-friendly instrumentation for globals. // Check if ASan should use GC-friendly instrumentation for globals.
@ -1128,6 +1136,21 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
EntryExitInstrumenterPass(/*PostInlining=*/false))); EntryExitInstrumenterPass(/*PostInlining=*/false)));
}); });
if (CodeGenOpts.SanitizeCoverageType ||
CodeGenOpts.SanitizeCoverageIndirectCalls ||
CodeGenOpts.SanitizeCoverageTraceCmp) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
PB.registerPipelineStartEPCallback(
[SancovOpts](ModulePassManager &MPM) {
MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts));
});
PB.registerOptimizerLastEPCallback(
[SancovOpts](FunctionPassManager &FPM,
PassBuilder::OptimizationLevel Level) {
FPM.addPass(SanitizerCoveragePass(SancovOpts));
});
}
// Register callbacks to schedule sanitizer passes at the appropriate part of // Register callbacks to schedule sanitizer passes at the appropriate part of
// the pipeline. // the pipeline.
// FIXME: either handle asan/the remaining sanitizers or error out // FIXME: either handle asan/the remaining sanitizers or error out
@ -1205,9 +1228,19 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
/*CompileKernel=*/true, /*Recover=*/true)); /*CompileKernel=*/true, /*Recover=*/true));
} }
if (CodeGenOpts.OptimizationLevel == 0) if (CodeGenOpts.OptimizationLevel == 0) {
if (CodeGenOpts.SanitizeCoverageType ||
CodeGenOpts.SanitizeCoverageIndirectCalls ||
CodeGenOpts.SanitizeCoverageTraceCmp) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts));
MPM.addPass(createModuleToFunctionPassAdaptor(
SanitizerCoveragePass(SancovOpts)));
}
addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts); addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts);
} }
}
// FIXME: We still use the legacy pass manager to do code generation. We // FIXME: We still use the legacy pass manager to do code generation. We
// create that pass manager here and use it as needed below. // create that pass manager here and use it as needed below.

View File

@ -0,0 +1,41 @@
// Test that SanitizerCoverage works under the new pass manager.
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto=thin -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0
// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto=thin -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2,CHECK-O2-THINLTO
extern void *memcpy(void *, const void *, unsigned long);
extern int printf(const char *restrict, ...);
int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) {
unsigned char buf[4];
if (size < 8)
return 0;
if (data[0] == 'h' && data[1] == 'i' && data[2] == '!') {
memcpy(buf, data, size);
printf("test: %.2X\n", buf[0]);
}
return 0;
}
// CHECK-DAG: declare void @__sanitizer_cov_pcs_init(i64*, i64*)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
// CHECK-O2-THINLTO-NOT: declare void @__sanitizer_cov_trace_const_cmp1(i8 zeroext, i8 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_const_cmp2(i16 zeroext, i16 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_const_cmp4(i32 zeroext, i32 zeroext)
// CHECK-O2-THINLTO-NOT: declare void @__sanitizer_cov_trace_const_cmp8(i64, i64)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_div8(i64)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_gep(i64)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*)
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc()
// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*)

View File

@ -360,7 +360,9 @@ void initializeSROALegacyPassPass(PassRegistry&);
void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSafeStackLegacyPassPass(PassRegistry&);
void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSafepointIRVerifierPass(PassRegistry&);
void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&);
void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeSanitizerCoverageFunctionCheckLegacyPassPass(PassRegistry &);
void initializeSanitizerCoverageLegacyPassPass(PassRegistry &);
void initializeModuleSanitizerCoverageLegacyPassPass(PassRegistry &);
void initializeScalarEvolutionWrapperPassPass(PassRegistry&); void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
void initializeScalarizeMaskedMemIntrinPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinPass(PassRegistry&);
void initializeScalarizerLegacyPassPass(PassRegistry&); void initializeScalarizerLegacyPassPass(PassRegistry&);

View File

@ -181,10 +181,6 @@ struct SanitizerCoverageOptions {
SanitizerCoverageOptions() = default; SanitizerCoverageOptions() = default;
}; };
// Insert SanitizerCoverage instrumentation.
ModulePass *createSanitizerCoverageModulePass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
/// Calculate what to divide by to scale counts. /// Calculate what to divide by to scale counts.
/// ///
/// Given the maximum count, calculate a divisor that will scale all the /// Given the maximum count, calculate a divisor that will scale all the

View File

@ -0,0 +1,62 @@
//===--------- Definition of the SanitizerCoverage class --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the SanitizerCoverage class which is a port of the legacy
// SanitizerCoverage pass to use the new PassManager infrastructure.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H
#define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERCOVERAGE_H
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Instrumentation.h"
namespace llvm {
/// This is the SanitizerCoverage pass used in the new pass manager. The
/// pass instruments functions for coverage.
class SanitizerCoveragePass : public PassInfoMixin<SanitizerCoveragePass> {
public:
explicit SanitizerCoveragePass(
SanitizerCoverageOptions Options = SanitizerCoverageOptions())
: Options(Options) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
private:
SanitizerCoverageOptions Options;
};
/// This is the ModuleSanitizerCoverage pass used in the new pass manager. This
/// adds initialization calls to the module for trace PC guards and 8bit
/// counters if they are requested.
class ModuleSanitizerCoveragePass
: public PassInfoMixin<ModuleSanitizerCoveragePass> {
public:
explicit ModuleSanitizerCoveragePass(
SanitizerCoverageOptions Options = SanitizerCoverageOptions())
: Options(Options) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
private:
SanitizerCoverageOptions Options;
};
// Insert SanitizerCoverage instrumentation.
FunctionPass *createSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
ModulePass *createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions());
} // namespace llvm
#endif

View File

@ -101,6 +101,7 @@
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Instrumentation/PoisonChecking.h" #include "llvm/Transforms/Instrumentation/PoisonChecking.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/ADCE.h"
#include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
@ -143,8 +144,8 @@
#include "llvm/Transforms/Scalar/LowerWidenableCondition.h" #include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"
#include "llvm/Transforms/Scalar/MemCpyOptimizer.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h"
#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"
#include "llvm/Transforms/Scalar/MergeICmps.h" #include "llvm/Transforms/Scalar/MergeICmps.h"
#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"
#include "llvm/Transforms/Scalar/NaryReassociate.h" #include "llvm/Transforms/Scalar/NaryReassociate.h"
#include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/NewGVN.h"
#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"

View File

@ -88,6 +88,7 @@ MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass(nullptr, nullptr))
MODULE_PASS("verify", VerifierPass()) MODULE_PASS("verify", VerifierPass())
MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false)) MODULE_PASS("asan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/false, false, true, false))
MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false)) MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false))
MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
MODULE_PASS("poison-checking", PoisonCheckingPass()) MODULE_PASS("poison-checking", PoisonCheckingPass())
#undef MODULE_PASS #undef MODULE_PASS
@ -245,6 +246,7 @@ FUNCTION_PASS("kasan", AddressSanitizerPass(true, false, false))
FUNCTION_PASS("msan", MemorySanitizerPass({})) FUNCTION_PASS("msan", MemorySanitizerPass({}))
FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true})) FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true}))
FUNCTION_PASS("tsan", ThreadSanitizerPass()) FUNCTION_PASS("tsan", ThreadSanitizerPass())
FUNCTION_PASS("sancov-func", SanitizerCoveragePass())
#undef FUNCTION_PASS #undef FUNCTION_PASS
#ifndef FUNCTION_PASS_WITH_PARAMS #ifndef FUNCTION_PASS_WITH_PARAMS

View File

@ -116,7 +116,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) {
initializeMemorySanitizerLegacyPassPass(Registry); initializeMemorySanitizerLegacyPassPass(Registry);
initializeHWAddressSanitizerLegacyPassPass(Registry); initializeHWAddressSanitizerLegacyPassPass(Registry);
initializeThreadSanitizerLegacyPassPass(Registry); initializeThreadSanitizerLegacyPassPass(Registry);
initializeSanitizerCoverageModulePass(Registry); initializeSanitizerCoverageLegacyPassPass(Registry);
initializeDataFlowSanitizerPass(Registry); initializeDataFlowSanitizerPass(Registry);
} }

View File

@ -10,6 +10,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/EHPersonalities.h"
@ -176,24 +177,168 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
return Options; return Options;
} }
class SanitizerCoverageModule : public ModulePass { bool canInstrumentWithSancov(const Function &F) {
public: if (F.empty())
SanitizerCoverageModule( return false;
const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) if (F.getName().find(".module_ctor") != std::string::npos)
: ModulePass(ID), Options(OverrideFromCL(Options)) { return false; // Should not instrument sanitizer init functions.
initializeSanitizerCoverageModulePass(*PassRegistry::getPassRegistry()); if (F.getName().startswith("__sanitizer_"))
return false; // Don't instrument __sanitizer_* callbacks.
// Don't touch available_externally functions, their actual body is elewhere.
if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
return false;
// Don't instrument MSVC CRT configuration helpers. They may run before normal
// initialization.
if (F.getName() == "__local_stdio_printf_options" ||
F.getName() == "__local_stdio_scanf_options")
return false;
if (isa<UnreachableInst>(F.getEntryBlock().getTerminator()))
return false;
// Don't instrument functions using SEH for now. Splitting basic blocks like
// we do for coverage breaks WinEHPrepare.
// FIXME: Remove this when SEH no longer uses landingpad pattern matching.
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return false;
return true;
} }
bool runOnModule(Module &M) override;
bool runOnFunction(Function &F);
static char ID; // Pass identification, replacement for typeid
StringRef getPassName() const override { return "SanitizerCoverageModule"; }
void getAnalysisUsage(AnalysisUsage &AU) const override { std::string getSectionStartImpl(const Triple &TargetTriple,
AU.addRequired<DominatorTreeWrapperPass>(); const std::string &Section) {
AU.addRequired<PostDominatorTreeWrapperPass>(); if (TargetTriple.isOSBinFormatMachO())
return "\1section$start$__DATA$__" + Section;
return "__start___" + Section;
}
std::string getSectionEndImpl(const Triple &TargetTriple,
const std::string &Section) {
if (TargetTriple.isOSBinFormatMachO())
return "\1section$end$__DATA$__" + Section;
return "__stop___" + Section;
}
/// This is a class for instrumenting the module to add calls to initializing
/// the trace PC guards and 8bit counter globals. This should only be done
/// though if there is at least one function that can be instrumented with
/// Sancov.
class ModuleSanitizerCoverage {
public:
ModuleSanitizerCoverage(const SanitizerCoverageOptions &Options)
: Options(OverrideFromCL(Options)) {}
bool instrumentModule(Module &M) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
return false;
Function *Ctor = nullptr;
LLVMContext *C = &(M.getContext());
const DataLayout *DL = &M.getDataLayout();
TargetTriple = Triple(M.getTargetTriple());
IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
Type *IntptrPtrTy = PointerType::getUnqual(IntptrTy);
IRBuilder<> IRB(*C);
Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
Int8Ty = IRB.getInt8Ty();
// Check that the __sancov_lowest_stack marker does not already exist.
Constant *SanCovLowestStackConstant =
M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
GlobalVariable *SanCovLowestStack =
dyn_cast<GlobalVariable>(SanCovLowestStackConstant);
if (!SanCovLowestStack) {
C->emitError(StringRef("'") + SanCovLowestStackName +
"' should not be declared by the user");
return true;
}
// We want to emit guard init calls if the module contains a function that
// we can instrument with SanitizerCoverage. We ignore any functions that
// were inserted by SanitizerCoverage and get the result from the analysis
// that checks for a valid function that the analysis may have run over.
if (!llvm::any_of(
M, [](const Function &F) { return canInstrumentWithSancov(F); }))
return false;
// Emit the init calls.
if (Options.TracePCGuard)
Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,
SanCovTracePCGuardInitName, Int32PtrTy,
SanCovGuardsSectionName);
if (Options.Inline8bitCounters)
Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
SanCov8bitCountersInitName, Int8PtrTy,
SanCovCountersSectionName);
if (Ctor && Options.PCTable) {
auto SecStartEnd =
CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
FunctionCallee InitFunction = declareSanitizerInitFunction(
M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
}
return Ctor;
} }
private: private:
Function *CreateInitCallsForSections(Module &M, const char *CtorName,
const char *InitFunctionName, Type *Ty,
const char *Section);
std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section,
Type *Ty);
std::string getSectionStart(const std::string &Section) const {
return getSectionStartImpl(TargetTriple, Section);
}
std::string getSectionEnd(const std::string &Section) const {
return getSectionEndImpl(TargetTriple, Section);
}
SanitizerCoverageOptions Options;
Triple TargetTriple;
Type *IntptrTy, *Int8PtrTy, *Int8Ty;
};
class ModuleSanitizerCoverageLegacyPass : public ModulePass {
public:
static char ID;
ModuleSanitizerCoverageLegacyPass(
SanitizerCoverageOptions Options = SanitizerCoverageOptions())
: ModulePass(ID), Options(Options) {
initializeModuleSanitizerCoverageLegacyPassPass(
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
ModuleSanitizerCoverage ModuleSancov(Options);
return ModuleSancov.instrumentModule(M);
};
StringRef getPassName() const override {
return "ModuleSanitizerCoverageLegacyPass";
}
private:
SanitizerCoverageOptions Options;
};
char ModuleSanitizerCoverageLegacyPass::ID = 0;
class SanitizerCoverage {
public:
SanitizerCoverage(Function &F, const SanitizerCoverageOptions &Options)
: CurModule(F.getParent()), Options(OverrideFromCL(Options)) {
initializeModule(*F.getParent());
}
~SanitizerCoverage() { finalizeModule(*CurModule); }
bool instrumentFunction(Function &F, const DominatorTree *DT,
const PostDominatorTree *PDT);
private:
void initializeModule(Module &M);
void finalizeModule(Module &M);
void InjectCoverageForIndirectCalls(Function &F, void InjectCoverageForIndirectCalls(Function &F,
ArrayRef<Instruction *> IndirCalls); ArrayRef<Instruction *> IndirCalls);
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets); void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
@ -212,11 +357,6 @@ private:
void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks); void CreateFunctionLocalArrays(Function &F, ArrayRef<BasicBlock *> AllBlocks);
void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx,
bool IsLeafFunc = true); bool IsLeafFunc = true);
Function *CreateInitCallsForSections(Module &M, const char *CtorName,
const char *InitFunctionName, Type *Ty,
const char *Section);
std::pair<Value *, Value *> CreateSecStartEnd(Module &M, const char *Section,
Type *Ty);
void SetNoSanitizeMetadata(Instruction *I) { void SetNoSanitizeMetadata(Instruction *I) {
I->setMetadata(I->getModule()->getMDKindID("nosanitize"), I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@ -252,10 +392,63 @@ private:
SanitizerCoverageOptions Options; SanitizerCoverageOptions Options;
}; };
class SanitizerCoverageLegacyPass : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
SanitizerCoverageLegacyPass(
SanitizerCoverageOptions Options = SanitizerCoverageOptions())
: FunctionPass(ID), Options(Options) {
initializeSanitizerCoverageLegacyPassPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
const DominatorTree *DT =
&getAnalysis<DominatorTreeWrapperPass>().getDomTree();
const PostDominatorTree *PDT =
&getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
SanitizerCoverage Sancov(F, Options);
return Sancov.instrumentFunction(F, DT, PDT);
}
StringRef getPassName() const override {
return "SanitizerCoverageLegacyPass";
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
// Make the module sancov pass required by this pass so that it runs when
// -sancov is passed.
AU.addRequired<ModuleSanitizerCoverageLegacyPass>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<PostDominatorTreeWrapperPass>();
}
private:
SanitizerCoverageOptions Options;
};
} // namespace } // namespace
PreservedAnalyses SanitizerCoveragePass::run(Function &F,
FunctionAnalysisManager &AM) {
const DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F);
const PostDominatorTree *PDT = &AM.getResult<PostDominatorTreeAnalysis>(F);
SanitizerCoverage Sancov(F, Options);
if (Sancov.instrumentFunction(F, DT, PDT))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
PreservedAnalyses ModuleSanitizerCoveragePass::run(Module &M,
ModuleAnalysisManager &AM) {
ModuleSanitizerCoverage ModuleSancov(Options);
if (ModuleSancov.instrumentModule(M))
return PreservedAnalyses::none();
return PreservedAnalyses::all();
}
std::pair<Value *, Value *> std::pair<Value *, Value *>
SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section, ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,
Type *Ty) { Type *Ty) {
GlobalVariable *SecStart = GlobalVariable *SecStart =
new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr,
@ -265,6 +458,7 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
nullptr, getSectionEnd(Section)); nullptr, getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility); SecEnd->setVisibility(GlobalValue::HiddenVisibility);
IRBuilder<> IRB(M.getContext()); IRBuilder<> IRB(M.getContext());
Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty); Value *SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty);
if (!TargetTriple.isOSBinFormatCOFF()) if (!TargetTriple.isOSBinFormatCOFF())
@ -278,7 +472,7 @@ SanitizerCoverageModule::CreateSecStartEnd(Module &M, const char *Section,
return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr); return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr);
} }
Function *SanitizerCoverageModule::CreateInitCallsForSections( Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty,
const char *Section) { const char *Section) {
auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); auto SecStartEnd = CreateSecStartEnd(M, Section, Ty);
@ -310,12 +504,11 @@ Function *SanitizerCoverageModule::CreateInitCallsForSections(
return CtorFunc; return CtorFunc;
} }
bool SanitizerCoverageModule::runOnModule(Module &M) { void SanitizerCoverage::initializeModule(Module &M) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
return false; return;
C = &(M.getContext()); C = &(M.getContext());
DL = &M.getDataLayout(); DL = &M.getDataLayout();
CurModule = &M;
CurModuleUniqueId = getUniqueModuleId(CurModule); CurModuleUniqueId = getUniqueModuleId(CurModule);
TargetTriple = Triple(M.getTargetTriple()); TargetTriple = Triple(M.getTargetTriple());
FunctionGuardArray = nullptr; FunctionGuardArray = nullptr;
@ -383,11 +576,6 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
Constant *SanCovLowestStackConstant = Constant *SanCovLowestStackConstant =
M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy);
SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant); SanCovLowestStack = dyn_cast<GlobalVariable>(SanCovLowestStackConstant);
if (!SanCovLowestStack) {
C->emitError(StringRef("'") + SanCovLowestStackName +
"' should not be declared by the user");
return true;
}
SanCovLowestStack->setThreadLocalMode( SanCovLowestStack->setThreadLocalMode(
GlobalValue::ThreadLocalMode::InitialExecTLSModel); GlobalValue::ThreadLocalMode::InitialExecTLSModel);
if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) if (Options.StackDepth && !SanCovLowestStack->isDeclaration())
@ -401,33 +589,14 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy);
SanCovTracePCGuard = SanCovTracePCGuard =
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
for (auto &F : M)
runOnFunction(F);
Function *Ctor = nullptr;
if (FunctionGuardArray)
Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName,
SanCovTracePCGuardInitName, Int32PtrTy,
SanCovGuardsSectionName);
if (Function8bitCounterArray)
Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName,
SanCov8bitCountersInitName, Int8PtrTy,
SanCovCountersSectionName);
if (Ctor && Options.PCTable) {
auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy);
FunctionCallee InitFunction = declareSanitizerInitFunction(
M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy});
IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second});
} }
void SanitizerCoverage::finalizeModule(Module &M) {
// We don't reference these arrays directly in any of our runtime functions, // We don't reference these arrays directly in any of our runtime functions,
// so we need to prevent them from being dead stripped. // so we need to prevent them from being dead stripped.
if (TargetTriple.isOSBinFormatMachO()) if (TargetTriple.isOSBinFormatMachO())
appendToUsed(M, GlobalsToAppendToUsed); appendToUsed(M, GlobalsToAppendToUsed);
appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed);
return true;
} }
// True if block has successors and it dominates all of them. // True if block has successors and it dominates all of them.
@ -518,28 +687,11 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
return true; return true;
} }
bool SanitizerCoverageModule::runOnFunction(Function &F) { bool SanitizerCoverage::instrumentFunction(Function &F, const DominatorTree *DT,
if (F.empty()) const PostDominatorTree *PDT) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
return false; return false;
if (F.getName().find(".module_ctor") != std::string::npos) if (!canInstrumentWithSancov(F))
return false; // Should not instrument sanitizer init functions.
if (F.getName().startswith("__sanitizer_"))
return false; // Don't instrument __sanitizer_* callbacks.
// Don't touch available_externally functions, their actual body is elewhere.
if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
return false;
// Don't instrument MSVC CRT configuration helpers. They may run before normal
// initialization.
if (F.getName() == "__local_stdio_printf_options" ||
F.getName() == "__local_stdio_scanf_options")
return false;
if (isa<UnreachableInst>(F.getEntryBlock().getTerminator()))
return false;
// Don't instrument functions using SEH for now. Splitting basic blocks like
// we do for coverage breaks WinEHPrepare.
// FIXME: Remove this when SEH no longer uses landingpad pattern matching.
if (F.hasPersonalityFn() &&
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
return false; return false;
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@ -550,10 +702,6 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
SmallVector<BinaryOperator *, 8> DivTraceTargets; SmallVector<BinaryOperator *, 8> DivTraceTargets;
SmallVector<GetElementPtrInst *, 8> GepTraceTargets; SmallVector<GetElementPtrInst *, 8> GepTraceTargets;
const DominatorTree *DT =
&getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
const PostDominatorTree *PDT =
&getAnalysis<PostDominatorTreeWrapperPass>(F).getPostDomTree();
bool IsLeafFunc = true; bool IsLeafFunc = true;
for (auto &BB : F) { for (auto &BB : F) {
@ -596,7 +744,7 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
return true; return true;
} }
GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection( GlobalVariable *SanitizerCoverage::CreateFunctionLocalArrayInSection(
size_t NumElements, Function &F, Type *Ty, const char *Section) { size_t NumElements, Function &F, Type *Ty, const char *Section) {
ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); ArrayType *ArrayTy = ArrayType::get(Ty, NumElements);
auto Array = new GlobalVariable( auto Array = new GlobalVariable(
@ -619,7 +767,7 @@ GlobalVariable *SanitizerCoverageModule::CreateFunctionLocalArrayInSection(
} }
GlobalVariable * GlobalVariable *
SanitizerCoverageModule::CreatePCArray(Function &F, SanitizerCoverage::CreatePCArray(Function &F,
ArrayRef<BasicBlock *> AllBlocks) { ArrayRef<BasicBlock *> AllBlocks) {
size_t N = AllBlocks.size(); size_t N = AllBlocks.size();
assert(N); assert(N);
@ -646,7 +794,7 @@ SanitizerCoverageModule::CreatePCArray(Function &F,
return PCArray; return PCArray;
} }
void SanitizerCoverageModule::CreateFunctionLocalArrays( void SanitizerCoverage::CreateFunctionLocalArrays(
Function &F, ArrayRef<BasicBlock *> AllBlocks) { Function &F, ArrayRef<BasicBlock *> AllBlocks) {
if (Options.TracePCGuard) if (Options.TracePCGuard)
FunctionGuardArray = CreateFunctionLocalArrayInSection( FunctionGuardArray = CreateFunctionLocalArrayInSection(
@ -660,7 +808,7 @@ void SanitizerCoverageModule::CreateFunctionLocalArrays(
FunctionPCsArray = CreatePCArray(F, AllBlocks); FunctionPCsArray = CreatePCArray(F, AllBlocks);
} }
bool SanitizerCoverageModule::InjectCoverage(Function &F, bool SanitizerCoverage::InjectCoverage(Function &F,
ArrayRef<BasicBlock *> AllBlocks, ArrayRef<BasicBlock *> AllBlocks,
bool IsLeafFunc) { bool IsLeafFunc) {
if (AllBlocks.empty()) return false; if (AllBlocks.empty()) return false;
@ -677,7 +825,7 @@ bool SanitizerCoverageModule::InjectCoverage(Function &F,
// The cache is used to speed up recording the caller-callee pairs. // The cache is used to speed up recording the caller-callee pairs.
// The address of the caller is passed implicitly via caller PC. // The address of the caller is passed implicitly via caller PC.
// CacheSize is encoded in the name of the run-time function. // CacheSize is encoded in the name of the run-time function.
void SanitizerCoverageModule::InjectCoverageForIndirectCalls( void SanitizerCoverage::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) { Function &F, ArrayRef<Instruction *> IndirCalls) {
if (IndirCalls.empty()) if (IndirCalls.empty())
return; return;
@ -696,7 +844,7 @@ void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
// __sanitizer_cov_trace_switch(CondValue, // __sanitizer_cov_trace_switch(CondValue,
// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... })
void SanitizerCoverageModule::InjectTraceForSwitch( void SanitizerCoverage::InjectTraceForSwitch(
Function &, ArrayRef<Instruction *> SwitchTraceTargets) { Function &, ArrayRef<Instruction *> SwitchTraceTargets) {
for (auto I : SwitchTraceTargets) { for (auto I : SwitchTraceTargets) {
if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) { if (SwitchInst *SI = dyn_cast<SwitchInst>(I)) {
@ -735,7 +883,7 @@ void SanitizerCoverageModule::InjectTraceForSwitch(
} }
} }
void SanitizerCoverageModule::InjectTraceForDiv( void SanitizerCoverage::InjectTraceForDiv(
Function &, ArrayRef<BinaryOperator *> DivTraceTargets) { Function &, ArrayRef<BinaryOperator *> DivTraceTargets) {
for (auto BO : DivTraceTargets) { for (auto BO : DivTraceTargets) {
IRBuilder<> IRB(BO); IRBuilder<> IRB(BO);
@ -753,7 +901,7 @@ void SanitizerCoverageModule::InjectTraceForDiv(
} }
} }
void SanitizerCoverageModule::InjectTraceForGep( void SanitizerCoverage::InjectTraceForGep(
Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) { Function &, ArrayRef<GetElementPtrInst *> GepTraceTargets) {
for (auto GEP : GepTraceTargets) { for (auto GEP : GepTraceTargets) {
IRBuilder<> IRB(GEP); IRBuilder<> IRB(GEP);
@ -764,7 +912,7 @@ void SanitizerCoverageModule::InjectTraceForGep(
} }
} }
void SanitizerCoverageModule::InjectTraceForCmp( void SanitizerCoverage::InjectTraceForCmp(
Function &, ArrayRef<Instruction *> CmpTraceTargets) { Function &, ArrayRef<Instruction *> CmpTraceTargets) {
for (auto I : CmpTraceTargets) { for (auto I : CmpTraceTargets) {
if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) { if (ICmpInst *ICMP = dyn_cast<ICmpInst>(I)) {
@ -799,9 +947,8 @@ void SanitizerCoverageModule::InjectTraceForCmp(
} }
} }
void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB, void SanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
size_t Idx, size_t Idx, bool IsLeafFunc) {
bool IsLeafFunc) {
BasicBlock::iterator IP = BB.getFirstInsertionPt(); BasicBlock::iterator IP = BB.getFirstInsertionPt();
bool IsEntryBB = &BB == &F.getEntryBlock(); bool IsEntryBB = &BB == &F.getEntryBlock();
DebugLoc EntryLoc; DebugLoc EntryLoc;
@ -860,7 +1007,7 @@ void SanitizerCoverageModule::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
} }
std::string std::string
SanitizerCoverageModule::getSectionName(const std::string &Section) const { SanitizerCoverage::getSectionName(const std::string &Section) const {
if (TargetTriple.isOSBinFormatCOFF()) { if (TargetTriple.isOSBinFormatCOFF()) {
if (Section == SanCovCountersSectionName) if (Section == SanCovCountersSectionName)
return ".SCOV$CM"; return ".SCOV$CM";
@ -874,32 +1021,33 @@ SanitizerCoverageModule::getSectionName(const std::string &Section) const {
} }
std::string std::string
SanitizerCoverageModule::getSectionStart(const std::string &Section) const { SanitizerCoverage::getSectionStart(const std::string &Section) const {
if (TargetTriple.isOSBinFormatMachO()) return getSectionStartImpl(TargetTriple, Section);
return "\1section$start$__DATA$__" + Section;
return "__start___" + Section;
} }
std::string std::string SanitizerCoverage::getSectionEnd(const std::string &Section) const {
SanitizerCoverageModule::getSectionEnd(const std::string &Section) const { return getSectionEndImpl(TargetTriple, Section);
if (TargetTriple.isOSBinFormatMachO())
return "\1section$end$__DATA$__" + Section;
return "__stop___" + Section;
} }
INITIALIZE_PASS(ModuleSanitizerCoverageLegacyPass, "module-sancov",
char SanitizerCoverageModule::ID = 0; "Pass for inserting sancov top-level initialization calls",
INITIALIZE_PASS_BEGIN(SanitizerCoverageModule, "sancov",
"SanitizerCoverage: TODO."
"ModulePass",
false, false) false, false)
char SanitizerCoverageLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(SanitizerCoverageLegacyPass, "sancov",
"Pass for instrumenting coverage on functions", false,
false)
INITIALIZE_PASS_DEPENDENCY(ModuleSanitizerCoverageLegacyPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_END(SanitizerCoverageModule, "sancov", INITIALIZE_PASS_END(SanitizerCoverageLegacyPass, "sancov",
"SanitizerCoverage: TODO." "Pass for instrumenting coverage on functions", false,
"ModulePass", false)
false, false) FunctionPass *llvm::createSanitizerCoverageLegacyPassPass(
ModulePass *llvm::createSanitizerCoverageModulePass(
const SanitizerCoverageOptions &Options) { const SanitizerCoverageOptions &Options) {
return new SanitizerCoverageModule(Options); return new SanitizerCoverageLegacyPass(Options);
}
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options) {
return new ModuleSanitizerCoverageLegacyPass(Options);
} }

View File

@ -1,5 +1,6 @@
; Checks that a function with no-return in the entry block is not instrumented. ; Checks that a function with no-return in the entry block is not instrumented.
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard ; CHECK-NOT: call void @__sanitizer_cov_trace_pc_guard
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -1,6 +1,8 @@
; Test -sanitizer-coverage-trace-compares=1 and how it prunes backedge compares. ; Test -sanitizer-coverage-trace-compares=1 and how it prunes backedge compares.
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=PRUNE
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -sanitizer-coverage-prune-blocks=0 -S | FileCheck %s --check-prefix=NOPRUNE
; 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
; 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
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
; 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
define i32 @blah(i32) #0 { define i32 @blah(i32) #0 {
%2 = icmp sgt i32 %0, 1 %2 = icmp sgt i32 %0, 1

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-compares=1 API declarations on a non-x86_64 arch ; Test -sanitizer-coverage-trace-compares=1 API declarations on a non-x86_64 arch
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
target triple = "i386-unknown-linux-gnu" target triple = "i386-unknown-linux-gnu"
define i32 @foo() #0 { define i32 @foo() #0 {
@ -7,16 +8,16 @@ entry:
ret i32 0 ret i32 0
} }
; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64)
; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8, i8) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8, i8)
; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16, i16) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16, i16)
; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32, i32) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32, i32)
; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
; CHECK: declare void @__sanitizer_cov_trace_div4(i32) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32)
; CHECK: declare void @__sanitizer_cov_trace_div8(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64)
; CHECK: declare void @__sanitizer_cov_trace_gep(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64)
; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*)
; CHECK: declare void @__sanitizer_cov_trace_pc() ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc()
; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*)
; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
; CHECK-NOT: declare ; CHECK-NOT: declare

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-compares=1 API declarations on x86_64 ; Test -sanitizer-coverage-trace-compares=1 API declarations on x86_64
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
define i32 @foo() #0 { define i32 @foo() #0 {
@ -7,16 +8,16 @@ entry:
ret i32 0 ret i32 0
} }
; CHECK: declare void @__sanitizer_cov_trace_pc_indir(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64)
; CHECK: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext)
; CHECK: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext)
; CHECK: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext)
; CHECK: declare void @__sanitizer_cov_trace_cmp8(i64, i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64)
; CHECK: declare void @__sanitizer_cov_trace_div4(i32 zeroext) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext)
; CHECK: declare void @__sanitizer_cov_trace_div8(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_div8(i64)
; CHECK: declare void @__sanitizer_cov_trace_gep(i64) ; CHECK-DAG: declare void @__sanitizer_cov_trace_gep(i64)
; CHECK: declare void @__sanitizer_cov_trace_switch(i64, i64*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*)
; CHECK: declare void @__sanitizer_cov_trace_pc() ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc()
; CHECK: declare void @__sanitizer_cov_trace_pc_guard(i32*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*)
; CHECK: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*) ; CHECK-DAG: declare void @__sanitizer_cov_trace_pc_guard_init(i32*, i32*)
; CHECK-NOT: declare ; CHECK-NOT: declare

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-compares=1 ; Test -sanitizer-coverage-trace-compares=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; 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
; Make sure we use the right comdat groups for COFF to avoid relocations ; Make sure we use the right comdat groups for COFF to avoid relocations
; against discarded sections. Internal linkage functions are also different from ; against discarded sections. Internal linkage functions are also different from

View File

@ -1,5 +1,6 @@
; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries. ; Checks that the PC and 8-bit Counter Arrays are placed in their own sections in COFF binaries.
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; 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
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.14.26433" target triple = "x86_64-pc-windows-msvc19.14.26433"

View File

@ -1,5 +1,6 @@
; Checks that sancov.module_ctor is marked used. ; Checks that sancov.module_ctor is marked used.
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; 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
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.14.26433" target triple = "x86_64-pc-windows-msvc19.14.26433"

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-compares=1 ; Test -sanitizer-coverage-trace-compares=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,6 +1,7 @@
; Test that coverage instrumentation does not lose debug location. ; Test that coverage instrumentation does not lose debug location.
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s
; C++ source: ; C++ source:
; 1: struct A { ; 1: struct A {

View File

@ -1,7 +1,9 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK_TRACE_PC
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s --check-prefix=CHECKPRUNE
; 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
; 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
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
define void @foo(i32* %a) sanitize_address { define void @foo(i32* %a) sanitize_address {

View File

@ -1,6 +1,7 @@
; Test that coverage instrumentation does not lose debug location. ; Test that coverage instrumentation does not lose debug location.
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s
; C++ source: ; C++ source:
; 1: void foo(int *a) { ; 1: void foo(int *a) {

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-divs=1 ; Test -sanitizer-coverage-trace-divs=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-divs=1 -S | FileCheck %s
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-geps=1 ; Test -sanitizer-coverage-trace-geps=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-geps=1 -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-inline-8bit-counters=1 ; Test -sanitizer-coverage-inline-8bit-counters=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-8bit-counters=1 -S | FileCheck %s
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,6 +1,8 @@
; Test that interposable symbols do not get put in comdats. ; Test that interposable symbols do not get put in comdats.
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-linux-gnu -S | FileCheck %s
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -mtriple x86_64-windows-msvc -S | FileCheck %s
; 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
; 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
define void @Vanilla() { define void @Vanilla() {
entry: entry:

View File

@ -1,6 +1,7 @@
; Tests that we don't insert __sanitizer_cov_trace_pc_guard_init or some such ; Tests that we don't insert __sanitizer_cov_trace_pc_guard_init or some such
; when there is no instrumentation. ; when there is no instrumentation.
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,6 +1,8 @@
; Test -sanitizer-coverage-pc-table=1 ; Test -sanitizer-coverage-pc-table=1
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-inline-8bit-counters -sanitizer-coverage-pc-table=1 -S | FileCheck %s
; 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
; 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
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,7 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc -sanitizer-coverage-prune-blocks=1 -S | FileCheck %s
; 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 ; 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
; 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
; 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
define i32 @foo(i32) #0 { define i32 @foo(i32) #0 {
%2 = icmp sgt i32 %0, 0 %2 = icmp sgt i32 %0, 0

View File

@ -1,6 +1,9 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=0 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=0 -S | FileCheck %s
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -S | FileCheck %s
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=0 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=2 -S | FileCheck %s
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc18.0.0" target triple = "i686-pc-windows-msvc18.0.0"

View File

@ -2,6 +2,8 @@
; user declares `__sancov_lowest_stack` with an unexpected type. ; user declares `__sancov_lowest_stack` with an unexpected type.
; RUN: not opt < %s -sancov -sanitizer-coverage-level=1 \ ; RUN: not opt < %s -sancov -sanitizer-coverage-level=1 \
; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s ; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s
; RUN: not opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \
; RUN: -sanitizer-coverage-stack-depth -S 2>&1 | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -4,6 +4,11 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \ ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 \
; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \ ; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
; RUN: -S | FileCheck %s ; RUN: -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 \
; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 \
; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
; RUN: -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,6 @@
; Test -sanitizer-coverage-trace-compares=1 (instrumenting a switch) ; Test -sanitizer-coverage-trace-compares=1 (instrumenting a switch)
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=1 -sanitizer-coverage-trace-compares=1 -S | FileCheck %s
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
; 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
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-trace-pc-guard -sanitizer-coverage-inline-8bit-counters -S | FileCheck %s
; 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
; Module ctors should have stable names across modules, not something like ; Module ctors should have stable names across modules, not something like
; @sancov.module_ctor.3 that may cause duplicate ctors after linked together. ; @sancov.module_ctor.3 that may cause duplicate ctors after linked together.

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD ; RUN: opt < %s -sancov -sanitizer-coverage-level=4 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_TRACE_PC_GUARD
; 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
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" 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"
target triple = "x86_64-apple-darwin10.0.0" target triple = "x86_64-apple-darwin10.0.0"

View File

@ -2,6 +2,9 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; Make sure asan does not instrument __sancov_gen_ ; Make sure asan does not instrument __sancov_gen_
; RUN: opt < %s -sancov -asan -asan-module -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s ; RUN: opt < %s -sancov -asan -asan-module -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
; RUN: opt < %s -passes='module(require<asan-globals-md>,sancov-module,asan-module),function(sancov-func,asan)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
$Foo = comdat any $Foo = comdat any

View File

@ -3,6 +3,10 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc-guard -S | FileCheck %s --check-prefix=CHECK_PC_GUARD
; 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 ; 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
; 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
; 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
; 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
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" 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"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
define void @foo(i32* %a) sanitize_address { define void @foo(i32* %a) sanitize_address {

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s ; RUN: opt < %s -S -sancov -sanitizer-coverage-level=3 | FileCheck %s
; RUN: opt < %s -S -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 | FileCheck %s
; The critical edges to unreachable_bb should not be split. ; The critical edges to unreachable_bb should not be split.
define i32 @foo(i32 %c, i32 %d) { define i32 @foo(i32 %c, i32 %d) {

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK ; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK
; RUN: opt < %s -passes='module(sancov-module),function(sancov-func)' -sanitizer-coverage-level=3 -sanitizer-coverage-trace-pc -S | FileCheck %s --check-prefix=CHECK
; Generated from this C++ source: ; Generated from this C++ source:
; $ clang -O2 t.cpp -S -emit-llvm ; $ clang -O2 t.cpp -S -emit-llvm