llvm.org GIT mirror llvm / ffba4c7
DataFlowSanitizer: Implement trampolines for function pointers passed to custom functions. Differential Revision: http://llvm-reviews.chandlerc.com/D1503 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189408 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 7 years ago
3 changed file(s) with 94 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
4747 #include "llvm/ADT/DenseMap.h"
4848 #include "llvm/ADT/DenseSet.h"
4949 #include "llvm/ADT/DepthFirstIterator.h"
50 #include "llvm/ADT/StringExtras.h"
5051 #include "llvm/Analysis/ValueTracking.h"
5152 #include "llvm/IR/InlineAsm.h"
5253 #include "llvm/IR/IRBuilder.h"
181182 bool isInstrumented(const Function *F);
182183 bool isInstrumented(const GlobalAlias *GA);
183184 FunctionType *getArgsFunctionType(FunctionType *T);
185 FunctionType *getTrampolineFunctionType(FunctionType *T);
184186 FunctionType *getCustomFunctionType(FunctionType *T);
185187 InstrumentedABI getInstrumentedABI();
186188 WrapperKind getWrapperKind(Function *F);
188190 Function *buildWrapperFunction(Function *F, StringRef NewFName,
189191 GlobalValue::LinkageTypes NewFLink,
190192 FunctionType *NewFT);
193 Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName);
191194
192195 public:
193196 DataFlowSanitizer(StringRef ABIListFile = StringRef(),
287290 return FunctionType::get(RetType, ArgTypes, T->isVarArg());
288291 }
289292
293 FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) {
294 assert(!T->isVarArg());
295 llvm::SmallVector ArgTypes;
296 ArgTypes.push_back(T->getPointerTo());
297 std::copy(T->param_begin(), T->param_end(), std::back_inserter(ArgTypes));
298 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i)
299 ArgTypes.push_back(ShadowTy);
300 Type *RetType = T->getReturnType();
301 if (!RetType->isVoidTy())
302 ArgTypes.push_back(ShadowPtrTy);
303 return FunctionType::get(T->getReturnType(), ArgTypes, false);
304 }
305
290306 FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
291307 assert(!T->isVarArg());
292308 llvm::SmallVector ArgTypes;
293 std::copy(T->param_begin(), T->param_end(), std::back_inserter(ArgTypes));
309 for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end(); i != e; ++i) {
310 FunctionType *FT;
311 if (isa(*i) &&
312 (FT = dyn_cast(cast(*i)->getElementType()))) {
313 ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo());
314 ArgTypes.push_back(Type::getInt8PtrTy(*Ctx));
315 } else {
316 ArgTypes.push_back(*i);
317 }
318 }
294319 for (unsigned i = 0, e = T->getNumParams(); i != e; ++i)
295320 ArgTypes.push_back(ShadowTy);
296321 Type *RetType = T->getReturnType();
414439 ReturnInst::Create(*Ctx, CI, BB);
415440
416441 return NewF;
442 }
443
444 Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT,
445 StringRef FName) {
446 FunctionType *FTT = getTrampolineFunctionType(FT);
447 Constant *C = Mod->getOrInsertFunction(FName, FTT);
448 Function *F = dyn_cast(C);
449 if (F && F->isDeclaration()) {
450 F->setLinkage(GlobalValue::LinkOnceODRLinkage);
451 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
452 std::vector Args;
453 Function::arg_iterator AI = F->arg_begin(); ++AI;
454 for (unsigned N = FT->getNumParams(); N != 0; ++AI, --N)
455 Args.push_back(&*AI);
456 CallInst *CI =
457 CallInst::Create(&F->getArgumentList().front(), Args, "", BB);
458 ReturnInst *RI;
459 if (FT->getReturnType()->isVoidTy())
460 RI = ReturnInst::Create(*Ctx, BB);
461 else
462 RI = ReturnInst::Create(*Ctx, CI, BB);
463
464 DFSanFunction DFSF(*this, F, /*IsNativeABI=*/true);
465 Function::arg_iterator ValAI = F->arg_begin(), ShadowAI = AI; ++ValAI;
466 for (unsigned N = FT->getNumParams(); N != 0; ++ValAI, ++ShadowAI, --N)
467 DFSF.ValShadowMap[ValAI] = ShadowAI;
468 DFSanVisitor(DFSF).visitCallInst(*CI);
469 if (!FT->getReturnType()->isVoidTy())
470 new StoreInst(DFSF.getShadow(RI->getReturnValue()),
471 &F->getArgumentList().back(), RI);
472 }
473
474 return C;
417475 }
418476
419477 bool DataFlowSanitizer::runOnModule(Module &M) {
11801238 std::vector Args;
11811239
11821240 CallSite::arg_iterator i = CS.arg_begin();
1183 for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
1184 Args.push_back(*i);
1241 for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) {
1242 Type *T = (*i)->getType();
1243 FunctionType *ParamFT;
1244 if (isa(T) &&
1245 (ParamFT = dyn_cast(
1246 cast(T)->getElementType()))) {
1247 std::string TName = "dfst";
1248 TName += utostr(FT->getNumParams() - n);
1249 TName += "$";
1250 TName += F->getName();
1251 Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
1252 Args.push_back(T);
1253 Args.push_back(
1254 IRB.CreateBitCast(*i, Type::getInt8PtrTy(*DFSF.DFS.Ctx)));
1255 } else {
1256 Args.push_back(*i);
1257 }
1258 }
11851259
11861260 i = CS.arg_begin();
11871261 for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
33 fun:functional=uninstrumented
44 fun:functional=functional
55
6 fun:custom1=uninstrumented
7 fun:custom1=custom
8
9 fun:custom2=uninstrumented
10 fun:custom2=custom
6 fun:custom*=uninstrumented
7 fun:custom*=custom
1515
1616 declare i32 @custom2(i32 %a, i32 %b)
1717
18 declare void @customcb(i32 (i32)* %cb)
19
20 declare i32 @cb(i32)
21
1822 ; CHECK: @"dfs$f"
1923 define void @f() {
2024 ; CHECK: %[[LABELRETURN:.*]] = alloca i16
2428
2529 ; CHECK: call i32 @__dfsw_custom2(i32 1, i32 2, i16 0, i16 0, i16* %[[LABELRETURN]])
2630 call i32 @custom2(i32 1, i32 2)
31
32 ; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @"dfs$cb" to i8*), i16 0)
33 call void @customcb(i32 (i32)* @cb)
2734
2835 ret void
2936 }
5764
5865 ; CHECK: declare void @__dfsw_custom1(i32, i32, i16, i16)
5966 ; CHECK: declare i32 @__dfsw_custom2(i32, i32, i16, i16, i16*)
67
68 ; CHECK-LABEL: define linkonce_odr i32 @"dfst0$customcb"(i32 (i32)*, i32, i16, i16*)
69 ; CHECK: %[[BC:.*]] = bitcast i32 (i32)* %0 to { i32, i16 } (i32, i16)*
70 ; CHECK: %[[CALL:.*]] = call { i32, i16 } %[[BC]](i32 %1, i16 %2)
71 ; CHECK: %[[XVAL0:.*]] = extractvalue { i32, i16 } %[[CALL]], 0
72 ; CHECK: %[[XVAL1:.*]] = extractvalue { i32, i16 } %[[CALL]], 1
73 ; CHECK: store i16 %[[XVAL1]], i16* %3
74 ; CHECK: ret i32 %[[XVAL0]]