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