forked from OSchip/llvm-project
[dfsan] Abort at runtime on indirect calls to uninstrumented vararg functions.
We currently have no infrastructure to support these correctly. This is accomplished by generating a call to a runtime library function that aborts at runtime in place of the regular wrapper for such functions. Direct calls are rewritten in the usual way during traversal of the caller's IR. We also remove the "split-stack" attribute from such wrappers, as the code generator cannot currently handle split-stack vararg functions. llvm-svn: 221360
This commit is contained in:
parent
9727e7865e
commit
a1099840ff
|
@ -234,12 +234,14 @@ class DataFlowSanitizer : public ModulePass {
|
|||
FunctionType *DFSanUnimplementedFnTy;
|
||||
FunctionType *DFSanSetLabelFnTy;
|
||||
FunctionType *DFSanNonzeroLabelFnTy;
|
||||
FunctionType *DFSanVarargWrapperFnTy;
|
||||
Constant *DFSanUnionFn;
|
||||
Constant *DFSanCheckedUnionFn;
|
||||
Constant *DFSanUnionLoadFn;
|
||||
Constant *DFSanUnimplementedFn;
|
||||
Constant *DFSanSetLabelFn;
|
||||
Constant *DFSanNonzeroLabelFn;
|
||||
Constant *DFSanVarargWrapperFn;
|
||||
MDNode *ColdCallWeights;
|
||||
DFSanABIList ABIList;
|
||||
DenseMap<Value *, Function *> UnwrappedFnMap;
|
||||
|
@ -439,6 +441,8 @@ bool DataFlowSanitizer::doInitialization(Module &M) {
|
|||
DFSanSetLabelArgs, /*isVarArg=*/false);
|
||||
DFSanNonzeroLabelFnTy = FunctionType::get(
|
||||
Type::getVoidTy(*Ctx), None, /*isVarArg=*/false);
|
||||
DFSanVarargWrapperFnTy = FunctionType::get(
|
||||
Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false);
|
||||
|
||||
if (GetArgTLSPtr) {
|
||||
Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
|
||||
|
@ -518,15 +522,26 @@ DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
|
|||
AttributeSet::ReturnIndex));
|
||||
|
||||
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", NewF);
|
||||
std::vector<Value *> Args;
|
||||
unsigned n = FT->getNumParams();
|
||||
for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n)
|
||||
Args.push_back(&*ai);
|
||||
CallInst *CI = CallInst::Create(F, Args, "", BB);
|
||||
if (FT->getReturnType()->isVoidTy())
|
||||
ReturnInst::Create(*Ctx, BB);
|
||||
else
|
||||
ReturnInst::Create(*Ctx, CI, BB);
|
||||
if (F->isVarArg()) {
|
||||
NewF->removeAttributes(
|
||||
AttributeSet::FunctionIndex,
|
||||
AttributeSet().addAttribute(*Ctx, AttributeSet::FunctionIndex,
|
||||
"split-stack"));
|
||||
CallInst::Create(DFSanVarargWrapperFn,
|
||||
IRBuilder<>(BB).CreateGlobalStringPtr(F->getName()), "",
|
||||
BB);
|
||||
new UnreachableInst(*Ctx, BB);
|
||||
} else {
|
||||
std::vector<Value *> Args;
|
||||
unsigned n = FT->getNumParams();
|
||||
for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n)
|
||||
Args.push_back(&*ai);
|
||||
CallInst *CI = CallInst::Create(F, Args, "", BB);
|
||||
if (FT->getReturnType()->isVoidTy())
|
||||
ReturnInst::Create(*Ctx, BB);
|
||||
else
|
||||
ReturnInst::Create(*Ctx, CI, BB);
|
||||
}
|
||||
|
||||
return NewF;
|
||||
}
|
||||
|
@ -617,6 +632,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
|
|||
}
|
||||
DFSanNonzeroLabelFn =
|
||||
Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
|
||||
DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper",
|
||||
DFSanVarargWrapperFnTy);
|
||||
|
||||
std::vector<Function *> FnsToInstrument;
|
||||
llvm::SmallPtrSet<Function *, 2> FnsWithNativeABI;
|
||||
|
@ -627,7 +644,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
|
|||
i != DFSanUnionLoadFn &&
|
||||
i != DFSanUnimplementedFn &&
|
||||
i != DFSanSetLabelFn &&
|
||||
i != DFSanNonzeroLabelFn)
|
||||
i != DFSanNonzeroLabelFn &&
|
||||
i != DFSanVarargWrapperFn)
|
||||
FnsToInstrument.push_back(&*i);
|
||||
}
|
||||
|
||||
|
@ -1363,6 +1381,11 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Calls to this function are synthesized in wrappers, and we shouldn't
|
||||
// instrument them.
|
||||
if (F == DFSF.DFS.DFSanVarargWrapperFn)
|
||||
return;
|
||||
|
||||
assert(!(cast<FunctionType>(
|
||||
CS.getCalledValue()->getType()->getPointerElementType())->isVarArg() &&
|
||||
dyn_cast<InvokeInst>(CS.getInstruction())));
|
||||
|
|
|
@ -29,6 +29,9 @@ declare void @custom1(i32 %a, i32 %b)
|
|||
; CHECK: ret { i32, i16 }
|
||||
declare i32 @custom2(i32 %a, i32 %b)
|
||||
|
||||
; CHECK: define linkonce_odr void @"dfsw$custom3"(i32, i16, i16*, ...)
|
||||
; CHECK: call void @__dfsan_vararg_wrapper(i8*
|
||||
; CHECK: unreachable
|
||||
declare void @custom3(i32 %a, ...)
|
||||
|
||||
declare i32 @custom4(i32 %a, ...)
|
||||
|
@ -83,8 +86,6 @@ define i32 (i32, i32)* @g(i32) {
|
|||
|
||||
; CHECK: declare void @__dfsw_custom1(i32, i32, i16, i16)
|
||||
; CHECK: declare i32 @__dfsw_custom2(i32, i32, i16, i16, i16*)
|
||||
; CHECK: declare void @__dfsw_custom3(i32, i16, i16*, ...)
|
||||
; CHECK: declare i32 @__dfsw_custom4(i32, i16, i16*, i16*, ...)
|
||||
|
||||
; CHECK-LABEL: define linkonce_odr i32 @"dfst0$customcb"(i32 (i32)*, i32, i16, i16*)
|
||||
; CHECK: %[[BC:.*]] = bitcast i32 (i32)* %0 to { i32, i16 } (i32, i16)*
|
||||
|
@ -94,3 +95,5 @@ define i32 (i32, i32)* @g(i32) {
|
|||
; CHECK: store i16 %[[XVAL1]], i16* %3
|
||||
; CHECK: ret i32 %[[XVAL0]]
|
||||
|
||||
; CHECK: declare void @__dfsw_custom3(i32, i16, i16*, ...)
|
||||
; CHECK: declare i32 @__dfsw_custom4(i32, i16, i16*, i16*, ...)
|
||||
|
|
Loading…
Reference in New Issue