xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- HWAddressSanitizer.cpp - memory access error detector --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
104824e7fdSDimitry Andric /// This file is a part of HWAddressSanitizer, an address basic correctness
114824e7fdSDimitry Andric /// checker based on tagged addressing.
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
158bcb0991SDimitry Andric #include "llvm/ADT/MapVector.h"
1681ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
18*0fca6ea1SDimitry Andric #include "llvm/ADT/Statistic.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
21*0fca6ea1SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
225f757f3fSDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h"
23bdd1243dSDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
24*0fca6ea1SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
25349cc55cSDimitry Andric #include "llvm/Analysis/PostDominators.h"
26*0fca6ea1SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
27fe6060f1SDimitry Andric #include "llvm/Analysis/StackSafetyAnalysis.h"
285f757f3fSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
29349cc55cSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
3081ad6265SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
318bcb0991SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
320b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
330b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
340b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
350b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
360b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
370b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
380b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
39349cc55cSDimitry Andric #include "llvm/IR/Dominators.h"
400b57cec5SDimitry Andric #include "llvm/IR/Function.h"
410b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
420b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
4381ad6265SDimitry Andric #include "llvm/IR/InstIterator.h"
440b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
450b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
460b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
470b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
480b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
490b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
500b57cec5SDimitry Andric #include "llvm/IR/Module.h"
510b57cec5SDimitry Andric #include "llvm/IR/Type.h"
520b57cec5SDimitry Andric #include "llvm/IR/Value.h"
530b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
540b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
550b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
56*0fca6ea1SDimitry Andric #include "llvm/Support/MD5.h"
57*0fca6ea1SDimitry Andric #include "llvm/Support/RandomNumberGenerator.h"
580b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
5906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
605ffd83dbSDimitry Andric #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
610b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
625f757f3fSDimitry Andric #include "llvm/Transforms/Utils/Local.h"
6381ad6265SDimitry Andric #include "llvm/Transforms/Utils/MemoryTaggingSupport.h"
640b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
650b57cec5SDimitry Andric #include "llvm/Transforms/Utils/PromoteMemToReg.h"
66bdd1243dSDimitry Andric #include <optional>
67*0fca6ea1SDimitry Andric #include <random>
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric using namespace llvm;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric #define DEBUG_TYPE "hwasan"
720b57cec5SDimitry Andric 
73e8d8bef9SDimitry Andric const char kHwasanModuleCtorName[] = "hwasan.module_ctor";
74e8d8bef9SDimitry Andric const char kHwasanNoteName[] = "hwasan.note";
75e8d8bef9SDimitry Andric const char kHwasanInitName[] = "__hwasan_init";
76e8d8bef9SDimitry Andric const char kHwasanPersonalityThunkName[] = "__hwasan_personality_thunk";
770b57cec5SDimitry Andric 
78e8d8bef9SDimitry Andric const char kHwasanShadowMemoryDynamicAddress[] =
790b57cec5SDimitry Andric     "__hwasan_shadow_memory_dynamic_address";
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
820b57cec5SDimitry Andric static const size_t kNumberOfAccessSizes = 5;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric static const size_t kDefaultShadowScale = 4;
850b57cec5SDimitry Andric static const uint64_t kDynamicShadowSentinel =
860b57cec5SDimitry Andric     std::numeric_limits<uint64_t>::max();
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric static const unsigned kShadowBaseAlignment = 32;
890b57cec5SDimitry Andric 
90fe6060f1SDimitry Andric static cl::opt<std::string>
91fe6060f1SDimitry Andric     ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix",
92fe6060f1SDimitry Andric                                  cl::desc("Prefix for memory access callbacks"),
93fe6060f1SDimitry Andric                                  cl::Hidden, cl::init("__hwasan_"));
940b57cec5SDimitry Andric 
9581ad6265SDimitry Andric static cl::opt<bool> ClKasanMemIntrinCallbackPrefix(
9681ad6265SDimitry Andric     "hwasan-kernel-mem-intrinsic-prefix",
9781ad6265SDimitry Andric     cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden,
9881ad6265SDimitry Andric     cl::init(false));
9981ad6265SDimitry Andric 
100fe6060f1SDimitry Andric static cl::opt<bool> ClInstrumentWithCalls(
101fe6060f1SDimitry Andric     "hwasan-instrument-with-calls",
102fe6060f1SDimitry Andric     cl::desc("instrument reads and writes with callbacks"), cl::Hidden,
103fe6060f1SDimitry Andric     cl::init(false));
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads",
1060b57cec5SDimitry Andric                                        cl::desc("instrument read instructions"),
1070b57cec5SDimitry Andric                                        cl::Hidden, cl::init(true));
1080b57cec5SDimitry Andric 
109fe6060f1SDimitry Andric static cl::opt<bool>
110fe6060f1SDimitry Andric     ClInstrumentWrites("hwasan-instrument-writes",
111fe6060f1SDimitry Andric                        cl::desc("instrument write instructions"), cl::Hidden,
112fe6060f1SDimitry Andric                        cl::init(true));
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric static cl::opt<bool> ClInstrumentAtomics(
1150b57cec5SDimitry Andric     "hwasan-instrument-atomics",
1160b57cec5SDimitry Andric     cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
1170b57cec5SDimitry Andric     cl::init(true));
1180b57cec5SDimitry Andric 
1195ffd83dbSDimitry Andric static cl::opt<bool> ClInstrumentByval("hwasan-instrument-byval",
1205ffd83dbSDimitry Andric                                        cl::desc("instrument byval arguments"),
1215ffd83dbSDimitry Andric                                        cl::Hidden, cl::init(true));
1225ffd83dbSDimitry Andric 
123fe6060f1SDimitry Andric static cl::opt<bool>
124fe6060f1SDimitry Andric     ClRecover("hwasan-recover",
1250b57cec5SDimitry Andric               cl::desc("Enable recovery mode (continue-after-error)."),
1260b57cec5SDimitry Andric               cl::Hidden, cl::init(false));
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
1290b57cec5SDimitry Andric                                        cl::desc("instrument stack (allocas)"),
1300b57cec5SDimitry Andric                                        cl::Hidden, cl::init(true));
1310b57cec5SDimitry Andric 
132fe6060f1SDimitry Andric static cl::opt<bool>
133fe6060f1SDimitry Andric     ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true),
134fe6060f1SDimitry Andric                      cl::Hidden, cl::desc("Use Stack Safety analysis results"),
135fe6060f1SDimitry Andric                      cl::Optional);
136fe6060f1SDimitry Andric 
137349cc55cSDimitry Andric static cl::opt<size_t> ClMaxLifetimes(
138349cc55cSDimitry Andric     "hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3),
139349cc55cSDimitry Andric     cl::ReallyHidden,
140349cc55cSDimitry Andric     cl::desc("How many lifetime ends to handle for a single alloca."),
141349cc55cSDimitry Andric     cl::Optional);
142349cc55cSDimitry Andric 
143349cc55cSDimitry Andric static cl::opt<bool>
144349cc55cSDimitry Andric     ClUseAfterScope("hwasan-use-after-scope",
145349cc55cSDimitry Andric                     cl::desc("detect use after scope within function"),
1465f757f3fSDimitry Andric                     cl::Hidden, cl::init(true));
147349cc55cSDimitry Andric 
1480b57cec5SDimitry Andric static cl::opt<bool> ClGenerateTagsWithCalls(
1490b57cec5SDimitry Andric     "hwasan-generate-tags-with-calls",
1500b57cec5SDimitry Andric     cl::desc("generate new tags with runtime library calls"), cl::Hidden,
1510b57cec5SDimitry Andric     cl::init(false));
1520b57cec5SDimitry Andric 
1538bcb0991SDimitry Andric static cl::opt<bool> ClGlobals("hwasan-globals", cl::desc("Instrument globals"),
15481ad6265SDimitry Andric                                cl::Hidden, cl::init(false));
1558bcb0991SDimitry Andric 
1560b57cec5SDimitry Andric static cl::opt<int> ClMatchAllTag(
1570b57cec5SDimitry Andric     "hwasan-match-all-tag",
1580b57cec5SDimitry Andric     cl::desc("don't report bad accesses via pointers with this tag"),
1590b57cec5SDimitry Andric     cl::Hidden, cl::init(-1));
1600b57cec5SDimitry Andric 
161fe6060f1SDimitry Andric static cl::opt<bool>
162fe6060f1SDimitry Andric     ClEnableKhwasan("hwasan-kernel",
1630b57cec5SDimitry Andric                     cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
1640b57cec5SDimitry Andric                     cl::Hidden, cl::init(false));
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric // These flags allow to change the shadow mapping and control how shadow memory
1670b57cec5SDimitry Andric // is accessed. The shadow mapping looks like:
1680b57cec5SDimitry Andric //    Shadow = (Mem >> scale) + offset
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric static cl::opt<uint64_t>
1710b57cec5SDimitry Andric     ClMappingOffset("hwasan-mapping-offset",
1720b57cec5SDimitry Andric                     cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
1730b57cec5SDimitry Andric                     cl::Hidden, cl::init(0));
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric static cl::opt<bool>
1760b57cec5SDimitry Andric     ClWithIfunc("hwasan-with-ifunc",
1770b57cec5SDimitry Andric                 cl::desc("Access dynamic shadow through an ifunc global on "
1780b57cec5SDimitry Andric                          "platforms that support this"),
1790b57cec5SDimitry Andric                 cl::Hidden, cl::init(false));
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric static cl::opt<bool> ClWithTls(
1820b57cec5SDimitry Andric     "hwasan-with-tls",
1830b57cec5SDimitry Andric     cl::desc("Access dynamic shadow through an thread-local pointer on "
1840b57cec5SDimitry Andric              "platforms that support this"),
1850b57cec5SDimitry Andric     cl::Hidden, cl::init(true));
1860b57cec5SDimitry Andric 
187*0fca6ea1SDimitry Andric static cl::opt<int> ClHotPercentileCutoff("hwasan-percentile-cutoff-hot",
188*0fca6ea1SDimitry Andric                                           cl::desc("Hot percentile cuttoff."));
189*0fca6ea1SDimitry Andric 
190*0fca6ea1SDimitry Andric static cl::opt<float>
191*0fca6ea1SDimitry Andric     ClRandomSkipRate("hwasan-random-rate",
192*0fca6ea1SDimitry Andric                      cl::desc("Probability value in the range [0.0, 1.0] "
193*0fca6ea1SDimitry Andric                               "to keep instrumentation of a function."));
194*0fca6ea1SDimitry Andric 
195*0fca6ea1SDimitry Andric STATISTIC(NumTotalFuncs, "Number of total funcs");
196*0fca6ea1SDimitry Andric STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
197*0fca6ea1SDimitry Andric STATISTIC(NumNoProfileSummaryFuncs, "Number of funcs without PS");
198*0fca6ea1SDimitry Andric 
199753f127fSDimitry Andric // Mode for selecting how to insert frame record info into the stack ring
200753f127fSDimitry Andric // buffer.
201753f127fSDimitry Andric enum RecordStackHistoryMode {
202753f127fSDimitry Andric   // Do not record frame record info.
203753f127fSDimitry Andric   none,
204753f127fSDimitry Andric 
205753f127fSDimitry Andric   // Insert instructions into the prologue for storing into the stack ring
206753f127fSDimitry Andric   // buffer directly.
207753f127fSDimitry Andric   instr,
208753f127fSDimitry Andric 
209753f127fSDimitry Andric   // Add a call to __hwasan_add_frame_record in the runtime.
210753f127fSDimitry Andric   libcall,
211753f127fSDimitry Andric };
212753f127fSDimitry Andric 
213753f127fSDimitry Andric static cl::opt<RecordStackHistoryMode> ClRecordStackHistory(
214753f127fSDimitry Andric     "hwasan-record-stack-history",
215753f127fSDimitry Andric     cl::desc("Record stack frames with tagged allocations in a thread-local "
216753f127fSDimitry Andric              "ring buffer"),
217753f127fSDimitry Andric     cl::values(clEnumVal(none, "Do not record stack ring history"),
218753f127fSDimitry Andric                clEnumVal(instr, "Insert instructions into the prologue for "
219753f127fSDimitry Andric                                 "storing into the stack ring buffer directly"),
220753f127fSDimitry Andric                clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for "
221753f127fSDimitry Andric                                   "storing into the stack ring buffer")),
222753f127fSDimitry Andric     cl::Hidden, cl::init(instr));
223753f127fSDimitry Andric 
2240b57cec5SDimitry Andric static cl::opt<bool>
2250b57cec5SDimitry Andric     ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
2260b57cec5SDimitry Andric                               cl::desc("instrument memory intrinsics"),
2270b57cec5SDimitry Andric                               cl::Hidden, cl::init(true));
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric static cl::opt<bool>
2300b57cec5SDimitry Andric     ClInstrumentLandingPads("hwasan-instrument-landing-pads",
2310b57cec5SDimitry Andric                             cl::desc("instrument landing pads"), cl::Hidden,
23281ad6265SDimitry Andric                             cl::init(false));
2338bcb0991SDimitry Andric 
2348bcb0991SDimitry Andric static cl::opt<bool> ClUseShortGranules(
2358bcb0991SDimitry Andric     "hwasan-use-short-granules",
2368bcb0991SDimitry Andric     cl::desc("use short granules in allocas and outlined checks"), cl::Hidden,
23781ad6265SDimitry Andric     cl::init(false));
2388bcb0991SDimitry Andric 
2398bcb0991SDimitry Andric static cl::opt<bool> ClInstrumentPersonalityFunctions(
2408bcb0991SDimitry Andric     "hwasan-instrument-personality-functions",
24181ad6265SDimitry Andric     cl::desc("instrument personality functions"), cl::Hidden);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
2440b57cec5SDimitry Andric                                        cl::desc("inline all checks"),
2450b57cec5SDimitry Andric                                        cl::Hidden, cl::init(false));
2460b57cec5SDimitry Andric 
2475f757f3fSDimitry Andric static cl::opt<bool> ClInlineFastPathChecks("hwasan-inline-fast-path-checks",
2485f757f3fSDimitry Andric                                             cl::desc("inline all checks"),
2495f757f3fSDimitry Andric                                             cl::Hidden, cl::init(false));
2505f757f3fSDimitry Andric 
251fe6060f1SDimitry Andric // Enabled from clang by "-fsanitize-hwaddress-experimental-aliasing".
252fe6060f1SDimitry Andric static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
253fe6060f1SDimitry Andric                                       cl::desc("Use page aliasing in HWASan"),
254fe6060f1SDimitry Andric                                       cl::Hidden, cl::init(false));
255fe6060f1SDimitry Andric 
2560b57cec5SDimitry Andric namespace {
2570b57cec5SDimitry Andric 
optOr(cl::opt<T> & Opt,T Other)258*0fca6ea1SDimitry Andric template <typename T> T optOr(cl::opt<T> &Opt, T Other) {
259*0fca6ea1SDimitry Andric   return Opt.getNumOccurrences() ? Opt : Other;
260*0fca6ea1SDimitry Andric }
261*0fca6ea1SDimitry Andric 
shouldUsePageAliases(const Triple & TargetTriple)262fe6060f1SDimitry Andric bool shouldUsePageAliases(const Triple &TargetTriple) {
263fe6060f1SDimitry Andric   return ClUsePageAliases && TargetTriple.getArch() == Triple::x86_64;
264fe6060f1SDimitry Andric }
265fe6060f1SDimitry Andric 
shouldInstrumentStack(const Triple & TargetTriple)266fe6060f1SDimitry Andric bool shouldInstrumentStack(const Triple &TargetTriple) {
267fe6060f1SDimitry Andric   return !shouldUsePageAliases(TargetTriple) && ClInstrumentStack;
268fe6060f1SDimitry Andric }
269fe6060f1SDimitry Andric 
shouldInstrumentWithCalls(const Triple & TargetTriple)270fe6060f1SDimitry Andric bool shouldInstrumentWithCalls(const Triple &TargetTriple) {
271*0fca6ea1SDimitry Andric   return optOr(ClInstrumentWithCalls, TargetTriple.getArch() == Triple::x86_64);
272fe6060f1SDimitry Andric }
273fe6060f1SDimitry Andric 
mightUseStackSafetyAnalysis(bool DisableOptimization)274fe6060f1SDimitry Andric bool mightUseStackSafetyAnalysis(bool DisableOptimization) {
275*0fca6ea1SDimitry Andric   return optOr(ClUseStackSafety, !DisableOptimization);
276fe6060f1SDimitry Andric }
277fe6060f1SDimitry Andric 
shouldUseStackSafetyAnalysis(const Triple & TargetTriple,bool DisableOptimization)278fe6060f1SDimitry Andric bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple,
279fe6060f1SDimitry Andric                                   bool DisableOptimization) {
280fe6060f1SDimitry Andric   return shouldInstrumentStack(TargetTriple) &&
281fe6060f1SDimitry Andric          mightUseStackSafetyAnalysis(DisableOptimization);
282fe6060f1SDimitry Andric }
283349cc55cSDimitry Andric 
shouldDetectUseAfterScope(const Triple & TargetTriple)284349cc55cSDimitry Andric bool shouldDetectUseAfterScope(const Triple &TargetTriple) {
285349cc55cSDimitry Andric   return ClUseAfterScope && shouldInstrumentStack(TargetTriple);
286349cc55cSDimitry Andric }
287349cc55cSDimitry Andric 
2880b57cec5SDimitry Andric /// An instrumentation pass implementing detection of addressability bugs
2890b57cec5SDimitry Andric /// using tagged pointers.
2900b57cec5SDimitry Andric class HWAddressSanitizer {
2910b57cec5SDimitry Andric public:
HWAddressSanitizer(Module & M,bool CompileKernel,bool Recover,const StackSafetyGlobalInfo * SSI)292fe6060f1SDimitry Andric   HWAddressSanitizer(Module &M, bool CompileKernel, bool Recover,
293fe6060f1SDimitry Andric                      const StackSafetyGlobalInfo *SSI)
294fe6060f1SDimitry Andric       : M(M), SSI(SSI) {
295*0fca6ea1SDimitry Andric     this->Recover = optOr(ClRecover, Recover);
296*0fca6ea1SDimitry Andric     this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel);
297*0fca6ea1SDimitry Andric     this->Rng = ClRandomSkipRate.getNumOccurrences() ? M.createRNG(DEBUG_TYPE)
298*0fca6ea1SDimitry Andric                                                      : nullptr;
2990b57cec5SDimitry Andric 
3008bcb0991SDimitry Andric     initializeModule();
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric 
3035f757f3fSDimitry Andric   void sanitizeFunction(Function &F, FunctionAnalysisManager &FAM);
3045f757f3fSDimitry Andric 
3055f757f3fSDimitry Andric private:
3065f757f3fSDimitry Andric   struct ShadowTagCheckInfo {
3075f757f3fSDimitry Andric     Instruction *TagMismatchTerm = nullptr;
3085f757f3fSDimitry Andric     Value *PtrLong = nullptr;
3095f757f3fSDimitry Andric     Value *AddrLong = nullptr;
3105f757f3fSDimitry Andric     Value *PtrTag = nullptr;
3115f757f3fSDimitry Andric     Value *MemTag = nullptr;
3125f757f3fSDimitry Andric   };
313fe6060f1SDimitry Andric 
314*0fca6ea1SDimitry Andric   bool selectiveInstrumentationShouldSkip(Function &F,
315*0fca6ea1SDimitry Andric                                           FunctionAnalysisManager &FAM) const;
3168bcb0991SDimitry Andric   void initializeModule();
317e8d8bef9SDimitry Andric   void createHwasanCtorComdat();
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   void initializeCallbacks(Module &M);
3200b57cec5SDimitry Andric 
321e8d8bef9SDimitry Andric   Value *getOpaqueNoopCast(IRBuilder<> &IRB, Value *Val);
322e8d8bef9SDimitry Andric 
3230b57cec5SDimitry Andric   Value *getDynamicShadowIfunc(IRBuilder<> &IRB);
324e8d8bef9SDimitry Andric   Value *getShadowNonTls(IRBuilder<> &IRB);
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   void untagPointerOperand(Instruction *I, Value *Addr);
3270b57cec5SDimitry Andric   Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
328349cc55cSDimitry Andric 
329349cc55cSDimitry Andric   int64_t getAccessInfo(bool IsWrite, unsigned AccessSizeIndex);
3305f757f3fSDimitry Andric   ShadowTagCheckInfo insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,
3315f757f3fSDimitry Andric                                           DomTreeUpdater &DTU, LoopInfo *LI);
332349cc55cSDimitry Andric   void instrumentMemAccessOutline(Value *Ptr, bool IsWrite,
333349cc55cSDimitry Andric                                   unsigned AccessSizeIndex,
3345f757f3fSDimitry Andric                                   Instruction *InsertBefore,
3355f757f3fSDimitry Andric                                   DomTreeUpdater &DTU, LoopInfo *LI);
3360b57cec5SDimitry Andric   void instrumentMemAccessInline(Value *Ptr, bool IsWrite,
3370b57cec5SDimitry Andric                                  unsigned AccessSizeIndex,
3385f757f3fSDimitry Andric                                  Instruction *InsertBefore, DomTreeUpdater &DTU,
3395f757f3fSDimitry Andric                                  LoopInfo *LI);
340*0fca6ea1SDimitry Andric   bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *MI);
3410b57cec5SDimitry Andric   void instrumentMemIntrinsic(MemIntrinsic *MI);
3425f757f3fSDimitry Andric   bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
3435f757f3fSDimitry Andric                            LoopInfo *LI);
344*0fca6ea1SDimitry Andric   bool ignoreAccessWithoutRemark(Instruction *Inst, Value *Ptr);
345*0fca6ea1SDimitry Andric   bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
346*0fca6ea1SDimitry Andric                     Value *Ptr);
347*0fca6ea1SDimitry Andric 
3485ffd83dbSDimitry Andric   void getInterestingMemoryOperands(
349*0fca6ea1SDimitry Andric       OptimizationRemarkEmitter &ORE, Instruction *I,
350*0fca6ea1SDimitry Andric       const TargetLibraryInfo &TLI,
3515f757f3fSDimitry Andric       SmallVectorImpl<InterestingMemoryOperand> &Interesting);
3520b57cec5SDimitry Andric 
353349cc55cSDimitry Andric   void tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, size_t Size);
3540b57cec5SDimitry Andric   Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
3550b57cec5SDimitry Andric   Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
35606c3fb27SDimitry Andric   bool instrumentStack(memtag::StackInfo &Info, Value *StackTag, Value *UARTag,
35781ad6265SDimitry Andric                        const DominatorTree &DT, const PostDominatorTree &PDT,
35881ad6265SDimitry Andric                        const LoopInfo &LI);
3590b57cec5SDimitry Andric   bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
3600b57cec5SDimitry Andric   Value *getNextTagWithCall(IRBuilder<> &IRB);
3610b57cec5SDimitry Andric   Value *getStackBaseTag(IRBuilder<> &IRB);
36206c3fb27SDimitry Andric   Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, unsigned AllocaNo);
36306c3fb27SDimitry Andric   Value *getUARTag(IRBuilder<> &IRB);
3640b57cec5SDimitry Andric 
365*0fca6ea1SDimitry Andric   Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB);
366fe6060f1SDimitry Andric   Value *applyTagMask(IRBuilder<> &IRB, Value *OldTag);
367fe6060f1SDimitry Andric   unsigned retagMask(unsigned AllocaNo);
368fe6060f1SDimitry Andric 
3690b57cec5SDimitry Andric   void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
3700b57cec5SDimitry Andric 
3718bcb0991SDimitry Andric   void instrumentGlobal(GlobalVariable *GV, uint8_t Tag);
3728bcb0991SDimitry Andric   void instrumentGlobals();
3738bcb0991SDimitry Andric 
374*0fca6ea1SDimitry Andric   Value *getCachedFP(IRBuilder<> &IRB);
375753f127fSDimitry Andric   Value *getFrameRecordInfo(IRBuilder<> &IRB);
37681ad6265SDimitry Andric 
3778bcb0991SDimitry Andric   void instrumentPersonalityFunctions();
3788bcb0991SDimitry Andric 
3790b57cec5SDimitry Andric   LLVMContext *C;
3808bcb0991SDimitry Andric   Module &M;
381fe6060f1SDimitry Andric   const StackSafetyGlobalInfo *SSI;
3820b57cec5SDimitry Andric   Triple TargetTriple;
383*0fca6ea1SDimitry Andric   std::unique_ptr<RandomNumberGenerator> Rng;
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   /// This struct defines the shadow mapping using the rule:
3860b57cec5SDimitry Andric   ///   shadow = (mem >> Scale) + Offset.
3870b57cec5SDimitry Andric   /// If InGlobal is true, then
3880b57cec5SDimitry Andric   ///   extern char __hwasan_shadow[];
3890b57cec5SDimitry Andric   ///   shadow = (mem >> Scale) + &__hwasan_shadow
3900b57cec5SDimitry Andric   /// If InTls is true, then
3910b57cec5SDimitry Andric   ///   extern char *__hwasan_tls;
3920b57cec5SDimitry Andric   ///   shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
393fe6060f1SDimitry Andric   ///
394fe6060f1SDimitry Andric   /// If WithFrameRecord is true, then __hwasan_tls will be used to access the
395fe6060f1SDimitry Andric   /// ring buffer for storing stack allocations on targets that support it.
3960b57cec5SDimitry Andric   struct ShadowMapping {
397bdd1243dSDimitry Andric     uint8_t Scale;
3980b57cec5SDimitry Andric     uint64_t Offset;
3990b57cec5SDimitry Andric     bool InGlobal;
4000b57cec5SDimitry Andric     bool InTls;
401fe6060f1SDimitry Andric     bool WithFrameRecord;
4020b57cec5SDimitry Andric 
403fe6060f1SDimitry Andric     void init(Triple &TargetTriple, bool InstrumentWithCalls);
getObjectAlignment__anon1b7bdbef0111::HWAddressSanitizer::ShadowMapping404bdd1243dSDimitry Andric     Align getObjectAlignment() const { return Align(1ULL << Scale); }
4050b57cec5SDimitry Andric   };
406349cc55cSDimitry Andric 
4070b57cec5SDimitry Andric   ShadowMapping Mapping;
4080b57cec5SDimitry Andric 
4098bcb0991SDimitry Andric   Type *VoidTy = Type::getVoidTy(M.getContext());
410*0fca6ea1SDimitry Andric   Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
411*0fca6ea1SDimitry Andric   PointerType *PtrTy = PointerType::getUnqual(M.getContext());
412*0fca6ea1SDimitry Andric   Type *Int8Ty = Type::getInt8Ty(M.getContext());
413*0fca6ea1SDimitry Andric   Type *Int32Ty = Type::getInt32Ty(M.getContext());
4148bcb0991SDimitry Andric   Type *Int64Ty = Type::getInt64Ty(M.getContext());
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   bool CompileKernel;
4170b57cec5SDimitry Andric   bool Recover;
418e8d8bef9SDimitry Andric   bool OutlinedChecks;
4195f757f3fSDimitry Andric   bool InlineFastPath;
4208bcb0991SDimitry Andric   bool UseShortGranules;
4218bcb0991SDimitry Andric   bool InstrumentLandingPads;
422fe6060f1SDimitry Andric   bool InstrumentWithCalls;
423fe6060f1SDimitry Andric   bool InstrumentStack;
424*0fca6ea1SDimitry Andric   bool InstrumentGlobals;
425349cc55cSDimitry Andric   bool DetectUseAfterScope;
426fe6060f1SDimitry Andric   bool UsePageAliases;
42706c3fb27SDimitry Andric   bool UseMatchAllCallback;
4280b57cec5SDimitry Andric 
429bdd1243dSDimitry Andric   std::optional<uint8_t> MatchAllTag;
430e8d8bef9SDimitry Andric 
431fe6060f1SDimitry Andric   unsigned PointerTagShift;
432fe6060f1SDimitry Andric   uint64_t TagMaskByte;
433fe6060f1SDimitry Andric 
4340b57cec5SDimitry Andric   Function *HwasanCtorFunction;
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
4370b57cec5SDimitry Andric   FunctionCallee HwasanMemoryAccessCallbackSized[2];
4380b57cec5SDimitry Andric 
43906c3fb27SDimitry Andric   FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
44006c3fb27SDimitry Andric   FunctionCallee HwasanHandleVfork;
44106c3fb27SDimitry Andric 
4420b57cec5SDimitry Andric   FunctionCallee HwasanTagMemoryFunc;
4430b57cec5SDimitry Andric   FunctionCallee HwasanGenerateTagFunc;
444753f127fSDimitry Andric   FunctionCallee HwasanRecordFrameRecordFunc;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   Constant *ShadowGlobal;
4470b57cec5SDimitry Andric 
448e8d8bef9SDimitry Andric   Value *ShadowBase = nullptr;
4490b57cec5SDimitry Andric   Value *StackBaseTag = nullptr;
450*0fca6ea1SDimitry Andric   Value *CachedFP = nullptr;
4510b57cec5SDimitry Andric   GlobalValue *ThreadPtrGlobal = nullptr;
4520b57cec5SDimitry Andric };
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric } // end anonymous namespace
4550b57cec5SDimitry Andric 
run(Module & M,ModuleAnalysisManager & MAM)4560b57cec5SDimitry Andric PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
4570b57cec5SDimitry Andric                                               ModuleAnalysisManager &MAM) {
458fe6060f1SDimitry Andric   const StackSafetyGlobalInfo *SSI = nullptr;
459349cc55cSDimitry Andric   auto TargetTriple = llvm::Triple(M.getTargetTriple());
460349cc55cSDimitry Andric   if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
461fe6060f1SDimitry Andric     SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M);
462349cc55cSDimitry Andric 
463349cc55cSDimitry Andric   HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
464349cc55cSDimitry Andric   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
46581ad6265SDimitry Andric   for (Function &F : M)
46606c3fb27SDimitry Andric     HWASan.sanitizeFunction(F, FAM);
467bdd1243dSDimitry Andric 
468bdd1243dSDimitry Andric   PreservedAnalyses PA = PreservedAnalyses::none();
4695f757f3fSDimitry Andric   // DominatorTreeAnalysis, PostDominatorTreeAnalysis, and LoopAnalysis
4705f757f3fSDimitry Andric   // are incrementally updated throughout this pass whenever
4715f757f3fSDimitry Andric   // SplitBlockAndInsertIfThen is called.
4725f757f3fSDimitry Andric   PA.preserve<DominatorTreeAnalysis>();
4735f757f3fSDimitry Andric   PA.preserve<PostDominatorTreeAnalysis>();
4745f757f3fSDimitry Andric   PA.preserve<LoopAnalysis>();
475bdd1243dSDimitry Andric   // GlobalsAA is considered stateless and does not get invalidated unless
476bdd1243dSDimitry Andric   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
477bdd1243dSDimitry Andric   // make changes that require GlobalsAA to be invalidated.
478bdd1243dSDimitry Andric   PA.abandon<GlobalsAA>();
479bdd1243dSDimitry Andric   return PA;
4800b57cec5SDimitry Andric }
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)481349cc55cSDimitry Andric void HWAddressSanitizerPass::printPipeline(
482349cc55cSDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
483349cc55cSDimitry Andric   static_cast<PassInfoMixin<HWAddressSanitizerPass> *>(this)->printPipeline(
484349cc55cSDimitry Andric       OS, MapClassName2PassName);
48506c3fb27SDimitry Andric   OS << '<';
486349cc55cSDimitry Andric   if (Options.CompileKernel)
487349cc55cSDimitry Andric     OS << "kernel;";
488349cc55cSDimitry Andric   if (Options.Recover)
489349cc55cSDimitry Andric     OS << "recover";
49006c3fb27SDimitry Andric   OS << '>';
491349cc55cSDimitry Andric }
4920b57cec5SDimitry Andric 
createHwasanCtorComdat()493e8d8bef9SDimitry Andric void HWAddressSanitizer::createHwasanCtorComdat() {
494e8d8bef9SDimitry Andric   std::tie(HwasanCtorFunction, std::ignore) =
495e8d8bef9SDimitry Andric       getOrCreateSanitizerCtorAndInitFunctions(
496e8d8bef9SDimitry Andric           M, kHwasanModuleCtorName, kHwasanInitName,
497e8d8bef9SDimitry Andric           /*InitArgTypes=*/{},
498e8d8bef9SDimitry Andric           /*InitArgs=*/{},
499e8d8bef9SDimitry Andric           // This callback is invoked when the functions are created the first
500e8d8bef9SDimitry Andric           // time. Hook them into the global ctors list in that case:
501e8d8bef9SDimitry Andric           [&](Function *Ctor, FunctionCallee) {
502e8d8bef9SDimitry Andric             Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
503e8d8bef9SDimitry Andric             Ctor->setComdat(CtorComdat);
504e8d8bef9SDimitry Andric             appendToGlobalCtors(M, Ctor, 0, Ctor);
505e8d8bef9SDimitry Andric           });
506e8d8bef9SDimitry Andric 
507e8d8bef9SDimitry Andric   // Create a note that contains pointers to the list of global
508e8d8bef9SDimitry Andric   // descriptors. Adding a note to the output file will cause the linker to
509e8d8bef9SDimitry Andric   // create a PT_NOTE program header pointing to the note that we can use to
510e8d8bef9SDimitry Andric   // find the descriptor list starting from the program headers. A function
511e8d8bef9SDimitry Andric   // provided by the runtime initializes the shadow memory for the globals by
512e8d8bef9SDimitry Andric   // accessing the descriptor list via the note. The dynamic loader needs to
513e8d8bef9SDimitry Andric   // call this function whenever a library is loaded.
514e8d8bef9SDimitry Andric   //
515e8d8bef9SDimitry Andric   // The reason why we use a note for this instead of a more conventional
516e8d8bef9SDimitry Andric   // approach of having a global constructor pass a descriptor list pointer to
517e8d8bef9SDimitry Andric   // the runtime is because of an order of initialization problem. With
518e8d8bef9SDimitry Andric   // constructors we can encounter the following problematic scenario:
519e8d8bef9SDimitry Andric   //
520e8d8bef9SDimitry Andric   // 1) library A depends on library B and also interposes one of B's symbols
521e8d8bef9SDimitry Andric   // 2) B's constructors are called before A's (as required for correctness)
522e8d8bef9SDimitry Andric   // 3) during construction, B accesses one of its "own" globals (actually
523e8d8bef9SDimitry Andric   //    interposed by A) and triggers a HWASAN failure due to the initialization
524e8d8bef9SDimitry Andric   //    for A not having happened yet
525e8d8bef9SDimitry Andric   //
526e8d8bef9SDimitry Andric   // Even without interposition it is possible to run into similar situations in
527e8d8bef9SDimitry Andric   // cases where two libraries mutually depend on each other.
528e8d8bef9SDimitry Andric   //
529e8d8bef9SDimitry Andric   // We only need one note per binary, so put everything for the note in a
530e8d8bef9SDimitry Andric   // comdat. This needs to be a comdat with an .init_array section to prevent
531e8d8bef9SDimitry Andric   // newer versions of lld from discarding the note.
532e8d8bef9SDimitry Andric   //
533e8d8bef9SDimitry Andric   // Create the note even if we aren't instrumenting globals. This ensures that
534e8d8bef9SDimitry Andric   // binaries linked from object files with both instrumented and
535e8d8bef9SDimitry Andric   // non-instrumented globals will end up with a note, even if a comdat from an
536e8d8bef9SDimitry Andric   // object file with non-instrumented globals is selected. The note is harmless
537e8d8bef9SDimitry Andric   // if the runtime doesn't support it, since it will just be ignored.
538e8d8bef9SDimitry Andric   Comdat *NoteComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
539e8d8bef9SDimitry Andric 
540e8d8bef9SDimitry Andric   Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
541bdd1243dSDimitry Andric   auto *Start =
542e8d8bef9SDimitry Andric       new GlobalVariable(M, Int8Arr0Ty, true, GlobalVariable::ExternalLinkage,
543e8d8bef9SDimitry Andric                          nullptr, "__start_hwasan_globals");
544e8d8bef9SDimitry Andric   Start->setVisibility(GlobalValue::HiddenVisibility);
545bdd1243dSDimitry Andric   auto *Stop =
546e8d8bef9SDimitry Andric       new GlobalVariable(M, Int8Arr0Ty, true, GlobalVariable::ExternalLinkage,
547e8d8bef9SDimitry Andric                          nullptr, "__stop_hwasan_globals");
548e8d8bef9SDimitry Andric   Stop->setVisibility(GlobalValue::HiddenVisibility);
549e8d8bef9SDimitry Andric 
550e8d8bef9SDimitry Andric   // Null-terminated so actually 8 bytes, which are required in order to align
551e8d8bef9SDimitry Andric   // the note properly.
552e8d8bef9SDimitry Andric   auto *Name = ConstantDataArray::get(*C, "LLVM\0\0\0");
553e8d8bef9SDimitry Andric 
554e8d8bef9SDimitry Andric   auto *NoteTy = StructType::get(Int32Ty, Int32Ty, Int32Ty, Name->getType(),
555e8d8bef9SDimitry Andric                                  Int32Ty, Int32Ty);
556e8d8bef9SDimitry Andric   auto *Note =
557e8d8bef9SDimitry Andric       new GlobalVariable(M, NoteTy, /*isConstant=*/true,
558e8d8bef9SDimitry Andric                          GlobalValue::PrivateLinkage, nullptr, kHwasanNoteName);
559e8d8bef9SDimitry Andric   Note->setSection(".note.hwasan.globals");
560e8d8bef9SDimitry Andric   Note->setComdat(NoteComdat);
561e8d8bef9SDimitry Andric   Note->setAlignment(Align(4));
562e8d8bef9SDimitry Andric 
563e8d8bef9SDimitry Andric   // The pointers in the note need to be relative so that the note ends up being
564e8d8bef9SDimitry Andric   // placed in rodata, which is the standard location for notes.
565e8d8bef9SDimitry Andric   auto CreateRelPtr = [&](Constant *Ptr) {
566e8d8bef9SDimitry Andric     return ConstantExpr::getTrunc(
567e8d8bef9SDimitry Andric         ConstantExpr::getSub(ConstantExpr::getPtrToInt(Ptr, Int64Ty),
568e8d8bef9SDimitry Andric                              ConstantExpr::getPtrToInt(Note, Int64Ty)),
569e8d8bef9SDimitry Andric         Int32Ty);
570e8d8bef9SDimitry Andric   };
571e8d8bef9SDimitry Andric   Note->setInitializer(ConstantStruct::getAnon(
572e8d8bef9SDimitry Andric       {ConstantInt::get(Int32Ty, 8),                           // n_namesz
573e8d8bef9SDimitry Andric        ConstantInt::get(Int32Ty, 8),                           // n_descsz
574e8d8bef9SDimitry Andric        ConstantInt::get(Int32Ty, ELF::NT_LLVM_HWASAN_GLOBALS), // n_type
575e8d8bef9SDimitry Andric        Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
576e8d8bef9SDimitry Andric   appendToCompilerUsed(M, Note);
577e8d8bef9SDimitry Andric 
578e8d8bef9SDimitry Andric   // Create a zero-length global in hwasan_globals so that the linker will
579e8d8bef9SDimitry Andric   // always create start and stop symbols.
580bdd1243dSDimitry Andric   auto *Dummy = new GlobalVariable(
581e8d8bef9SDimitry Andric       M, Int8Arr0Ty, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage,
582e8d8bef9SDimitry Andric       Constant::getNullValue(Int8Arr0Ty), "hwasan.dummy.global");
583e8d8bef9SDimitry Andric   Dummy->setSection("hwasan_globals");
584e8d8bef9SDimitry Andric   Dummy->setComdat(NoteComdat);
585e8d8bef9SDimitry Andric   Dummy->setMetadata(LLVMContext::MD_associated,
586e8d8bef9SDimitry Andric                      MDNode::get(*C, ValueAsMetadata::get(Note)));
587e8d8bef9SDimitry Andric   appendToCompilerUsed(M, Dummy);
588e8d8bef9SDimitry Andric }
589e8d8bef9SDimitry Andric 
5900b57cec5SDimitry Andric /// Module-level initialization.
5910b57cec5SDimitry Andric ///
5920b57cec5SDimitry Andric /// inserts a call to __hwasan_init to the module's constructor list.
initializeModule()5938bcb0991SDimitry Andric void HWAddressSanitizer::initializeModule() {
5940b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
5950b57cec5SDimitry Andric   TargetTriple = Triple(M.getTargetTriple());
5960b57cec5SDimitry Andric 
597fe6060f1SDimitry Andric   // x86_64 currently has two modes:
598fe6060f1SDimitry Andric   // - Intel LAM (default)
599fe6060f1SDimitry Andric   // - pointer aliasing (heap only)
600fe6060f1SDimitry Andric   bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
601fe6060f1SDimitry Andric   UsePageAliases = shouldUsePageAliases(TargetTriple);
602fe6060f1SDimitry Andric   InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
603fe6060f1SDimitry Andric   InstrumentStack = shouldInstrumentStack(TargetTriple);
604349cc55cSDimitry Andric   DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
605fe6060f1SDimitry Andric   PointerTagShift = IsX86_64 ? 57 : 56;
606fe6060f1SDimitry Andric   TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
607fe6060f1SDimitry Andric 
608fe6060f1SDimitry Andric   Mapping.init(TargetTriple, InstrumentWithCalls);
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   C = &(M.getContext());
6110b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   HwasanCtorFunction = nullptr;
6148bcb0991SDimitry Andric 
6158bcb0991SDimitry Andric   // Older versions of Android do not have the required runtime support for
6168bcb0991SDimitry Andric   // short granules, global or personality function instrumentation. On other
6178bcb0991SDimitry Andric   // platforms we currently require using the latest version of the runtime.
6188bcb0991SDimitry Andric   bool NewRuntime =
6198bcb0991SDimitry Andric       !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30);
6208bcb0991SDimitry Andric 
621*0fca6ea1SDimitry Andric   UseShortGranules = optOr(ClUseShortGranules, NewRuntime);
622*0fca6ea1SDimitry Andric   OutlinedChecks = (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) &&
623bdd1243dSDimitry Andric                    TargetTriple.isOSBinFormatELF() &&
624*0fca6ea1SDimitry Andric                    !optOr(ClInlineAllChecks, Recover);
625e8d8bef9SDimitry Andric 
626*0fca6ea1SDimitry Andric   // These platforms may prefer less inlining to reduce binary size.
627*0fca6ea1SDimitry Andric   InlineFastPath = optOr(ClInlineFastPathChecks, !(TargetTriple.isAndroid() ||
628*0fca6ea1SDimitry Andric                                                    TargetTriple.isOSFuchsia()));
6295f757f3fSDimitry Andric 
630e8d8bef9SDimitry Andric   if (ClMatchAllTag.getNumOccurrences()) {
631e8d8bef9SDimitry Andric     if (ClMatchAllTag != -1) {
632e8d8bef9SDimitry Andric       MatchAllTag = ClMatchAllTag & 0xFF;
633e8d8bef9SDimitry Andric     }
634e8d8bef9SDimitry Andric   } else if (CompileKernel) {
635e8d8bef9SDimitry Andric     MatchAllTag = 0xFF;
636e8d8bef9SDimitry Andric   }
63706c3fb27SDimitry Andric   UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
6388bcb0991SDimitry Andric 
6398bcb0991SDimitry Andric   // If we don't have personality function support, fall back to landing pads.
640*0fca6ea1SDimitry Andric   InstrumentLandingPads = optOr(ClInstrumentLandingPads, !NewRuntime);
641*0fca6ea1SDimitry Andric 
642*0fca6ea1SDimitry Andric   InstrumentGlobals =
643*0fca6ea1SDimitry Andric       !CompileKernel && !UsePageAliases && optOr(ClGlobals, NewRuntime);
6448bcb0991SDimitry Andric 
6450b57cec5SDimitry Andric   if (!CompileKernel) {
646e8d8bef9SDimitry Andric     createHwasanCtorComdat();
647fe6060f1SDimitry Andric 
648*0fca6ea1SDimitry Andric     if (InstrumentGlobals)
6498bcb0991SDimitry Andric       instrumentGlobals();
6508bcb0991SDimitry Andric 
6518bcb0991SDimitry Andric     bool InstrumentPersonalityFunctions =
652*0fca6ea1SDimitry Andric         optOr(ClInstrumentPersonalityFunctions, NewRuntime);
6538bcb0991SDimitry Andric     if (InstrumentPersonalityFunctions)
6548bcb0991SDimitry Andric       instrumentPersonalityFunctions();
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   if (!TargetTriple.isAndroid()) {
6580b57cec5SDimitry Andric     Constant *C = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
6590b57cec5SDimitry Andric       auto *GV = new GlobalVariable(M, IntptrTy, /*isConstant=*/false,
6600b57cec5SDimitry Andric                                     GlobalValue::ExternalLinkage, nullptr,
6610b57cec5SDimitry Andric                                     "__hwasan_tls", nullptr,
6620b57cec5SDimitry Andric                                     GlobalVariable::InitialExecTLSModel);
6630b57cec5SDimitry Andric       appendToCompilerUsed(M, GV);
6640b57cec5SDimitry Andric       return GV;
6650b57cec5SDimitry Andric     });
6660b57cec5SDimitry Andric     ThreadPtrGlobal = cast<GlobalVariable>(C);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric 
initializeCallbacks(Module & M)6700b57cec5SDimitry Andric void HWAddressSanitizer::initializeCallbacks(Module &M) {
6710b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
67206c3fb27SDimitry Andric   const std::string MatchAllStr = UseMatchAllCallback ? "_match_all" : "";
67306c3fb27SDimitry Andric   FunctionType *HwasanMemoryAccessCallbackSizedFnTy,
67406c3fb27SDimitry Andric       *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
67506c3fb27SDimitry Andric       *HwasanMemsetFnTy;
67606c3fb27SDimitry Andric   if (UseMatchAllCallback) {
67706c3fb27SDimitry Andric     HwasanMemoryAccessCallbackSizedFnTy =
67806c3fb27SDimitry Andric         FunctionType::get(VoidTy, {IntptrTy, IntptrTy, Int8Ty}, false);
67906c3fb27SDimitry Andric     HwasanMemoryAccessCallbackFnTy =
68006c3fb27SDimitry Andric         FunctionType::get(VoidTy, {IntptrTy, Int8Ty}, false);
6815f757f3fSDimitry Andric     HwasanMemTransferFnTy =
6825f757f3fSDimitry Andric         FunctionType::get(PtrTy, {PtrTy, PtrTy, IntptrTy, Int8Ty}, false);
6835f757f3fSDimitry Andric     HwasanMemsetFnTy =
6845f757f3fSDimitry Andric         FunctionType::get(PtrTy, {PtrTy, Int32Ty, IntptrTy, Int8Ty}, false);
68506c3fb27SDimitry Andric   } else {
68606c3fb27SDimitry Andric     HwasanMemoryAccessCallbackSizedFnTy =
68706c3fb27SDimitry Andric         FunctionType::get(VoidTy, {IntptrTy, IntptrTy}, false);
68806c3fb27SDimitry Andric     HwasanMemoryAccessCallbackFnTy =
68906c3fb27SDimitry Andric         FunctionType::get(VoidTy, {IntptrTy}, false);
69006c3fb27SDimitry Andric     HwasanMemTransferFnTy =
6915f757f3fSDimitry Andric         FunctionType::get(PtrTy, {PtrTy, PtrTy, IntptrTy}, false);
69206c3fb27SDimitry Andric     HwasanMemsetFnTy =
6935f757f3fSDimitry Andric         FunctionType::get(PtrTy, {PtrTy, Int32Ty, IntptrTy}, false);
69406c3fb27SDimitry Andric   }
69506c3fb27SDimitry Andric 
6960b57cec5SDimitry Andric   for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
6970b57cec5SDimitry Andric     const std::string TypeStr = AccessIsWrite ? "store" : "load";
6980b57cec5SDimitry Andric     const std::string EndingStr = Recover ? "_noabort" : "";
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric     HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(
70106c3fb27SDimitry Andric         ClMemoryAccessCallbackPrefix + TypeStr + "N" + MatchAllStr + EndingStr,
70206c3fb27SDimitry Andric         HwasanMemoryAccessCallbackSizedFnTy);
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric     for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
7050b57cec5SDimitry Andric          AccessSizeIndex++) {
7060b57cec5SDimitry Andric       HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
70706c3fb27SDimitry Andric           M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr +
70806c3fb27SDimitry Andric                                     itostr(1ULL << AccessSizeIndex) +
70906c3fb27SDimitry Andric                                     MatchAllStr + EndingStr,
71006c3fb27SDimitry Andric                                 HwasanMemoryAccessCallbackFnTy);
7110b57cec5SDimitry Andric     }
7120b57cec5SDimitry Andric   }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   const std::string MemIntrinCallbackPrefix =
71581ad6265SDimitry Andric       (CompileKernel && !ClKasanMemIntrinCallbackPrefix)
71681ad6265SDimitry Andric           ? std::string("")
71781ad6265SDimitry Andric           : ClMemoryAccessCallbackPrefix;
7180b57cec5SDimitry Andric 
71906c3fb27SDimitry Andric   HwasanMemmove = M.getOrInsertFunction(
72006c3fb27SDimitry Andric       MemIntrinCallbackPrefix + "memmove" + MatchAllStr, HwasanMemTransferFnTy);
72106c3fb27SDimitry Andric   HwasanMemcpy = M.getOrInsertFunction(
72206c3fb27SDimitry Andric       MemIntrinCallbackPrefix + "memcpy" + MatchAllStr, HwasanMemTransferFnTy);
72306c3fb27SDimitry Andric   HwasanMemset = M.getOrInsertFunction(
72406c3fb27SDimitry Andric       MemIntrinCallbackPrefix + "memset" + MatchAllStr, HwasanMemsetFnTy);
72506c3fb27SDimitry Andric 
72606c3fb27SDimitry Andric   HwasanTagMemoryFunc = M.getOrInsertFunction("__hwasan_tag_memory", VoidTy,
7275f757f3fSDimitry Andric                                               PtrTy, Int8Ty, IntptrTy);
72806c3fb27SDimitry Andric   HwasanGenerateTagFunc =
72906c3fb27SDimitry Andric       M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);
73006c3fb27SDimitry Andric 
73106c3fb27SDimitry Andric   HwasanRecordFrameRecordFunc =
73206c3fb27SDimitry Andric       M.getOrInsertFunction("__hwasan_add_frame_record", VoidTy, Int64Ty);
73306c3fb27SDimitry Andric 
73406c3fb27SDimitry Andric   ShadowGlobal =
73506c3fb27SDimitry Andric       M.getOrInsertGlobal("__hwasan_shadow", ArrayType::get(Int8Ty, 0));
73606c3fb27SDimitry Andric 
73706c3fb27SDimitry Andric   HwasanHandleVfork =
73806c3fb27SDimitry Andric       M.getOrInsertFunction("__hwasan_handle_vfork", VoidTy, IntptrTy);
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric 
getOpaqueNoopCast(IRBuilder<> & IRB,Value * Val)741e8d8bef9SDimitry Andric Value *HWAddressSanitizer::getOpaqueNoopCast(IRBuilder<> &IRB, Value *Val) {
7420b57cec5SDimitry Andric   // An empty inline asm with input reg == output reg.
7430b57cec5SDimitry Andric   // An opaque no-op cast, basically.
744e8d8bef9SDimitry Andric   // This prevents code bloat as a result of rematerializing trivial definitions
745e8d8bef9SDimitry Andric   // such as constants or global addresses at every load and store.
746e8d8bef9SDimitry Andric   InlineAsm *Asm =
7475f757f3fSDimitry Andric       InlineAsm::get(FunctionType::get(PtrTy, {Val->getType()}, false),
7480b57cec5SDimitry Andric                      StringRef(""), StringRef("=r,0"),
7490b57cec5SDimitry Andric                      /*hasSideEffects=*/false);
750e8d8bef9SDimitry Andric   return IRB.CreateCall(Asm, {Val}, ".hwasan.shadow");
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric 
getDynamicShadowIfunc(IRBuilder<> & IRB)753e8d8bef9SDimitry Andric Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {
754e8d8bef9SDimitry Andric   return getOpaqueNoopCast(IRB, ShadowGlobal);
755e8d8bef9SDimitry Andric }
756e8d8bef9SDimitry Andric 
getShadowNonTls(IRBuilder<> & IRB)757e8d8bef9SDimitry Andric Value *HWAddressSanitizer::getShadowNonTls(IRBuilder<> &IRB) {
7580b57cec5SDimitry Andric   if (Mapping.Offset != kDynamicShadowSentinel)
759e8d8bef9SDimitry Andric     return getOpaqueNoopCast(
760e8d8bef9SDimitry Andric         IRB, ConstantExpr::getIntToPtr(
7615f757f3fSDimitry Andric                  ConstantInt::get(IntptrTy, Mapping.Offset), PtrTy));
7620b57cec5SDimitry Andric 
763bdd1243dSDimitry Andric   if (Mapping.InGlobal)
7640b57cec5SDimitry Andric     return getDynamicShadowIfunc(IRB);
765bdd1243dSDimitry Andric 
7660b57cec5SDimitry Andric   Value *GlobalDynamicAddress =
7670b57cec5SDimitry Andric       IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
7685f757f3fSDimitry Andric           kHwasanShadowMemoryDynamicAddress, PtrTy);
7695f757f3fSDimitry Andric   return IRB.CreateLoad(PtrTy, GlobalDynamicAddress);
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
ignoreAccessWithoutRemark(Instruction * Inst,Value * Ptr)772*0fca6ea1SDimitry Andric bool HWAddressSanitizer::ignoreAccessWithoutRemark(Instruction *Inst,
773*0fca6ea1SDimitry Andric                                                    Value *Ptr) {
774bdd1243dSDimitry Andric   // Do not instrument accesses from different address spaces; we cannot deal
7750b57cec5SDimitry Andric   // with them.
7765ffd83dbSDimitry Andric   Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType());
7770b57cec5SDimitry Andric   if (PtrTy->getPointerAddressSpace() != 0)
7785ffd83dbSDimitry Andric     return true;
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   // Ignore swifterror addresses.
7810b57cec5SDimitry Andric   // swifterror memory addresses are mem2reg promoted by instruction
7820b57cec5SDimitry Andric   // selection. As such they cannot have regular uses like an instrumentation
7830b57cec5SDimitry Andric   // function and it makes no sense to track them as memory.
7845ffd83dbSDimitry Andric   if (Ptr->isSwiftError())
7855ffd83dbSDimitry Andric     return true;
7865ffd83dbSDimitry Andric 
787349cc55cSDimitry Andric   if (findAllocaForValue(Ptr)) {
788349cc55cSDimitry Andric     if (!InstrumentStack)
789349cc55cSDimitry Andric       return true;
790349cc55cSDimitry Andric     if (SSI && SSI->stackAccessIsSafe(*Inst))
791349cc55cSDimitry Andric       return true;
792349cc55cSDimitry Andric   }
793*0fca6ea1SDimitry Andric 
794*0fca6ea1SDimitry Andric   if (isa<GlobalVariable>(getUnderlyingObject(Ptr))) {
795*0fca6ea1SDimitry Andric     if (!InstrumentGlobals)
796*0fca6ea1SDimitry Andric       return true;
797*0fca6ea1SDimitry Andric     // TODO: Optimize inbound global accesses, like Asan `instrumentMop`.
798*0fca6ea1SDimitry Andric   }
799*0fca6ea1SDimitry Andric 
8005ffd83dbSDimitry Andric   return false;
8010b57cec5SDimitry Andric }
8020b57cec5SDimitry Andric 
ignoreAccess(OptimizationRemarkEmitter & ORE,Instruction * Inst,Value * Ptr)803*0fca6ea1SDimitry Andric bool HWAddressSanitizer::ignoreAccess(OptimizationRemarkEmitter &ORE,
804*0fca6ea1SDimitry Andric                                       Instruction *Inst, Value *Ptr) {
805*0fca6ea1SDimitry Andric   bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
806*0fca6ea1SDimitry Andric   if (Ignored) {
807*0fca6ea1SDimitry Andric     ORE.emit(
808*0fca6ea1SDimitry Andric         [&]() { return OptimizationRemark(DEBUG_TYPE, "ignoreAccess", Inst); });
809*0fca6ea1SDimitry Andric   } else {
810*0fca6ea1SDimitry Andric     ORE.emit([&]() {
811*0fca6ea1SDimitry Andric       return OptimizationRemarkMissed(DEBUG_TYPE, "ignoreAccess", Inst);
812*0fca6ea1SDimitry Andric     });
813*0fca6ea1SDimitry Andric   }
814*0fca6ea1SDimitry Andric   return Ignored;
815*0fca6ea1SDimitry Andric }
816*0fca6ea1SDimitry Andric 
getInterestingMemoryOperands(OptimizationRemarkEmitter & ORE,Instruction * I,const TargetLibraryInfo & TLI,SmallVectorImpl<InterestingMemoryOperand> & Interesting)8175ffd83dbSDimitry Andric void HWAddressSanitizer::getInterestingMemoryOperands(
818*0fca6ea1SDimitry Andric     OptimizationRemarkEmitter &ORE, Instruction *I,
819*0fca6ea1SDimitry Andric     const TargetLibraryInfo &TLI,
8205f757f3fSDimitry Andric     SmallVectorImpl<InterestingMemoryOperand> &Interesting) {
8215ffd83dbSDimitry Andric   // Skip memory accesses inserted by another instrumentation.
82281ad6265SDimitry Andric   if (I->hasMetadata(LLVMContext::MD_nosanitize))
8235ffd83dbSDimitry Andric     return;
8245ffd83dbSDimitry Andric 
8255ffd83dbSDimitry Andric   // Do not instrument the load fetching the dynamic shadow address.
826e8d8bef9SDimitry Andric   if (ShadowBase == I)
8275ffd83dbSDimitry Andric     return;
8285ffd83dbSDimitry Andric 
8295ffd83dbSDimitry Andric   if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
830*0fca6ea1SDimitry Andric     if (!ClInstrumentReads || ignoreAccess(ORE, I, LI->getPointerOperand()))
8315ffd83dbSDimitry Andric       return;
8325ffd83dbSDimitry Andric     Interesting.emplace_back(I, LI->getPointerOperandIndex(), false,
8335ffd83dbSDimitry Andric                              LI->getType(), LI->getAlign());
8345ffd83dbSDimitry Andric   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
835*0fca6ea1SDimitry Andric     if (!ClInstrumentWrites || ignoreAccess(ORE, I, SI->getPointerOperand()))
8365ffd83dbSDimitry Andric       return;
8375ffd83dbSDimitry Andric     Interesting.emplace_back(I, SI->getPointerOperandIndex(), true,
8385ffd83dbSDimitry Andric                              SI->getValueOperand()->getType(), SI->getAlign());
8395ffd83dbSDimitry Andric   } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
840*0fca6ea1SDimitry Andric     if (!ClInstrumentAtomics || ignoreAccess(ORE, I, RMW->getPointerOperand()))
8415ffd83dbSDimitry Andric       return;
8425ffd83dbSDimitry Andric     Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true,
843bdd1243dSDimitry Andric                              RMW->getValOperand()->getType(), std::nullopt);
8445ffd83dbSDimitry Andric   } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
845*0fca6ea1SDimitry Andric     if (!ClInstrumentAtomics || ignoreAccess(ORE, I, XCHG->getPointerOperand()))
8465ffd83dbSDimitry Andric       return;
8475ffd83dbSDimitry Andric     Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true,
848bdd1243dSDimitry Andric                              XCHG->getCompareOperand()->getType(),
849bdd1243dSDimitry Andric                              std::nullopt);
850bdd1243dSDimitry Andric   } else if (auto *CI = dyn_cast<CallInst>(I)) {
851349cc55cSDimitry Andric     for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
8525ffd83dbSDimitry Andric       if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) ||
853*0fca6ea1SDimitry Andric           ignoreAccess(ORE, I, CI->getArgOperand(ArgNo)))
8545ffd83dbSDimitry Andric         continue;
8555ffd83dbSDimitry Andric       Type *Ty = CI->getParamByValType(ArgNo);
8565ffd83dbSDimitry Andric       Interesting.emplace_back(I, ArgNo, false, Ty, Align(1));
8575ffd83dbSDimitry Andric     }
8585f757f3fSDimitry Andric     maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI);
8595ffd83dbSDimitry Andric   }
8600b57cec5SDimitry Andric }
8610b57cec5SDimitry Andric 
getPointerOperandIndex(Instruction * I)8620b57cec5SDimitry Andric static unsigned getPointerOperandIndex(Instruction *I) {
8630b57cec5SDimitry Andric   if (LoadInst *LI = dyn_cast<LoadInst>(I))
8640b57cec5SDimitry Andric     return LI->getPointerOperandIndex();
8650b57cec5SDimitry Andric   if (StoreInst *SI = dyn_cast<StoreInst>(I))
8660b57cec5SDimitry Andric     return SI->getPointerOperandIndex();
8670b57cec5SDimitry Andric   if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I))
8680b57cec5SDimitry Andric     return RMW->getPointerOperandIndex();
8690b57cec5SDimitry Andric   if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I))
8700b57cec5SDimitry Andric     return XCHG->getPointerOperandIndex();
8710b57cec5SDimitry Andric   report_fatal_error("Unexpected instruction");
8720b57cec5SDimitry Andric   return -1;
8730b57cec5SDimitry Andric }
8740b57cec5SDimitry Andric 
TypeSizeToSizeIndex(uint32_t TypeSize)8750b57cec5SDimitry Andric static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
87606c3fb27SDimitry Andric   size_t Res = llvm::countr_zero(TypeSize / 8);
8770b57cec5SDimitry Andric   assert(Res < kNumberOfAccessSizes);
8780b57cec5SDimitry Andric   return Res;
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
untagPointerOperand(Instruction * I,Value * Addr)8810b57cec5SDimitry Andric void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
882bdd1243dSDimitry Andric   if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64 ||
883bdd1243dSDimitry Andric       TargetTriple.isRISCV64())
8840b57cec5SDimitry Andric     return;
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric   IRBuilder<> IRB(I);
8870b57cec5SDimitry Andric   Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
8880b57cec5SDimitry Andric   Value *UntaggedPtr =
8890b57cec5SDimitry Andric       IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType());
8900b57cec5SDimitry Andric   I->setOperand(getPointerOperandIndex(I), UntaggedPtr);
8910b57cec5SDimitry Andric }
8920b57cec5SDimitry Andric 
memToShadow(Value * Mem,IRBuilder<> & IRB)8930b57cec5SDimitry Andric Value *HWAddressSanitizer::memToShadow(Value *Mem, IRBuilder<> &IRB) {
8940b57cec5SDimitry Andric   // Mem >> Scale
8950b57cec5SDimitry Andric   Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale);
8960b57cec5SDimitry Andric   if (Mapping.Offset == 0)
8975f757f3fSDimitry Andric     return IRB.CreateIntToPtr(Shadow, PtrTy);
8980b57cec5SDimitry Andric   // (Mem >> Scale) + Offset
8997a6dacacSDimitry Andric   return IRB.CreatePtrAdd(ShadowBase, Shadow);
9000b57cec5SDimitry Andric }
9010b57cec5SDimitry Andric 
getAccessInfo(bool IsWrite,unsigned AccessSizeIndex)902349cc55cSDimitry Andric int64_t HWAddressSanitizer::getAccessInfo(bool IsWrite,
903349cc55cSDimitry Andric                                           unsigned AccessSizeIndex) {
904bdd1243dSDimitry Andric   return (CompileKernel << HWASanAccessInfo::CompileKernelShift) |
905bdd1243dSDimitry Andric          (MatchAllTag.has_value() << HWASanAccessInfo::HasMatchAllShift) |
906bdd1243dSDimitry Andric          (MatchAllTag.value_or(0) << HWASanAccessInfo::MatchAllShift) |
907bdd1243dSDimitry Andric          (Recover << HWASanAccessInfo::RecoverShift) |
908bdd1243dSDimitry Andric          (IsWrite << HWASanAccessInfo::IsWriteShift) |
909e8d8bef9SDimitry Andric          (AccessSizeIndex << HWASanAccessInfo::AccessSizeShift);
910349cc55cSDimitry Andric }
9110b57cec5SDimitry Andric 
9125f757f3fSDimitry Andric HWAddressSanitizer::ShadowTagCheckInfo
insertShadowTagCheck(Value * Ptr,Instruction * InsertBefore,DomTreeUpdater & DTU,LoopInfo * LI)9135f757f3fSDimitry Andric HWAddressSanitizer::insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,
9145f757f3fSDimitry Andric                                          DomTreeUpdater &DTU, LoopInfo *LI) {
9155f757f3fSDimitry Andric   ShadowTagCheckInfo R;
9165f757f3fSDimitry Andric 
9175f757f3fSDimitry Andric   IRBuilder<> IRB(InsertBefore);
9185f757f3fSDimitry Andric 
9195f757f3fSDimitry Andric   R.PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
9205f757f3fSDimitry Andric   R.PtrTag =
9215f757f3fSDimitry Andric       IRB.CreateTrunc(IRB.CreateLShr(R.PtrLong, PointerTagShift), Int8Ty);
9225f757f3fSDimitry Andric   R.AddrLong = untagPointer(IRB, R.PtrLong);
9235f757f3fSDimitry Andric   Value *Shadow = memToShadow(R.AddrLong, IRB);
9245f757f3fSDimitry Andric   R.MemTag = IRB.CreateLoad(Int8Ty, Shadow);
9255f757f3fSDimitry Andric   Value *TagMismatch = IRB.CreateICmpNE(R.PtrTag, R.MemTag);
9265f757f3fSDimitry Andric 
9275f757f3fSDimitry Andric   if (MatchAllTag.has_value()) {
9285f757f3fSDimitry Andric     Value *TagNotIgnored = IRB.CreateICmpNE(
9295f757f3fSDimitry Andric         R.PtrTag, ConstantInt::get(R.PtrTag->getType(), *MatchAllTag));
9305f757f3fSDimitry Andric     TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);
9315f757f3fSDimitry Andric   }
9325f757f3fSDimitry Andric 
9335f757f3fSDimitry Andric   R.TagMismatchTerm = SplitBlockAndInsertIfThen(
9345f757f3fSDimitry Andric       TagMismatch, InsertBefore, false,
935*0fca6ea1SDimitry Andric       MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);
9365f757f3fSDimitry Andric 
9375f757f3fSDimitry Andric   return R;
9385f757f3fSDimitry Andric }
9395f757f3fSDimitry Andric 
instrumentMemAccessOutline(Value * Ptr,bool IsWrite,unsigned AccessSizeIndex,Instruction * InsertBefore,DomTreeUpdater & DTU,LoopInfo * LI)940349cc55cSDimitry Andric void HWAddressSanitizer::instrumentMemAccessOutline(Value *Ptr, bool IsWrite,
941349cc55cSDimitry Andric                                                     unsigned AccessSizeIndex,
9425f757f3fSDimitry Andric                                                     Instruction *InsertBefore,
9435f757f3fSDimitry Andric                                                     DomTreeUpdater &DTU,
9445f757f3fSDimitry Andric                                                     LoopInfo *LI) {
945349cc55cSDimitry Andric   assert(!UsePageAliases);
946349cc55cSDimitry Andric   const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
9475f757f3fSDimitry Andric 
9485f757f3fSDimitry Andric   if (InlineFastPath)
9495f757f3fSDimitry Andric     InsertBefore =
9505f757f3fSDimitry Andric         insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
9515f757f3fSDimitry Andric 
952349cc55cSDimitry Andric   IRBuilder<> IRB(InsertBefore);
9530b57cec5SDimitry Andric   Module *M = IRB.GetInsertBlock()->getParent()->getParent();
954*0fca6ea1SDimitry Andric   bool useFixedShadowIntrinsic = false;
955*0fca6ea1SDimitry Andric   // The memaccess fixed shadow intrinsic is only supported on AArch64,
956*0fca6ea1SDimitry Andric   // which allows a 16-bit immediate to be left-shifted by 32.
957*0fca6ea1SDimitry Andric   // Since kShadowBaseAlignment == 32, and Linux by default will not
958*0fca6ea1SDimitry Andric   // mmap above 48-bits, practically any valid shadow offset is
959*0fca6ea1SDimitry Andric   // representable.
960*0fca6ea1SDimitry Andric   // In particular, an offset of 4TB (1024 << 32) is representable, and
961*0fca6ea1SDimitry Andric   // ought to be good enough for anybody.
962*0fca6ea1SDimitry Andric   if (TargetTriple.isAArch64() && Mapping.Offset != kDynamicShadowSentinel) {
963*0fca6ea1SDimitry Andric     uint16_t offset_shifted = Mapping.Offset >> 32;
964*0fca6ea1SDimitry Andric     useFixedShadowIntrinsic = (uint64_t)offset_shifted << 32 == Mapping.Offset;
965*0fca6ea1SDimitry Andric   }
966*0fca6ea1SDimitry Andric 
967*0fca6ea1SDimitry Andric   if (useFixedShadowIntrinsic)
968*0fca6ea1SDimitry Andric     IRB.CreateCall(
969*0fca6ea1SDimitry Andric         Intrinsic::getDeclaration(
970*0fca6ea1SDimitry Andric             M, UseShortGranules
971*0fca6ea1SDimitry Andric                    ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
972*0fca6ea1SDimitry Andric                    : Intrinsic::hwasan_check_memaccess_fixedshadow),
973*0fca6ea1SDimitry Andric         {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
974*0fca6ea1SDimitry Andric          ConstantInt::get(Int64Ty, Mapping.Offset)});
975*0fca6ea1SDimitry Andric   else
9768bcb0991SDimitry Andric     IRB.CreateCall(Intrinsic::getDeclaration(
9778bcb0991SDimitry Andric                        M, UseShortGranules
9788bcb0991SDimitry Andric                               ? Intrinsic::hwasan_check_memaccess_shortgranules
9798bcb0991SDimitry Andric                               : Intrinsic::hwasan_check_memaccess),
980e8d8bef9SDimitry Andric                    {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric 
instrumentMemAccessInline(Value * Ptr,bool IsWrite,unsigned AccessSizeIndex,Instruction * InsertBefore,DomTreeUpdater & DTU,LoopInfo * LI)983349cc55cSDimitry Andric void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
984349cc55cSDimitry Andric                                                    unsigned AccessSizeIndex,
9855f757f3fSDimitry Andric                                                    Instruction *InsertBefore,
9865f757f3fSDimitry Andric                                                    DomTreeUpdater &DTU,
9875f757f3fSDimitry Andric                                                    LoopInfo *LI) {
988349cc55cSDimitry Andric   assert(!UsePageAliases);
989349cc55cSDimitry Andric   const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
990349cc55cSDimitry Andric 
9915f757f3fSDimitry Andric   ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
9920b57cec5SDimitry Andric 
9935f757f3fSDimitry Andric   IRBuilder<> IRB(TCI.TagMismatchTerm);
9940b57cec5SDimitry Andric   Value *OutOfShortGranuleTagRange =
9955f757f3fSDimitry Andric       IRB.CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
9965f757f3fSDimitry Andric   Instruction *CheckFailTerm = SplitBlockAndInsertIfThen(
9975f757f3fSDimitry Andric       OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
998*0fca6ea1SDimitry Andric       MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);
9990b57cec5SDimitry Andric 
10005f757f3fSDimitry Andric   IRB.SetInsertPoint(TCI.TagMismatchTerm);
10015f757f3fSDimitry Andric   Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(TCI.PtrLong, 15), Int8Ty);
10020b57cec5SDimitry Andric   PtrLowBits = IRB.CreateAdd(
10030b57cec5SDimitry Andric       PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
10045f757f3fSDimitry Andric   Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, TCI.MemTag);
10055f757f3fSDimitry Andric   SplitBlockAndInsertIfThen(PtrLowBitsOOB, TCI.TagMismatchTerm, false,
1006*0fca6ea1SDimitry Andric                             MDBuilder(*C).createUnlikelyBranchWeights(), &DTU,
10075f757f3fSDimitry Andric                             LI, CheckFailTerm->getParent());
10080b57cec5SDimitry Andric 
10095f757f3fSDimitry Andric   IRB.SetInsertPoint(TCI.TagMismatchTerm);
10105f757f3fSDimitry Andric   Value *InlineTagAddr = IRB.CreateOr(TCI.AddrLong, 15);
10115f757f3fSDimitry Andric   InlineTagAddr = IRB.CreateIntToPtr(InlineTagAddr, PtrTy);
10120b57cec5SDimitry Andric   Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr);
10135f757f3fSDimitry Andric   Value *InlineTagMismatch = IRB.CreateICmpNE(TCI.PtrTag, InlineTag);
10145f757f3fSDimitry Andric   SplitBlockAndInsertIfThen(InlineTagMismatch, TCI.TagMismatchTerm, false,
1015*0fca6ea1SDimitry Andric                             MDBuilder(*C).createUnlikelyBranchWeights(), &DTU,
10165f757f3fSDimitry Andric                             LI, CheckFailTerm->getParent());
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   IRB.SetInsertPoint(CheckFailTerm);
10190b57cec5SDimitry Andric   InlineAsm *Asm;
10200b57cec5SDimitry Andric   switch (TargetTriple.getArch()) {
10210b57cec5SDimitry Andric   case Triple::x86_64:
10220b57cec5SDimitry Andric     // The signal handler will find the data address in rdi.
10230b57cec5SDimitry Andric     Asm = InlineAsm::get(
10245f757f3fSDimitry Andric         FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1025e8d8bef9SDimitry Andric         "int3\nnopl " +
1026e8d8bef9SDimitry Andric             itostr(0x40 + (AccessInfo & HWASanAccessInfo::RuntimeMask)) +
1027e8d8bef9SDimitry Andric             "(%rax)",
10280b57cec5SDimitry Andric         "{rdi}",
10290b57cec5SDimitry Andric         /*hasSideEffects=*/true);
10300b57cec5SDimitry Andric     break;
10310b57cec5SDimitry Andric   case Triple::aarch64:
10320b57cec5SDimitry Andric   case Triple::aarch64_be:
10330b57cec5SDimitry Andric     // The signal handler will find the data address in x0.
10340b57cec5SDimitry Andric     Asm = InlineAsm::get(
10355f757f3fSDimitry Andric         FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1036fe6060f1SDimitry Andric         "brk #" + itostr(0x900 + (AccessInfo & HWASanAccessInfo::RuntimeMask)),
10370b57cec5SDimitry Andric         "{x0}",
10380b57cec5SDimitry Andric         /*hasSideEffects=*/true);
10390b57cec5SDimitry Andric     break;
1040bdd1243dSDimitry Andric   case Triple::riscv64:
1041bdd1243dSDimitry Andric     // The signal handler will find the data address in x10.
1042bdd1243dSDimitry Andric     Asm = InlineAsm::get(
10435f757f3fSDimitry Andric         FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1044bdd1243dSDimitry Andric         "ebreak\naddiw x0, x11, " +
1045bdd1243dSDimitry Andric             itostr(0x40 + (AccessInfo & HWASanAccessInfo::RuntimeMask)),
1046bdd1243dSDimitry Andric         "{x10}",
1047bdd1243dSDimitry Andric         /*hasSideEffects=*/true);
1048bdd1243dSDimitry Andric     break;
10490b57cec5SDimitry Andric   default:
10500b57cec5SDimitry Andric     report_fatal_error("unsupported architecture");
10510b57cec5SDimitry Andric   }
10525f757f3fSDimitry Andric   IRB.CreateCall(Asm, TCI.PtrLong);
10530b57cec5SDimitry Andric   if (Recover)
10545f757f3fSDimitry Andric     cast<BranchInst>(CheckFailTerm)
10555f757f3fSDimitry Andric         ->setSuccessor(0, TCI.TagMismatchTerm->getParent());
10560b57cec5SDimitry Andric }
10570b57cec5SDimitry Andric 
ignoreMemIntrinsic(OptimizationRemarkEmitter & ORE,MemIntrinsic * MI)1058*0fca6ea1SDimitry Andric bool HWAddressSanitizer::ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE,
1059*0fca6ea1SDimitry Andric                                             MemIntrinsic *MI) {
1060349cc55cSDimitry Andric   if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
1061*0fca6ea1SDimitry Andric     return (!ClInstrumentWrites || ignoreAccess(ORE, MTI, MTI->getDest())) &&
1062*0fca6ea1SDimitry Andric            (!ClInstrumentReads || ignoreAccess(ORE, MTI, MTI->getSource()));
1063349cc55cSDimitry Andric   }
1064349cc55cSDimitry Andric   if (isa<MemSetInst>(MI))
1065*0fca6ea1SDimitry Andric     return !ClInstrumentWrites || ignoreAccess(ORE, MI, MI->getDest());
1066349cc55cSDimitry Andric   return false;
1067349cc55cSDimitry Andric }
1068349cc55cSDimitry Andric 
instrumentMemIntrinsic(MemIntrinsic * MI)10690b57cec5SDimitry Andric void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
10700b57cec5SDimitry Andric   IRBuilder<> IRB(MI);
10710b57cec5SDimitry Andric   if (isa<MemTransferInst>(MI)) {
10725f757f3fSDimitry Andric     SmallVector<Value *, 4> Args{
10735f757f3fSDimitry Andric         MI->getOperand(0), MI->getOperand(1),
10745f757f3fSDimitry Andric         IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)};
10755f757f3fSDimitry Andric 
10765f757f3fSDimitry Andric     if (UseMatchAllCallback)
10775f757f3fSDimitry Andric       Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
10785f757f3fSDimitry Andric     IRB.CreateCall(isa<MemMoveInst>(MI) ? HwasanMemmove : HwasanMemcpy, Args);
10790b57cec5SDimitry Andric   } else if (isa<MemSetInst>(MI)) {
10805f757f3fSDimitry Andric     SmallVector<Value *, 4> Args{
10815f757f3fSDimitry Andric         MI->getOperand(0),
108206c3fb27SDimitry Andric         IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
10835f757f3fSDimitry Andric         IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)};
10845f757f3fSDimitry Andric     if (UseMatchAllCallback)
10855f757f3fSDimitry Andric       Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
10865f757f3fSDimitry Andric     IRB.CreateCall(HwasanMemset, Args);
108706c3fb27SDimitry Andric   }
10880b57cec5SDimitry Andric   MI->eraseFromParent();
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
instrumentMemAccess(InterestingMemoryOperand & O,DomTreeUpdater & DTU,LoopInfo * LI)10915f757f3fSDimitry Andric bool HWAddressSanitizer::instrumentMemAccess(InterestingMemoryOperand &O,
10925f757f3fSDimitry Andric                                              DomTreeUpdater &DTU,
10935f757f3fSDimitry Andric                                              LoopInfo *LI) {
10945ffd83dbSDimitry Andric   Value *Addr = O.getPtr();
10950b57cec5SDimitry Andric 
10965ffd83dbSDimitry Andric   LLVM_DEBUG(dbgs() << "Instrumenting: " << O.getInsn() << "\n");
10970b57cec5SDimitry Andric 
10985ffd83dbSDimitry Andric   if (O.MaybeMask)
10990b57cec5SDimitry Andric     return false; // FIXME
11000b57cec5SDimitry Andric 
11015ffd83dbSDimitry Andric   IRBuilder<> IRB(O.getInsn());
110206c3fb27SDimitry Andric   if (!O.TypeStoreSize.isScalable() && isPowerOf2_64(O.TypeStoreSize) &&
110306c3fb27SDimitry Andric       (O.TypeStoreSize / 8 <= (1ULL << (kNumberOfAccessSizes - 1))) &&
1104bdd1243dSDimitry Andric       (!O.Alignment || *O.Alignment >= Mapping.getObjectAlignment() ||
110506c3fb27SDimitry Andric        *O.Alignment >= O.TypeStoreSize / 8)) {
110606c3fb27SDimitry Andric     size_t AccessSizeIndex = TypeSizeToSizeIndex(O.TypeStoreSize);
1107fe6060f1SDimitry Andric     if (InstrumentWithCalls) {
11085f757f3fSDimitry Andric       SmallVector<Value *, 2> Args{IRB.CreatePointerCast(Addr, IntptrTy)};
11095f757f3fSDimitry Andric       if (UseMatchAllCallback)
11105f757f3fSDimitry Andric         Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
111106c3fb27SDimitry Andric       IRB.CreateCall(HwasanMemoryAccessCallback[O.IsWrite][AccessSizeIndex],
11125f757f3fSDimitry Andric                      Args);
1113349cc55cSDimitry Andric     } else if (OutlinedChecks) {
11145f757f3fSDimitry Andric       instrumentMemAccessOutline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),
11155f757f3fSDimitry Andric                                  DTU, LI);
11160b57cec5SDimitry Andric     } else {
11175f757f3fSDimitry Andric       instrumentMemAccessInline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),
11185f757f3fSDimitry Andric                                 DTU, LI);
11190b57cec5SDimitry Andric     }
11200b57cec5SDimitry Andric   } else {
11215f757f3fSDimitry Andric     SmallVector<Value *, 3> Args{
11225f757f3fSDimitry Andric         IRB.CreatePointerCast(Addr, IntptrTy),
112306c3fb27SDimitry Andric         IRB.CreateUDiv(IRB.CreateTypeSize(IntptrTy, O.TypeStoreSize),
11245f757f3fSDimitry Andric                        ConstantInt::get(IntptrTy, 8))};
11255f757f3fSDimitry Andric     if (UseMatchAllCallback)
11265f757f3fSDimitry Andric       Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
11275f757f3fSDimitry Andric     IRB.CreateCall(HwasanMemoryAccessCallbackSized[O.IsWrite], Args);
11280b57cec5SDimitry Andric   }
11295ffd83dbSDimitry Andric   untagPointerOperand(O.getInsn(), Addr);
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric   return true;
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric 
tagAlloca(IRBuilder<> & IRB,AllocaInst * AI,Value * Tag,size_t Size)1134349cc55cSDimitry Andric void HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag,
1135fe6060f1SDimitry Andric                                    size_t Size) {
11368bcb0991SDimitry Andric   size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());
11378bcb0991SDimitry Andric   if (!UseShortGranules)
11388bcb0991SDimitry Andric     Size = AlignedSize;
11390b57cec5SDimitry Andric 
114006c3fb27SDimitry Andric   Tag = IRB.CreateTrunc(Tag, Int8Ty);
1141fe6060f1SDimitry Andric   if (InstrumentWithCalls) {
11420b57cec5SDimitry Andric     IRB.CreateCall(HwasanTagMemoryFunc,
11435f757f3fSDimitry Andric                    {IRB.CreatePointerCast(AI, PtrTy), Tag,
11440b57cec5SDimitry Andric                     ConstantInt::get(IntptrTy, AlignedSize)});
11450b57cec5SDimitry Andric   } else {
11460b57cec5SDimitry Andric     size_t ShadowSize = Size >> Mapping.Scale;
114706c3fb27SDimitry Andric     Value *AddrLong = untagPointer(IRB, IRB.CreatePointerCast(AI, IntptrTy));
114806c3fb27SDimitry Andric     Value *ShadowPtr = memToShadow(AddrLong, IRB);
11490b57cec5SDimitry Andric     // If this memset is not inlined, it will be intercepted in the hwasan
11500b57cec5SDimitry Andric     // runtime library. That's OK, because the interceptor skips the checks if
11510b57cec5SDimitry Andric     // the address is in the shadow region.
11520b57cec5SDimitry Andric     // FIXME: the interceptor is not as fast as real memset. Consider lowering
11530b57cec5SDimitry Andric     // llvm.memset right here into either a sequence of stores, or a call to
11540b57cec5SDimitry Andric     // hwasan_tag_memory.
11550b57cec5SDimitry Andric     if (ShadowSize)
115606c3fb27SDimitry Andric       IRB.CreateMemSet(ShadowPtr, Tag, ShadowSize, Align(1));
11570b57cec5SDimitry Andric     if (Size != AlignedSize) {
1158bdd1243dSDimitry Andric       const uint8_t SizeRemainder = Size % Mapping.getObjectAlignment().value();
1159bdd1243dSDimitry Andric       IRB.CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
11600b57cec5SDimitry Andric                       IRB.CreateConstGEP1_32(Int8Ty, ShadowPtr, ShadowSize));
11615f757f3fSDimitry Andric       IRB.CreateStore(
11625f757f3fSDimitry Andric           Tag, IRB.CreateConstGEP1_32(Int8Ty, IRB.CreatePointerCast(AI, PtrTy),
11630b57cec5SDimitry Andric                                       AlignedSize - 1));
11640b57cec5SDimitry Andric     }
11650b57cec5SDimitry Andric   }
11660b57cec5SDimitry Andric }
11670b57cec5SDimitry Andric 
retagMask(unsigned AllocaNo)1168fe6060f1SDimitry Andric unsigned HWAddressSanitizer::retagMask(unsigned AllocaNo) {
1169fe6060f1SDimitry Andric   if (TargetTriple.getArch() == Triple::x86_64)
1170fe6060f1SDimitry Andric     return AllocaNo & TagMaskByte;
1171fe6060f1SDimitry Andric 
11720b57cec5SDimitry Andric   // A list of 8-bit numbers that have at most one run of non-zero bits.
11730b57cec5SDimitry Andric   // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
11740b57cec5SDimitry Andric   // masks.
11750b57cec5SDimitry Andric   // The list does not include the value 255, which is used for UAR.
11760b57cec5SDimitry Andric   //
11770b57cec5SDimitry Andric   // Because we are more likely to use earlier elements of this list than later
11780b57cec5SDimitry Andric   // ones, it is sorted in increasing order of probability of collision with a
11790b57cec5SDimitry Andric   // mask allocated (temporally) nearby. The program that generated this list
11800b57cec5SDimitry Andric   // can be found at:
11810b57cec5SDimitry Andric   // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
118206c3fb27SDimitry Andric   static const unsigned FastMasks[] = {
118306c3fb27SDimitry Andric       0,   128, 64, 192, 32,  96,  224, 112, 240, 48, 16,  120,
118406c3fb27SDimitry Andric       248, 56,  24, 8,   124, 252, 60,  28,  12,  4,  126, 254,
118506c3fb27SDimitry Andric       62,  30,  14, 6,   2,   127, 63,  31,  15,  7,  3,   1};
1186bdd1243dSDimitry Andric   return FastMasks[AllocaNo % std::size(FastMasks)];
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric 
applyTagMask(IRBuilder<> & IRB,Value * OldTag)1189fe6060f1SDimitry Andric Value *HWAddressSanitizer::applyTagMask(IRBuilder<> &IRB, Value *OldTag) {
119006c3fb27SDimitry Andric   if (TagMaskByte == 0xFF)
119106c3fb27SDimitry Andric     return OldTag; // No need to clear the tag byte.
119206c3fb27SDimitry Andric   return IRB.CreateAnd(OldTag,
119306c3fb27SDimitry Andric                        ConstantInt::get(OldTag->getType(), TagMaskByte));
1194fe6060f1SDimitry Andric }
1195fe6060f1SDimitry Andric 
getNextTagWithCall(IRBuilder<> & IRB)11960b57cec5SDimitry Andric Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
11970b57cec5SDimitry Andric   return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
getStackBaseTag(IRBuilder<> & IRB)12000b57cec5SDimitry Andric Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
12010b57cec5SDimitry Andric   if (ClGenerateTagsWithCalls)
120206c3fb27SDimitry Andric     return nullptr;
12030b57cec5SDimitry Andric   if (StackBaseTag)
12040b57cec5SDimitry Andric     return StackBaseTag;
12050b57cec5SDimitry Andric   // Extract some entropy from the stack pointer for the tags.
12060b57cec5SDimitry Andric   // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
12070b57cec5SDimitry Andric   // between functions).
1208*0fca6ea1SDimitry Andric   Value *FramePointerLong = getCachedFP(IRB);
12090b57cec5SDimitry Andric   Value *StackTag =
1210*0fca6ea1SDimitry Andric       applyTagMask(IRB, IRB.CreateXor(FramePointerLong,
1211*0fca6ea1SDimitry Andric                                       IRB.CreateLShr(FramePointerLong, 20)));
1212fe6060f1SDimitry Andric   StackTag->setName("hwasan.stack.base.tag");
12130b57cec5SDimitry Andric   return StackTag;
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric 
getAllocaTag(IRBuilder<> & IRB,Value * StackTag,unsigned AllocaNo)12160b57cec5SDimitry Andric Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
121706c3fb27SDimitry Andric                                         unsigned AllocaNo) {
12180b57cec5SDimitry Andric   if (ClGenerateTagsWithCalls)
12190b57cec5SDimitry Andric     return getNextTagWithCall(IRB);
122006c3fb27SDimitry Andric   return IRB.CreateXor(
122106c3fb27SDimitry Andric       StackTag, ConstantInt::get(StackTag->getType(), retagMask(AllocaNo)));
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric 
getUARTag(IRBuilder<> & IRB)122406c3fb27SDimitry Andric Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB) {
1225*0fca6ea1SDimitry Andric   Value *FramePointerLong = getCachedFP(IRB);
122606c3fb27SDimitry Andric   Value *UARTag =
1227*0fca6ea1SDimitry Andric       applyTagMask(IRB, IRB.CreateLShr(FramePointerLong, PointerTagShift));
122806c3fb27SDimitry Andric 
122906c3fb27SDimitry Andric   UARTag->setName("hwasan.uar.tag");
123006c3fb27SDimitry Andric   return UARTag;
12310b57cec5SDimitry Andric }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric // Add a tag to an address.
tagPointer(IRBuilder<> & IRB,Type * Ty,Value * PtrLong,Value * Tag)12340b57cec5SDimitry Andric Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
12350b57cec5SDimitry Andric                                       Value *PtrLong, Value *Tag) {
1236fe6060f1SDimitry Andric   assert(!UsePageAliases);
12370b57cec5SDimitry Andric   Value *TaggedPtrLong;
12380b57cec5SDimitry Andric   if (CompileKernel) {
12390b57cec5SDimitry Andric     // Kernel addresses have 0xFF in the most significant byte.
1240fe6060f1SDimitry Andric     Value *ShiftedTag =
1241fe6060f1SDimitry Andric         IRB.CreateOr(IRB.CreateShl(Tag, PointerTagShift),
1242fe6060f1SDimitry Andric                      ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
12430b57cec5SDimitry Andric     TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
12440b57cec5SDimitry Andric   } else {
1245fe6060f1SDimitry Andric     // Userspace can simply do OR (tag << PointerTagShift);
1246fe6060f1SDimitry Andric     Value *ShiftedTag = IRB.CreateShl(Tag, PointerTagShift);
12470b57cec5SDimitry Andric     TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
12480b57cec5SDimitry Andric   }
12490b57cec5SDimitry Andric   return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric // Remove tag from an address.
untagPointer(IRBuilder<> & IRB,Value * PtrLong)12530b57cec5SDimitry Andric Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
1254fe6060f1SDimitry Andric   assert(!UsePageAliases);
12550b57cec5SDimitry Andric   Value *UntaggedPtrLong;
12560b57cec5SDimitry Andric   if (CompileKernel) {
12570b57cec5SDimitry Andric     // Kernel addresses have 0xFF in the most significant byte.
1258fe6060f1SDimitry Andric     UntaggedPtrLong =
1259fe6060f1SDimitry Andric         IRB.CreateOr(PtrLong, ConstantInt::get(PtrLong->getType(),
126006c3fb27SDimitry Andric                                                TagMaskByte << PointerTagShift));
12610b57cec5SDimitry Andric   } else {
12620b57cec5SDimitry Andric     // Userspace addresses have 0x00.
126306c3fb27SDimitry Andric     UntaggedPtrLong = IRB.CreateAnd(
126406c3fb27SDimitry Andric         PtrLong, ConstantInt::get(PtrLong->getType(),
126506c3fb27SDimitry Andric                                   ~(TagMaskByte << PointerTagShift)));
12660b57cec5SDimitry Andric   }
12670b57cec5SDimitry Andric   return UntaggedPtrLong;
12680b57cec5SDimitry Andric }
12690b57cec5SDimitry Andric 
getHwasanThreadSlotPtr(IRBuilder<> & IRB)1270*0fca6ea1SDimitry Andric Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB) {
12710b57cec5SDimitry Andric   // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
1272*0fca6ea1SDimitry Andric   // in Bionic's libc/platform/bionic/tls_defines.h.
1273*0fca6ea1SDimitry Andric   constexpr int SanitizerSlot = 6;
1274*0fca6ea1SDimitry Andric   if (TargetTriple.isAArch64() && TargetTriple.isAndroid())
1275*0fca6ea1SDimitry Andric     return memtag::getAndroidSlotPtr(IRB, SanitizerSlot);
12760b57cec5SDimitry Andric   return ThreadPtrGlobal;
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
getCachedFP(IRBuilder<> & IRB)1279*0fca6ea1SDimitry Andric Value *HWAddressSanitizer::getCachedFP(IRBuilder<> &IRB) {
1280*0fca6ea1SDimitry Andric   if (!CachedFP)
1281*0fca6ea1SDimitry Andric     CachedFP = memtag::getFP(IRB);
1282*0fca6ea1SDimitry Andric   return CachedFP;
128381ad6265SDimitry Andric }
128481ad6265SDimitry Andric 
getFrameRecordInfo(IRBuilder<> & IRB)1285753f127fSDimitry Andric Value *HWAddressSanitizer::getFrameRecordInfo(IRBuilder<> &IRB) {
12860b57cec5SDimitry Andric   // Prepare ring buffer data.
1287*0fca6ea1SDimitry Andric   Value *PC = memtag::getPC(TargetTriple, IRB);
1288*0fca6ea1SDimitry Andric   Value *FP = getCachedFP(IRB);
128981ad6265SDimitry Andric 
1290*0fca6ea1SDimitry Andric   // Mix FP and PC.
12910b57cec5SDimitry Andric   // Assumptions:
12920b57cec5SDimitry Andric   // PC is 0x0000PPPPPPPPPPPP  (48 bits are meaningful, others are zero)
1293*0fca6ea1SDimitry Andric   // FP is 0xfffffffffffFFFF0  (4 lower bits are zero)
1294*0fca6ea1SDimitry Andric   // We only really need ~20 lower non-zero bits (FFFF), so we mix like this:
1295*0fca6ea1SDimitry Andric   //       0xFFFFPPPPPPPPPPPP
1296*0fca6ea1SDimitry Andric   //
1297*0fca6ea1SDimitry Andric   // FP works because in AArch64FrameLowering::getFrameIndexReference, we
1298*0fca6ea1SDimitry Andric   // prefer FP-relative offsets for functions compiled with HWASan.
1299*0fca6ea1SDimitry Andric   FP = IRB.CreateShl(FP, 44);
1300*0fca6ea1SDimitry Andric   return IRB.CreateOr(PC, FP);
1301753f127fSDimitry Andric }
1302753f127fSDimitry Andric 
emitPrologue(IRBuilder<> & IRB,bool WithFrameRecord)1303753f127fSDimitry Andric void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
1304753f127fSDimitry Andric   if (!Mapping.InTls)
1305753f127fSDimitry Andric     ShadowBase = getShadowNonTls(IRB);
1306753f127fSDimitry Andric   else if (!WithFrameRecord && TargetTriple.isAndroid())
1307753f127fSDimitry Andric     ShadowBase = getDynamicShadowIfunc(IRB);
1308753f127fSDimitry Andric 
1309753f127fSDimitry Andric   if (!WithFrameRecord && ShadowBase)
1310753f127fSDimitry Andric     return;
1311753f127fSDimitry Andric 
1312753f127fSDimitry Andric   Value *SlotPtr = nullptr;
1313753f127fSDimitry Andric   Value *ThreadLong = nullptr;
1314753f127fSDimitry Andric   Value *ThreadLongMaybeUntagged = nullptr;
1315753f127fSDimitry Andric 
1316753f127fSDimitry Andric   auto getThreadLongMaybeUntagged = [&]() {
1317753f127fSDimitry Andric     if (!SlotPtr)
1318*0fca6ea1SDimitry Andric       SlotPtr = getHwasanThreadSlotPtr(IRB);
1319753f127fSDimitry Andric     if (!ThreadLong)
1320753f127fSDimitry Andric       ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
1321753f127fSDimitry Andric     // Extract the address field from ThreadLong. Unnecessary on AArch64 with
1322753f127fSDimitry Andric     // TBI.
1323753f127fSDimitry Andric     return TargetTriple.isAArch64() ? ThreadLong
1324753f127fSDimitry Andric                                     : untagPointer(IRB, ThreadLong);
1325753f127fSDimitry Andric   };
1326753f127fSDimitry Andric 
1327753f127fSDimitry Andric   if (WithFrameRecord) {
1328753f127fSDimitry Andric     switch (ClRecordStackHistory) {
1329753f127fSDimitry Andric     case libcall: {
1330753f127fSDimitry Andric       // Emit a runtime call into hwasan rather than emitting instructions for
1331753f127fSDimitry Andric       // recording stack history.
1332753f127fSDimitry Andric       Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1333753f127fSDimitry Andric       IRB.CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1334753f127fSDimitry Andric       break;
1335753f127fSDimitry Andric     }
1336753f127fSDimitry Andric     case instr: {
1337753f127fSDimitry Andric       ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1338753f127fSDimitry Andric 
1339753f127fSDimitry Andric       StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric       // Store data to ring buffer.
1342753f127fSDimitry Andric       Value *FrameRecordInfo = getFrameRecordInfo(IRB);
13435f757f3fSDimitry Andric       Value *RecordPtr =
13445f757f3fSDimitry Andric           IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IRB.getPtrTy(0));
1345753f127fSDimitry Andric       IRB.CreateStore(FrameRecordInfo, RecordPtr);
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric       // Update the ring buffer. Top byte of ThreadLong defines the size of the
13480b57cec5SDimitry Andric       // buffer in pages, it must be a power of two, and the start of the buffer
13490b57cec5SDimitry Andric       // must be aligned by twice that much. Therefore wrap around of the ring
13500b57cec5SDimitry Andric       // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
13510b57cec5SDimitry Andric       // The use of AShr instead of LShr is due to
13520b57cec5SDimitry Andric       //   https://bugs.llvm.org/show_bug.cgi?id=39030
13530b57cec5SDimitry Andric       // Runtime library makes sure not to use the highest bit.
1354*0fca6ea1SDimitry Andric       //
1355*0fca6ea1SDimitry Andric       // Mechanical proof of this address calculation can be found at:
1356*0fca6ea1SDimitry Andric       // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/prove_hwasanwrap.smt2
1357*0fca6ea1SDimitry Andric       //
1358*0fca6ea1SDimitry Andric       // Example of the wrap case for N = 1
1359*0fca6ea1SDimitry Andric       // Pointer:   0x01AAAAAAAAAAAFF8
1360*0fca6ea1SDimitry Andric       //                     +
1361*0fca6ea1SDimitry Andric       //            0x0000000000000008
1362*0fca6ea1SDimitry Andric       //                     =
1363*0fca6ea1SDimitry Andric       //            0x01AAAAAAAAAAB000
1364*0fca6ea1SDimitry Andric       //                     &
1365*0fca6ea1SDimitry Andric       // WrapMask:  0xFFFFFFFFFFFFF000
1366*0fca6ea1SDimitry Andric       //                     =
1367*0fca6ea1SDimitry Andric       //            0x01AAAAAAAAAAA000
1368*0fca6ea1SDimitry Andric       //
1369*0fca6ea1SDimitry Andric       // Then the WrapMask will be a no-op until the next wrap case.
13700b57cec5SDimitry Andric       Value *WrapMask = IRB.CreateXor(
13710b57cec5SDimitry Andric           IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
13720b57cec5SDimitry Andric           ConstantInt::get(IntptrTy, (uint64_t)-1));
13730b57cec5SDimitry Andric       Value *ThreadLongNew = IRB.CreateAnd(
13740b57cec5SDimitry Andric           IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
13750b57cec5SDimitry Andric       IRB.CreateStore(ThreadLongNew, SlotPtr);
1376753f127fSDimitry Andric       break;
1377753f127fSDimitry Andric     }
1378753f127fSDimitry Andric     case none: {
1379753f127fSDimitry Andric       llvm_unreachable(
1380753f127fSDimitry Andric           "A stack history recording mode should've been selected.");
1381753f127fSDimitry Andric     }
1382753f127fSDimitry Andric     }
13830b57cec5SDimitry Andric   }
13840b57cec5SDimitry Andric 
1385fe6060f1SDimitry Andric   if (!ShadowBase) {
1386753f127fSDimitry Andric     if (!ThreadLongMaybeUntagged)
1387753f127fSDimitry Andric       ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1388753f127fSDimitry Andric 
13890b57cec5SDimitry Andric     // Get shadow base address by aligning RecordPtr up.
13900b57cec5SDimitry Andric     // Note: this is not correct if the pointer is already aligned.
13910b57cec5SDimitry Andric     // Runtime library will make sure this never happens.
1392e8d8bef9SDimitry Andric     ShadowBase = IRB.CreateAdd(
13930b57cec5SDimitry Andric         IRB.CreateOr(
13940b57cec5SDimitry Andric             ThreadLongMaybeUntagged,
13950b57cec5SDimitry Andric             ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
13960b57cec5SDimitry Andric         ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
13975f757f3fSDimitry Andric     ShadowBase = IRB.CreateIntToPtr(ShadowBase, PtrTy);
13980b57cec5SDimitry Andric   }
1399fe6060f1SDimitry Andric }
14000b57cec5SDimitry Andric 
instrumentLandingPads(SmallVectorImpl<Instruction * > & LandingPadVec)14010b57cec5SDimitry Andric bool HWAddressSanitizer::instrumentLandingPads(
14020b57cec5SDimitry Andric     SmallVectorImpl<Instruction *> &LandingPadVec) {
14030b57cec5SDimitry Andric   for (auto *LP : LandingPadVec) {
1404*0fca6ea1SDimitry Andric     IRBuilder<> IRB(LP->getNextNonDebugInstruction());
14050b57cec5SDimitry Andric     IRB.CreateCall(
140606c3fb27SDimitry Andric         HwasanHandleVfork,
1407*0fca6ea1SDimitry Andric         {memtag::readRegister(
1408*0fca6ea1SDimitry Andric             IRB, (TargetTriple.getArch() == Triple::x86_64) ? "rsp" : "sp")});
14090b57cec5SDimitry Andric   }
14100b57cec5SDimitry Andric   return true;
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric 
instrumentStack(memtag::StackInfo & SInfo,Value * StackTag,Value * UARTag,const DominatorTree & DT,const PostDominatorTree & PDT,const LoopInfo & LI)141381ad6265SDimitry Andric bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo,
141406c3fb27SDimitry Andric                                          Value *StackTag, Value *UARTag,
141581ad6265SDimitry Andric                                          const DominatorTree &DT,
141681ad6265SDimitry Andric                                          const PostDominatorTree &PDT,
141781ad6265SDimitry Andric                                          const LoopInfo &LI) {
14180b57cec5SDimitry Andric   // Ideally, we want to calculate tagged stack base pointer, and rewrite all
14190b57cec5SDimitry Andric   // alloca addresses using that. Unfortunately, offsets are not known yet
14200b57cec5SDimitry Andric   // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
14210b57cec5SDimitry Andric   // temp, shift-OR it into each alloca address and xor with the retag mask.
14220b57cec5SDimitry Andric   // This generates one extra instruction per alloca use.
1423349cc55cSDimitry Andric   unsigned int I = 0;
1424349cc55cSDimitry Andric 
142581ad6265SDimitry Andric   for (auto &KV : SInfo.AllocasToInstrument) {
1426349cc55cSDimitry Andric     auto N = I++;
1427349cc55cSDimitry Andric     auto *AI = KV.first;
142881ad6265SDimitry Andric     memtag::AllocaInfo &Info = KV.second;
1429*0fca6ea1SDimitry Andric     IRBuilder<> IRB(AI->getNextNonDebugInstruction());
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric     // Replace uses of the alloca with tagged address.
143206c3fb27SDimitry Andric     Value *Tag = getAllocaTag(IRB, StackTag, N);
14330b57cec5SDimitry Andric     Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
143406c3fb27SDimitry Andric     Value *AINoTagLong = untagPointer(IRB, AILong);
143506c3fb27SDimitry Andric     Value *Replacement = tagPointer(IRB, AI->getType(), AINoTagLong, Tag);
14360b57cec5SDimitry Andric     std::string Name =
14370b57cec5SDimitry Andric         AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
14380b57cec5SDimitry Andric     Replacement->setName(Name + ".hwasan");
14390b57cec5SDimitry Andric 
144081ad6265SDimitry Andric     size_t Size = memtag::getAllocaSizeInBytes(*AI);
144181ad6265SDimitry Andric     size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());
14420b57cec5SDimitry Andric 
14435f757f3fSDimitry Andric     Value *AICast = IRB.CreatePointerCast(AI, PtrTy);
144481ad6265SDimitry Andric 
144581ad6265SDimitry Andric     auto HandleLifetime = [&](IntrinsicInst *II) {
144681ad6265SDimitry Andric       // Set the lifetime intrinsic to cover the whole alloca. This reduces the
144781ad6265SDimitry Andric       // set of assumptions we need to make about the lifetime. Without this we
144881ad6265SDimitry Andric       // would need to ensure that we can track the lifetime pointer to a
144981ad6265SDimitry Andric       // constant offset from the alloca, and would still need to change the
145081ad6265SDimitry Andric       // size to include the extra alignment we use for the untagging to make
145181ad6265SDimitry Andric       // the size consistent.
145281ad6265SDimitry Andric       //
145381ad6265SDimitry Andric       // The check for standard lifetime below makes sure that we have exactly
145481ad6265SDimitry Andric       // one set of start / end in any execution (i.e. the ends are not
145581ad6265SDimitry Andric       // reachable from each other), so this will not cause any problems.
145681ad6265SDimitry Andric       II->setArgOperand(0, ConstantInt::get(Int64Ty, AlignedSize));
145781ad6265SDimitry Andric       II->setArgOperand(1, AICast);
145881ad6265SDimitry Andric     };
145981ad6265SDimitry Andric     llvm::for_each(Info.LifetimeStart, HandleLifetime);
146081ad6265SDimitry Andric     llvm::for_each(Info.LifetimeEnd, HandleLifetime);
146181ad6265SDimitry Andric 
146206c3fb27SDimitry Andric     AI->replaceUsesWithIf(Replacement, [AICast, AILong](const Use &U) {
146381ad6265SDimitry Andric       auto *User = U.getUser();
1464*0fca6ea1SDimitry Andric       return User != AILong && User != AICast &&
1465*0fca6ea1SDimitry Andric              !memtag::isLifetimeIntrinsic(User);
146681ad6265SDimitry Andric     });
146781ad6265SDimitry Andric 
1468*0fca6ea1SDimitry Andric     memtag::annotateDebugRecords(Info, retagMask(N));
14690b57cec5SDimitry Andric 
1470349cc55cSDimitry Andric     auto TagEnd = [&](Instruction *Node) {
1471349cc55cSDimitry Andric       IRB.SetInsertPoint(Node);
147281ad6265SDimitry Andric       // When untagging, use the `AlignedSize` because we need to set the tags
147306c3fb27SDimitry Andric       // for the entire alloca to original. If we used `Size` here, we would
147481ad6265SDimitry Andric       // keep the last granule tagged, and store zero in the last byte of the
147581ad6265SDimitry Andric       // last granule, due to how short granules are implemented.
1476349cc55cSDimitry Andric       tagAlloca(IRB, AI, UARTag, AlignedSize);
1477349cc55cSDimitry Andric     };
147881ad6265SDimitry Andric     // Calls to functions that may return twice (e.g. setjmp) confuse the
147981ad6265SDimitry Andric     // postdominator analysis, and will leave us to keep memory tagged after
148081ad6265SDimitry Andric     // function return. Work around this by always untagging at every return
148181ad6265SDimitry Andric     // statement if return_twice functions are called.
148204eeddc0SDimitry Andric     bool StandardLifetime =
1483*0fca6ea1SDimitry Andric         !SInfo.CallsReturnTwice &&
148481ad6265SDimitry Andric         SInfo.UnrecognizedLifetimes.empty() &&
148581ad6265SDimitry Andric         memtag::isStandardLifetime(Info.LifetimeStart, Info.LifetimeEnd, &DT,
1486*0fca6ea1SDimitry Andric                                    &LI, ClMaxLifetimes);
148781ad6265SDimitry Andric     if (DetectUseAfterScope && StandardLifetime) {
148804eeddc0SDimitry Andric       IntrinsicInst *Start = Info.LifetimeStart[0];
148904eeddc0SDimitry Andric       IRB.SetInsertPoint(Start->getNextNode());
14900b57cec5SDimitry Andric       tagAlloca(IRB, AI, Tag, Size);
149181ad6265SDimitry Andric       if (!memtag::forAllReachableExits(DT, PDT, LI, Start, Info.LifetimeEnd,
149281ad6265SDimitry Andric                                         SInfo.RetVec, TagEnd)) {
1493349cc55cSDimitry Andric         for (auto *End : Info.LifetimeEnd)
1494349cc55cSDimitry Andric           End->eraseFromParent();
1495349cc55cSDimitry Andric       }
1496349cc55cSDimitry Andric     } else {
1497349cc55cSDimitry Andric       tagAlloca(IRB, AI, Tag, Size);
149881ad6265SDimitry Andric       for (auto *RI : SInfo.RetVec)
149904eeddc0SDimitry Andric         TagEnd(RI);
150081ad6265SDimitry Andric       // We inserted tagging outside of the lifetimes, so we have to remove
150181ad6265SDimitry Andric       // them.
1502349cc55cSDimitry Andric       for (auto &II : Info.LifetimeStart)
1503349cc55cSDimitry Andric         II->eraseFromParent();
1504349cc55cSDimitry Andric       for (auto &II : Info.LifetimeEnd)
1505349cc55cSDimitry Andric         II->eraseFromParent();
15060b57cec5SDimitry Andric     }
1507bdd1243dSDimitry Andric     memtag::alignAndPadAlloca(Info, Mapping.getObjectAlignment());
15080b57cec5SDimitry Andric   }
150981ad6265SDimitry Andric   for (auto &I : SInfo.UnrecognizedLifetimes)
1510349cc55cSDimitry Andric     I->eraseFromParent();
15110b57cec5SDimitry Andric   return true;
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric 
emitRemark(const Function & F,OptimizationRemarkEmitter & ORE,bool Skip)1514*0fca6ea1SDimitry Andric static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE,
1515*0fca6ea1SDimitry Andric                        bool Skip) {
1516*0fca6ea1SDimitry Andric   if (Skip) {
1517*0fca6ea1SDimitry Andric     ORE.emit([&]() {
1518*0fca6ea1SDimitry Andric       return OptimizationRemark(DEBUG_TYPE, "Skip", &F)
1519*0fca6ea1SDimitry Andric              << "Skipped: F=" << ore::NV("Function", &F);
1520*0fca6ea1SDimitry Andric     });
1521*0fca6ea1SDimitry Andric   } else {
1522*0fca6ea1SDimitry Andric     ORE.emit([&]() {
1523*0fca6ea1SDimitry Andric       return OptimizationRemarkMissed(DEBUG_TYPE, "Sanitize", &F)
1524*0fca6ea1SDimitry Andric              << "Sanitized: F=" << ore::NV("Function", &F);
1525*0fca6ea1SDimitry Andric     });
1526*0fca6ea1SDimitry Andric   }
1527*0fca6ea1SDimitry Andric }
1528*0fca6ea1SDimitry Andric 
selectiveInstrumentationShouldSkip(Function & F,FunctionAnalysisManager & FAM) const1529*0fca6ea1SDimitry Andric bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1530*0fca6ea1SDimitry Andric     Function &F, FunctionAnalysisManager &FAM) const {
1531*0fca6ea1SDimitry Andric   bool Skip = [&]() {
1532*0fca6ea1SDimitry Andric     if (ClRandomSkipRate.getNumOccurrences()) {
1533*0fca6ea1SDimitry Andric       std::bernoulli_distribution D(ClRandomSkipRate);
1534*0fca6ea1SDimitry Andric       return !D(*Rng);
1535*0fca6ea1SDimitry Andric     }
1536*0fca6ea1SDimitry Andric     if (!ClHotPercentileCutoff.getNumOccurrences())
1537*0fca6ea1SDimitry Andric       return false;
1538*0fca6ea1SDimitry Andric     auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
1539*0fca6ea1SDimitry Andric     ProfileSummaryInfo *PSI =
1540*0fca6ea1SDimitry Andric         MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
1541*0fca6ea1SDimitry Andric     if (!PSI || !PSI->hasProfileSummary()) {
1542*0fca6ea1SDimitry Andric       ++NumNoProfileSummaryFuncs;
1543*0fca6ea1SDimitry Andric       return false;
1544*0fca6ea1SDimitry Andric     }
1545*0fca6ea1SDimitry Andric     return PSI->isFunctionHotInCallGraphNthPercentile(
1546*0fca6ea1SDimitry Andric         ClHotPercentileCutoff, &F, FAM.getResult<BlockFrequencyAnalysis>(F));
1547*0fca6ea1SDimitry Andric   }();
1548*0fca6ea1SDimitry Andric   emitRemark(F, FAM.getResult<OptimizationRemarkEmitterAnalysis>(F), Skip);
1549*0fca6ea1SDimitry Andric   return Skip;
1550*0fca6ea1SDimitry Andric }
1551*0fca6ea1SDimitry Andric 
sanitizeFunction(Function & F,FunctionAnalysisManager & FAM)155206c3fb27SDimitry Andric void HWAddressSanitizer::sanitizeFunction(Function &F,
155381ad6265SDimitry Andric                                           FunctionAnalysisManager &FAM) {
15540b57cec5SDimitry Andric   if (&F == HwasanCtorFunction)
155506c3fb27SDimitry Andric     return;
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric   if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
155806c3fb27SDimitry Andric     return;
15590b57cec5SDimitry Andric 
1560*0fca6ea1SDimitry Andric   if (F.empty())
1561*0fca6ea1SDimitry Andric     return;
1562*0fca6ea1SDimitry Andric 
1563*0fca6ea1SDimitry Andric   NumTotalFuncs++;
1564*0fca6ea1SDimitry Andric 
1565*0fca6ea1SDimitry Andric   OptimizationRemarkEmitter &ORE =
1566*0fca6ea1SDimitry Andric       FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
1567*0fca6ea1SDimitry Andric 
1568*0fca6ea1SDimitry Andric   if (selectiveInstrumentationShouldSkip(F, FAM))
1569*0fca6ea1SDimitry Andric     return;
1570*0fca6ea1SDimitry Andric 
1571*0fca6ea1SDimitry Andric   NumInstrumentedFuncs++;
1572*0fca6ea1SDimitry Andric 
15730b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
15740b57cec5SDimitry Andric 
15755ffd83dbSDimitry Andric   SmallVector<InterestingMemoryOperand, 16> OperandsToInstrument;
15765ffd83dbSDimitry Andric   SmallVector<MemIntrinsic *, 16> IntrinToInstrument;
15770b57cec5SDimitry Andric   SmallVector<Instruction *, 8> LandingPadVec;
15785f757f3fSDimitry Andric   const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
157981ad6265SDimitry Andric 
1580bdd1243dSDimitry Andric   memtag::StackInfoBuilder SIB(SSI);
158181ad6265SDimitry Andric   for (auto &Inst : instructions(F)) {
1582349cc55cSDimitry Andric     if (InstrumentStack) {
158381ad6265SDimitry Andric       SIB.visit(Inst);
1584fe6060f1SDimitry Andric     }
15850b57cec5SDimitry Andric 
15868bcb0991SDimitry Andric     if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
15870b57cec5SDimitry Andric       LandingPadVec.push_back(&Inst);
15880b57cec5SDimitry Andric 
1589*0fca6ea1SDimitry Andric     getInterestingMemoryOperands(ORE, &Inst, TLI, OperandsToInstrument);
15905ffd83dbSDimitry Andric 
15915ffd83dbSDimitry Andric     if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&Inst))
1592*0fca6ea1SDimitry Andric       if (!ignoreMemIntrinsic(ORE, MI))
15935ffd83dbSDimitry Andric         IntrinToInstrument.push_back(MI);
15940b57cec5SDimitry Andric   }
159581ad6265SDimitry Andric 
159681ad6265SDimitry Andric   memtag::StackInfo &SInfo = SIB.get();
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric   initializeCallbacks(*F.getParent());
15990b57cec5SDimitry Andric 
16000b57cec5SDimitry Andric   if (!LandingPadVec.empty())
160106c3fb27SDimitry Andric     instrumentLandingPads(LandingPadVec);
16020b57cec5SDimitry Andric 
160381ad6265SDimitry Andric   if (SInfo.AllocasToInstrument.empty() && F.hasPersonalityFn() &&
16048bcb0991SDimitry Andric       F.getPersonalityFn()->getName() == kHwasanPersonalityThunkName) {
16058bcb0991SDimitry Andric     // __hwasan_personality_thunk is a no-op for functions without an
16068bcb0991SDimitry Andric     // instrumented stack, so we can drop it.
16078bcb0991SDimitry Andric     F.setPersonalityFn(nullptr);
16088bcb0991SDimitry Andric   }
16098bcb0991SDimitry Andric 
161081ad6265SDimitry Andric   if (SInfo.AllocasToInstrument.empty() && OperandsToInstrument.empty() &&
16115ffd83dbSDimitry Andric       IntrinToInstrument.empty())
161206c3fb27SDimitry Andric     return;
16130b57cec5SDimitry Andric 
1614e8d8bef9SDimitry Andric   assert(!ShadowBase);
16150b57cec5SDimitry Andric 
1616*0fca6ea1SDimitry Andric   // Remove memory attributes that are about to become invalid.
1617*0fca6ea1SDimitry Andric   // HWASan checks read from shadow, which invalidates memory(argmem: *)
1618*0fca6ea1SDimitry Andric   // Short granule checks on function arguments read from the argument memory
1619*0fca6ea1SDimitry Andric   // (last byte of the granule), which invalidates writeonly.
1620*0fca6ea1SDimitry Andric   F.removeFnAttr(llvm::Attribute::Memory);
1621*0fca6ea1SDimitry Andric   for (auto &A : F.args())
1622*0fca6ea1SDimitry Andric     A.removeAttr(llvm::Attribute::WriteOnly);
1623*0fca6ea1SDimitry Andric 
1624*0fca6ea1SDimitry Andric   BasicBlock::iterator InsertPt = F.getEntryBlock().begin();
1625*0fca6ea1SDimitry Andric   IRBuilder<> EntryIRB(&F.getEntryBlock(), InsertPt);
16260b57cec5SDimitry Andric   emitPrologue(EntryIRB,
1627753f127fSDimitry Andric                /*WithFrameRecord*/ ClRecordStackHistory != none &&
162881ad6265SDimitry Andric                    Mapping.WithFrameRecord &&
162981ad6265SDimitry Andric                    !SInfo.AllocasToInstrument.empty());
16300b57cec5SDimitry Andric 
163181ad6265SDimitry Andric   if (!SInfo.AllocasToInstrument.empty()) {
163281ad6265SDimitry Andric     const DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
163381ad6265SDimitry Andric     const PostDominatorTree &PDT = FAM.getResult<PostDominatorTreeAnalysis>(F);
163481ad6265SDimitry Andric     const LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
163506c3fb27SDimitry Andric     Value *StackTag = getStackBaseTag(EntryIRB);
163606c3fb27SDimitry Andric     Value *UARTag = getUARTag(EntryIRB);
163706c3fb27SDimitry Andric     instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric 
16400b57cec5SDimitry Andric   // If we split the entry block, move any allocas that were originally in the
16410b57cec5SDimitry Andric   // entry block back into the entry block so that they aren't treated as
16420b57cec5SDimitry Andric   // dynamic allocas.
16430b57cec5SDimitry Andric   if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {
1644*0fca6ea1SDimitry Andric     InsertPt = F.getEntryBlock().begin();
1645349cc55cSDimitry Andric     for (Instruction &I :
1646349cc55cSDimitry Andric          llvm::make_early_inc_range(*EntryIRB.GetInsertBlock())) {
1647349cc55cSDimitry Andric       if (auto *AI = dyn_cast<AllocaInst>(&I))
16480b57cec5SDimitry Andric         if (isa<ConstantInt>(AI->getArraySize()))
1649*0fca6ea1SDimitry Andric           I.moveBefore(F.getEntryBlock(), InsertPt);
16500b57cec5SDimitry Andric     }
16510b57cec5SDimitry Andric   }
16520b57cec5SDimitry Andric 
16535f757f3fSDimitry Andric   DominatorTree *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
16545f757f3fSDimitry Andric   PostDominatorTree *PDT = FAM.getCachedResult<PostDominatorTreeAnalysis>(F);
16555f757f3fSDimitry Andric   LoopInfo *LI = FAM.getCachedResult<LoopAnalysis>(F);
16565f757f3fSDimitry Andric   DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
16575ffd83dbSDimitry Andric   for (auto &Operand : OperandsToInstrument)
16585f757f3fSDimitry Andric     instrumentMemAccess(Operand, DTU, LI);
16595f757f3fSDimitry Andric   DTU.flush();
16605ffd83dbSDimitry Andric 
16615ffd83dbSDimitry Andric   if (ClInstrumentMemIntrinsics && !IntrinToInstrument.empty()) {
1662bdd1243dSDimitry Andric     for (auto *Inst : IntrinToInstrument)
1663bdd1243dSDimitry Andric       instrumentMemIntrinsic(Inst);
16645ffd83dbSDimitry Andric   }
16650b57cec5SDimitry Andric 
1666e8d8bef9SDimitry Andric   ShadowBase = nullptr;
16670b57cec5SDimitry Andric   StackBaseTag = nullptr;
1668*0fca6ea1SDimitry Andric   CachedFP = nullptr;
16690b57cec5SDimitry Andric }
16700b57cec5SDimitry Andric 
instrumentGlobal(GlobalVariable * GV,uint8_t Tag)16718bcb0991SDimitry Andric void HWAddressSanitizer::instrumentGlobal(GlobalVariable *GV, uint8_t Tag) {
1672fe6060f1SDimitry Andric   assert(!UsePageAliases);
16738bcb0991SDimitry Andric   Constant *Initializer = GV->getInitializer();
16748bcb0991SDimitry Andric   uint64_t SizeInBytes =
16758bcb0991SDimitry Andric       M.getDataLayout().getTypeAllocSize(Initializer->getType());
16768bcb0991SDimitry Andric   uint64_t NewSize = alignTo(SizeInBytes, Mapping.getObjectAlignment());
16778bcb0991SDimitry Andric   if (SizeInBytes != NewSize) {
16788bcb0991SDimitry Andric     // Pad the initializer out to the next multiple of 16 bytes and add the
16798bcb0991SDimitry Andric     // required short granule tag.
16808bcb0991SDimitry Andric     std::vector<uint8_t> Init(NewSize - SizeInBytes, 0);
16818bcb0991SDimitry Andric     Init.back() = Tag;
16828bcb0991SDimitry Andric     Constant *Padding = ConstantDataArray::get(*C, Init);
16838bcb0991SDimitry Andric     Initializer = ConstantStruct::getAnon({Initializer, Padding});
16848bcb0991SDimitry Andric   }
16858bcb0991SDimitry Andric 
16868bcb0991SDimitry Andric   auto *NewGV = new GlobalVariable(M, Initializer->getType(), GV->isConstant(),
16878bcb0991SDimitry Andric                                    GlobalValue::ExternalLinkage, Initializer,
16888bcb0991SDimitry Andric                                    GV->getName() + ".hwasan");
16898bcb0991SDimitry Andric   NewGV->copyAttributesFrom(GV);
16908bcb0991SDimitry Andric   NewGV->setLinkage(GlobalValue::PrivateLinkage);
16918bcb0991SDimitry Andric   NewGV->copyMetadata(GV, 0);
16928bcb0991SDimitry Andric   NewGV->setAlignment(
1693bdd1243dSDimitry Andric       std::max(GV->getAlign().valueOrOne(), Mapping.getObjectAlignment()));
16948bcb0991SDimitry Andric 
16958bcb0991SDimitry Andric   // It is invalid to ICF two globals that have different tags. In the case
16968bcb0991SDimitry Andric   // where the size of the global is a multiple of the tag granularity the
16978bcb0991SDimitry Andric   // contents of the globals may be the same but the tags (i.e. symbol values)
16988bcb0991SDimitry Andric   // may be different, and the symbols are not considered during ICF. In the
16998bcb0991SDimitry Andric   // case where the size is not a multiple of the granularity, the short granule
17008bcb0991SDimitry Andric   // tags would discriminate two globals with different tags, but there would
17018bcb0991SDimitry Andric   // otherwise be nothing stopping such a global from being incorrectly ICF'd
17028bcb0991SDimitry Andric   // with an uninstrumented (i.e. tag 0) global that happened to have the short
17038bcb0991SDimitry Andric   // granule tag in the last byte.
17048bcb0991SDimitry Andric   NewGV->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
17058bcb0991SDimitry Andric 
17068bcb0991SDimitry Andric   // Descriptor format (assuming little-endian):
17078bcb0991SDimitry Andric   // bytes 0-3: relative address of global
17088bcb0991SDimitry Andric   // bytes 4-6: size of global (16MB ought to be enough for anyone, but in case
17098bcb0991SDimitry Andric   // it isn't, we create multiple descriptors)
17108bcb0991SDimitry Andric   // byte 7: tag
17118bcb0991SDimitry Andric   auto *DescriptorTy = StructType::get(Int32Ty, Int32Ty);
17128bcb0991SDimitry Andric   const uint64_t MaxDescriptorSize = 0xfffff0;
17138bcb0991SDimitry Andric   for (uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
17148bcb0991SDimitry Andric        DescriptorPos += MaxDescriptorSize) {
17158bcb0991SDimitry Andric     auto *Descriptor =
17168bcb0991SDimitry Andric         new GlobalVariable(M, DescriptorTy, true, GlobalValue::PrivateLinkage,
17178bcb0991SDimitry Andric                            nullptr, GV->getName() + ".hwasan.descriptor");
17188bcb0991SDimitry Andric     auto *GVRelPtr = ConstantExpr::getTrunc(
17198bcb0991SDimitry Andric         ConstantExpr::getAdd(
17208bcb0991SDimitry Andric             ConstantExpr::getSub(
17218bcb0991SDimitry Andric                 ConstantExpr::getPtrToInt(NewGV, Int64Ty),
17228bcb0991SDimitry Andric                 ConstantExpr::getPtrToInt(Descriptor, Int64Ty)),
17238bcb0991SDimitry Andric             ConstantInt::get(Int64Ty, DescriptorPos)),
17248bcb0991SDimitry Andric         Int32Ty);
17258bcb0991SDimitry Andric     uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
17268bcb0991SDimitry Andric     auto *SizeAndTag = ConstantInt::get(Int32Ty, Size | (uint32_t(Tag) << 24));
17278bcb0991SDimitry Andric     Descriptor->setComdat(NewGV->getComdat());
17288bcb0991SDimitry Andric     Descriptor->setInitializer(ConstantStruct::getAnon({GVRelPtr, SizeAndTag}));
17298bcb0991SDimitry Andric     Descriptor->setSection("hwasan_globals");
17308bcb0991SDimitry Andric     Descriptor->setMetadata(LLVMContext::MD_associated,
17318bcb0991SDimitry Andric                             MDNode::get(*C, ValueAsMetadata::get(NewGV)));
17328bcb0991SDimitry Andric     appendToCompilerUsed(M, Descriptor);
17338bcb0991SDimitry Andric   }
17348bcb0991SDimitry Andric 
17358bcb0991SDimitry Andric   Constant *Aliasee = ConstantExpr::getIntToPtr(
17368bcb0991SDimitry Andric       ConstantExpr::getAdd(
17378bcb0991SDimitry Andric           ConstantExpr::getPtrToInt(NewGV, Int64Ty),
1738fe6060f1SDimitry Andric           ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)),
17398bcb0991SDimitry Andric       GV->getType());
17408bcb0991SDimitry Andric   auto *Alias = GlobalAlias::create(GV->getValueType(), GV->getAddressSpace(),
17418bcb0991SDimitry Andric                                     GV->getLinkage(), "", Aliasee, &M);
17428bcb0991SDimitry Andric   Alias->setVisibility(GV->getVisibility());
17438bcb0991SDimitry Andric   Alias->takeName(GV);
17448bcb0991SDimitry Andric   GV->replaceAllUsesWith(Alias);
17458bcb0991SDimitry Andric   GV->eraseFromParent();
17468bcb0991SDimitry Andric }
17478bcb0991SDimitry Andric 
instrumentGlobals()17488bcb0991SDimitry Andric void HWAddressSanitizer::instrumentGlobals() {
17498bcb0991SDimitry Andric   std::vector<GlobalVariable *> Globals;
17508bcb0991SDimitry Andric   for (GlobalVariable &GV : M.globals()) {
175181ad6265SDimitry Andric     if (GV.hasSanitizerMetadata() && GV.getSanitizerMetadata().NoHWAddress)
1752fe6060f1SDimitry Andric       continue;
1753fe6060f1SDimitry Andric 
17545f757f3fSDimitry Andric     if (GV.isDeclarationForLinker() || GV.getName().starts_with("llvm.") ||
17558bcb0991SDimitry Andric         GV.isThreadLocal())
17568bcb0991SDimitry Andric       continue;
17578bcb0991SDimitry Andric 
17588bcb0991SDimitry Andric     // Common symbols can't have aliases point to them, so they can't be tagged.
17598bcb0991SDimitry Andric     if (GV.hasCommonLinkage())
17608bcb0991SDimitry Andric       continue;
17618bcb0991SDimitry Andric 
17628bcb0991SDimitry Andric     // Globals with custom sections may be used in __start_/__stop_ enumeration,
17638bcb0991SDimitry Andric     // which would be broken both by adding tags and potentially by the extra
17648bcb0991SDimitry Andric     // padding/alignment that we insert.
17658bcb0991SDimitry Andric     if (GV.hasSection())
17668bcb0991SDimitry Andric       continue;
17678bcb0991SDimitry Andric 
17688bcb0991SDimitry Andric     Globals.push_back(&GV);
17698bcb0991SDimitry Andric   }
17708bcb0991SDimitry Andric 
17718bcb0991SDimitry Andric   MD5 Hasher;
17728bcb0991SDimitry Andric   Hasher.update(M.getSourceFileName());
17738bcb0991SDimitry Andric   MD5::MD5Result Hash;
17748bcb0991SDimitry Andric   Hasher.final(Hash);
1775349cc55cSDimitry Andric   uint8_t Tag = Hash[0];
17768bcb0991SDimitry Andric 
177706c3fb27SDimitry Andric   assert(TagMaskByte >= 16);
177806c3fb27SDimitry Andric 
17798bcb0991SDimitry Andric   for (GlobalVariable *GV : Globals) {
178006c3fb27SDimitry Andric     // Don't allow globals to be tagged with something that looks like a
178106c3fb27SDimitry Andric     // short-granule tag, otherwise we lose inter-granule overflow detection, as
178206c3fb27SDimitry Andric     // the fast path shadow-vs-address check succeeds.
178306c3fb27SDimitry Andric     if (Tag < 16 || Tag > TagMaskByte)
178406c3fb27SDimitry Andric       Tag = 16;
17858bcb0991SDimitry Andric     instrumentGlobal(GV, Tag++);
17868bcb0991SDimitry Andric   }
17878bcb0991SDimitry Andric }
17888bcb0991SDimitry Andric 
instrumentPersonalityFunctions()17898bcb0991SDimitry Andric void HWAddressSanitizer::instrumentPersonalityFunctions() {
17908bcb0991SDimitry Andric   // We need to untag stack frames as we unwind past them. That is the job of
17918bcb0991SDimitry Andric   // the personality function wrapper, which either wraps an existing
17928bcb0991SDimitry Andric   // personality function or acts as a personality function on its own. Each
17938bcb0991SDimitry Andric   // function that has a personality function or that can be unwound past has
17948bcb0991SDimitry Andric   // its personality function changed to a thunk that calls the personality
17958bcb0991SDimitry Andric   // function wrapper in the runtime.
17968bcb0991SDimitry Andric   MapVector<Constant *, std::vector<Function *>> PersonalityFns;
17978bcb0991SDimitry Andric   for (Function &F : M) {
17988bcb0991SDimitry Andric     if (F.isDeclaration() || !F.hasFnAttribute(Attribute::SanitizeHWAddress))
17998bcb0991SDimitry Andric       continue;
18008bcb0991SDimitry Andric 
18018bcb0991SDimitry Andric     if (F.hasPersonalityFn()) {
18028bcb0991SDimitry Andric       PersonalityFns[F.getPersonalityFn()->stripPointerCasts()].push_back(&F);
18038bcb0991SDimitry Andric     } else if (!F.hasFnAttribute(Attribute::NoUnwind)) {
18048bcb0991SDimitry Andric       PersonalityFns[nullptr].push_back(&F);
18058bcb0991SDimitry Andric     }
18068bcb0991SDimitry Andric   }
18078bcb0991SDimitry Andric 
18088bcb0991SDimitry Andric   if (PersonalityFns.empty())
18098bcb0991SDimitry Andric     return;
18108bcb0991SDimitry Andric 
18118bcb0991SDimitry Andric   FunctionCallee HwasanPersonalityWrapper = M.getOrInsertFunction(
18125f757f3fSDimitry Andric       "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
18135f757f3fSDimitry Andric       PtrTy, PtrTy, PtrTy, PtrTy);
18148bcb0991SDimitry Andric   FunctionCallee UnwindGetGR = M.getOrInsertFunction("_Unwind_GetGR", VoidTy);
18158bcb0991SDimitry Andric   FunctionCallee UnwindGetCFA = M.getOrInsertFunction("_Unwind_GetCFA", VoidTy);
18168bcb0991SDimitry Andric 
18178bcb0991SDimitry Andric   for (auto &P : PersonalityFns) {
18188bcb0991SDimitry Andric     std::string ThunkName = kHwasanPersonalityThunkName;
18198bcb0991SDimitry Andric     if (P.first)
18208bcb0991SDimitry Andric       ThunkName += ("." + P.first->getName()).str();
18218bcb0991SDimitry Andric     FunctionType *ThunkFnTy = FunctionType::get(
18225f757f3fSDimitry Andric         Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy}, false);
18238bcb0991SDimitry Andric     bool IsLocal = P.first && (!isa<GlobalValue>(P.first) ||
18248bcb0991SDimitry Andric                                cast<GlobalValue>(P.first)->hasLocalLinkage());
18258bcb0991SDimitry Andric     auto *ThunkFn = Function::Create(ThunkFnTy,
18268bcb0991SDimitry Andric                                      IsLocal ? GlobalValue::InternalLinkage
18278bcb0991SDimitry Andric                                              : GlobalValue::LinkOnceODRLinkage,
18288bcb0991SDimitry Andric                                      ThunkName, &M);
18298bcb0991SDimitry Andric     if (!IsLocal) {
18308bcb0991SDimitry Andric       ThunkFn->setVisibility(GlobalValue::HiddenVisibility);
18318bcb0991SDimitry Andric       ThunkFn->setComdat(M.getOrInsertComdat(ThunkName));
18328bcb0991SDimitry Andric     }
18338bcb0991SDimitry Andric 
18348bcb0991SDimitry Andric     auto *BB = BasicBlock::Create(*C, "entry", ThunkFn);
18358bcb0991SDimitry Andric     IRBuilder<> IRB(BB);
18368bcb0991SDimitry Andric     CallInst *WrapperCall = IRB.CreateCall(
18378bcb0991SDimitry Andric         HwasanPersonalityWrapper,
18388bcb0991SDimitry Andric         {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
18398bcb0991SDimitry Andric          ThunkFn->getArg(3), ThunkFn->getArg(4),
18405f757f3fSDimitry Andric          P.first ? P.first : Constant::getNullValue(PtrTy),
18415f757f3fSDimitry Andric          UnwindGetGR.getCallee(), UnwindGetCFA.getCallee()});
18428bcb0991SDimitry Andric     WrapperCall->setTailCall();
18438bcb0991SDimitry Andric     IRB.CreateRet(WrapperCall);
18448bcb0991SDimitry Andric 
18458bcb0991SDimitry Andric     for (Function *F : P.second)
18468bcb0991SDimitry Andric       F->setPersonalityFn(ThunkFn);
18478bcb0991SDimitry Andric   }
18488bcb0991SDimitry Andric }
18498bcb0991SDimitry Andric 
init(Triple & TargetTriple,bool InstrumentWithCalls)1850fe6060f1SDimitry Andric void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple,
1851fe6060f1SDimitry Andric                                              bool InstrumentWithCalls) {
18520b57cec5SDimitry Andric   Scale = kDefaultShadowScale;
1853fe6060f1SDimitry Andric   if (TargetTriple.isOSFuchsia()) {
1854fe6060f1SDimitry Andric     // Fuchsia is always PIE, which means that the beginning of the address
1855fe6060f1SDimitry Andric     // space is always available.
18560b57cec5SDimitry Andric     InGlobal = false;
18570b57cec5SDimitry Andric     InTls = false;
18580b57cec5SDimitry Andric     Offset = 0;
1859fe6060f1SDimitry Andric     WithFrameRecord = true;
1860fe6060f1SDimitry Andric   } else if (ClMappingOffset.getNumOccurrences() > 0) {
1861fe6060f1SDimitry Andric     InGlobal = false;
1862fe6060f1SDimitry Andric     InTls = false;
1863fe6060f1SDimitry Andric     Offset = ClMappingOffset;
1864fe6060f1SDimitry Andric     WithFrameRecord = false;
1865fe6060f1SDimitry Andric   } else if (ClEnableKhwasan || InstrumentWithCalls) {
1866fe6060f1SDimitry Andric     InGlobal = false;
1867fe6060f1SDimitry Andric     InTls = false;
1868fe6060f1SDimitry Andric     Offset = 0;
1869fe6060f1SDimitry Andric     WithFrameRecord = false;
18700b57cec5SDimitry Andric   } else if (ClWithIfunc) {
18710b57cec5SDimitry Andric     InGlobal = true;
18720b57cec5SDimitry Andric     InTls = false;
18730b57cec5SDimitry Andric     Offset = kDynamicShadowSentinel;
1874fe6060f1SDimitry Andric     WithFrameRecord = false;
18750b57cec5SDimitry Andric   } else if (ClWithTls) {
18760b57cec5SDimitry Andric     InGlobal = false;
18770b57cec5SDimitry Andric     InTls = true;
18780b57cec5SDimitry Andric     Offset = kDynamicShadowSentinel;
1879fe6060f1SDimitry Andric     WithFrameRecord = true;
18800b57cec5SDimitry Andric   } else {
18810b57cec5SDimitry Andric     InGlobal = false;
18820b57cec5SDimitry Andric     InTls = false;
18830b57cec5SDimitry Andric     Offset = kDynamicShadowSentinel;
1884fe6060f1SDimitry Andric     WithFrameRecord = false;
18850b57cec5SDimitry Andric   }
18860b57cec5SDimitry Andric }
1887