1 //===- MemoryTaggingSupport.h - helpers for memory tagging implementations ===// 2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3 // See https://llvm.org/LICENSE.txt for license information. 4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file declares common infrastructure for HWAddressSanitizer and 9 // Aarch64StackTagging. 10 // 11 //===----------------------------------------------------------------------===// 12 #ifndef LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H 13 #define LLVM_TRANSFORMS_UTILS_MEMORYTAGGINGSUPPORT_H 14 15 #include "llvm/ADT/MapVector.h" 16 #include "llvm/ADT/STLFunctionalExtras.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/Analysis/LoopInfo.h" 19 #include "llvm/Analysis/StackSafetyAnalysis.h" 20 #include "llvm/IR/IRBuilder.h" 21 #include "llvm/Support/Alignment.h" 22 23 namespace llvm { 24 class DominatorTree; 25 class DbgVariableIntrinsic; 26 class IntrinsicInst; 27 class PostDominatorTree; 28 class AllocaInst; 29 class Instruction; 30 namespace memtag { 31 // For an alloca valid between lifetime markers Start and Ends, call the 32 // Callback for all possible exits out of the lifetime in the containing 33 // function, which can return from the instructions in RetVec. 34 // 35 // Returns whether Ends covered all possible exits. If they did not, 36 // the caller should remove Ends to ensure that work done at the other 37 // exits does not happen outside of the lifetime. 38 bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, 39 const LoopInfo &LI, const Instruction *Start, 40 const SmallVectorImpl<IntrinsicInst *> &Ends, 41 const SmallVectorImpl<Instruction *> &RetVec, 42 llvm::function_ref<void(Instruction *)> Callback); 43 44 bool isStandardLifetime(const SmallVectorImpl<IntrinsicInst *> &LifetimeStart, 45 const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd, 46 const DominatorTree *DT, const LoopInfo *LI, 47 size_t MaxLifetimes); 48 49 Instruction *getUntagLocationIfFunctionExit(Instruction &Inst); 50 51 struct AllocaInfo { 52 AllocaInst *AI; 53 SmallVector<IntrinsicInst *, 2> LifetimeStart; 54 SmallVector<IntrinsicInst *, 2> LifetimeEnd; 55 SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics; 56 // Non-intrinsic records of variable locations. 57 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; 58 }; 59 60 struct StackInfo { 61 MapVector<AllocaInst *, AllocaInfo> AllocasToInstrument; 62 SmallVector<Instruction *, 4> UnrecognizedLifetimes; 63 SmallVector<Instruction *, 8> RetVec; 64 bool CallsReturnTwice = false; 65 }; 66 67 class StackInfoBuilder { 68 public: StackInfoBuilder(const StackSafetyGlobalInfo * SSI)69 StackInfoBuilder(const StackSafetyGlobalInfo *SSI) : SSI(SSI) {} 70 71 void visit(Instruction &Inst); 72 bool isInterestingAlloca(const AllocaInst &AI); get()73 StackInfo &get() { return Info; }; 74 75 private: 76 StackInfo Info; 77 const StackSafetyGlobalInfo *SSI; 78 }; 79 80 uint64_t getAllocaSizeInBytes(const AllocaInst &AI); 81 void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align); 82 bool isLifetimeIntrinsic(Value *V); 83 84 Value *readRegister(IRBuilder<> &IRB, StringRef Name); 85 Value *getFP(IRBuilder<> &IRB); 86 Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB); 87 Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot); 88 89 void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag); 90 91 } // namespace memtag 92 } // namespace llvm 93 94 #endif 95