mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 04:09:45 +00:00
[asan] add experimental basic-block tracing to asan-coverage; also fix -fsanitize-coverage=3 which was broken by r221718
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222290 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6272b8c4be
commit
0dd5e22d89
@ -89,6 +89,7 @@ static const int kMaxAsanStackMallocSizeClass = 10;
|
||||
static const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_";
|
||||
static const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_";
|
||||
static const char *const kAsanGenPrefix = "__asan_gen_";
|
||||
static const char *const kSanCovGenPrefix = "__sancov_gen_";
|
||||
static const char *const kAsanPoisonStackMemoryName =
|
||||
"__asan_poison_stack_memory";
|
||||
static const char *const kAsanUnpoisonStackMemoryName =
|
||||
@ -619,7 +620,8 @@ static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
|
||||
}
|
||||
|
||||
static bool GlobalWasGeneratedByAsan(GlobalVariable *G) {
|
||||
return G->getName().find(kAsanGenPrefix) == 0;
|
||||
return G->getName().find(kAsanGenPrefix) == 0 ||
|
||||
G->getName().find(kSanCovGenPrefix) == 0;
|
||||
}
|
||||
|
||||
Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
|
||||
|
@ -56,6 +56,8 @@ using namespace llvm;
|
||||
static const char *const kSanCovModuleInitName = "__sanitizer_cov_module_init";
|
||||
static const char *const kSanCovName = "__sanitizer_cov";
|
||||
static const char *const kSanCovIndirCallName = "__sanitizer_cov_indir_call16";
|
||||
static const char *const kSanCovTraceEnter = "__sanitizer_cov_trace_func_enter";
|
||||
static const char *const kSanCovTraceBB = "__sanitizer_cov_trace_basic_block";
|
||||
static const char *const kSanCovModuleCtorName = "sancov.module_ctor";
|
||||
static const uint64_t kSanCtorAndDtorPriority = 1;
|
||||
|
||||
@ -71,15 +73,19 @@ static cl::opt<int> ClCoverageBlockThreshold(
|
||||
"are more than this number of blocks."),
|
||||
cl::Hidden, cl::init(1500));
|
||||
|
||||
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));
|
||||
|
||||
namespace {
|
||||
|
||||
class SanitizerCoverageModule : public ModulePass {
|
||||
public:
|
||||
SanitizerCoverageModule(int CoverageLevel = 0)
|
||||
SanitizerCoverageModule(int CoverageLevel = 0)
|
||||
: ModulePass(ID),
|
||||
CoverageLevel(std::max(CoverageLevel, (int)ClCoverageLevel)) {
|
||||
initializeBreakCriticalEdgesPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
CoverageLevel(std::max(CoverageLevel, (int)ClCoverageLevel)) {}
|
||||
bool runOnModule(Module &M) override;
|
||||
bool runOnFunction(Function &F);
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
@ -88,8 +94,6 @@ class SanitizerCoverageModule : public ModulePass {
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
if (CoverageLevel >= 3)
|
||||
AU.addRequiredID(BreakCriticalEdgesID);
|
||||
AU.addRequired<DataLayoutPass>();
|
||||
}
|
||||
|
||||
@ -98,10 +102,12 @@ class SanitizerCoverageModule : public ModulePass {
|
||||
ArrayRef<Instruction *> IndirCalls);
|
||||
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
|
||||
ArrayRef<Instruction *> IndirCalls);
|
||||
bool InjectTracing(Function &F, ArrayRef<BasicBlock *> AllBlocks);
|
||||
void InjectCoverageAtBlock(Function &F, BasicBlock &BB);
|
||||
Function *SanCovFunction;
|
||||
Function *SanCovIndirCallFunction;
|
||||
Function *SanCovModuleInit;
|
||||
Function *SanCovTraceEnter, *SanCovTraceBB;
|
||||
Type *IntptrTy;
|
||||
LLVMContext *C;
|
||||
|
||||
@ -141,6 +147,13 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
||||
kSanCovModuleInitName, Type::getVoidTy(*C), IntptrTy, nullptr));
|
||||
SanCovModuleInit->setLinkage(Function::ExternalLinkage);
|
||||
|
||||
if (ClExperimentalTracing) {
|
||||
SanCovTraceEnter = checkInterfaceFunction(
|
||||
M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, IntptrTy, nullptr));
|
||||
SanCovTraceBB = checkInterfaceFunction(
|
||||
M.getOrInsertFunction(kSanCovTraceBB, VoidTy, IntptrTy, nullptr));
|
||||
}
|
||||
|
||||
for (auto &F : M)
|
||||
runOnFunction(F);
|
||||
|
||||
@ -155,6 +168,8 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
||||
// For now instrument only functions that will also be asan-instrumented.
|
||||
if (!F.hasFnAttribute(Attribute::SanitizeAddress))
|
||||
return false;
|
||||
if (CoverageLevel >= 3)
|
||||
SplitAllCriticalEdges(F, this);
|
||||
SmallVector<Instruction*, 8> IndirCalls;
|
||||
SmallVector<BasicBlock*, 16> AllBlocks;
|
||||
for (auto &BB : F) {
|
||||
@ -167,6 +182,25 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
||||
}
|
||||
}
|
||||
InjectCoverage(F, AllBlocks, IndirCalls);
|
||||
InjectTracing(F, AllBlocks);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Experimental support for tracing.
|
||||
// Basicaly, insert a callback at the beginning of every basic block.
|
||||
// Every callback gets a pointer to a uniqie global for internal storage.
|
||||
bool SanitizerCoverageModule::InjectTracing(Function &F,
|
||||
ArrayRef<BasicBlock *> AllBlocks) {
|
||||
if (!ClExperimentalTracing) return false;
|
||||
Type *Ty = ArrayType::get(IntptrTy, 1); // May need to use more words later.
|
||||
for (auto BB : AllBlocks) {
|
||||
IRBuilder<> IRB(BB->getFirstInsertionPt());
|
||||
GlobalVariable *TraceCache = new GlobalVariable(
|
||||
*F.getParent(), Ty, false, GlobalValue::PrivateLinkage,
|
||||
Constant::getNullValue(Ty), "__sancov_gen_trace_cache");
|
||||
IRB.CreateCall(&F.getEntryBlock() == BB ? SanCovTraceEnter : SanCovTraceBB,
|
||||
IRB.CreatePointerCast(TraceCache, IntptrTy));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ entry:
|
||||
; CHECK3: call void @__sanitizer_cov
|
||||
; CHECK3: call void @__sanitizer_cov
|
||||
; CHECK3: call void @__sanitizer_cov
|
||||
; CHECK3-NOT: ret void
|
||||
; CHECK3: call void @__sanitizer_cov
|
||||
; CHECK3-NOT: call void @__sanitizer_cov
|
||||
; CHECK3: ret void
|
||||
|
33
test/Instrumentation/SanitizerCoverage/tracing.ll
Normal file
33
test/Instrumentation/SanitizerCoverage/tracing.ll
Normal file
@ -0,0 +1,33 @@
|
||||
; Test -sanitizer-coverage-experimental-tracing
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=1 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK1
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=3 -sanitizer-coverage-experimental-tracing -S | FileCheck %s --check-prefix=CHECK3
|
||||
|
||||
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"
|
||||
define void @foo(i32* %a) sanitize_address {
|
||||
entry:
|
||||
%tobool = icmp eq i32* %a, null
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
if.then: ; preds = %entry
|
||||
store i32 0, i32* %a, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %entry, %if.then
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK1-LABEL: define void @foo
|
||||
; CHECK1: call void @__sanitizer_cov_trace_func_enter
|
||||
; CHECK1: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK1: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK1-NOT: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK1: ret void
|
||||
|
||||
; CHECK3-LABEL: define void @foo
|
||||
; CHECK3: call void @__sanitizer_cov_trace_func_enter
|
||||
; CHECK3: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK3: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK3: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK3-NOT: call void @__sanitizer_cov_trace_basic_block
|
||||
; CHECK3: ret void
|
Loading…
Reference in New Issue
Block a user