[dfsan] New calling convention for custom functions with variadic arguments.

Summary:
The previous calling convention prevented custom functions from being able
to access argument labels unless it knew how many variadic arguments there
were, and of which type. This restriction made it impossible to correctly
model functions in the printf family, as it is legal to pass more arguments
than required to those functions. We now pass arguments in the following order:

non-vararg arguments
labels for non-vararg arguments
[if vararg function, pointer to array of labels for vararg arguments]
[if non-void function, pointer to label for return value]
vararg arguments

Differential Revision: http://reviews.llvm.org/D6028

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220906 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne
2014-10-30 13:22:57 +00:00
parent b0d3f64971
commit 015aedb1b5
2 changed files with 51 additions and 29 deletions

View File

@ -389,12 +389,6 @@ FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) {
}
FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
if (T->isVarArg()) {
// The labels are passed after all the arguments so there is no need to
// adjust the function type.
return T;
}
llvm::SmallVector<Type *, 4> ArgTypes;
for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end();
i != e; ++i) {
@ -409,10 +403,12 @@ FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
}
for (unsigned i = 0, e = T->getNumParams(); i != e; ++i)
ArgTypes.push_back(ShadowTy);
if (T->isVarArg())
ArgTypes.push_back(ShadowPtrTy);
Type *RetType = T->getReturnType();
if (!RetType->isVoidTy())
ArgTypes.push_back(ShadowPtrTy);
return FunctionType::get(T->getReturnType(), ArgTypes, false);
return FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg());
}
bool DataFlowSanitizer::doInitialization(Module &M) {
@ -1419,7 +1415,7 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
std::vector<Value *> Args;
CallSite::arg_iterator i = CS.arg_begin();
for (unsigned n = CS.arg_size(); n != 0; ++i, --n) {
for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) {
Type *T = (*i)->getType();
FunctionType *ParamFT;
if (isa<PointerType>(T) &&
@ -1439,9 +1435,23 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
}
i = CS.arg_begin();
for (unsigned n = CS.arg_size(); n != 0; ++i, --n)
for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
Args.push_back(DFSF.getShadow(*i));
if (FT->isVarArg()) {
auto LabelVAAlloca =
new AllocaInst(ArrayType::get(DFSF.DFS.ShadowTy,
CS.arg_size() - FT->getNumParams()),
"labelva", DFSF.F->getEntryBlock().begin());
for (unsigned n = 0; i != CS.arg_end(); ++i, ++n) {
auto LabelVAPtr = IRB.CreateStructGEP(LabelVAAlloca, n);
IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr);
}
Args.push_back(IRB.CreateStructGEP(LabelVAAlloca, 0));
}
if (!FT->getReturnType()->isVoidTy()) {
if (!DFSF.LabelReturnAlloca) {
DFSF.LabelReturnAlloca =
@ -1451,6 +1461,9 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
Args.push_back(DFSF.LabelReturnAlloca);
}
for (i = CS.arg_begin() + FT->getNumParams(); i != CS.arg_end(); ++i)
Args.push_back(*i);
CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
CustomCI->setCallingConv(CI->getCallingConv());
CustomCI->setAttributes(CI->getAttributes());