mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221360 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
72ced73d45
commit
7cc4447ccf
@ -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
Block a user