53 #define DEBUG_TYPE "sancov"
60 static const char *
const kSanCovTraceBB =
"__sanitizer_cov_trace_basic_block";
66 cl::desc(
"Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, "
67 "3: all blocks and critical edges, "
68 "4: above plus indirect calls"),
72 "sanitizer-coverage-block-threshold",
73 cl::desc(
"Use a callback with a guard check inside it if there are"
74 " more than this number of blocks."),
79 cl::desc(
"Experimental basic-block tracing: insert "
80 "callbacks at every basic block"),
85 cl::desc(
"Experimental tracing of CMP and similar "
96 cl::desc(
"Experimental 8-bit counters"),
103 switch (LegacyCoverageLevel) {
135 class SanitizerCoverageModule :
public ModulePass {
137 SanitizerCoverageModule(
140 bool runOnModule(
Module &M)
override;
143 const char *getPassName()
const override {
144 return "SanitizerCoverageModule";
148 void InjectCoverageForIndirectCalls(
Function &
F,
154 unsigned NumberOfInstrumentedBlocks() {
155 return SanCovFunction->getNumUses() + SanCovWithCheckFunction->getNumUses();
160 Function *SanCovTraceEnter, *SanCovTraceBB;
163 Type *IntptrTy, *Int64Ty;
175 bool SanitizerCoverageModule::runOnModule(
Module &M) {
191 SanCovIndirCallFunction =
194 SanCovTraceCmpFunction =
203 if (Options.TraceBB) {
217 nullptr,
"__sancov_gen_cov_tmp");
218 if (Options.Use8bitCounters)
219 EightBitCounterArray =
221 nullptr,
"__sancov_gen_cov_tmp");
226 auto N = NumberOfInstrumentedBlocks();
237 GuardArray->replaceAllUsesWith(
238 IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
239 GuardArray->eraseFromParent();
242 if (Options.Use8bitCounters) {
244 static const int kCounterAlignment = 16;
250 RealEightBitCounterArray->
setAlignment(kCounterAlignment);
251 EightBitCounterArray->replaceAllUsesWith(
252 IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy));
253 EightBitCounterArray->eraseFromParent();
266 {Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy},
267 {IRB.CreatePointerCast(RealGuardArray, Int32PtrTy),
269 Options.Use8bitCounters
270 ? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)
272 IRB.CreatePointerCast(ModuleName, Int8PtrTy)});
279 bool SanitizerCoverageModule::runOnFunction(
Function &
F) {
280 if (F.
empty())
return false;
281 if (F.
getName().
find(
".module_ctor") != std::string::npos)
290 for (
auto &Inst : BB) {
291 if (Options.IndirectCalls) {
293 if (CS && !
CS.getCalledFunction())
296 if (Options.TraceCmp && isa<ICmpInst>(&Inst))
300 InjectCoverage(F, AllBlocks);
301 InjectCoverageForIndirectCalls(F, IndirCalls);
302 InjectTraceForCmp(F, CmpTraceTargets);
306 bool SanitizerCoverageModule::InjectCoverage(
Function &F,
308 switch (Options.CoverageType) {
316 for (
auto BB : AllBlocks)
317 InjectCoverageAtBlock(F, *BB, UseCalls);
330 void SanitizerCoverageModule::InjectCoverageForIndirectCalls(
332 if (IndirCalls.
empty())
return;
333 const int kCacheSize = 16;
334 const int kCacheAlignment = 64;
336 for (
auto I : IndirCalls) {
339 Value *Callee =
CS.getCalledValue();
340 if (isa<InlineAsm>(Callee))
continue;
345 IRB.CreateCall(SanCovIndirCallFunction,
346 {IRB.CreatePointerCast(Callee, IntptrTy),
347 IRB.CreatePointerCast(CalleeCache, IntptrTy)});
351 void SanitizerCoverageModule::InjectTraceForCmp(
353 for (
auto I : CmpTraceTargets) {
359 uint64_t TypeSize =
DL->getTypeStoreSizeInBits(A0->
getType());
362 SanCovTraceCmpFunction,
364 IRB.CreateIntCast(A0, Int64Ty,
true),
365 IRB.CreateIntCast(A1, Int64Ty,
true)});
370 void SanitizerCoverageModule::SetNoSanitizeMetadata(
Instruction *
I) {
389 for (; IP != BE; ++IP) {
401 EntryLoc = IP->getDebugLoc();
405 IRB.SetCurrentDebugLocation(EntryLoc);
407 Value *GuardP = IRB.CreateAdd(
408 IRB.CreatePointerCast(GuardArray, IntptrTy),
411 GuardP = IRB.CreateIntToPtr(GuardP, Int32PtrTy);
413 IRB.CreateCall(SanCovWithCheckFunction, GuardP);
418 SetNoSanitizeMetadata(Load);
422 IRB.SetInsertPoint(Ins);
423 IRB.SetCurrentDebugLocation(EntryLoc);
425 IRB.CreateCall(SanCovFunction, GuardP);
426 IRB.CreateCall(EmptyAsm, {});
429 if (Options.Use8bitCounters) {
430 IRB.SetInsertPoint(IP);
432 IRB.CreatePointerCast(EightBitCounterArray, IntptrTy),
434 P = IRB.CreateIntToPtr(P, IRB.getInt8PtrTy());
438 SetNoSanitizeMetadata(LI);
439 SetNoSanitizeMetadata(SI);
442 if (Options.TraceBB) {
445 IRB.SetInsertPoint(IP);
446 IRB.CreateCall(IsEntryBB ? SanCovTraceEnter : SanCovTraceBB, GuardP);
452 "SanitizerCoverage: TODO."
453 "ModulePass",
false,
false)
456 return new SanitizerCoverageModule(Options);
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
getString - This method constructs a CDS and initializes it with a text string.
Function * checkSanitizerInterfaceFunction(Constant *FuncOrBitcast)
A Module instance is used to store all the information related to an LLVM module. ...
static cl::opt< unsigned > ClCoverageBlockThreshold("sanitizer-coverage-block-threshold", cl::desc("Use a callback with a guard check inside it if there are"" more than this number of blocks."), cl::Hidden, cl::init(500))
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
void appendToGlobalCtors(Module &M, Function *F, int Priority)
Append F to the list of global ctors of module M with the given Priority.
TerminatorInst * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DominatorTree *DT=nullptr)
SplitBlockAndInsertIfThen - Split the containing block at the specified instruction - everything befo...
Like Internal, but omit from symbol table.
Externally visible function.
static const uint64_t kSanCtorAndDtorPriority
const Function * getParent() const
Return the enclosing method, or null if none.
LoadInst - an instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
unsigned SplitAllCriticalEdges(Function &F, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions())
void setAlignment(unsigned Align)
static cl::opt< int > ClCoverageLevel("sanitizer-coverage-level", cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, ""3: all blocks and critical edges, ""4: above plus indirect calls"), cl::Hidden, cl::init(0))
static Constant * getNullValue(Type *Ty)
StringRef getName() const
Return a constant reference to the value's name.
DILocation * get() const
Get the underlying DILocation.
static const char *const kSanCovIndirCallName
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static const char *const kSanCovName
DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
static cl::opt< bool > ClExperimentalCMPTracing("sanitizer-coverage-experimental-trace-compares", cl::desc("Experimental tracing of CMP and similar ""instructions"), cl::Hidden, cl::init(false))
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
StoreInst - an instruction for storing to memory.
static const char *const kSanCovTraceEnter
size_t size() const
size - Get the array size.
initializer< Ty > init(const Ty &Val)
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
static cl::opt< bool > ClExperimentalTracing("sanitizer-coverage-experimental-tracing", cl::desc("Experimental basic-block tracing: insert ""callbacks at every basic block"), cl::Hidden, cl::init(false))
This is an important base class in LLVM.
static const char *const kSanCovTraceBB
static Type * getVoidTy(LLVMContext &C)
static const char *const kSanCovModuleCtorName
This instruction compares its operands according to the predicate given to the constructor.
bool empty() const
empty - Check if the array is empty.
void setAlignment(unsigned Align)
static const char *const kSanCovWithCheckName
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
void setMetadata(unsigned KindID, MDNode *Node)
setMetadata - Set the metadata of the specified kind to the specified node.
static PointerType * getUnqual(Type *ElementType)
PointerType::getUnqual - This constructs a pointer to an object of the specified type in the generic ...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool isStaticAlloca() const
isStaticAlloca - Return true if this alloca is in the entry block of the function and is a constant s...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
enum llvm::SanitizerCoverageOptions::Type CoverageType
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
const BasicBlock & getEntryBlock() const
INITIALIZE_PASS(SanitizerCoverageModule,"sancov","SanitizerCoverage: TODO.""ModulePass", false, false) ModulePass *llvm
bool isIntegerTy() const
isIntegerTy - True if this is an instance of IntegerType.
static cl::opt< bool > ClUse8bitCounters("sanitizer-coverage-8bit-counters", cl::desc("Experimental 8-bit counters"), cl::Hidden, cl::init(false))
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static const char *const kSanCovModuleInitName
static IntegerType * getInt32Ty(LLVMContext &C)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static const char *const kSanCovTraceCmp
static ArrayType * get(Type *ElementType, uint64_t NumElements)
ArrayType::get - This static method is the primary way to construct an ArrayType. ...
std::pair< Function *, Function * > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs)
Creates sanitizer constructor function, and calls sanitizer's init function from it.
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
C - The default llvm calling convention, compatible with C.
StringRef - Represent a constant reference to a string, i.e.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
ModulePass * createSanitizerCoverageModulePass(const SanitizerCoverageOptions &Options=SanitizerCoverageOptions())
unsigned getMDKindID(StringRef Name) const
Return a unique non-zero ID for the specified metadata kind.
static IntegerType * getInt8Ty(LLVMContext &C)
const BasicBlock * getParent() const
LLVMContext & getContext() const
Get the global data context.
AllocaInst - an instruction to allocate memory on the stack.