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 if (!ClEnableKhwasan) { 190 std::tie(HwasanCtorFunction, std::ignore) = 191 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName, 192 kHwasanInitName, 193 /*InitArgTypes=*/{}, 194 /*InitArgs=*/{}); 195 appendToGlobalCtors(M, HwasanCtorFunction, 0); 196 } 197 return true; 198 } 199 200 void HWAddressSanitizer::initializeCallbacks(Module &M) { 201 IRBuilder<> IRB(*C); 202 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 203 const std::string TypeStr = AccessIsWrite ? "store" : "load"; 204 const std::string EndingStr = Recover ? "_noabort" : ""; 205 206 HwasanMemoryAccessCallbackSized[AccessIsWrite] = 207 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 208 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr, 209 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false))); 210 211 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 212 AccessSizeIndex++) { 213 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] = 214 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 215 ClMemoryAccessCallbackPrefix + TypeStr + 216 itostr(1ULL << AccessSizeIndex) + EndingStr, 217 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false))); 218 } 219 } 220 221 HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 222 "__hwasan_tag_memory", IRB.getVoidTy(), IntptrTy, Int8Ty, IntptrTy)); 223 HwasanGenerateTagFunc = checkSanitizerInterfaceFunction( 224 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty)); 225 } 226 227 Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, 228 bool *IsWrite, 229 uint64_t *TypeSize, 230 unsigned *Alignment, 231 Value **MaybeMask) { 232 // Skip memory accesses inserted by another instrumentation. 233 if (I->getMetadata("nosanitize")) return nullptr; 234 235 Value *PtrOperand = nullptr; 236 const DataLayout &DL = I->getModule()->getDataLayout(); 237 if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 238 if (!ClInstrumentReads) return nullptr; 239 *IsWrite = false; 240 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType()); 241 *Alignment = LI->getAlignment(); 242 PtrOperand = LI->getPointerOperand(); 243 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 244 if (!ClInstrumentWrites) return nullptr; 245 *IsWrite = true; 246 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType()); 247 *Alignment = SI->getAlignment(); 248 PtrOperand = SI->getPointerOperand(); 249 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 250 if (!ClInstrumentAtomics) return nullptr; 251 *IsWrite = true; 252 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType()); 253 *Alignment = 0; 254 PtrOperand = RMW->getPointerOperand(); 255 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 256 if (!ClInstrumentAtomics) return nullptr; 257 *IsWrite = true; 258 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType()); 259 *Alignment = 0; 260 PtrOperand = XCHG->getPointerOperand(); 261 } 262 263 if (PtrOperand) { 264 // Do not instrument acesses from different address spaces; we cannot deal 265 // with them. 266 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType()); 267 if (PtrTy->getPointerAddressSpace() != 0) 268 return nullptr; 269 270 // Ignore swifterror addresses. 271 // swifterror memory addresses are mem2reg promoted by instruction 272 // selection. As such they cannot have regular uses like an instrumentation 273 // function and it makes no sense to track them as memory. 274 if (PtrOperand->isSwiftError()) 275 return nullptr; 276 } 277 278 return PtrOperand; 279 } 280 281 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 282 size_t Res = countTrailingZeros(TypeSize / 8); 283 assert(Res < kNumberOfAccessSizes); 284 return Res; 285 } 286 287 void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 288 unsigned AccessSizeIndex, 289 Instruction *InsertBefore) { 290 IRBuilder<> IRB(InsertBefore); 291 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), IRB.getInt8Ty()); 292 Value *AddrLong = 293 IRB.CreateAnd(PtrLong, ConstantInt::get(PtrLong->getType(), 294 ~(0xFFULL << kPointerTagShift))); 295 Value *ShadowLong = IRB.CreateLShr(AddrLong, kShadowScale); 296 if (ClMappingOffset) 297 ShadowLong = IRB.CreateAdd( 298 ShadowLong, ConstantInt::get(PtrLong->getType(), ClMappingOffset, 299 /*isSigned=*/false)); 300 Value *MemTag = 301 IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, IRB.getInt8PtrTy())); 302 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag); 303 304 TerminatorInst *CheckTerm = 305 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover, 306 MDBuilder(*C).createBranchWeights(1, 100000)); 307 308 IRB.SetInsertPoint(CheckTerm); 309 // The signal handler will find the data address in x0. 310 InlineAsm *Asm = InlineAsm::get( 311 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 312 "hlt #" + 313 itostr(0x100 + Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex), 314 "{x0}", 315 /*hasSideEffects=*/true); 316 IRB.CreateCall(Asm, PtrLong); 317 } 318 319 bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) { 320 DEBUG(dbgs() << "Instrumenting: " << *I << "\n"); 321 bool IsWrite = false; 322 unsigned Alignment = 0; 323 uint64_t TypeSize = 0; 324 Value *MaybeMask = nullptr; 325 Value *Addr = 326 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask); 327 328 if (!Addr) 329 return false; 330 331 if (MaybeMask) 332 return false; //FIXME 333 334 IRBuilder<> IRB(I); 335 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 336 if (isPowerOf2_64(TypeSize) && 337 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) && 338 (Alignment >= (1UL << kShadowScale) || Alignment == 0 || 339 Alignment >= TypeSize / 8)) { 340 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 341 if (ClInstrumentWithCalls) { 342 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex], 343 AddrLong); 344 } else { 345 instrumentMemAccessInline(AddrLong, IsWrite, AccessSizeIndex, I); 346 } 347 } else { 348 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite], 349 {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)}); 350 } 351 352 return true; 353 } 354 355 static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) { 356 uint64_t ArraySize = 1; 357 if (AI.isArrayAllocation()) { 358 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize()); 359 assert(CI && "non-constant array size"); 360 ArraySize = CI->getZExtValue(); 361 } 362 Type *Ty = AI.getAllocatedType(); 363 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty); 364 return SizeInBytes * ArraySize; 365 } 366 367 bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, 368 Value *Tag) { 369 size_t Size = (getAllocaSizeInBytes(*AI) + kAllocaAlignment - 1) & 370 ~(kAllocaAlignment - 1); 371 372 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); 373 if (ClInstrumentWithCalls) { 374 IRB.CreateCall(HwasanTagMemoryFunc, 375 {IRB.CreatePointerCast(AI, IntptrTy), JustTag, 376 ConstantInt::get(IntptrTy, Size)}); 377 } else { 378 size_t ShadowSize = Size >> kShadowScale; 379 Value *ShadowPtr = IRB.CreateIntToPtr( 380 IRB.CreateLShr(IRB.CreatePointerCast(AI, IntptrTy), kShadowScale), 381 IRB.getInt8PtrTy()); 382 // If this memset is not inlined, it will be intercepted in the hwasan 383 // runtime library. That's OK, because the interceptor skips the checks if 384 // the address is in the shadow region. 385 // FIXME: the interceptor is not as fast as real memset. Consider lowering 386 // llvm.memset right here into either a sequence of stores, or a call to 387 // hwasan_tag_memory. 388 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1); 389 } 390 return true; 391 } 392 393 static unsigned RetagMask(unsigned AllocaNo) { 394 // A list of 8-bit numbers that have at most one run of non-zero bits. 395 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these 396 // masks. 397 // The list does not include the value 255, which is used for UAR. 398 static unsigned FastMasks[] = { 399 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24, 400 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120, 401 124, 126, 127, 128, 192, 224, 240, 248, 252, 254}; 402 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))]; 403 } 404 405 Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) { 406 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy); 407 } 408 409 Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { 410 if (ClGenerateTagsWithCalls) 411 return nullptr; 412 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend 413 // first). 414 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 415 auto GetStackPointerFn = 416 Intrinsic::getDeclaration(M, Intrinsic::frameaddress); 417 Value *StackPointer = IRB.CreateCall( 418 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())}); 419 420 // Extract some entropy from the stack pointer for the tags. 421 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ 422 // between functions). 423 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy); 424 Value *StackTag = 425 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20), 426 "hwasan.stack.base.tag"); 427 return StackTag; 428 } 429 430 Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag, 431 AllocaInst *AI, unsigned AllocaNo) { 432 if (ClGenerateTagsWithCalls) 433 return getNextTagWithCall(IRB); 434 return IRB.CreateXor(StackTag, 435 ConstantInt::get(IntptrTy, RetagMask(AllocaNo))); 436 } 437 438 Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) { 439 if (ClGenerateTagsWithCalls) 440 return getNextTagWithCall(IRB); 441 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU)); 442 } 443 444 bool HWAddressSanitizer::instrumentStack( 445 SmallVectorImpl<AllocaInst *> &Allocas, 446 SmallVectorImpl<Instruction *> &RetVec) { 447 Function *F = Allocas[0]->getParent()->getParent(); 448 Instruction *InsertPt = &*F->getEntryBlock().begin(); 449 IRBuilder<> IRB(InsertPt); 450 451 Value *StackTag = getStackBaseTag(IRB); 452 453 // Ideally, we want to calculate tagged stack base pointer, and rewrite all 454 // alloca addresses using that. Unfortunately, offsets are not known yet 455 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a 456 // temp, shift-OR it into each alloca address and xor with the retag mask. 457 // This generates one extra instruction per alloca use. 458 for (unsigned N = 0; N < Allocas.size(); ++N) { 459 auto *AI = Allocas[N]; 460 IRB.SetInsertPoint(AI->getNextNode()); 461 462 // Replace uses of the alloca with tagged address. 463 Value *Tag = getAllocaTag(IRB, StackTag, AI, N); 464 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy); 465 std::string Name = 466 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N); 467 Value *Replacement = IRB.CreateIntToPtr( 468 IRB.CreateOr(AILong, IRB.CreateShl(Tag, kPointerTagShift)), 469 AI->getType(), Name + ".hwasan"); 470 471 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) { 472 Use &U = *UI++; 473 if (U.getUser() != AILong) 474 U.set(Replacement); 475 } 476 477 tagAlloca(IRB, AI, Tag); 478 479 for (auto RI : RetVec) { 480 IRB.SetInsertPoint(RI); 481 482 // Re-tag alloca memory with the special UAR tag. 483 Value *Tag = getUARTag(IRB, StackTag); 484 tagAlloca(IRB, AI, Tag); 485 } 486 } 487 488 return true; 489 } 490 491 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { 492 return (AI.getAllocatedType()->isSized() && 493 // FIXME: instrument dynamic allocas, too 494 AI.isStaticAlloca() && 495 // alloca() may be called with 0 size, ignore it. 496 getAllocaSizeInBytes(AI) > 0 && 497 // We are only interested in allocas not promotable to registers. 498 // Promotable allocas are common under -O0. 499 !isAllocaPromotable(&AI) && 500 // inalloca allocas are not treated as static, and we don't want 501 // dynamic alloca instrumentation for them as well. 502 !AI.isUsedWithInAlloca() && 503 // swifterror allocas are register promoted by ISel 504 !AI.isSwiftError()); 505 } 506 507 bool HWAddressSanitizer::runOnFunction(Function &F) { 508 if (&F == HwasanCtorFunction) 509 return false; 510 511 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress)) 512 return false; 513 514 DEBUG(dbgs() << "Function: " << F.getName() << "\n"); 515 516 initializeCallbacks(*F.getParent()); 517 518 bool Changed = false; 519 SmallVector<Instruction*, 16> ToInstrument; 520 SmallVector<AllocaInst*, 8> AllocasToInstrument; 521 SmallVector<Instruction*, 8> RetVec; 522 for (auto &BB : F) { 523 for (auto &Inst : BB) { 524 if (ClInstrumentStack) 525 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { 526 // Realign all allocas. We don't want small uninteresting allocas to 527 // hide in instrumented alloca's padding. 528 if (AI->getAlignment() < kAllocaAlignment) 529 AI->setAlignment(kAllocaAlignment); 530 // Instrument some of them. 531 if (isInterestingAlloca(*AI)) 532 AllocasToInstrument.push_back(AI); 533 continue; 534 } 535 536 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) || isa<CleanupReturnInst>(Inst)) 537 RetVec.push_back(&Inst); 538 539 Value *MaybeMask = nullptr; 540 bool IsWrite; 541 unsigned Alignment; 542 uint64_t TypeSize; 543 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize, 544 &Alignment, &MaybeMask); 545 if (Addr || isa<MemIntrinsic>(Inst)) 546 ToInstrument.push_back(&Inst); 547 } 548 } 549 550 if (!AllocasToInstrument.empty()) 551 Changed |= instrumentStack(AllocasToInstrument, RetVec); 552 553 for (auto Inst : ToInstrument) 554 Changed |= instrumentMemAccess(Inst); 555 556 return Changed; 557 } 558