blob: 9085da6e11384bad38cbb94fa362f1025c26b695 [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);
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000213 Value *readRegister(IRBuilder<> &IRB, StringRef Name);
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000214 bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000215 Value *getNextTagWithCall(IRBuilder<> &IRB);
216 Value *getStackBaseTag(IRBuilder<> &IRB);
217 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI,
218 unsigned AllocaNo);
219 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000220
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000221 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000222 void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000223
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000224private:
225 LLVMContext *C;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000226 std::string CurModuleUniqueId;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000227 Triple TargetTriple;
James Y Knight13680222019-02-01 02:28:03 +0000228 FunctionCallee HWAsanMemmove, HWAsanMemcpy, HWAsanMemset;
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000229 FunctionCallee HWAsanHandleVfork;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000230
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000231 // Frame description is a way to pass names/sizes of local variables
232 // to the run-time w/o adding extra executable code in every function.
233 // We do this by creating a separate section with {PC,Descr} pairs and passing
234 // the section beg/end to __hwasan_init_frames() at module init time.
235 std::string createFrameString(ArrayRef<AllocaInst*> Allocas);
236 void createFrameGlobal(Function &F, const std::string &FrameString);
237 // Get the section name for frame descriptions. Currently ELF-only.
238 const char *getFrameSection() { return "__hwasan_frames"; }
239 const char *getFrameSectionBeg() { return "__start___hwasan_frames"; }
240 const char *getFrameSectionEnd() { return "__stop___hwasan_frames"; }
241 GlobalVariable *createFrameSectionBound(Module &M, Type *Ty,
242 const char *Name) {
243 auto GV = new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
244 nullptr, Name);
245 GV->setVisibility(GlobalValue::HiddenVisibility);
246 return GV;
247 }
248
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000249 /// This struct defines the shadow mapping using the rule:
250 /// shadow = (mem >> Scale) + Offset.
251 /// If InGlobal is true, then
252 /// extern char __hwasan_shadow[];
253 /// shadow = (mem >> Scale) + &__hwasan_shadow
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000254 /// If InTls is true, then
255 /// extern char *__hwasan_tls;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000256 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000257 struct ShadowMapping {
258 int Scale;
259 uint64_t Offset;
260 bool InGlobal;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000261 bool InTls;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000262
263 void init(Triple &TargetTriple);
264 unsigned getAllocaAlignment() const { return 1U << Scale; }
265 };
266 ShadowMapping Mapping;
267
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000268 Type *IntptrTy;
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000269 Type *Int8PtrTy;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000270 Type *Int8Ty;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000271 Type *Int32Ty;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000272
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000273 bool CompileKernel;
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000274 bool Recover;
275
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000276 Function *HwasanCtorFunction;
277
James Y Knight13680222019-02-01 02:28:03 +0000278 FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
279 FunctionCallee HwasanMemoryAccessCallbackSized[2];
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000280
James Y Knight13680222019-02-01 02:28:03 +0000281 FunctionCallee HwasanTagMemoryFunc;
282 FunctionCallee HwasanGenerateTagFunc;
283 FunctionCallee HwasanThreadEnterFunc;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000284
285 Constant *ShadowGlobal;
286
287 Value *LocalDynamicShadow = nullptr;
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000288 Value *StackBaseTag = nullptr;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000289 GlobalValue *ThreadPtrGlobal = nullptr;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000290};
291
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000292class HWAddressSanitizerLegacyPass : public FunctionPass {
293public:
294 // Pass identification, replacement for typeid.
295 static char ID;
296
297 explicit HWAddressSanitizerLegacyPass(bool CompileKernel = false,
298 bool Recover = false)
299 : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover) {}
300
301 StringRef getPassName() const override { return "HWAddressSanitizer"; }
302
303 bool runOnFunction(Function &F) override {
304 HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
305 return HWASan.sanitizeFunction(F);
306 }
307
308private:
309 bool CompileKernel;
310 bool Recover;
311};
312
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000313} // end anonymous namespace
314
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000315char HWAddressSanitizerLegacyPass::ID = 0;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000316
317INITIALIZE_PASS_BEGIN(
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000318 HWAddressSanitizerLegacyPass, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000319 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
320 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000321INITIALIZE_PASS_END(
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000322 HWAddressSanitizerLegacyPass, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000323 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
324 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000325
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000326FunctionPass *llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel,
327 bool Recover) {
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000328 assert(!CompileKernel || Recover);
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000329 return new HWAddressSanitizerLegacyPass(CompileKernel, Recover);
330}
331
332HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover)
333 : CompileKernel(CompileKernel), Recover(Recover) {}
334
335PreservedAnalyses HWAddressSanitizerPass::run(Function &F,
336 FunctionAnalysisManager &FAM) {
337 HWAddressSanitizer HWASan(*F.getParent(), CompileKernel, Recover);
338 if (HWASan.sanitizeFunction(F))
339 return PreservedAnalyses::none();
340 return PreservedAnalyses::all();
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000341}
342
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000343/// Module-level initialization.
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000344///
345/// inserts a call to __hwasan_init to the module's constructor list.
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000346void HWAddressSanitizer::initializeModule(Module &M) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000347 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000348 auto &DL = M.getDataLayout();
349
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000350 TargetTriple = Triple(M.getTargetTriple());
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000351
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000352 Mapping.init(TargetTriple);
353
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000354 C = &(M.getContext());
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000355 CurModuleUniqueId = getUniqueModuleId(&M);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000356 IRBuilder<> IRB(*C);
357 IntptrTy = IRB.getIntPtrTy(DL);
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000358 Int8PtrTy = IRB.getInt8PtrTy();
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000359 Int8Ty = IRB.getInt8Ty();
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000360 Int32Ty = IRB.getInt32Ty();
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000361
Benjamin Kramerbfc1d972018-01-18 14:19:04 +0000362 HwasanCtorFunction = nullptr;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000363 if (!CompileKernel) {
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000364 std::tie(HwasanCtorFunction, std::ignore) =
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000365 getOrCreateSanitizerCtorAndInitFunctions(
366 M, kHwasanModuleCtorName, kHwasanInitName,
367 /*InitArgTypes=*/{},
368 /*InitArgs=*/{},
369 // This callback is invoked when the functions are created the first
370 // time. Hook them into the global ctors list in that case:
371 [&](Function *Ctor, FunctionCallee) {
372 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
373 Ctor->setComdat(CtorComdat);
374 appendToGlobalCtors(M, Ctor, 0, Ctor);
375
376 IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator());
377 IRBCtor.CreateCall(
378 declareSanitizerInitFunction(M, "__hwasan_init_frames",
379 {Int8PtrTy, Int8PtrTy}),
380 {createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
381 createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
382 });
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000383
Peter Collingbourned3a3e4b2018-12-17 22:56:34 +0000384 // Create a zero-length global in __hwasan_frame so that the linker will
385 // always create start and stop symbols.
386 //
387 // N.B. If we ever start creating associated metadata in this pass this
388 // global will need to be associated with the ctor.
389 Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000390 M.getOrInsertGlobal("__hwasan", Int8Arr0Ty, [&] {
391 auto *GV = new GlobalVariable(
392 M, Int8Arr0Ty, /*isConstantGlobal=*/true, GlobalValue::PrivateLinkage,
393 Constant::getNullValue(Int8Arr0Ty), "__hwasan");
394 GV->setSection(getFrameSection());
395 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
396 GV->setComdat(CtorComdat);
397 appendToCompilerUsed(M, GV);
398 return GV;
399 });
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000400 }
401
Leonard Chan0cdd3b12019-05-14 21:17:21 +0000402 if (!TargetTriple.isAndroid()) {
403 Constant *C = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
404 auto *GV = new GlobalVariable(M, IntptrTy, /*isConstantGlobal=*/false,
405 GlobalValue::ExternalLinkage, nullptr,
406 "__hwasan_tls", nullptr,
407 GlobalVariable::InitialExecTLSModel);
408 appendToCompilerUsed(M, GV);
409 return GV;
410 });
411 ThreadPtrGlobal = cast<GlobalVariable>(C);
412 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000413}
414
415void HWAddressSanitizer::initializeCallbacks(Module &M) {
416 IRBuilder<> IRB(*C);
417 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
418 const std::string TypeStr = AccessIsWrite ? "store" : "load";
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000419 const std::string EndingStr = Recover ? "_noabort" : "";
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000420
James Y Knight13680222019-02-01 02:28:03 +0000421 HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(
422 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr,
423 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000424
425 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
426 AccessSizeIndex++) {
427 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
James Y Knight13680222019-02-01 02:28:03 +0000428 M.getOrInsertFunction(
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000429 ClMemoryAccessCallbackPrefix + TypeStr +
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000430 itostr(1ULL << AccessSizeIndex) + EndingStr,
James Y Knight13680222019-02-01 02:28:03 +0000431 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000432 }
433 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000434
James Y Knight13680222019-02-01 02:28:03 +0000435 HwasanTagMemoryFunc = M.getOrInsertFunction(
436 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy);
437 HwasanGenerateTagFunc =
438 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000439
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000440 ShadowGlobal = M.getOrInsertGlobal("__hwasan_shadow",
441 ArrayType::get(IRB.getInt8Ty(), 0));
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000442
443 const std::string MemIntrinCallbackPrefix =
444 CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix;
James Y Knight13680222019-02-01 02:28:03 +0000445 HWAsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove",
446 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
447 IRB.getInt8PtrTy(), IntptrTy);
448 HWAsanMemcpy = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memcpy",
449 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
450 IRB.getInt8PtrTy(), IntptrTy);
451 HWAsanMemset = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memset",
452 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
453 IRB.getInt32Ty(), IntptrTy);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000454
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000455 HWAsanHandleVfork =
456 M.getOrInsertFunction("__hwasan_handle_vfork", IRB.getVoidTy(), IntptrTy);
457
James Y Knight13680222019-02-01 02:28:03 +0000458 HwasanThreadEnterFunc =
459 M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy());
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000460}
461
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000462Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {
463 // An empty inline asm with input reg == output reg.
464 // An opaque no-op cast, basically.
465 InlineAsm *Asm = InlineAsm::get(
466 FunctionType::get(Int8PtrTy, {ShadowGlobal->getType()}, false),
467 StringRef(""), StringRef("=r,0"),
468 /*hasSideEffects=*/false);
469 return IRB.CreateCall(Asm, {ShadowGlobal}, ".hwasan.shadow");
470}
471
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000472Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000473 // Generate code only when dynamic addressing is needed.
474 if (Mapping.Offset != kDynamicShadowSentinel)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000475 return nullptr;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000476
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000477 if (Mapping.InGlobal) {
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000478 return getDynamicShadowIfunc(IRB);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000479 } else {
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000480 Value *GlobalDynamicAddress =
481 IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000482 kHwasanShadowMemoryDynamicAddress, Int8PtrTy);
James Y Knight14359ef2019-02-01 20:44:24 +0000483 return IRB.CreateLoad(Int8PtrTy, GlobalDynamicAddress);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000484 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000485}
486
487Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000488 bool *IsWrite,
489 uint64_t *TypeSize,
490 unsigned *Alignment,
491 Value **MaybeMask) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000492 // Skip memory accesses inserted by another instrumentation.
493 if (I->getMetadata("nosanitize")) return nullptr;
494
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000495 // Do not instrument the load fetching the dynamic shadow address.
496 if (LocalDynamicShadow == I)
497 return nullptr;
498
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000499 Value *PtrOperand = nullptr;
500 const DataLayout &DL = I->getModule()->getDataLayout();
501 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
502 if (!ClInstrumentReads) return nullptr;
503 *IsWrite = false;
504 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
505 *Alignment = LI->getAlignment();
506 PtrOperand = LI->getPointerOperand();
507 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
508 if (!ClInstrumentWrites) return nullptr;
509 *IsWrite = true;
510 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
511 *Alignment = SI->getAlignment();
512 PtrOperand = SI->getPointerOperand();
513 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
514 if (!ClInstrumentAtomics) return nullptr;
515 *IsWrite = true;
516 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
517 *Alignment = 0;
518 PtrOperand = RMW->getPointerOperand();
519 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
520 if (!ClInstrumentAtomics) return nullptr;
521 *IsWrite = true;
522 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
523 *Alignment = 0;
524 PtrOperand = XCHG->getPointerOperand();
525 }
526
527 if (PtrOperand) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000528 // Do not instrument accesses from different address spaces; we cannot deal
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000529 // with them.
530 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType());
531 if (PtrTy->getPointerAddressSpace() != 0)
532 return nullptr;
533
534 // Ignore swifterror addresses.
535 // swifterror memory addresses are mem2reg promoted by instruction
536 // selection. As such they cannot have regular uses like an instrumentation
537 // function and it makes no sense to track them as memory.
538 if (PtrOperand->isSwiftError())
539 return nullptr;
540 }
541
542 return PtrOperand;
543}
544
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000545static unsigned getPointerOperandIndex(Instruction *I) {
546 if (LoadInst *LI = dyn_cast<LoadInst>(I))
547 return LI->getPointerOperandIndex();
548 if (StoreInst *SI = dyn_cast<StoreInst>(I))
549 return SI->getPointerOperandIndex();
550 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I))
551 return RMW->getPointerOperandIndex();
552 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I))
553 return XCHG->getPointerOperandIndex();
554 report_fatal_error("Unexpected instruction");
555 return -1;
556}
557
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000558static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
559 size_t Res = countTrailingZeros(TypeSize / 8);
560 assert(Res < kNumberOfAccessSizes);
561 return Res;
562}
563
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000564void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
565 if (TargetTriple.isAArch64())
566 return;
567
568 IRBuilder<> IRB(I);
569 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
570 Value *UntaggedPtr =
571 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType());
572 I->setOperand(getPointerOperandIndex(I), UntaggedPtr);
573}
574
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000575Value *HWAddressSanitizer::shadowBase() {
576 if (LocalDynamicShadow)
577 return LocalDynamicShadow;
578 return ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, Mapping.Offset),
579 Int8PtrTy);
580}
581
582Value *HWAddressSanitizer::memToShadow(Value *Mem, IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000583 // Mem >> Scale
584 Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale);
585 if (Mapping.Offset == 0)
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000586 return IRB.CreateIntToPtr(Shadow, Int8PtrTy);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000587 // (Mem >> Scale) + Offset
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000588 return IRB.CreateGEP(Int8Ty, shadowBase(), Shadow);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000589}
590
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000591void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000592 unsigned AccessSizeIndex,
593 Instruction *InsertBefore) {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000594 const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex;
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000595 IRBuilder<> IRB(InsertBefore);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000596
597 if (!ClInlineAllChecks && TargetTriple.isAArch64() &&
598 TargetTriple.isOSBinFormatELF() && !Recover) {
599 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
600 Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy);
601 IRB.CreateCall(
602 Intrinsic::getDeclaration(M, Intrinsic::hwasan_check_memaccess),
603 {shadowBase(), Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
604 return;
605 }
606
607 Value *PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000608 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift),
609 IRB.getInt8Ty());
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000610 Value *AddrLong = untagPointer(IRB, PtrLong);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000611 Value *Shadow = memToShadow(AddrLong, IRB);
James Y Knight14359ef2019-02-01 20:44:24 +0000612 Value *MemTag = IRB.CreateLoad(Int8Ty, Shadow);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000613 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag);
614
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000615 int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ?
616 ClMatchAllTag : (CompileKernel ? 0xFF : -1);
617 if (matchAllTag != -1) {
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000618 Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag,
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000619 ConstantInt::get(PtrTag->getType(), matchAllTag));
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000620 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);
621 }
622
Chandler Carruth4a2d58e2018-10-15 09:34:05 +0000623 Instruction *CheckTerm =
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000624 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000625 MDBuilder(*C).createBranchWeights(1, 100000));
626
627 IRB.SetInsertPoint(CheckTerm);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000628 InlineAsm *Asm;
629 switch (TargetTriple.getArch()) {
630 case Triple::x86_64:
631 // The signal handler will find the data address in rdi.
632 Asm = InlineAsm::get(
633 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
634 "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)",
635 "{rdi}",
636 /*hasSideEffects=*/true);
637 break;
638 case Triple::aarch64:
639 case Triple::aarch64_be:
640 // The signal handler will find the data address in x0.
641 Asm = InlineAsm::get(
642 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
643 "brk #" + itostr(0x900 + AccessInfo),
644 "{x0}",
645 /*hasSideEffects=*/true);
646 break;
647 default:
648 report_fatal_error("unsupported architecture");
649 }
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000650 IRB.CreateCall(Asm, PtrLong);
651}
652
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000653void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
654 IRBuilder<> IRB(MI);
655 if (isa<MemTransferInst>(MI)) {
656 IRB.CreateCall(
657 isa<MemMoveInst>(MI) ? HWAsanMemmove : HWAsanMemcpy,
658 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
659 IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
660 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
661 } else if (isa<MemSetInst>(MI)) {
662 IRB.CreateCall(
663 HWAsanMemset,
664 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
665 IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
666 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
667 }
668 MI->eraseFromParent();
669}
670
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000671bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000672 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000673 bool IsWrite = false;
674 unsigned Alignment = 0;
675 uint64_t TypeSize = 0;
676 Value *MaybeMask = nullptr;
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000677
678 if (ClInstrumentMemIntrinsics && isa<MemIntrinsic>(I)) {
679 instrumentMemIntrinsic(cast<MemIntrinsic>(I));
680 return true;
681 }
682
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000683 Value *Addr =
684 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask);
685
686 if (!Addr)
687 return false;
688
689 if (MaybeMask)
690 return false; //FIXME
691
692 IRBuilder<> IRB(I);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000693 if (isPowerOf2_64(TypeSize) &&
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000694 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) &&
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000695 (Alignment >= (1UL << Mapping.Scale) || Alignment == 0 ||
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000696 Alignment >= TypeSize / 8)) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000697 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000698 if (ClInstrumentWithCalls) {
699 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000700 IRB.CreatePointerCast(Addr, IntptrTy));
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000701 } else {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000702 instrumentMemAccessInline(Addr, IsWrite, AccessSizeIndex, I);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000703 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000704 } else {
705 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000706 {IRB.CreatePointerCast(Addr, IntptrTy),
707 ConstantInt::get(IntptrTy, TypeSize / 8)});
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000708 }
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000709 untagPointerOperand(I, Addr);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000710
711 return true;
712}
713
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000714static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) {
715 uint64_t ArraySize = 1;
716 if (AI.isArrayAllocation()) {
717 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize());
718 assert(CI && "non-constant array size");
719 ArraySize = CI->getZExtValue();
720 }
721 Type *Ty = AI.getAllocatedType();
722 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty);
723 return SizeInBytes * ArraySize;
724}
725
726bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI,
727 Value *Tag) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000728 size_t Size = (getAllocaSizeInBytes(*AI) + Mapping.getAllocaAlignment() - 1) &
729 ~(Mapping.getAllocaAlignment() - 1);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000730
731 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty());
732 if (ClInstrumentWithCalls) {
733 IRB.CreateCall(HwasanTagMemoryFunc,
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000734 {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag,
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000735 ConstantInt::get(IntptrTy, Size)});
736 } else {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000737 size_t ShadowSize = Size >> Mapping.Scale;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000738 Value *ShadowPtr = memToShadow(IRB.CreatePointerCast(AI, IntptrTy), IRB);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000739 // If this memset is not inlined, it will be intercepted in the hwasan
740 // runtime library. That's OK, because the interceptor skips the checks if
741 // the address is in the shadow region.
742 // FIXME: the interceptor is not as fast as real memset. Consider lowering
743 // llvm.memset right here into either a sequence of stores, or a call to
744 // hwasan_tag_memory.
745 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1);
746 }
747 return true;
748}
749
750static unsigned RetagMask(unsigned AllocaNo) {
751 // A list of 8-bit numbers that have at most one run of non-zero bits.
752 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
753 // masks.
754 // The list does not include the value 255, which is used for UAR.
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000755 //
756 // Because we are more likely to use earlier elements of this list than later
757 // ones, it is sorted in increasing order of probability of collision with a
758 // mask allocated (temporally) nearby. The program that generated this list
759 // can be found at:
760 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
761 static unsigned FastMasks[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
762 48, 16, 120, 248, 56, 24, 8, 124, 252,
763 60, 28, 12, 4, 126, 254, 62, 30, 14,
764 6, 2, 127, 63, 31, 15, 7, 3, 1};
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000765 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
766}
767
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000768Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
769 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
770}
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000771
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000772Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
773 if (ClGenerateTagsWithCalls)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000774 return getNextTagWithCall(IRB);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000775 if (StackBaseTag)
776 return StackBaseTag;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000777 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
778 // first).
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000779 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
780 auto GetStackPointerFn =
781 Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
782 Value *StackPointer = IRB.CreateCall(
783 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())});
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000784
785 // Extract some entropy from the stack pointer for the tags.
786 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
787 // between functions).
788 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy);
789 Value *StackTag =
790 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20),
791 "hwasan.stack.base.tag");
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000792 return StackTag;
793}
794
795Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
796 AllocaInst *AI, unsigned AllocaNo) {
797 if (ClGenerateTagsWithCalls)
798 return getNextTagWithCall(IRB);
799 return IRB.CreateXor(StackTag,
800 ConstantInt::get(IntptrTy, RetagMask(AllocaNo)));
801}
802
803Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
Alex Shlyapnikov788764c2018-06-29 20:20:17 +0000804 if (ClUARRetagToZero)
805 return ConstantInt::get(IntptrTy, 0);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000806 if (ClGenerateTagsWithCalls)
807 return getNextTagWithCall(IRB);
808 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
809}
810
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000811// Add a tag to an address.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000812Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
813 Value *PtrLong, Value *Tag) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000814 Value *TaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000815 if (CompileKernel) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000816 // Kernel addresses have 0xFF in the most significant byte.
817 Value *ShiftedTag = IRB.CreateOr(
818 IRB.CreateShl(Tag, kPointerTagShift),
819 ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1));
820 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
821 } else {
822 // Userspace can simply do OR (tag << 56);
823 Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift);
824 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
825 }
826 return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
827}
828
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000829// Remove tag from an address.
830Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
831 Value *UntaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000832 if (CompileKernel) {
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000833 // Kernel addresses have 0xFF in the most significant byte.
834 UntaggedPtrLong = IRB.CreateOr(PtrLong,
835 ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift));
836 } else {
837 // Userspace addresses have 0x00.
838 UntaggedPtrLong = IRB.CreateAnd(PtrLong,
839 ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift)));
840 }
841 return UntaggedPtrLong;
842}
843
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000844Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) {
845 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
846 if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) {
Evgeniy Stepanov0184c532019-01-05 00:44:58 +0000847 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
848 // in Bionic's libc/private/bionic_tls.h.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000849 Function *ThreadPointerFunc =
850 Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
851 Value *SlotPtr = IRB.CreatePointerCast(
James Y Knight77160752019-02-01 20:44:47 +0000852 IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
853 IRB.CreateCall(ThreadPointerFunc), 0x30),
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000854 Ty->getPointerTo(0));
855 return SlotPtr;
856 }
857 if (ThreadPtrGlobal)
858 return ThreadPtrGlobal;
859
860
861 return nullptr;
862}
863
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000864// Creates a string with a description of the stack frame (set of Allocas).
865// The string is intended to be human readable.
866// The current form is: Size1 Name1; Size2 Name2; ...
867std::string
868HWAddressSanitizer::createFrameString(ArrayRef<AllocaInst *> Allocas) {
869 std::ostringstream Descr;
870 for (auto AI : Allocas)
871 Descr << getAllocaSizeInBytes(*AI) << " " << AI->getName().str() << "; ";
872 return Descr.str();
873}
874
875// Creates a global in the frame section which consists of two pointers:
876// the function PC and the frame string constant.
877void HWAddressSanitizer::createFrameGlobal(Function &F,
878 const std::string &FrameString) {
879 Module &M = *F.getParent();
880 auto DescrGV = createPrivateGlobalForString(M, FrameString, true);
881 auto PtrPairTy = StructType::get(F.getType(), DescrGV->getType());
882 auto GV = new GlobalVariable(
883 M, PtrPairTy, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage,
884 ConstantStruct::get(PtrPairTy, (Constant *)&F, (Constant *)DescrGV),
885 "__hwasan");
886 GV->setSection(getFrameSection());
887 appendToCompilerUsed(M, GV);
888 // 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 +0000889 if (auto Comdat =
890 GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
891 GV->setComdat(Comdat);
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000892}
893
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000894void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
895 if (!Mapping.InTls) {
896 LocalDynamicShadow = getDynamicShadowNonTls(IRB);
897 return;
898 }
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000899
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000900 if (!WithFrameRecord && TargetTriple.isAndroid()) {
901 LocalDynamicShadow = getDynamicShadowIfunc(IRB);
902 return;
903 }
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000904
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000905 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
906 assert(SlotPtr);
907
James Y Knight14359ef2019-02-01 20:44:24 +0000908 Instruction *ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000909
910 Function *F = IRB.GetInsertBlock()->getParent();
911 if (F->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") {
912 Value *ThreadLongEqZero =
913 IRB.CreateICmpEQ(ThreadLong, ConstantInt::get(IntptrTy, 0));
914 auto *Br = cast<BranchInst>(SplitBlockAndInsertIfThen(
915 ThreadLongEqZero, cast<Instruction>(ThreadLongEqZero)->getNextNode(),
916 false, MDBuilder(*C).createBranchWeights(1, 100000)));
917
918 IRB.SetInsertPoint(Br);
919 // FIXME: This should call a new runtime function with a custom calling
920 // convention to avoid needing to spill all arguments here.
921 IRB.CreateCall(HwasanThreadEnterFunc);
James Y Knight14359ef2019-02-01 20:44:24 +0000922 LoadInst *ReloadThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000923
924 IRB.SetInsertPoint(&*Br->getSuccessor(0)->begin());
925 PHINode *ThreadLongPhi = IRB.CreatePHI(IntptrTy, 2);
926 ThreadLongPhi->addIncoming(ThreadLong, ThreadLong->getParent());
927 ThreadLongPhi->addIncoming(ReloadThreadLong, ReloadThreadLong->getParent());
928 ThreadLong = ThreadLongPhi;
929 }
930
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000931 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI.
932 Value *ThreadLongMaybeUntagged =
933 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong);
934
935 if (WithFrameRecord) {
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000936 StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
937
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000938 // Prepare ring buffer data.
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000939 Value *PC;
940 if (TargetTriple.getArch() == Triple::aarch64)
941 PC = readRegister(IRB, "pc");
942 else
943 PC = IRB.CreatePtrToInt(F, IntptrTy);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000944 auto GetStackPointerFn =
945 Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress);
946 Value *SP = IRB.CreatePtrToInt(
947 IRB.CreateCall(GetStackPointerFn,
948 {Constant::getNullValue(IRB.getInt32Ty())}),
949 IntptrTy);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000950 // Mix SP and PC.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000951 // Assumptions:
952 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
953 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
954 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this:
955 // 0xSSSSPPPPPPPPPPPP
956 SP = IRB.CreateShl(SP, 44);
957
958 // Store data to ring buffer.
959 Value *RecordPtr =
960 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IntptrTy->getPointerTo(0));
961 IRB.CreateStore(IRB.CreateOr(PC, SP), RecordPtr);
962
963 // Update the ring buffer. Top byte of ThreadLong defines the size of the
964 // buffer in pages, it must be a power of two, and the start of the buffer
965 // must be aligned by twice that much. Therefore wrap around of the ring
966 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
967 // The use of AShr instead of LShr is due to
968 // https://bugs.llvm.org/show_bug.cgi?id=39030
969 // Runtime library makes sure not to use the highest bit.
970 Value *WrapMask = IRB.CreateXor(
971 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
972 ConstantInt::get(IntptrTy, (uint64_t)-1));
973 Value *ThreadLongNew = IRB.CreateAnd(
974 IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
975 IRB.CreateStore(ThreadLongNew, SlotPtr);
976 }
977
978 // Get shadow base address by aligning RecordPtr up.
979 // Note: this is not correct if the pointer is already aligned.
980 // Runtime library will make sure this never happens.
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000981 LocalDynamicShadow = IRB.CreateAdd(
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000982 IRB.CreateOr(
983 ThreadLongMaybeUntagged,
984 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
985 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
Peter Collingbourned57f7cc2019-06-17 23:39:51 +0000986 LocalDynamicShadow = IRB.CreateIntToPtr(LocalDynamicShadow, Int8PtrTy);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000987}
988
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000989Value *HWAddressSanitizer::readRegister(IRBuilder<> &IRB, StringRef Name) {
990 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000991 Function *ReadRegister =
992 Intrinsic::getDeclaration(M, Intrinsic::read_register, IntptrTy);
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000993 MDNode *MD = MDNode::get(*C, {MDString::get(*C, Name)});
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000994 Value *Args[] = {MetadataAsValue::get(*C, MD)};
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000995 return IRB.CreateCall(ReadRegister, Args);
996}
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +0000997
Peter Collingbourne5378afc2019-06-27 23:24:07 +0000998bool HWAddressSanitizer::instrumentLandingPads(
999 SmallVectorImpl<Instruction *> &LandingPadVec) {
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001000 for (auto *LP : LandingPadVec) {
1001 IRBuilder<> IRB(LP->getNextNode());
Peter Collingbourne5378afc2019-06-27 23:24:07 +00001002 IRB.CreateCall(
1003 HWAsanHandleVfork,
1004 {readRegister(IRB, (TargetTriple.getArch() == Triple::x86_64) ? "rsp"
1005 : "sp")});
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001006 }
1007 return true;
1008}
1009
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001010bool HWAddressSanitizer::instrumentStack(
1011 SmallVectorImpl<AllocaInst *> &Allocas,
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001012 DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001013 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001014 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
1015 // alloca addresses using that. Unfortunately, offsets are not known yet
1016 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
1017 // temp, shift-OR it into each alloca address and xor with the retag mask.
1018 // This generates one extra instruction per alloca use.
1019 for (unsigned N = 0; N < Allocas.size(); ++N) {
1020 auto *AI = Allocas[N];
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001021 IRBuilder<> IRB(AI->getNextNode());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001022
1023 // Replace uses of the alloca with tagged address.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001024 Value *Tag = getAllocaTag(IRB, StackTag, AI, N);
1025 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +00001026 Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001027 std::string Name =
1028 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +00001029 Replacement->setName(Name + ".hwasan");
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001030
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001031 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001032 Use &U = *UI++;
1033 if (U.getUser() != AILong)
1034 U.set(Replacement);
1035 }
1036
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001037 for (auto *DDI : AllocaDeclareMap.lookup(AI)) {
1038 DIExpression *OldExpr = DDI->getExpression();
1039 DIExpression *NewExpr = DIExpression::append(
1040 OldExpr, {dwarf::DW_OP_LLVM_tag_offset, RetagMask(N)});
1041 DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr));
1042 }
1043
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001044 tagAlloca(IRB, AI, Tag);
1045
1046 for (auto RI : RetVec) {
1047 IRB.SetInsertPoint(RI);
1048
1049 // Re-tag alloca memory with the special UAR tag.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +00001050 Value *Tag = getUARTag(IRB, StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001051 tagAlloca(IRB, AI, Tag);
1052 }
1053 }
1054
1055 return true;
1056}
1057
1058bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
1059 return (AI.getAllocatedType()->isSized() &&
1060 // FIXME: instrument dynamic allocas, too
1061 AI.isStaticAlloca() &&
1062 // alloca() may be called with 0 size, ignore it.
1063 getAllocaSizeInBytes(AI) > 0 &&
1064 // We are only interested in allocas not promotable to registers.
1065 // Promotable allocas are common under -O0.
1066 !isAllocaPromotable(&AI) &&
1067 // inalloca allocas are not treated as static, and we don't want
1068 // dynamic alloca instrumentation for them as well.
1069 !AI.isUsedWithInAlloca() &&
1070 // swifterror allocas are register promoted by ISel
1071 !AI.isSwiftError());
1072}
1073
Leonard Chan0cdd3b12019-05-14 21:17:21 +00001074bool HWAddressSanitizer::sanitizeFunction(Function &F) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001075 if (&F == HwasanCtorFunction)
1076 return false;
1077
1078 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
1079 return false;
1080
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001081 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001082
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001083 SmallVector<Instruction*, 16> ToInstrument;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001084 SmallVector<AllocaInst*, 8> AllocasToInstrument;
1085 SmallVector<Instruction*, 8> RetVec;
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001086 SmallVector<Instruction*, 8> LandingPadVec;
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001087 DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> AllocaDeclareMap;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001088 for (auto &BB : F) {
1089 for (auto &Inst : BB) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001090 if (ClInstrumentStack)
1091 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
1092 // Realign all allocas. We don't want small uninteresting allocas to
1093 // hide in instrumented alloca's padding.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001094 if (AI->getAlignment() < Mapping.getAllocaAlignment())
1095 AI->setAlignment(Mapping.getAllocaAlignment());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001096 // Instrument some of them.
1097 if (isInterestingAlloca(*AI))
1098 AllocasToInstrument.push_back(AI);
1099 continue;
1100 }
1101
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001102 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) ||
1103 isa<CleanupReturnInst>(Inst))
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001104 RetVec.push_back(&Inst);
1105
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001106 if (auto *DDI = dyn_cast<DbgDeclareInst>(&Inst))
1107 if (auto *Alloca = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
1108 AllocaDeclareMap[Alloca].push_back(DDI);
1109
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001110 if (ClInstrumentLandingPads && isa<LandingPadInst>(Inst))
1111 LandingPadVec.push_back(&Inst);
1112
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001113 Value *MaybeMask = nullptr;
1114 bool IsWrite;
1115 unsigned Alignment;
1116 uint64_t TypeSize;
1117 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize,
1118 &Alignment, &MaybeMask);
1119 if (Addr || isa<MemIntrinsic>(Inst))
1120 ToInstrument.push_back(&Inst);
1121 }
1122 }
1123
Evgeniy Stepanov7f281b22019-05-16 23:54:41 +00001124 initializeCallbacks(*F.getParent());
1125
1126 if (!LandingPadVec.empty())
1127 instrumentLandingPads(LandingPadVec);
1128
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001129 if (AllocasToInstrument.empty() && ToInstrument.empty())
1130 return false;
1131
Kostya Serebryanyaf955972018-10-23 00:50:40 +00001132 if (ClCreateFrameDescriptions && !AllocasToInstrument.empty())
1133 createFrameGlobal(F, createFrameString(AllocasToInstrument));
1134
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001135
1136 assert(!LocalDynamicShadow);
1137
1138 Instruction *InsertPt = &*F.getEntryBlock().begin();
1139 IRBuilder<> EntryIRB(InsertPt);
Peter Collingbourned57f7cc2019-06-17 23:39:51 +00001140 emitPrologue(EntryIRB,
1141 /*WithFrameRecord*/ ClRecordStackHistory &&
1142 !AllocasToInstrument.empty());
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001143
1144 bool Changed = false;
1145 if (!AllocasToInstrument.empty()) {
1146 Value *StackTag =
1147 ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB);
Peter Collingbournefb9ce102019-06-17 23:39:41 +00001148 Changed |= instrumentStack(AllocasToInstrument, AllocaDeclareMap, RetVec,
1149 StackTag);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001150 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001151
Peter Collingbourne1a8acfb2019-01-25 02:08:46 +00001152 // If we split the entry block, move any allocas that were originally in the
1153 // entry block back into the entry block so that they aren't treated as
1154 // dynamic allocas.
1155 if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {
1156 InsertPt = &*F.getEntryBlock().begin();
1157 for (auto II = EntryIRB.GetInsertBlock()->begin(),
1158 IE = EntryIRB.GetInsertBlock()->end();
1159 II != IE;) {
1160 Instruction *I = &*II++;
1161 if (auto *AI = dyn_cast<AllocaInst>(I))
1162 if (isa<ConstantInt>(AI->getArraySize()))
1163 I->moveBefore(InsertPt);
1164 }
1165 }
1166
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001167 for (auto Inst : ToInstrument)
1168 Changed |= instrumentMemAccess(Inst);
1169
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001170 LocalDynamicShadow = nullptr;
Peter Collingbourned57f7cc2019-06-17 23:39:51 +00001171 StackBaseTag = nullptr;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001172
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001173 return Changed;
1174}
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001175
1176void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001177 Scale = kDefaultShadowScale;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001178 if (ClMappingOffset.getNumOccurrences() > 0) {
1179 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001180 InTls = false;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001181 Offset = ClMappingOffset;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001182 } else if (ClEnableKhwasan || ClInstrumentWithCalls) {
1183 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001184 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001185 Offset = 0;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001186 } else if (ClWithIfunc) {
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001187 InGlobal = true;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001188 InTls = false;
1189 Offset = kDynamicShadowSentinel;
1190 } else if (ClWithTls) {
1191 InGlobal = false;
1192 InTls = true;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001193 Offset = kDynamicShadowSentinel;
1194 } else {
1195 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001196 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001197 Offset = kDynamicShadowSentinel;
1198 }
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001199}