blob: 4f6dae0cc405e9c2154b5d70d6e5503aa1c26d67 [file] [log] [blame]
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001//===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00006//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file is a part of HWAddressSanitizer, an address sanity checker
11/// based on tagged addressing.
12//===----------------------------------------------------------------------===//
13
Leonard Chan0cdd3b12019-05-14 21:17:21 +000014#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000015#include "llvm/ADT/SmallVector.h"
16#include "llvm/ADT/StringExtras.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/Triple.h"
19#include "llvm/IR/Attributes.h"
20#include "llvm/IR/BasicBlock.h"
21#include "llvm/IR/Constant.h"
22#include "llvm/IR/Constants.h"
23#include "llvm/IR/DataLayout.h"
Peter Collingbournefb9ce102019-06-17 23:39:41 +000024#include "llvm/IR/DebugInfoMetadata.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000025#include "llvm/IR/DerivedTypes.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/IRBuilder.h"
28#include "llvm/IR/InlineAsm.h"
29#include "llvm/IR/InstVisitor.h"
30#include "llvm/IR/Instruction.h"
31#include "llvm/IR/Instructions.h"
32#include "llvm/IR/IntrinsicInst.h"
33#include "llvm/IR/Intrinsics.h"
34#include "llvm/IR/LLVMContext.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000035#include "llvm/IR/MDBuilder.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000036#include "llvm/IR/Module.h"
37#include "llvm/IR/Type.h"
38#include "llvm/IR/Value.h"
39#include "llvm/Pass.h"
40#include "llvm/Support/Casting.h"
41#include "llvm/Support/CommandLine.h"
42#include "llvm/Support/Debug.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000043#include "llvm/Support/raw_ostream.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000044#include "llvm/Transforms/Instrumentation.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000045#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000046#include "llvm/Transforms/Utils/ModuleUtils.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000047#include "llvm/Transforms/Utils/PromoteMemToReg.h"
Kostya Serebryanyaf955972018-10-23 00:50:40 +000048#include <sstream>
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000049
50using namespace llvm;
51
52#define DEBUG_TYPE "hwasan"
53
54static const char *const kHwasanModuleCtorName = "hwasan.module_ctor";
55static const char *const kHwasanInitName = "__hwasan_init";
56
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +000057static const char *const kHwasanShadowMemoryDynamicAddress =
58 "__hwasan_shadow_memory_dynamic_address";
59
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000060// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
61static const size_t kNumberOfAccessSizes = 5;
62
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +000063static const size_t kDefaultShadowScale = 4;
64static const uint64_t kDynamicShadowSentinel =
65 std::numeric_limits<uint64_t>::max();
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +000066static const unsigned kPointerTagShift = 56;
67
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +000068static const unsigned kShadowBaseAlignment = 32;
69
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000070static cl::opt<std::string> ClMemoryAccessCallbackPrefix(
71 "hwasan-memory-access-callback-prefix",
72 cl::desc("Prefix for memory access callbacks"), cl::Hidden,
73 cl::init("__hwasan_"));
74
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +000075static cl::opt<bool>
76 ClInstrumentWithCalls("hwasan-instrument-with-calls",
77 cl::desc("instrument reads and writes with callbacks"),
78 cl::Hidden, cl::init(false));
79
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000080static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads",
81 cl::desc("instrument read instructions"),
82 cl::Hidden, cl::init(true));
83
84static cl::opt<bool> ClInstrumentWrites(
85 "hwasan-instrument-writes", cl::desc("instrument write instructions"),
86 cl::Hidden, cl::init(true));
87
88static cl::opt<bool> ClInstrumentAtomics(
89 "hwasan-instrument-atomics",
90 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
91 cl::init(true));
92
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +000093static cl::opt<bool> ClRecover(
94 "hwasan-recover",
95 cl::desc("Enable recovery mode (continue-after-error)."),
96 cl::Hidden, cl::init(false));
97
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000098static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
99 cl::desc("instrument stack (allocas)"),
100 cl::Hidden, cl::init(true));
101
Alex Shlyapnikov788764c2018-06-29 20:20:17 +0000102static cl::opt<bool> ClUARRetagToZero(
103 "hwasan-uar-retag-to-zero",
104 cl::desc("Clear alloca tags before returning from the function to allow "
105 "non-instrumented and instrumented function calls mix. When set "
106 "to false, allocas are retagged before returning from the "
107 "function to detect use after return."),
108 cl::Hidden, cl::init(true));
109
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000110static cl::opt<bool> ClGenerateTagsWithCalls(
111 "hwasan-generate-tags-with-calls",
112 cl::desc("generate new tags with runtime library calls"), cl::Hidden,
113 cl::init(false));
114
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000115static cl::opt<int> ClMatchAllTag(
116 "hwasan-match-all-tag",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000117 cl::desc("don't report bad accesses via pointers with this tag"),
118 cl::Hidden, cl::init(-1));
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000119
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000120static cl::opt<bool> ClEnableKhwasan(
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000121 "hwasan-kernel",
122 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000123 cl::Hidden, cl::init(false));
124
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000125// These flags allow to change the shadow mapping and control how shadow memory
126// is accessed. The shadow mapping looks like:
127// Shadow = (Mem >> scale) + offset
128
Fangrui Songb5f39842019-04-24 02:40:20 +0000129static cl::opt<uint64_t>
130 ClMappingOffset("hwasan-mapping-offset",
131 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
132 cl::Hidden, cl::init(0));
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000133
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +0000134static cl::opt<bool>
135 ClWithIfunc("hwasan-with-ifunc",
136 cl::desc("Access dynamic shadow through an ifunc global on "
137 "platforms that support this"),
138 cl::Hidden, cl::init(false));
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000139
140static cl::opt<bool> ClWithTls(
141 "hwasan-with-tls",
142 cl::desc("Access dynamic shadow through an thread-local pointer on "
143 "platforms that support this"),
144 cl::Hidden, cl::init(true));
145
146static cl::opt<bool>
147 ClRecordStackHistory("hwasan-record-stack-history",
148 cl::desc("Record stack frames with tagged allocations "
149 "in a thread-local ring buffer"),
150 cl::Hidden, cl::init(true));
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000151static cl::opt<bool>
152 ClCreateFrameDescriptions("hwasan-create-frame-descriptions",
153 cl::desc("create static frame descriptions"),
154 cl::Hidden, cl::init(true));
155
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000156static cl::opt<bool>
157 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
158 cl::desc("instrument memory intrinsics"),
Eugene Leviant4dc3a3f2018-12-24 16:02:48 +0000159 cl::Hidden, cl::init(true));
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000160
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000161static cl::opt<bool>
162 ClInstrumentLandingPads("hwasan-instrument-landing-pads",
163 cl::desc("instrument landing pads"), cl::Hidden,
164 cl::init(true));
165
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000166static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
167 cl::desc("inline all checks"),
168 cl::Hidden, cl::init(false));
169
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000170namespace {
171
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000172/// An instrumentation pass implementing detection of addressability bugs
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000173/// using tagged pointers.
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000174class HWAddressSanitizer {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000175public:
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000176 explicit HWAddressSanitizer(Module &M, bool CompileKernel = false,
177 bool Recover = false) {
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000178 this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover;
179 this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ?
180 ClEnableKhwasan : CompileKernel;
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000181
182 initializeModule(M);
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000183 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000184
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000185 bool sanitizeFunction(Function &F);
186 void initializeModule(Module &M);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000187
188 void initializeCallbacks(Module &M);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000189
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000190 Value *getDynamicShadowIfunc(IRBuilder<> &IRB);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000191 Value *getDynamicShadowNonTls(IRBuilder<> &IRB);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000192
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000193 void untagPointerOperand(Instruction *I, Value *Addr);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000194 Value *shadowBase();
195 Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
196 void instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000197 unsigned AccessSizeIndex,
198 Instruction *InsertBefore);
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000199 void instrumentMemIntrinsic(MemIntrinsic *MI);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000200 bool instrumentMemAccess(Instruction *I);
201 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
202 uint64_t *TypeSize, unsigned *Alignment,
203 Value **MaybeMask);
204
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000205 bool isInterestingAlloca(const AllocaInst &AI);
206 bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000207 Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000208 Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
Peter Collingbournefb9ce102019-06-17 23:39:41 +0000209 bool instrumentStack(
210 SmallVectorImpl<AllocaInst *> &Allocas,
211 DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
212 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000213 bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000214 Value *getNextTagWithCall(IRBuilder<> &IRB);
215 Value *getStackBaseTag(IRBuilder<> &IRB);
216 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI,
217 unsigned AllocaNo);
218 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000219
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000220 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000221 void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000222
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000223private:
224 LLVMContext *C;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000225 std::string CurModuleUniqueId;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000226 Triple TargetTriple;
James Y Knight13680222019-02-01 02:28:03 +0000227 FunctionCallee HWAsanMemmove, HWAsanMemcpy, HWAsanMemset;
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000228 FunctionCallee HWAsanHandleVfork;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000229
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000230 // Frame description is a way to pass names/sizes of local variables
231 // to the run-time w/o adding extra executable code in every function.
232 // We do this by creating a separate section with {PC,Descr} pairs and passing
233 // the section beg/end to __hwasan_init_frames() at module init time.
234 std::string createFrameString(ArrayRef<AllocaInst*> Allocas);
235 void createFrameGlobal(Function &F, const std::string &FrameString);
236 // Get the section name for frame descriptions. Currently ELF-only.
237 const char *getFrameSection() { return "__hwasan_frames"; }
238 const char *getFrameSectionBeg() { return "__start___hwasan_frames"; }
239 const char *getFrameSectionEnd() { return "__stop___hwasan_frames"; }
240 GlobalVariable *createFrameSectionBound(Module &M, Type *Ty,
241 const char *Name) {
242 auto GV = new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
243 nullptr, Name);
244 GV->setVisibility(GlobalValue::HiddenVisibility);
245 return GV;
246 }
247
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000248 /// This struct defines the shadow mapping using the rule:
249 /// shadow = (mem >> Scale) + Offset.
250 /// If InGlobal is true, then
251 /// extern char __hwasan_shadow[];
252 /// shadow = (mem >> Scale) + &__hwasan_shadow
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000253 /// If InTls is true, then
254 /// extern char *__hwasan_tls;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000255 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000256 struct ShadowMapping {
257 int Scale;
258 uint64_t Offset;
259 bool InGlobal;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000260 bool InTls;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000261
262 void init(Triple &TargetTriple);
263 unsigned getAllocaAlignment() const { return 1U << Scale; }
264 };
265 ShadowMapping Mapping;
266
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000267 Type *IntptrTy;
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000268 Type *Int8PtrTy;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000269 Type *Int8Ty;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000270 Type *Int32Ty;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000271
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000272 bool CompileKernel;
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000273 bool Recover;
274
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000275 Function *HwasanCtorFunction;
276
James Y Knight13680222019-02-01 02:28:03 +0000277 FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
278 FunctionCallee HwasanMemoryAccessCallbackSized[2];
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000279
James Y Knight13680222019-02-01 02:28:03 +0000280 FunctionCallee HwasanTagMemoryFunc;
281 FunctionCallee HwasanGenerateTagFunc;
282 FunctionCallee HwasanThreadEnterFunc;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000283
284 Constant *ShadowGlobal;
285
286 Value *LocalDynamicShadow = nullptr;
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000287 Value *StackBaseTag = nullptr;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000288 GlobalValue *ThreadPtrGlobal = nullptr;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000289};
290
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000291class HWAddressSanitizerLegacyPass : public FunctionPass {
292public:
293 // Pass identification, replacement for typeid.
294 static char ID;
295
296 explicit HWAddressSanitizerLegacyPass(bool CompileKernel = false,
297 bool Recover = false)
298 : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover) {}
299
300 StringRef getPassName() const override { return "HWAddressSanitizer"; }
301
302 bool runOnFunction(Function &F) override {
303 HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
304 return HWASan.sanitizeFunction(F);
305 }
306
307private:
308 bool CompileKernel;
309 bool Recover;
310};
311
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000312} // end anonymous namespace
313
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000314char HWAddressSanitizerLegacyPass::ID = 0;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000315
316INITIALIZE_PASS_BEGIN(
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000317 HWAddressSanitizerLegacyPass, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000318 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
319 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000320INITIALIZE_PASS_END(
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000321 HWAddressSanitizerLegacyPass, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000322 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
323 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000324
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000325FunctionPass *llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel,
326 bool Recover) {
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000327 assert(!CompileKernel || Recover);
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000328 return new HWAddressSanitizerLegacyPass(CompileKernel, Recover);
329}
330
331HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover)
332 : CompileKernel(CompileKernel), Recover(Recover) {}
333
334PreservedAnalyses HWAddressSanitizerPass::run(Function &F,
335 FunctionAnalysisManager &FAM) {
336 HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
337 if (HWASan.sanitizeFunction(F))
338 return PreservedAnalyses::none();
339 return PreservedAnalyses::all();
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000340}
341
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000342/// Module-level initialization.
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000343///
344/// inserts a call to __hwasan_init to the module's constructor list.
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000345void HWAddressSanitizer::initializeModule(Module &M) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000346 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000347 auto &DL = M.getDataLayout();
348
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000349 TargetTriple = Triple(M.getTargetTriple());
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000350
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000351 Mapping.init(TargetTriple);
352
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000353 C = &(M.getContext());
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000354 CurModuleUniqueId = getUniqueModuleId(&M);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000355 IRBuilder<> IRB(*C);
356 IntptrTy = IRB.getIntPtrTy(DL);
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000357 Int8PtrTy = IRB.getInt8PtrTy();
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000358 Int8Ty = IRB.getInt8Ty();
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000359 Int32Ty = IRB.getInt32Ty();
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000360
Benjamin Kramerbfc1d972018-01-18 14:19:04 +0000361 HwasanCtorFunction = nullptr;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000362 if (!CompileKernel) {
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000363 std::tie(HwasanCtorFunction, std::ignore) =
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000364 getOrCreateSanitizerCtorAndInitFunctions(
365 M, kHwasanModuleCtorName, kHwasanInitName,
366 /*InitArgTypes=*/{},
367 /*InitArgs=*/{},
368 // This callback is invoked when the functions are created the first
369 // time. Hook them into the global ctors list in that case:
370 [&](Function *Ctor, FunctionCallee) {
371 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
372 Ctor->setComdat(CtorComdat);
373 appendToGlobalCtors(M, Ctor, 0, Ctor);
374
375 IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
376 IRBCtor.CreateCall(
377 declareSanitizerInitFunction(M, "__hwasan_init_frames",
378 {Int8PtrTy, Int8PtrTy}),
379 {createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
380 createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
381 });
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000382
Peter Collingbourned3a3e4b2018-12-17 22:56:34 +0000383 // Create a zero-length global in __hwasan_frame so that the linker will
384 // always create start and stop symbols.
385 //
386 // N.B. If we ever start creating associated metadata in this pass this
387 // global will need to be associated with the ctor.
388 Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000389 M.getOrInsertGlobal("__hwasan", Int8Arr0Ty, [&] {
390 auto *GV = new GlobalVariable(
391 M, Int8Arr0Ty, /*isConstantGlobal=*/true, GlobalValue::PrivateLinkage,
392 Constant::getNullValue(Int8Arr0Ty), "__hwasan");
393 GV->setSection(getFrameSection());
394 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
395 GV->setComdat(CtorComdat);
396 appendToCompilerUsed(M, GV);
397 return GV;
398 });
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000399 }
400
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000401 if (!TargetTriple.isAndroid()) {
402 Constant *C = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
403 auto *GV = new GlobalVariable(M, IntptrTy, /*isConstantGlobal=*/false,
404 GlobalValue::ExternalLinkage, nullptr,
405 "__hwasan_tls", nullptr,
406 GlobalVariable::InitialExecTLSModel);
407 appendToCompilerUsed(M, GV);
408 return GV;
409 });
410 ThreadPtrGlobal = cast<GlobalVariable>(C);
411 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000412}
413
414void HWAddressSanitizer::initializeCallbacks(Module &M) {
415 IRBuilder<> IRB(*C);
416 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
417 const std::string TypeStr = AccessIsWrite ? "store" : "load";
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000418 const std::string EndingStr = Recover ? "_noabort" : "";
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000419
James Y Knight13680222019-02-01 02:28:03 +0000420 HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(
421 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr,
422 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000423
424 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
425 AccessSizeIndex++) {
426 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
James Y Knight13680222019-02-01 02:28:03 +0000427 M.getOrInsertFunction(
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000428 ClMemoryAccessCallbackPrefix + TypeStr +
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000429 itostr(1ULL << AccessSizeIndex) + EndingStr,
James Y Knight13680222019-02-01 02:28:03 +0000430 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000431 }
432 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000433
James Y Knight13680222019-02-01 02:28:03 +0000434 HwasanTagMemoryFunc = M.getOrInsertFunction(
435 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy);
436 HwasanGenerateTagFunc =
437 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000438
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000439 ShadowGlobal = M.getOrInsertGlobal("__hwasan_shadow",
440 ArrayType::get(IRB.getInt8Ty(), 0));
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000441
442 const std::string MemIntrinCallbackPrefix =
443 CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix;
James Y Knight13680222019-02-01 02:28:03 +0000444 HWAsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove",
445 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
446 IRB.getInt8PtrTy(), IntptrTy);
447 HWAsanMemcpy = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memcpy",
448 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
449 IRB.getInt8PtrTy(), IntptrTy);
450 HWAsanMemset = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memset",
451 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
452 IRB.getInt32Ty(), IntptrTy);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000453
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000454 HWAsanHandleVfork =
455 M.getOrInsertFunction("__hwasan_handle_vfork", IRB.getVoidTy(), IntptrTy);
456
James Y Knight13680222019-02-01 02:28:03 +0000457 HwasanThreadEnterFunc =
458 M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy());
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000459}
460
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000461Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {
462 // An empty inline asm with input reg == output reg.
463 // An opaque no-op cast, basically.
464 InlineAsm *Asm = InlineAsm::get(
465 FunctionType::get(Int8PtrTy, {ShadowGlobal->getType()}, false),
466 StringRef(""), StringRef("=r,0"),
467 /*hasSideEffects=*/false);
468 return IRB.CreateCall(Asm, {ShadowGlobal}, ".hwasan.shadow");
469}
470
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000471Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000472 // Generate code only when dynamic addressing is needed.
473 if (Mapping.Offset != kDynamicShadowSentinel)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000474 return nullptr;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000475
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000476 if (Mapping.InGlobal) {
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000477 return getDynamicShadowIfunc(IRB);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000478 } else {
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000479 Value *GlobalDynamicAddress =
480 IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000481 kHwasanShadowMemoryDynamicAddress, Int8PtrTy);
James Y Knight14359ef2019-02-01 20:44:24 +0000482 return IRB.CreateLoad(Int8PtrTy, GlobalDynamicAddress);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000483 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000484}
485
486Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000487 bool *IsWrite,
488 uint64_t *TypeSize,
489 unsigned *Alignment,
490 Value **MaybeMask) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000491 // Skip memory accesses inserted by another instrumentation.
492 if (I->getMetadata("nosanitize")) return nullptr;
493
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000494 // Do not instrument the load fetching the dynamic shadow address.
495 if (LocalDynamicShadow == I)
496 return nullptr;
497
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000498 Value *PtrOperand = nullptr;
499 const DataLayout &DL = I->getModule()->getDataLayout();
500 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
501 if (!ClInstrumentReads) return nullptr;
502 *IsWrite = false;
503 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
504 *Alignment = LI->getAlignment();
505 PtrOperand = LI->getPointerOperand();
506 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
507 if (!ClInstrumentWrites) return nullptr;
508 *IsWrite = true;
509 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
510 *Alignment = SI->getAlignment();
511 PtrOperand = SI->getPointerOperand();
512 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
513 if (!ClInstrumentAtomics) return nullptr;
514 *IsWrite = true;
515 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
516 *Alignment = 0;
517 PtrOperand = RMW->getPointerOperand();
518 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
519 if (!ClInstrumentAtomics) return nullptr;
520 *IsWrite = true;
521 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
522 *Alignment = 0;
523 PtrOperand = XCHG->getPointerOperand();
524 }
525
526 if (PtrOperand) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000527 // Do not instrument accesses from different address spaces; we cannot deal
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000528 // with them.
529 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType());
530 if (PtrTy->getPointerAddressSpace() != 0)
531 return nullptr;
532
533 // Ignore swifterror addresses.
534 // swifterror memory addresses are mem2reg promoted by instruction
535 // selection. As such they cannot have regular uses like an instrumentation
536 // function and it makes no sense to track them as memory.
537 if (PtrOperand->isSwiftError())
538 return nullptr;
539 }
540
541 return PtrOperand;
542}
543
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000544static unsigned getPointerOperandIndex(Instruction *I) {
545 if (LoadInst *LI = dyn_cast<LoadInst>(I))
546 return LI->getPointerOperandIndex();
547 if (StoreInst *SI = dyn_cast<StoreInst>(I))
548 return SI->getPointerOperandIndex();
549 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I))
550 return RMW->getPointerOperandIndex();
551 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I))
552 return XCHG->getPointerOperandIndex();
553 report_fatal_error("Unexpected instruction");
554 return -1;
555}
556
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000557static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
558 size_t Res = countTrailingZeros(TypeSize / 8);
559 assert(Res < kNumberOfAccessSizes);
560 return Res;
561}
562
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000563void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
564 if (TargetTriple.isAArch64())
565 return;
566
567 IRBuilder<> IRB(I);
568 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
569 Value *UntaggedPtr =
570 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType());
571 I->setOperand(getPointerOperandIndex(I), UntaggedPtr);
572}
573
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000574Value *HWAddressSanitizer::shadowBase() {
575 if (LocalDynamicShadow)
576 return LocalDynamicShadow;
577 return ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, Mapping.Offset),
578 Int8PtrTy);
579}
580
581Value *HWAddressSanitizer::memToShadow(Value *Mem, IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000582 // Mem >> Scale
583 Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale);
584 if (Mapping.Offset == 0)
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000585 return IRB.CreateIntToPtr(Shadow, Int8PtrTy);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000586 // (Mem >> Scale) + Offset
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000587 return IRB.CreateGEP(Int8Ty, shadowBase(), Shadow);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000588}
589
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000590void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000591 unsigned AccessSizeIndex,
592 Instruction *InsertBefore) {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000593 const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex;
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000594 IRBuilder<> IRB(InsertBefore);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000595
596 if (!ClInlineAllChecks && TargetTriple.isAArch64() &&
597 TargetTriple.isOSBinFormatELF() && !Recover) {
598 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
599 Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy);
600 IRB.CreateCall(
601 Intrinsic::getDeclaration(M, Intrinsic::hwasan_check_memaccess),
602 {shadowBase(), Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
603 return;
604 }
605
606 Value *PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000607 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift),
608 IRB.getInt8Ty());
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000609 Value *AddrLong = untagPointer(IRB, PtrLong);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000610 Value *Shadow = memToShadow(AddrLong, IRB);
James Y Knight14359ef2019-02-01 20:44:24 +0000611 Value *MemTag = IRB.CreateLoad(Int8Ty, Shadow);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000612 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag);
613
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000614 int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ?
615 ClMatchAllTag : (CompileKernel ? 0xFF : -1);
616 if (matchAllTag != -1) {
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000617 Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag,
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000618 ConstantInt::get(PtrTag->getType(), matchAllTag));
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000619 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);
620 }
621
Chandler Carruth4a2d58e2018-10-15 09:34:05 +0000622 Instruction *CheckTerm =
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000623 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000624 MDBuilder(*C).createBranchWeights(1, 100000));
625
626 IRB.SetInsertPoint(CheckTerm);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000627 InlineAsm *Asm;
628 switch (TargetTriple.getArch()) {
629 case Triple::x86_64:
630 // The signal handler will find the data address in rdi.
631 Asm = InlineAsm::get(
632 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
633 "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)",
634 "{rdi}",
635 /*hasSideEffects=*/true);
636 break;
637 case Triple::aarch64:
638 case Triple::aarch64_be:
639 // The signal handler will find the data address in x0.
640 Asm = InlineAsm::get(
641 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
642 "brk #" + itostr(0x900 + AccessInfo),
643 "{x0}",
644 /*hasSideEffects=*/true);
645 break;
646 default:
647 report_fatal_error("unsupported architecture");
648 }
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000649 IRB.CreateCall(Asm, PtrLong);
650}
651
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000652void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
653 IRBuilder<> IRB(MI);
654 if (isa<MemTransferInst>(MI)) {
655 IRB.CreateCall(
656 isa<MemMoveInst>(MI) ? HWAsanMemmove : HWAsanMemcpy,
657 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
658 IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
659 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
660 } else if (isa<MemSetInst>(MI)) {
661 IRB.CreateCall(
662 HWAsanMemset,
663 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
664 IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
665 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
666 }
667 MI->eraseFromParent();
668}
669
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000670bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000671 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000672 bool IsWrite = false;
673 unsigned Alignment = 0;
674 uint64_t TypeSize = 0;
675 Value *MaybeMask = nullptr;
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000676
677 if (ClInstrumentMemIntrinsics && isa<MemIntrinsic>(I)) {
678 instrumentMemIntrinsic(cast<MemIntrinsic>(I));
679 return true;
680 }
681
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000682 Value *Addr =
683 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask);
684
685 if (!Addr)
686 return false;
687
688 if (MaybeMask)
689 return false; //FIXME
690
691 IRBuilder<> IRB(I);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000692 if (isPowerOf2_64(TypeSize) &&
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000693 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) &&
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000694 (Alignment >= (1UL << Mapping.Scale) || Alignment == 0 ||
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000695 Alignment >= TypeSize / 8)) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000696 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000697 if (ClInstrumentWithCalls) {
698 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000699 IRB.CreatePointerCast(Addr, IntptrTy));
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000700 } else {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000701 instrumentMemAccessInline(Addr, IsWrite, AccessSizeIndex, I);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000702 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000703 } else {
704 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000705 {IRB.CreatePointerCast(Addr, IntptrTy),
706 ConstantInt::get(IntptrTy, TypeSize / 8)});
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000707 }
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000708 untagPointerOperand(I, Addr);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000709
710 return true;
711}
712
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000713static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) {
714 uint64_t ArraySize = 1;
715 if (AI.isArrayAllocation()) {
716 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize());
717 assert(CI && "non-constant array size");
718 ArraySize = CI->getZExtValue();
719 }
720 Type *Ty = AI.getAllocatedType();
721 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty);
722 return SizeInBytes * ArraySize;
723}
724
725bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI,
726 Value *Tag) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000727 size_t Size = (getAllocaSizeInBytes(*AI) + Mapping.getAllocaAlignment() - 1) &
728 ~(Mapping.getAllocaAlignment() - 1);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000729
730 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty());
731 if (ClInstrumentWithCalls) {
732 IRB.CreateCall(HwasanTagMemoryFunc,
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000733 {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag,
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000734 ConstantInt::get(IntptrTy, Size)});
735 } else {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000736 size_t ShadowSize = Size >> Mapping.Scale;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000737 Value *ShadowPtr = memToShadow(IRB.CreatePointerCast(AI, IntptrTy), IRB);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000738 // If this memset is not inlined, it will be intercepted in the hwasan
739 // runtime library. That's OK, because the interceptor skips the checks if
740 // the address is in the shadow region.
741 // FIXME: the interceptor is not as fast as real memset. Consider lowering
742 // llvm.memset right here into either a sequence of stores, or a call to
743 // hwasan_tag_memory.
744 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1);
745 }
746 return true;
747}
748
749static unsigned RetagMask(unsigned AllocaNo) {
750 // A list of 8-bit numbers that have at most one run of non-zero bits.
751 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
752 // masks.
753 // The list does not include the value 255, which is used for UAR.
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000754 //
755 // Because we are more likely to use earlier elements of this list than later
756 // ones, it is sorted in increasing order of probability of collision with a
757 // mask allocated (temporally) nearby. The program that generated this list
758 // can be found at:
759 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
760 static unsigned FastMasks[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
761 48, 16, 120, 248, 56, 24, 8, 124, 252,
762 60, 28, 12, 4, 126, 254, 62, 30, 14,
763 6, 2, 127, 63, 31, 15, 7, 3, 1};
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000764 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
765}
766
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000767Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
768 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
769}
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000770
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000771Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
772 if (ClGenerateTagsWithCalls)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000773 return getNextTagWithCall(IRB);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000774 if (StackBaseTag)
775 return StackBaseTag;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000776 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
777 // first).
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000778 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
779 auto GetStackPointerFn =
780 Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
781 Value *StackPointer = IRB.CreateCall(
782 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())});
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000783
784 // Extract some entropy from the stack pointer for the tags.
785 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
786 // between functions).
787 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy);
788 Value *StackTag =
789 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20),
790 "hwasan.stack.base.tag");
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000791 return StackTag;
792}
793
794Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
795 AllocaInst *AI, unsigned AllocaNo) {
796 if (ClGenerateTagsWithCalls)
797 return getNextTagWithCall(IRB);
798 return IRB.CreateXor(StackTag,
799 ConstantInt::get(IntptrTy, RetagMask(AllocaNo)));
800}
801
802Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
Alex Shlyapnikov788764c2018-06-29 20:20:17 +0000803 if (ClUARRetagToZero)
804 return ConstantInt::get(IntptrTy, 0);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000805 if (ClGenerateTagsWithCalls)
806 return getNextTagWithCall(IRB);
807 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
808}
809
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000810// Add a tag to an address.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000811Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
812 Value *PtrLong, Value *Tag) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000813 Value *TaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000814 if (CompileKernel) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000815 // Kernel addresses have 0xFF in the most significant byte.
816 Value *ShiftedTag = IRB.CreateOr(
817 IRB.CreateShl(Tag, kPointerTagShift),
818 ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1));
819 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
820 } else {
821 // Userspace can simply do OR (tag << 56);
822 Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift);
823 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
824 }
825 return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
826}
827
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000828// Remove tag from an address.
829Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
830 Value *UntaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000831 if (CompileKernel) {
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000832 // Kernel addresses have 0xFF in the most significant byte.
833 UntaggedPtrLong = IRB.CreateOr(PtrLong,
834 ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift));
835 } else {
836 // Userspace addresses have 0x00.
837 UntaggedPtrLong = IRB.CreateAnd(PtrLong,
838 ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift)));
839 }
840 return UntaggedPtrLong;
841}
842
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000843Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) {
844 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
845 if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) {
Evgeniy Stepanov0184c532019-01-05 00:44:58 +0000846 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
847 // in Bionic's libc/private/bionic_tls.h.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000848 Function *ThreadPointerFunc =
849 Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
850 Value *SlotPtr = IRB.CreatePointerCast(
James Y Knight77160752019-02-01 20:44:47 +0000851 IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
852 IRB.CreateCall(ThreadPointerFunc), 0x30),
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000853 Ty->getPointerTo(0));
854 return SlotPtr;
855 }
856 if (ThreadPtrGlobal)
857 return ThreadPtrGlobal;
858
859
860 return nullptr;
861}
862
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000863// Creates a string with a description of the stack frame (set of Allocas).
864// The string is intended to be human readable.
865// The current form is: Size1 Name1; Size2 Name2; ...
866std::string
867HWAddressSanitizer::createFrameString(ArrayRef<AllocaInst *> Allocas) {
868 std::ostringstream Descr;
869 for (auto AI : Allocas)
870 Descr << getAllocaSizeInBytes(*AI) << " " << AI->getName().str() << "; ";
871 return Descr.str();
872}
873
874// Creates a global in the frame section which consists of two pointers:
875// the function PC and the frame string constant.
876void HWAddressSanitizer::createFrameGlobal(Function &F,
877 const std::string &FrameString) {
878 Module &M = *F.getParent();
879 auto DescrGV = createPrivateGlobalForString(M, FrameString, true);
880 auto PtrPairTy = StructType::get(F.getType(), DescrGV->getType());
881 auto GV = new GlobalVariable(
882 M, PtrPairTy, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage,
883 ConstantStruct::get(PtrPairTy, (Constant *)&F, (Constant *)DescrGV),
884 "__hwasan");
885 GV->setSection(getFrameSection());
886 appendToCompilerUsed(M, GV);
887 // Put GV into the F's Comadat so that if F is deleted GV can be deleted too.
Peter Collingbourned3a3e4b2018-12-17 22:56:34 +0000888 if (auto Comdat =
889 GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
890 GV->setComdat(Comdat);
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000891}
892
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000893void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
894 if (!Mapping.InTls) {
895 LocalDynamicShadow = getDynamicShadowNonTls(IRB);
896 return;
897 }
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000898
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000899 if (!WithFrameRecord && TargetTriple.isAndroid()) {
900 LocalDynamicShadow = getDynamicShadowIfunc(IRB);
901 return;
902 }
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000903
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000904 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
905 assert(SlotPtr);
906
James Y Knight14359ef2019-02-01 20:44:24 +0000907 Instruction *ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000908
909 Function *F = IRB.GetInsertBlock()->getParent();
910 if (F->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") {
911 Value *ThreadLongEqZero =
912 IRB.CreateICmpEQ(ThreadLong, ConstantInt::get(IntptrTy, 0));
913 auto *Br = cast<BranchInst>(SplitBlockAndInsertIfThen(
914 ThreadLongEqZero, cast<Instruction>(ThreadLongEqZero)->getNextNode(),
915 false, MDBuilder(*C).createBranchWeights(1, 100000)));
916
917 IRB.SetInsertPoint(Br);
918 // FIXME: This should call a new runtime function with a custom calling
919 // convention to avoid needing to spill all arguments here.
920 IRB.CreateCall(HwasanThreadEnterFunc);
James Y Knight14359ef2019-02-01 20:44:24 +0000921 LoadInst *ReloadThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000922
923 IRB.SetInsertPoint(&*Br->getSuccessor(0)->begin());
924 PHINode *ThreadLongPhi = IRB.CreatePHI(IntptrTy, 2);
925 ThreadLongPhi->addIncoming(ThreadLong, ThreadLong->getParent());
926 ThreadLongPhi->addIncoming(ReloadThreadLong, ReloadThreadLong->getParent());
927 ThreadLong = ThreadLongPhi;
928 }
929
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000930 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI.
931 Value *ThreadLongMaybeUntagged =
932 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong);
933
934 if (WithFrameRecord) {
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000935 StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
936
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000937 // Prepare ring buffer data.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000938 auto PC = IRB.CreatePtrToInt(F, IntptrTy);
939 auto GetStackPointerFn =
940 Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress);
941 Value *SP = IRB.CreatePtrToInt(
942 IRB.CreateCall(GetStackPointerFn,
943 {Constant::getNullValue(IRB.getInt32Ty())}),
944 IntptrTy);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000945 // Mix SP and PC.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000946 // Assumptions:
947 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
948 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
949 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this:
950 // 0xSSSSPPPPPPPPPPPP
951 SP = IRB.CreateShl(SP, 44);
952
953 // Store data to ring buffer.
954 Value *RecordPtr =
955 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IntptrTy->getPointerTo(0));
956 IRB.CreateStore(IRB.CreateOr(PC, SP), RecordPtr);
957
958 // Update the ring buffer. Top byte of ThreadLong defines the size of the
959 // buffer in pages, it must be a power of two, and the start of the buffer
960 // must be aligned by twice that much. Therefore wrap around of the ring
961 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
962 // The use of AShr instead of LShr is due to
963 // https://bugs.llvm.org/show_bug.cgi?id=39030
964 // Runtime library makes sure not to use the highest bit.
965 Value *WrapMask = IRB.CreateXor(
966 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
967 ConstantInt::get(IntptrTy, (uint64_t)-1));
968 Value *ThreadLongNew = IRB.CreateAnd(
969 IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
970 IRB.CreateStore(ThreadLongNew, SlotPtr);
971 }
972
973 // Get shadow base address by aligning RecordPtr up.
974 // Note: this is not correct if the pointer is already aligned.
975 // Runtime library will make sure this never happens.
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000976 LocalDynamicShadow = IRB.CreateAdd(
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000977 IRB.CreateOr(
978 ThreadLongMaybeUntagged,
979 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
980 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000981 LocalDynamicShadow = IRB.CreateIntToPtr(LocalDynamicShadow, Int8PtrTy);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000982}
983
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000984bool HWAddressSanitizer::instrumentLandingPads(
985 SmallVectorImpl<Instruction *> &LandingPadVec) {
986 Module *M = LandingPadVec[0]->getModule();
987 Function *ReadRegister =
988 Intrinsic::getDeclaration(M, Intrinsic::read_register, IntptrTy);
989 const char *RegName =
990 (TargetTriple.getArch() == Triple::x86_64) ? "rsp" : "sp";
991 MDNode *MD = MDNode::get(*C, {MDString::get(*C, RegName)});
992 Value *Args[] = {MetadataAsValue::get(*C, MD)};
993
994 for (auto *LP : LandingPadVec) {
995 IRBuilder<> IRB(LP->getNextNode());
996 IRB.CreateCall(HWAsanHandleVfork, {IRB.CreateCall(ReadRegister, Args)});
997 }
998 return true;
999}
1000
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001001bool HWAddressSanitizer::instrumentStack(
1002 SmallVectorImpl<AllocaInst *> &Allocas,
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001003 DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001004 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001005 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
1006 // alloca addresses using that. Unfortunately, offsets are not known yet
1007 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
1008 // temp, shift-OR it into each alloca address and xor with the retag mask.
1009 // This generates one extra instruction per alloca use.
1010 for (unsigned N = 0; N < Allocas.size(); ++N) {
1011 auto *AI = Allocas[N];
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001012 IRBuilder<> IRB(AI->getNextNode());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001013
1014 // Replace uses of the alloca with tagged address.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001015 Value *Tag = getAllocaTag(IRB, StackTag, AI, N);
1016 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +00001017 Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001018 std::string Name =
1019 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +00001020 Replacement->setName(Name + ".hwasan");
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001021
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001022 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001023 Use &U = *UI++;
1024 if (U.getUser() != AILong)
1025 U.set(Replacement);
1026 }
1027
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001028 for (auto *DDI : AllocaDeclareMap.lookup(AI)) {
1029 DIExpression *OldExpr = DDI->getExpression();
1030 DIExpression *NewExpr = DIExpression::append(
1031 OldExpr, {dwarf::DW_OP_LLVM_tag_offset, RetagMask(N)});
1032 DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr));
1033 }
1034
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001035 tagAlloca(IRB, AI, Tag);
1036
1037 for (auto RI : RetVec) {
1038 IRB.SetInsertPoint(RI);
1039
1040 // Re-tag alloca memory with the special UAR tag.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001041 Value *Tag = getUARTag(IRB, StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001042 tagAlloca(IRB, AI, Tag);
1043 }
1044 }
1045
1046 return true;
1047}
1048
1049bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
1050 return (AI.getAllocatedType()->isSized() &&
1051 // FIXME: instrument dynamic allocas, too
1052 AI.isStaticAlloca() &&
1053 // alloca() may be called with 0 size, ignore it.
1054 getAllocaSizeInBytes(AI) > 0 &&
1055 // We are only interested in allocas not promotable to registers.
1056 // Promotable allocas are common under -O0.
1057 !isAllocaPromotable(&AI) &&
1058 // inalloca allocas are not treated as static, and we don't want
1059 // dynamic alloca instrumentation for them as well.
1060 !AI.isUsedWithInAlloca() &&
1061 // swifterror allocas are register promoted by ISel
1062 !AI.isSwiftError());
1063}
1064
Leonard Chan0cdd3b12019-05-14 21:17:21 +00001065bool HWAddressSanitizer::sanitizeFunction(Function &F) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001066 if (&F == HwasanCtorFunction)
1067 return false;
1068
1069 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
1070 return false;
1071
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001072 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001073
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001074 SmallVector<Instruction*, 16> ToInstrument;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001075 SmallVector<AllocaInst*, 8> AllocasToInstrument;
1076 SmallVector<Instruction*, 8> RetVec;
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001077 SmallVector<Instruction*, 8> LandingPadVec;
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001078 DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> AllocaDeclareMap;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001079 for (auto &BB : F) {
1080 for (auto &Inst : BB) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001081 if (ClInstrumentStack)
1082 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
1083 // Realign all allocas. We don't want small uninteresting allocas to
1084 // hide in instrumented alloca's padding.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001085 if (AI->getAlignment() < Mapping.getAllocaAlignment())
1086 AI->setAlignment(Mapping.getAllocaAlignment());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001087 // Instrument some of them.
1088 if (isInterestingAlloca(*AI))
1089 AllocasToInstrument.push_back(AI);
1090 continue;
1091 }
1092
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001093 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) ||
1094 isa<CleanupReturnInst>(Inst))
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001095 RetVec.push_back(&Inst);
1096
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001097 if (auto *DDI = dyn_cast<DbgDeclareInst>(&Inst))
1098 if (auto *Alloca = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
1099 AllocaDeclareMap[Alloca].push_back(DDI);
1100
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001101 if (ClInstrumentLandingPads && isa<LandingPadInst>(Inst))
1102 LandingPadVec.push_back(&Inst);
1103
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001104 Value *MaybeMask = nullptr;
1105 bool IsWrite;
1106 unsigned Alignment;
1107 uint64_t TypeSize;
1108 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize,
1109 &Alignment, &MaybeMask);
1110 if (Addr || isa<MemIntrinsic>(Inst))
1111 ToInstrument.push_back(&Inst);
1112 }
1113 }
1114
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001115 initializeCallbacks(*F.getParent());
1116
1117 if (!LandingPadVec.empty())
1118 instrumentLandingPads(LandingPadVec);
1119
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001120 if (AllocasToInstrument.empty() && ToInstrument.empty())
1121 return false;
1122
Kostya Serebryanyaf955972018-10-23 00:50:40 +00001123 if (ClCreateFrameDescriptions && !AllocasToInstrument.empty())
1124 createFrameGlobal(F, createFrameString(AllocasToInstrument));
1125
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001126
1127 assert(!LocalDynamicShadow);
1128
1129 Instruction *InsertPt = &*F.getEntryBlock().begin();
1130 IRBuilder<> EntryIRB(InsertPt);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +00001131 emitPrologue(EntryIRB,
1132 /*WithFrameRecord*/ ClRecordStackHistory &&
1133 !AllocasToInstrument.empty());
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001134
1135 bool Changed = false;
1136 if (!AllocasToInstrument.empty()) {
1137 Value *StackTag =
1138 ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB);
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001139 Changed |= instrumentStack(AllocasToInstrument, AllocaDeclareMap, RetVec,
1140 StackTag);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001141 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001142
Peter Collingbourne1a8acfb2019-01-25 02:08:46 +00001143 // If we split the entry block, move any allocas that were originally in the
1144 // entry block back into the entry block so that they aren't treated as
1145 // dynamic allocas.
1146 if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {
1147 InsertPt = &*F.getEntryBlock().begin();
1148 for (auto II = EntryIRB.GetInsertBlock()->begin(),
1149 IE = EntryIRB.GetInsertBlock()->end();
1150 II != IE;) {
1151 Instruction *I = &*II++;
1152 if (auto *AI = dyn_cast<AllocaInst>(I))
1153 if (isa<ConstantInt>(AI->getArraySize()))
1154 I->moveBefore(InsertPt);
1155 }
1156 }
1157
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001158 for (auto Inst : ToInstrument)
1159 Changed |= instrumentMemAccess(Inst);
1160
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001161 LocalDynamicShadow = nullptr;
Peter Collingbourned57f7cc2019-06-17 23:39:51 +00001162 StackBaseTag = nullptr;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001163
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001164 return Changed;
1165}
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001166
1167void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001168 Scale = kDefaultShadowScale;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001169 if (ClMappingOffset.getNumOccurrences() > 0) {
1170 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001171 InTls = false;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001172 Offset = ClMappingOffset;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001173 } else if (ClEnableKhwasan || ClInstrumentWithCalls) {
1174 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001175 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001176 Offset = 0;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001177 } else if (ClWithIfunc) {
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001178 InGlobal = true;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001179 InTls = false;
1180 Offset = kDynamicShadowSentinel;
1181 } else if (ClWithTls) {
1182 InGlobal = false;
1183 InTls = true;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001184 Offset = kDynamicShadowSentinel;
1185 } else {
1186 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001187 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001188 Offset = kDynamicShadowSentinel;
1189 }
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001190}