llvm.org GIT mirror llvm / 1c8b825
[ASan] Fix lifetime intrinsics handling. Now for each intrinsic we check if it describes one of 'interesting' allocas. Assume that allocas can go through casts and phi-nodes before apperaring as llvm.lifetime arguments git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171153 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 6 years ago
2 changed file(s) with 118 addition(s) and 73 deletion(s). Raw diff Collapse all Expand all
1717 #include "llvm/Transforms/Instrumentation.h"
1818 #include "BlackList.h"
1919 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/DenseMap.h"
2021 #include "llvm/ADT/DepthFirstIterator.h"
2122 #include "llvm/ADT/OwningPtr.h"
2223 #include "llvm/ADT/SmallSet.h"
315316 Function *AsanStackMallocFunc, *AsanStackFreeFunc;
316317 Function *AsanPoisonStackMemoryFunc, *AsanUnpoisonStackMemoryFunc;
317318
319 // Stores a place and arguments of poisoning/unpoisoning call for alloca.
320 struct AllocaPoisonCall {
321 IntrinsicInst *InsBefore;
322 uint64_t Size;
323 bool DoPoison;
324 };
325 SmallVector AllocaPoisonCallVec;
326
327 // Maps Value to an AllocaInst from which the Value is originated.
328 typedef DenseMap AllocaForValueMapTy;
329 AllocaForValueMapTy AllocaForValue;
330
318331 FunctionStackPoisoner(Function &F, AddressSanitizer &ASan)
319332 : F(F), ASan(ASan), DIB(*F.getParent()), C(ASan.C),
320333 IntptrTy(ASan.IntptrTy), IntptrPtrTy(PointerType::get(IntptrTy, 0)),
353366
354367 /// \brief Collect Alloca instructions we want (and can) handle.
355368 void visitAllocaInst(AllocaInst &AI) {
356 if (AI.isArrayAllocation()) return;
357 if (!AI.isStaticAlloca()) return;
358 if (!AI.getAllocatedType()->isSized()) return;
369 if (!isInterestingAlloca(AI)) return;
359370
360371 StackAlignment = std::max(StackAlignment, AI.getAlignment());
361372 AllocaVec.push_back(&AI);
363374 TotalStackSize += AlignedSize;
364375 }
365376
377 /// \brief Collect lifetime intrinsic calls to check for use-after-scope
378 /// errors.
379 void visitIntrinsicInst(IntrinsicInst &II) {
380 if (!ASan.CheckLifetime) return;
381 Intrinsic::ID ID = II.getIntrinsicID();
382 if (ID != Intrinsic::lifetime_start &&
383 ID != Intrinsic::lifetime_end)
384 return;
385 // Found lifetime intrinsic, add ASan instrumentation if necessary.
386 ConstantInt *Size = dyn_cast(II.getArgOperand(0));
387 // If size argument is undefined, don't do anything.
388 if (Size->isMinusOne()) return;
389 // Check that size doesn't saturate uint64_t and can
390 // be stored in IntptrTy.
391 const uint64_t SizeValue = Size->getValue().getLimitedValue();
392 if (SizeValue == ~0ULL ||
393 !ConstantInt::isValueValidForType(IntptrTy, SizeValue))
394 return;
395 // Find alloca instruction that corresponds to llvm.lifetime argument.
396 AllocaInst *AI = findAllocaForValue(II.getArgOperand(1));
397 if (!AI) return;
398 bool DoPoison = (ID == Intrinsic::lifetime_end);
399 AllocaPoisonCall APC = {&II, SizeValue, DoPoison};
400 AllocaPoisonCallVec.push_back(APC);
401 }
402
366403 // ---------------------- Helpers.
367404 void initializeCallbacks(Module &M);
405
406 // Check if we want (and can) handle this alloca.
407 bool isInterestingAlloca(AllocaInst &AI) {
408 return (!AI.isArrayAllocation() &&
409 AI.isStaticAlloca() &&
410 AI.getAllocatedType()->isSized());
411 }
368412
369413 uint64_t getAllocaSizeInBytes(AllocaInst *AI) {
370414 Type *Ty = AI->getAllocatedType();
379423 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
380424 return getAlignedSize(SizeInBytes);
381425 }
426 /// Finds alloca where the value comes from.
427 AllocaInst *findAllocaForValue(Value *V);
382428 void poisonRedZones(const ArrayRef &AllocaVec, IRBuilder<> IRB,
383429 Value *ShadowBase, bool DoPoison);
384430 void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> IRB, bool DoPoison);
385 /// Analyze lifetime intrinsics for given alloca. Use Value* instead of
386 /// AllocaInst* here, as we call this method after we merge all allocas into a
387 /// single one. Returns true if ASan added some instrumentation.
388 bool handleAllocaLifetime(Value *Alloca);
389 /// Analyze lifetime intrinsics for a specific value, casted from alloca.
390 /// Returns true if if ASan added some instrumentation.
391 bool handleValueLifetime(Value *V);
392431 };
393432
394433 } // namespace
11531192 // Poison the full redzone at right.
11541193 Ptr = IRB.CreateAdd(ShadowBase,
11551194 ConstantInt::get(IntptrTy, Pos >> MappingScale()));
1156 Value *Poison = i == AllocaVec.size() - 1 ? PoisonRight : PoisonMid;
1195 bool LastAlloca = (i == AllocaVec.size() - 1);
1196 Value *Poison = LastAlloca ? PoisonRight : PoisonMid;
11571197 IRB.CreateStore(Poison, IRB.CreateIntToPtr(Ptr, RZPtrTy));
11581198
11591199 Pos += RedzoneSize();
11611201 }
11621202
11631203 void FunctionStackPoisoner::poisonStack() {
1164 bool HavePoisonedAllocas = false;
11651204 uint64_t LocalStackSize = TotalStackSize +
11661205 (AllocaVec.size() + 1) * RedzoneSize();
11671206
11681207 bool DoStackMalloc = ASan.CheckUseAfterReturn
11691208 && LocalStackSize <= kMaxStackMallocSize;
11701209
1210 assert(AllocaVec.size() > 0);
11711211 Instruction *InsBefore = AllocaVec[0];
11721212 IRBuilder<> IRB(InsBefore);
11731213
11911231 SmallString<2048> StackDescriptionStorage;
11921232 raw_svector_ostream StackDescription(StackDescriptionStorage);
11931233 StackDescription << F.getName() << " " << AllocaVec.size() << " ";
1234
1235 // Insert poison calls for lifetime intrinsics for alloca.
1236 bool HavePoisonedAllocas = false;
1237 for (size_t i = 0, n = AllocaPoisonCallVec.size(); i < n; i++) {
1238 const AllocaPoisonCall &APC = AllocaPoisonCallVec[i];
1239 IntrinsicInst *II = APC.InsBefore;
1240 AllocaInst *AI = findAllocaForValue(II->getArgOperand(1));
1241 assert(AI);
1242 IRBuilder<> IRB(II);
1243 poisonAlloca(AI, APC.Size, IRB, APC.DoPoison);
1244 HavePoisonedAllocas |= APC.DoPoison;
1245 }
11941246
11951247 uint64_t Pos = RedzoneSize();
11961248 // Replace Alloca instructions with base+offset.
12071259 AI->getType());
12081260 replaceDbgDeclareForAlloca(AI, NewAllocaPtr, DIB);
12091261 AI->replaceAllUsesWith(NewAllocaPtr);
1210 // Analyze lifetime intrinsics only for static allocas we handle.
1211 if (ASan.CheckLifetime)
1212 HavePoisonedAllocas |= handleAllocaLifetime(NewAllocaPtr);
12131262 Pos += AlignedSize + RedzoneSize();
12141263 }
12151264 assert(Pos == LocalStackSize);
12771326 // variable may go in and out of scope several times, e.g. in loops).
12781327 // (3) if we poisoned at least one %alloca in a function,
12791328 // unpoison the whole stack frame at function exit.
1280 bool FunctionStackPoisoner::handleAllocaLifetime(Value *Alloca) {
1281 assert(ASan.CheckLifetime);
1282 Type *AllocaType = Alloca->getType();
1283 Type *Int8PtrTy = Type::getInt8PtrTy(AllocaType->getContext());
1284
1285 bool Res = false;
1286 // Typical code looks like this:
1287 // %alloca = alloca ,
1288 // ... some code ...
1289 // %val1 = bitcast * %alloca to i8*
1290 // call void @llvm.lifetime.start(i64 , i8* %val1)
1291 // ... more code ...
1292 // %val2 = bitcast * %alloca to i8*
1293 // call void @llvm.lifetime.start(i64 , i8* %val2)
1294 // That is, to handle %alloca we must find all its casts to
1295 // i8* values, and find lifetime instructions for these values.
1296 if (AllocaType == Int8PtrTy)
1297 Res |= handleValueLifetime(Alloca);
1298 for (Value::use_iterator UI = Alloca->use_begin(), UE = Alloca->use_end();
1299 UI != UE; ++UI) {
1300 if (UI->getType() != Int8PtrTy) continue;
1301 if (UI->stripPointerCasts() != Alloca) continue;
1302 Res |= handleValueLifetime(*UI);
1303 }
1329
1330 AllocaInst *FunctionStackPoisoner::findAllocaForValue(Value *V) {
1331 if (AllocaInst *AI = dyn_cast(V))
1332 // We're intested only in allocas we can handle.
1333 return isInterestingAlloca(*AI) ? AI : 0;
1334 // See if we've already calculated (or started to calculate) alloca for a
1335 // given value.
1336 AllocaForValueMapTy::iterator I = AllocaForValue.find(V);
1337 if (I != AllocaForValue.end())
1338 return I->second;
1339 // Store 0 while we're calculating alloca for value V to avoid
1340 // infinite recursion if the value references itself.
1341 AllocaForValue[V] = 0;
1342 AllocaInst *Res = 0;
1343 if (CastInst *CI = dyn_cast(V))
1344 Res = findAllocaForValue(CI->getOperand(0));
1345 else if (PHINode *PN = dyn_cast(V)) {
1346 for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
1347 Value *IncValue = PN->getIncomingValue(i);
1348 // Allow self-referencing phi-nodes.
1349 if (IncValue == PN) continue;
1350 AllocaInst *IncValueAI = findAllocaForValue(IncValue);
1351 // AI for incoming values should exist and should all be equal.
1352 if (IncValueAI == 0 || (Res != 0 && IncValueAI != Res))
1353 return 0;
1354 Res = IncValueAI;
1355 }
1356 }
1357 if (Res != 0)
1358 AllocaForValue[V] = Res;
13041359 return Res;
13051360 }
1306
1307 bool FunctionStackPoisoner::handleValueLifetime(Value *V) {
1308 assert(ASan.CheckLifetime);
1309 bool Res = false;
1310 for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;
1311 ++UI) {
1312 IntrinsicInst *II = dyn_cast(*UI);
1313 if (!II) continue;
1314 Intrinsic::ID ID = II->getIntrinsicID();
1315 if (ID != Intrinsic::lifetime_start &&
1316 ID != Intrinsic::lifetime_end)
1317 continue;
1318 if (V != II->getArgOperand(1))
1319 continue;
1320 // Found lifetime intrinsic, add ASan instrumentation if necessary.
1321 ConstantInt *Size = dyn_cast(II->getArgOperand(0));
1322 // If size argument is undefined, don't do anything.
1323 if (Size->isMinusOne())
1324 continue;
1325 // Check that size doesn't saturate uint64_t and can
1326 // be stored in IntptrTy.
1327 const uint64_t SizeValue = Size->getValue().getLimitedValue();
1328 if (SizeValue == ~0ULL ||
1329 !ConstantInt::isValueValidForType(IntptrTy, SizeValue)) {
1330 continue;
1331 }
1332 IRBuilder<> IRB(II);
1333 bool DoPoison = (ID == Intrinsic::lifetime_end);
1334 poisonAlloca(V, SizeValue, IRB, DoPoison);
1335 Res = true;
1336 }
1337 return Res;
1338 }
3030 %i.ptr = bitcast i32* %i to i8*
3131 call void @llvm.lifetime.start(i64 3, i8* %i.ptr)
3232 ; Memory is unpoisoned at llvm.lifetime.start
33 ; CHECK: %[[VAR:[^ ]*]] = ptrtoint i8* %i.ptr to i64
33 ; CHECK: %[[VAR:[^ ]*]] = ptrtoint i32* %{{[^ ]+}} to i64
3434 ; CHECK-NEXT: call void @__asan_unpoison_stack_memory(i64 %[[VAR]], i64 3)
3535 call void @llvm.lifetime.end(i64 4, i8* %i.ptr)
3636 call void @llvm.lifetime.end(i64 2, i8* %i.ptr)
5858 ; CHECK: ret void
5959 ret void
6060 }
61
62 ; Check that arguments of lifetime may come from phi nodes.
63 define void @phi_args(i1 %x) address_safety {
64 ; CHECK: @phi_args
65
66 entry:
67 %i = alloca i64, align 4
68 %i.ptr = bitcast i64* %i to i8*
69 call void @llvm.lifetime.start(i64 8, i8* %i.ptr)
70 ; CHECK: __asan_unpoison_stack_memory
71 br i1 %x, label %bb0, label %bb1
72
73 bb0:
74 %i.ptr2 = bitcast i64* %i to i8*
75 br label %bb1
76
77 bb1:
78 %i.phi = phi i8* [ %i.ptr, %entry ], [ %i.ptr2, %bb0 ]
79 call void @llvm.lifetime.end(i64 8, i8* %i.phi)
80 ; CHECK: __asan_poison_stack_memory
81 ; CHECK: ret void
82 ret void
83 }