[PATCH] DataFlowSanitizer: Add a debugging feature to help us track nonzero labels.
Peter Collingbourne
peter at pcc.me.uk
Wed Aug 14 14:49:29 PDT 2013
Hi eugenis,
When the -dfsan-debug-nonzero-labels parameter is supplied, the code
is instrumented such that when a call parameter, return value or load
produces a nonzero label, the function __dfsan_nonzero_label is called.
The idea is that a debugger breakpoint can be set on this function
in a nominally label-free program to help identify any bugs in the
instrumentation pass causing labels to be introduced.
http://llvm-reviews.chandlerc.com/D1405
Files:
lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
test/Instrumentation/DataFlowSanitizer/debug-nonzero-labels.ll
Index: lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
===================================================================
--- lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -95,6 +95,12 @@
cl::desc("Use the argument ABI rather than the TLS ABI"),
cl::Hidden);
+static cl::opt<bool> ClDebugNonzeroLabels(
+ "dfsan-debug-nonzero-labels",
+ cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, "
+ "load or return with a nonzero label"),
+ cl::Hidden);
+
namespace {
class DataFlowSanitizer : public ModulePass {
@@ -160,10 +166,12 @@
FunctionType *DFSanUnionLoadFnTy;
FunctionType *DFSanUnimplementedFnTy;
FunctionType *DFSanSetLabelFnTy;
+ FunctionType *DFSanNonzeroLabelFnTy;
Constant *DFSanUnionFn;
Constant *DFSanUnionLoadFn;
Constant *DFSanUnimplementedFn;
Constant *DFSanSetLabelFn;
+ Constant *DFSanNonzeroLabelFn;
MDNode *ColdCallWeights;
OwningPtr<SpecialCaseList> ABIList;
DenseMap<Value *, Function *> UnwrappedFnMap;
@@ -197,6 +205,7 @@
DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
std::vector<std::pair<PHINode *, PHINode *> > PHIFixups;
DenseSet<Instruction *> SkipInsts;
+ DenseSet<Value *> NonZeroChecks;
DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI)
: DFS(DFS), F(F), IA(DFS.getInstrumentedABI()),
@@ -311,6 +320,8 @@
Type *DFSanSetLabelArgs[3] = { ShadowTy, Type::getInt8PtrTy(*Ctx), IntptrTy };
DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
DFSanSetLabelArgs, /*isVarArg=*/false);
+ DFSanNonzeroLabelFnTy = FunctionType::get(
+ Type::getVoidTy(*Ctx), ArrayRef<Type *>(), /*isVarArg=*/false);
if (GetArgTLSPtr) {
Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
@@ -389,15 +400,18 @@
if (Function *F = dyn_cast<Function>(DFSanSetLabelFn)) {
F->addAttribute(1, Attribute::ZExt);
}
+ DFSanNonzeroLabelFn =
+ Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
std::vector<Function *> FnsToInstrument;
llvm::SmallPtrSet<Function *, 2> FnsWithNativeABI;
for (Module::iterator i = M.begin(), e = M.end(); i != e; ++i) {
if (!i->isIntrinsic() &&
i != DFSanUnionFn &&
i != DFSanUnionLoadFn &&
i != DFSanUnimplementedFn &&
- i != DFSanSetLabelFn)
+ i != DFSanSetLabelFn &&
+ i != DFSanNonzeroLabelFn)
FnsToInstrument.push_back(&*i);
}
@@ -560,6 +574,31 @@
val, DFSF.getShadow(i->first->getIncomingValue(val)));
}
}
+
+ // -dfsan-debug-nonzero-labels will split the CFG in all kinds of crazy
+ // places (i.e. instructions in basic blocks we haven't even begun visiting
+ // yet). To make our life easier, do this work in a pass after the main
+ // instrumentation.
+ if (ClDebugNonzeroLabels) {
+ for (DenseSet<Value *>::iterator i = DFSF.NonZeroChecks.begin(),
+ e = DFSF.NonZeroChecks.end();
+ i != e; ++i) {
+ Instruction *Pos;
+ if (Instruction *I = dyn_cast<Instruction>(*i))
+ Pos = I->getNextNode();
+ else
+ Pos = DFSF.F->getEntryBlock().begin();
+ while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
+ Pos = Pos->getNextNode();
+ IRBuilder<> IRB(Pos);
+ Instruction *NeInst = cast<Instruction>(
+ IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow));
+ BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen(
+ NeInst, /*Unreachable=*/ false, ColdCallWeights));
+ IRBuilder<> ThenIRB(BI);
+ ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn);
+ }
+ }
}
return false;
@@ -618,6 +657,7 @@
break;
}
}
+ NonZeroChecks.insert(Shadow);
} else {
Shadow = DFS.ZeroShadow;
}
@@ -814,7 +854,11 @@
Value *LoadedShadow =
DFSF.loadShadow(LI.getPointerOperand(), Size, Align, &LI);
Value *PtrShadow = DFSF.getShadow(LI.getPointerOperand());
- DFSF.setShadow(&LI, DFSF.DFS.combineShadows(LoadedShadow, PtrShadow, &LI));
+ Value *CombinedShadow = DFSF.DFS.combineShadows(LoadedShadow, PtrShadow, &LI);
+ if (CombinedShadow != DFSF.DFS.ZeroShadow)
+ DFSF.NonZeroChecks.insert(CombinedShadow);
+
+ DFSF.setShadow(&LI, CombinedShadow);
}
void DFSanFunction::storeShadow(Value *Addr, uint64_t Size, uint64_t Align,
@@ -1131,6 +1175,7 @@
LoadInst *LI = NextIRB.CreateLoad(DFSF.getRetvalTLS());
DFSF.SkipInsts.insert(LI);
DFSF.setShadow(CS.getInstruction(), LI);
+ DFSF.NonZeroChecks.insert(LI);
}
}
@@ -1184,6 +1229,7 @@
ExtractValueInst::Create(NewCS.getInstruction(), 1, "", Next);
DFSF.SkipInsts.insert(ExShadow);
DFSF.setShadow(ExVal, ExShadow);
+ DFSF.NonZeroChecks.insert(ExShadow);
CS.getInstruction()->replaceAllUsesWith(ExVal);
}
Index: test/Instrumentation/DataFlowSanitizer/debug-nonzero-labels.ll
===================================================================
--- /dev/null
+++ test/Instrumentation/DataFlowSanitizer/debug-nonzero-labels.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -dfsan -dfsan-args-abi -dfsan-debug-nonzero-labels -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-S128"
+
+declare i32 @g()
+
+; CHECK: define { i32, i16 } @f(i32, i16)
+define i32 @f(i32) {
+ ; CHECK: [[LOCALLABELALLOCA:%.*]] = alloca i16
+ ; CHECK: [[ARGCMP:%.*]] = icmp ne i16 %1, 0
+ ; CHECK: br i1 [[ARGCMP]]
+ %i = alloca i32
+ store i32 %0, i32* %i
+ ; CHECK: [[CALL:%.*]] = call { i32, i16 } @g()
+ ; CHECK: [[CALLLABEL:%.*]] = extractvalue { i32, i16 } [[CALL]], 1
+ ; CHECK: [[CALLCMP:%.*]] = icmp ne i16 [[CALLLABEL]], 0
+ ; CHECK: br i1 [[CALLCMP]]
+ %call = call i32 @g()
+ ; CHECK: [[LOCALLABEL:%.*]] = load i16* [[LOCALLABELALLOCA]]
+ ; CHECK: [[LOCALCMP:%.*]] = icmp ne i16 [[LOCALLABEL]], 0
+ ; CHECK: br i1 [[LOCALCMP]]
+ %load = load i32* %i
+ ret i32 %load
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1405.1.patch
Type: text/x-patch
Size: 6186 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130814/7eeec8ba/attachment.bin>
More information about the llvm-commits
mailing list