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