forked from OSchip/llvm-project
[MSan][MIPS] VarArgHelper for MIPS64
Reviewers: Reviewers: eugenis, kcc, samsonov, petarj Subscribers: dsanders, sagar, llvm-commits Differential Revision: http://reviews.llvm.org/D7182 llvm-svn: 229667
This commit is contained in:
parent
81e9239e07
commit
518946e440
|
@ -337,6 +337,7 @@ class MemorySanitizer : public FunctionPass {
|
|||
|
||||
friend struct MemorySanitizerVisitor;
|
||||
friend struct VarArgAMD64Helper;
|
||||
friend struct VarArgMIPS64Helper;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -2844,6 +2845,106 @@ struct VarArgAMD64Helper : public VarArgHelper {
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief MIPS64-specific implementation of VarArgHelper.
|
||||
struct VarArgMIPS64Helper : public VarArgHelper {
|
||||
Function &F;
|
||||
MemorySanitizer &MS;
|
||||
MemorySanitizerVisitor &MSV;
|
||||
Value *VAArgTLSCopy;
|
||||
Value *VAArgSize;
|
||||
|
||||
SmallVector<CallInst*, 16> VAStartInstrumentationList;
|
||||
|
||||
VarArgMIPS64Helper(Function &F, MemorySanitizer &MS,
|
||||
MemorySanitizerVisitor &MSV)
|
||||
: F(F), MS(MS), MSV(MSV), VAArgTLSCopy(nullptr),
|
||||
VAArgSize(nullptr) {}
|
||||
|
||||
void visitCallSite(CallSite &CS, IRBuilder<> &IRB) override {
|
||||
unsigned VAArgOffset = 0;
|
||||
for (CallSite::arg_iterator ArgIt = CS.arg_begin() + 1, End = CS.arg_end();
|
||||
ArgIt != End; ++ArgIt) {
|
||||
Value *A = *ArgIt;
|
||||
Value *Base;
|
||||
uint64_t ArgSize = MS.DL->getTypeAllocSize(A->getType());
|
||||
#if defined(__MIPSEB__) || defined(MIPSEB)
|
||||
// Adjusting the shadow for argument with size < 8 to match the placement
|
||||
// of bits in big endian system
|
||||
if (ArgSize < 8)
|
||||
VAArgOffset += (8 - ArgSize);
|
||||
#endif
|
||||
Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset);
|
||||
VAArgOffset += ArgSize;
|
||||
VAArgOffset = RoundUpToAlignment(VAArgOffset, 8);
|
||||
IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
|
||||
}
|
||||
|
||||
Constant *TotalVAArgSize = ConstantInt::get(IRB.getInt64Ty(), VAArgOffset);
|
||||
// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
|
||||
// a new class member i.e. it is the total size of all VarArgs.
|
||||
IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
|
||||
}
|
||||
|
||||
/// \brief Compute the shadow address for a given va_arg.
|
||||
Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
|
||||
int ArgOffset) {
|
||||
Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
|
||||
Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
|
||||
return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
|
||||
"_msarg");
|
||||
}
|
||||
|
||||
void visitVAStartInst(VAStartInst &I) override {
|
||||
IRBuilder<> IRB(&I);
|
||||
VAStartInstrumentationList.push_back(&I);
|
||||
Value *VAListTag = I.getArgOperand(0);
|
||||
Value *ShadowPtr = MSV.getShadowPtr(VAListTag, IRB.getInt8Ty(), IRB);
|
||||
IRB.CreateMemSet(ShadowPtr, Constant::getNullValue(IRB.getInt8Ty()),
|
||||
/* size */8, /* alignment */8, false);
|
||||
}
|
||||
|
||||
void visitVACopyInst(VACopyInst &I) override {
|
||||
IRBuilder<> IRB(&I);
|
||||
Value *VAListTag = I.getArgOperand(0);
|
||||
Value *ShadowPtr = MSV.getShadowPtr(VAListTag, IRB.getInt8Ty(), IRB);
|
||||
// Unpoison the whole __va_list_tag.
|
||||
// FIXME: magic ABI constants.
|
||||
IRB.CreateMemSet(ShadowPtr, Constant::getNullValue(IRB.getInt8Ty()),
|
||||
/* size */8, /* alignment */8, false);
|
||||
}
|
||||
|
||||
void finalizeInstrumentation() override {
|
||||
assert(!VAArgSize && !VAArgTLSCopy &&
|
||||
"finalizeInstrumentation called twice");
|
||||
IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI());
|
||||
VAArgSize = IRB.CreateLoad(MS.VAArgOverflowSizeTLS);
|
||||
Value *CopySize = IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0),
|
||||
VAArgSize);
|
||||
|
||||
if (!VAStartInstrumentationList.empty()) {
|
||||
// If there is a va_start in this function, make a backup copy of
|
||||
// va_arg_tls somewhere in the function entry block.
|
||||
VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
|
||||
IRB.CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8);
|
||||
}
|
||||
|
||||
// Instrument va_start.
|
||||
// Copy va_list shadow from the backup copy of the TLS contents.
|
||||
for (size_t i = 0, n = VAStartInstrumentationList.size(); i < n; i++) {
|
||||
CallInst *OrigInst = VAStartInstrumentationList[i];
|
||||
IRBuilder<> IRB(OrigInst->getNextNode());
|
||||
Value *VAListTag = OrigInst->getArgOperand(0);
|
||||
Value *RegSaveAreaPtrPtr =
|
||||
IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
|
||||
Type::getInt64PtrTy(*MS.C));
|
||||
Value *RegSaveAreaPtr = IRB.CreateLoad(RegSaveAreaPtrPtr);
|
||||
Value *RegSaveAreaShadowPtr =
|
||||
MSV.getShadowPtr(RegSaveAreaPtr, IRB.getInt8Ty(), IRB);
|
||||
IRB.CreateMemCpy(RegSaveAreaShadowPtr, VAArgTLSCopy, CopySize, 8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A no-op implementation of VarArgHelper.
|
||||
struct VarArgNoOpHelper : public VarArgHelper {
|
||||
VarArgNoOpHelper(Function &F, MemorySanitizer &MS,
|
||||
|
@ -2865,6 +2966,9 @@ VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
|
|||
llvm::Triple TargetTriple(Func.getParent()->getTargetTriple());
|
||||
if (TargetTriple.getArch() == llvm::Triple::x86_64)
|
||||
return new VarArgAMD64Helper(Func, Msan, Visitor);
|
||||
else if (TargetTriple.getArch() == llvm::Triple::mips64 ||
|
||||
TargetTriple.getArch() == llvm::Triple::mips64el)
|
||||
return new VarArgMIPS64Helper(Func, Msan, Visitor);
|
||||
else
|
||||
return new VarArgNoOpHelper(Func, Msan, Visitor);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue