forked from OSchip/llvm-project
[sancov] Pruning full dominator blocks from instrumentation.
Summary: This is the first simple attempt to reduce number of coverage- instrumented blocks. If a basic block dominates all its successors, then its coverage information is useless to us. Ingore such blocks if santizer-coverage-prune-tree option is set. Differential Revision: http://reviews.llvm.org/D17626 llvm-svn: 261949
This commit is contained in:
parent
7ed9361896
commit
5971f18133
|
@ -28,13 +28,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/EHPersonalities.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
|
@ -45,6 +46,7 @@
|
|||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
|
@ -94,6 +96,11 @@ static cl::opt<bool>
|
|||
"instructions"),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
static cl::opt<bool> ClPruneBlocks(
|
||||
"sanitizer-coverage-prune-blocks",
|
||||
cl::desc("Reduce the number of instrumented blocks (experimental)"),
|
||||
cl::Hidden, cl::init(false));
|
||||
|
||||
// Experimental 8-bit counters used as an additional search heuristic during
|
||||
// coverage-guided fuzzing.
|
||||
// The counters are not thread-friendly:
|
||||
|
@ -298,6 +305,22 @@ bool SanitizerCoverageModule::runOnModule(Module &M) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool shouldInstrumentBlock(const BasicBlock *BB,
|
||||
const DominatorTree *DT) {
|
||||
if (!ClPruneBlocks)
|
||||
return true;
|
||||
if (succ_begin(BB) == succ_end(BB))
|
||||
return true;
|
||||
|
||||
// Check if BB dominates all its successors.
|
||||
for (const BasicBlock *SUCC : make_range(succ_begin(BB), succ_end(BB))) {
|
||||
if (!DT->dominates(BB, SUCC))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
||||
if (F.empty()) return false;
|
||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
|
@ -311,11 +334,15 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
|||
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
|
||||
SplitAllCriticalEdges(F);
|
||||
SmallVector<Instruction*, 8> IndirCalls;
|
||||
SmallVector<BasicBlock*, 16> AllBlocks;
|
||||
SmallVector<BasicBlock *, 16> BlocksToInstrument;
|
||||
SmallVector<Instruction*, 8> CmpTraceTargets;
|
||||
SmallVector<Instruction*, 8> SwitchTraceTargets;
|
||||
|
||||
DominatorTree DT;
|
||||
DT.recalculate(F);
|
||||
for (auto &BB : F) {
|
||||
AllBlocks.push_back(&BB);
|
||||
if (shouldInstrumentBlock(&BB, &DT))
|
||||
BlocksToInstrument.push_back(&BB);
|
||||
for (auto &Inst : BB) {
|
||||
if (Options.IndirectCalls) {
|
||||
CallSite CS(&Inst);
|
||||
|
@ -330,7 +357,8 @@ bool SanitizerCoverageModule::runOnFunction(Function &F) {
|
|||
}
|
||||
}
|
||||
}
|
||||
InjectCoverage(F, AllBlocks);
|
||||
|
||||
InjectCoverage(F, BlocksToInstrument);
|
||||
InjectCoverageForIndirectCalls(F, IndirCalls);
|
||||
InjectTraceForCmp(F, CmpTraceTargets);
|
||||
InjectTraceForSwitch(F, SwitchTraceTargets);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
; RUN: -S | FileCheck %s --check-prefix=CHECK2
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -sanitizer-coverage-block-threshold=1 \
|
||||
; RUN: -S | FileCheck %s --check-prefix=CHECK_WITH_CHECK
|
||||
; RUN: opt < %s -sancov -sanitizer-coverage-level=2 -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 triple = "x86_64-unknown-linux-gnu"
|
||||
|
@ -134,3 +135,11 @@ entry:
|
|||
; CHECK4-LABEL: define void @call_unreachable
|
||||
; CHECK4-NOT: __sanitizer_cov
|
||||
; CHECK4: unreachable
|
||||
|
||||
; CHECKPRUNE-LABEL: define void @foo
|
||||
; CHECKPRUNE: call void @__sanitizer_cov
|
||||
; CHECKPRUNE: call void asm sideeffect "", ""()
|
||||
; CHECKPRUNE: call void @__sanitizer_cov
|
||||
; CHECKPRUNE: call void asm sideeffect "", ""()
|
||||
; CHECKPRUNE-NOT: call void @__sanitizer_cov
|
||||
; CHECKPRUNE: ret void
|
||||
|
|
Loading…
Reference in New Issue