1 //===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// This file is a part of HWAddressSanitizer, an address sanity checker 12 /// based on tagged addressing. 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/IR/Attributes.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/Constant.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/IRBuilder.h" 27 #include "llvm/IR/InlineAsm.h" 28 #include "llvm/IR/InstVisitor.h" 29 #include "llvm/IR/Instruction.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/IntrinsicInst.h" 32 #include "llvm/IR/Intrinsics.h" 33 #include "llvm/IR/LLVMContext.h" 34 #include "llvm/IR/MDBuilder.h" 35 #include "llvm/IR/Module.h" 36 #include "llvm/IR/Type.h" 37 #include "llvm/IR/Value.h" 38 #include "llvm/Pass.h" 39 #include "llvm/Support/Casting.h" 40 #include "llvm/Support/CommandLine.h" 41 #include "llvm/Support/Debug.h" 42 #include "llvm/Support/raw_ostream.h" 43 #include "llvm/Transforms/Instrumentation.h" 44 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 45 #include "llvm/Transforms/Utils/ModuleUtils.h" 46 #include "llvm/Transforms/Utils/PromoteMemToReg.h" 47 48 using namespace llvm; 49 50 #define DEBUG_TYPE "hwasan" 51 52 static const char *const kHwasanModuleCtorName = "hwasan.module_ctor"; 53 static const char *const kHwasanInitName = "__hwasan_init"; 54 55 // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 56 static const size_t kNumberOfAccessSizes = 5; 57 58 static const size_t kShadowScale = 4; 59 static const unsigned kAllocaAlignment = 1U << kShadowScale; 60 static const unsigned kPointerTagShift = 56; 61 62 static cl::opt<std::string> ClMemoryAccessCallbackPrefix( 63 "hwasan-memory-access-callback-prefix", 64 cl::desc("Prefix for memory access callbacks"), cl::Hidden, 65 cl::init("__hwasan_")); 66 67 static cl::opt<bool> 68 ClInstrumentWithCalls("hwasan-instrument-with-calls", 69 cl::desc("instrument reads and writes with callbacks"), 70 cl::Hidden, cl::init(false)); 71 72 static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads", 73 cl::desc("instrument read instructions"), 74 cl::Hidden, cl::init(true)); 75 76 static cl::opt<bool> ClInstrumentWrites( 77 "hwasan-instrument-writes", cl::desc("instrument write instructions"), 78 cl::Hidden, cl::init(true)); 79 80 static cl::opt<bool> ClInstrumentAtomics( 81 "hwasan-instrument-atomics", 82 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, 83 cl::init(true)); 84 85 static cl::opt<bool> ClRecover( 86 "hwasan-recover", 87 cl::desc("Enable recovery mode (continue-after-error)."), 88 cl::Hidden, cl::init(false)); 89 90 static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack", 91 cl::desc("instrument stack (allocas)"), 92 cl::Hidden, cl::init(true)); 93 94 static cl::opt<bool> ClGenerateTagsWithCalls( 95 "hwasan-generate-tags-with-calls", 96 cl::desc("generate new tags with runtime library calls"), cl::Hidden, 97 cl::init(false)); 98 99 static cl::opt<unsigned long long> ClMappingOffset( 100 "hwasan-mapping-offset", 101 cl::desc("offset of hwasan shadow mapping [EXPERIMENTAL]"), cl::Hidden, 102 cl::init(0)); 103 104 static cl::opt<bool> ClEnableKhwasan( 105 "hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), 106 cl::Hidden, cl::init(false)); 107 108 namespace { 109 110 /// \brief An instrumentation pass implementing detection of addressability bugs 111 /// using tagged pointers. 112 class HWAddressSanitizer : public FunctionPass { 113 public: 114 // Pass identification, replacement for typeid. 115 static char ID; 116 117 HWAddressSanitizer(bool Recover = false) 118 : FunctionPass(ID), Recover(Recover || ClRecover) {} 119 120 StringRef getPassName() const override { return "HWAddressSanitizer"; } 121 122 bool runOnFunction(Function &F) override; 123 bool doInitialization(Module &M) override; 124 125 void initializeCallbacks(Module &M); 126 void instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 127 unsigned AccessSizeIndex, 128 Instruction *InsertBefore); 129 bool instrumentMemAccess(Instruction *I); 130 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, 131 uint64_t *TypeSize, unsigned *Alignment, 132 Value **MaybeMask); 133 134 bool isInterestingAlloca(const AllocaInst &AI); 135 bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag); 136 bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas, 137 SmallVectorImpl<Instruction *> &RetVec); 138 Value *getNextTagWithCall(IRBuilder<> &IRB); 139 Value *getStackBaseTag(IRBuilder<> &IRB); 140 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI, 141 unsigned AllocaNo); 142 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag); 143 144 private: 145 LLVMContext *C; 146 Type *IntptrTy; 147 Type *Int8Ty; 148 149 bool Recover; 150 151 Function *HwasanCtorFunction; 152 153 Function *HwasanMemoryAccessCallback[2][kNumberOfAccessSizes]; 154 Function *HwasanMemoryAccessCallbackSized[2]; 155 156 Function *HwasanTagMemoryFunc; 157 Function *HwasanGenerateTagFunc; 158 }; 159 160 } // end anonymous namespace 161 162 char HWAddressSanitizer::ID = 0; 163 164 INITIALIZE_PASS_BEGIN( 165 HWAddressSanitizer, "hwasan", 166 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false) 167 INITIALIZE_PASS_END( 168 HWAddressSanitizer, "hwasan", 169 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, false) 170 171 FunctionPass *llvm::createHWAddressSanitizerPass(bool Recover) { 172 return new HWAddressSanitizer(Recover); 173 } 174 175 /// \brief Module-level initialization. 176 /// 177 /// inserts a call to __hwasan_init to the module's constructor list. 178 bool HWAddressSanitizer::doInitialization(Module &M) { 179 DEBUG(dbgs() << "Init " << M.getName() << "\n"); 180 auto &DL = M.getDataLayout(); 181 182 Triple TargetTriple(M.getTargetTriple()); 183 184 C = &(M.getContext()); 185 IRBuilder<> IRB(*C); 186 IntptrTy = IRB.getIntPtrTy(DL); 187 Int8Ty = IRB.getInt8Ty(); 188 189 HwasanCtorFunction = nullptr; 190 if (!ClEnableKhwasan) { 191 std::tie(HwasanCtorFunction, std::ignore) = 192 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName, 193 kHwasanInitName, 194 /*InitArgTypes=*/{}, 195 /*InitArgs=*/{}); 196 appendToGlobalCtors(M, HwasanCtorFunction, 0); 197 } 198 return true; 199 } 200 201 void HWAddressSanitizer::initializeCallbacks(Module &M) { 202 IRBuilder<> IRB(*C); 203 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 204 const std::string TypeStr = AccessIsWrite ? "store" : "load"; 205 const std::string EndingStr = Recover ? "_noabort" : ""; 206 207 HwasanMemoryAccessCallbackSized[AccessIsWrite] = 208 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 209 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr, 210 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false))); 211 212 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 213 AccessSizeIndex++) { 214 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] = 215 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 216 ClMemoryAccessCallbackPrefix + TypeStr + 217 itostr(1ULL << AccessSizeIndex) + EndingStr, 218 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false))); 219 } 220 } 221 222 HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 223 "__hwasan_tag_memory", IRB.getVoidTy(), IntptrTy, Int8Ty, IntptrTy)); 224 HwasanGenerateTagFunc = checkSanitizerInterfaceFunction( 225 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty)); 226 } 227 228 Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, 229 bool *IsWrite, 230 uint64_t *TypeSize, 231 unsigned *Alignment, 232 Value **MaybeMask) { 233 // Skip memory accesses inserted by another instrumentation. 234 if (I->getMetadata("nosanitize")) return nullptr; 235 236 Value *PtrOperand = nullptr; 237 const DataLayout &DL = I->getModule()->getDataLayout(); 238 if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 239 if (!ClInstrumentReads) return nullptr; 240 *IsWrite = false; 241 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType()); 242 *Alignment = LI->getAlignment(); 243 PtrOperand = LI->getPointerOperand(); 244 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 245 if (!ClInstrumentWrites) return nullptr; 246 *IsWrite = true; 247 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType()); 248 *Alignment = SI->getAlignment(); 249 PtrOperand = SI->getPointerOperand(); 250 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 251 if (!ClInstrumentAtomics) return nullptr; 252 *IsWrite = true; 253 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType()); 254 *Alignment = 0; 255 PtrOperand = RMW->getPointerOperand(); 256 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 257 if (!ClInstrumentAtomics) return nullptr; 258 *IsWrite = true; 259 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType()); 260 *Alignment = 0; 261 PtrOperand = XCHG->getPointerOperand(); 262 } 263 264 if (PtrOperand) { 265 // Do not instrument acesses from different address spaces; we cannot deal 266 // with them. 267 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType()); 268 if (PtrTy->getPointerAddressSpace() != 0) 269 return nullptr; 270 271 // Ignore swifterror addresses. 272 // swifterror memory addresses are mem2reg promoted by instruction 273 // selection. As such they cannot have regular uses like an instrumentation 274 // function and it makes no sense to track them as memory. 275 if (PtrOperand->isSwiftError()) 276 return nullptr; 277 } 278 279 return PtrOperand; 280 } 281 282 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 283 size_t Res = countTrailingZeros(TypeSize / 8); 284 assert(Res < kNumberOfAccessSizes); 285 return Res; 286 } 287 288 void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 289 unsigned AccessSizeIndex, 290 Instruction *InsertBefore) { 291 IRBuilder<> IRB(InsertBefore); 292 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), IRB.getInt8Ty()); 293 Value *AddrLong = 294 IRB.CreateAnd(PtrLong, ConstantInt::get(PtrLong->getType(), 295 ~(0xFFULL << kPointerTagShift))); 296 Value *ShadowLong = IRB.CreateLShr(AddrLong, kShadowScale); 297 if (ClMappingOffset) 298 ShadowLong = IRB.CreateAdd( 299 ShadowLong, ConstantInt::get(PtrLong->getType(), ClMappingOffset, 300 /*isSigned=*/false)); 301 Value *MemTag = 302 IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, IRB.getInt8PtrTy())); 303 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag); 304 305 TerminatorInst *CheckTerm = 306 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover, 307 MDBuilder(*C).createBranchWeights(1, 100000)); 308 309 IRB.SetInsertPoint(CheckTerm); 310 // The signal handler will find the data address in x0. 311 InlineAsm *Asm = InlineAsm::get( 312 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 313 "hlt #" + 314 itostr(0x100 + Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex), 315 "{x0}", 316 /*hasSideEffects=*/true); 317 IRB.CreateCall(Asm, PtrLong); 318 } 319 320 bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) { 321 DEBUG(dbgs() << "Instrumenting: " << *I << "\n"); 322 bool IsWrite = false; 323 unsigned Alignment = 0; 324 uint64_t TypeSize = 0; 325 Value *MaybeMask = nullptr; 326 Value *Addr = 327 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask); 328 329 if (!Addr) 330 return false; 331 332 if (MaybeMask) 333 return false; //FIXME 334 335 IRBuilder<> IRB(I); 336 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 337 if (isPowerOf2_64(TypeSize) && 338 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) && 339 (Alignment >= (1UL << kShadowScale) || Alignment == 0 || 340 Alignment >= TypeSize / 8)) { 341 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 342 if (ClInstrumentWithCalls) { 343 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex], 344 AddrLong); 345 } else { 346 instrumentMemAccessInline(AddrLong, IsWrite, AccessSizeIndex, I); 347 } 348 } else { 349 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite], 350 {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)}); 351 } 352 353 return true; 354 } 355 356 static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) { 357 uint64_t ArraySize = 1; 358 if (AI.isArrayAllocation()) { 359 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize()); 360 assert(CI && "non-constant array size"); 361 ArraySize = CI->getZExtValue(); 362 } 363 Type *Ty = AI.getAllocatedType(); 364 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty); 365 return SizeInBytes * ArraySize; 366 } 367 368 bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, 369 Value *Tag) { 370 size_t Size = (getAllocaSizeInBytes(*AI) + kAllocaAlignment - 1) & 371 ~(kAllocaAlignment - 1); 372 373 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); 374 if (ClInstrumentWithCalls) { 375 IRB.CreateCall(HwasanTagMemoryFunc, 376 {IRB.CreatePointerCast(AI, IntptrTy), JustTag, 377 ConstantInt::get(IntptrTy, Size)}); 378 } else { 379 size_t ShadowSize = Size >> kShadowScale; 380 Value *ShadowPtr = IRB.CreateIntToPtr( 381 IRB.CreateLShr(IRB.CreatePointerCast(AI, IntptrTy), kShadowScale), 382 IRB.getInt8PtrTy()); 383 // If this memset is not inlined, it will be intercepted in the hwasan 384 // runtime library. That's OK, because the interceptor skips the checks if 385 // the address is in the shadow region. 386 // FIXME: the interceptor is not as fast as real memset. Consider lowering 387 // llvm.memset right here into either a sequence of stores, or a call to 388 // hwasan_tag_memory. 389 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1); 390 } 391 return true; 392 } 393 394 static unsigned RetagMask(unsigned AllocaNo) { 395 // A list of 8-bit numbers that have at most one run of non-zero bits. 396 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these 397 // masks. 398 // The list does not include the value 255, which is used for UAR. 399 static unsigned FastMasks[] = { 400 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24, 401 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120, 402 124, 126, 127, 128, 192, 224, 240, 248, 252, 254}; 403 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))]; 404 } 405 406 Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) { 407 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy); 408 } 409 410 Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { 411 if (ClGenerateTagsWithCalls) 412 return nullptr; 413 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend 414 // first). 415 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 416 auto GetStackPointerFn = 417 Intrinsic::getDeclaration(M, Intrinsic::frameaddress); 418 Value *StackPointer = IRB.CreateCall( 419 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())}); 420 421 // Extract some entropy from the stack pointer for the tags. 422 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ 423 // between functions). 424 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy); 425 Value *StackTag = 426 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20), 427 "hwasan.stack.base.tag"); 428 return StackTag; 429 } 430 431 Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag, 432 AllocaInst *AI, unsigned AllocaNo) { 433 if (ClGenerateTagsWithCalls) 434 return getNextTagWithCall(IRB); 435 return IRB.CreateXor(StackTag, 436 ConstantInt::get(IntptrTy, RetagMask(AllocaNo))); 437 } 438 439 Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) { 440 if (ClGenerateTagsWithCalls) 441 return getNextTagWithCall(IRB); 442 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU)); 443 } 444 445 bool HWAddressSanitizer::instrumentStack( 446 SmallVectorImpl<AllocaInst *> &Allocas, 447 SmallVectorImpl<Instruction *> &RetVec) { 448 Function *F = Allocas[0]->getParent()->getParent(); 449 Instruction *InsertPt = &*F->getEntryBlock().begin(); 450 IRBuilder<> IRB(InsertPt); 451 452 Value *StackTag = getStackBaseTag(IRB); 453 454 // Ideally, we want to calculate tagged stack base pointer, and rewrite all 455 // alloca addresses using that. Unfortunately, offsets are not known yet 456 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a 457 // temp, shift-OR it into each alloca address and xor with the retag mask. 458 // This generates one extra instruction per alloca use. 459 for (unsigned N = 0; N < Allocas.size(); ++N) { 460 auto *AI = Allocas[N]; 461 IRB.SetInsertPoint(AI->getNextNode()); 462 463 // Replace uses of the alloca with tagged address. 464 Value *Tag = getAllocaTag(IRB, StackTag, AI, N); 465 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy); 466 std::string Name = 467 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N); 468 Value *Replacement = IRB.CreateIntToPtr( 469 IRB.CreateOr(AILong, IRB.CreateShl(Tag, kPointerTagShift)), 470 AI->getType(), Name + ".hwasan"); 471 472 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) { 473 Use &U = *UI++; 474 if (U.getUser() != AILong) 475 U.set(Replacement); 476 } 477 478 tagAlloca(IRB, AI, Tag); 479 480 for (auto RI : RetVec) { 481 IRB.SetInsertPoint(RI); 482 483 // Re-tag alloca memory with the special UAR tag. 484 Value *Tag = getUARTag(IRB, StackTag); 485 tagAlloca(IRB, AI, Tag); 486 } 487 } 488 489 return true; 490 } 491 492 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { 493 return (AI.getAllocatedType()->isSized() && 494 // FIXME: instrument dynamic allocas, too 495 AI.isStaticAlloca() && 496 // alloca() may be called with 0 size, ignore it. 497 getAllocaSizeInBytes(AI) > 0 && 498 // We are only interested in allocas not promotable to registers. 499 // Promotable allocas are common under -O0. 500 !isAllocaPromotable(&AI) && 501 // inalloca allocas are not treated as static, and we don't want 502 // dynamic alloca instrumentation for them as well. 503 !AI.isUsedWithInAlloca() && 504 // swifterror allocas are register promoted by ISel 505 !AI.isSwiftError()); 506 } 507 508 bool HWAddressSanitizer::runOnFunction(Function &F) { 509 if (&F == HwasanCtorFunction) 510 return false; 511 512 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress)) 513 return false; 514 515 DEBUG(dbgs() << "Function: " << F.getName() << "\n"); 516 517 initializeCallbacks(*F.getParent()); 518 519 bool Changed = false; 520 SmallVector<Instruction*, 16> ToInstrument; 521 SmallVector<AllocaInst*, 8> AllocasToInstrument; 522 SmallVector<Instruction*, 8> RetVec; 523 for (auto &BB : F) { 524 for (auto &Inst : BB) { 525 if (ClInstrumentStack) 526 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { 527 // Realign all allocas. We don't want small uninteresting allocas to 528 // hide in instrumented alloca's padding. 529 if (AI->getAlignment() < kAllocaAlignment) 530 AI->setAlignment(kAllocaAlignment); 531 // Instrument some of them. 532 if (isInterestingAlloca(*AI)) 533 AllocasToInstrument.push_back(AI); 534 continue; 535 } 536 537 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) || isa<CleanupReturnInst>(Inst)) 538 RetVec.push_back(&Inst); 539 540 Value *MaybeMask = nullptr; 541 bool IsWrite; 542 unsigned Alignment; 543 uint64_t TypeSize; 544 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize, 545 &Alignment, &MaybeMask); 546 if (Addr || isa<MemIntrinsic>(Inst)) 547 ToInstrument.push_back(&Inst); 548 } 549 } 550 551 if (!AllocasToInstrument.empty()) 552 Changed |= instrumentStack(AllocasToInstrument, RetVec); 553 554 for (auto Inst : ToInstrument) 555 Changed |= instrumentMemAccess(Inst); 556 557 return Changed; 558 } 559