blob: 254e9ecd3eab2f9d263fea5e03fff5253691535f [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
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/ADT/Triple.h"
18#include "llvm/IR/Attributes.h"
19#include "llvm/IR/BasicBlock.h"
20#include "llvm/IR/Constant.h"
21#include "llvm/IR/Constants.h"
22#include "llvm/IR/DataLayout.h"
23#include "llvm/IR/DerivedTypes.h"
24#include "llvm/IR/Function.h"
25#include "llvm/IR/IRBuilder.h"
26#include "llvm/IR/InlineAsm.h"
27#include "llvm/IR/InstVisitor.h"
28#include "llvm/IR/Instruction.h"
29#include "llvm/IR/Instructions.h"
30#include "llvm/IR/IntrinsicInst.h"
31#include "llvm/IR/Intrinsics.h"
32#include "llvm/IR/LLVMContext.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000033#include "llvm/IR/MDBuilder.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000034#include "llvm/IR/Module.h"
35#include "llvm/IR/Type.h"
36#include "llvm/IR/Value.h"
37#include "llvm/Pass.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/Debug.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000041#include "llvm/Support/raw_ostream.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000042#include "llvm/Transforms/Instrumentation.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000043#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000044#include "llvm/Transforms/Utils/ModuleUtils.h"
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000045#include "llvm/Transforms/Utils/PromoteMemToReg.h"
Kostya Serebryanyaf955972018-10-23 00:50:40 +000046#include <sstream>
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000047
48using namespace llvm;
49
50#define DEBUG_TYPE "hwasan"
51
52static const char *const kHwasanModuleCtorName = "hwasan.module_ctor";
53static const char *const kHwasanInitName = "__hwasan_init";
54
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +000055static const char *const kHwasanShadowMemoryDynamicAddress =
56 "__hwasan_shadow_memory_dynamic_address";
57
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000058// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
59static const size_t kNumberOfAccessSizes = 5;
60
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +000061static const size_t kDefaultShadowScale = 4;
62static const uint64_t kDynamicShadowSentinel =
63 std::numeric_limits<uint64_t>::max();
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +000064static const unsigned kPointerTagShift = 56;
65
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +000066static const unsigned kShadowBaseAlignment = 32;
67
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000068static cl::opt<std::string> ClMemoryAccessCallbackPrefix(
69 "hwasan-memory-access-callback-prefix",
70 cl::desc("Prefix for memory access callbacks"), cl::Hidden,
71 cl::init("__hwasan_"));
72
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +000073static cl::opt<bool>
74 ClInstrumentWithCalls("hwasan-instrument-with-calls",
75 cl::desc("instrument reads and writes with callbacks"),
76 cl::Hidden, cl::init(false));
77
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +000078static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads",
79 cl::desc("instrument read instructions"),
80 cl::Hidden, cl::init(true));
81
82static cl::opt<bool> ClInstrumentWrites(
83 "hwasan-instrument-writes", cl::desc("instrument write instructions"),
84 cl::Hidden, cl::init(true));
85
86static cl::opt<bool> ClInstrumentAtomics(
87 "hwasan-instrument-atomics",
88 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
89 cl::init(true));
90
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +000091static cl::opt<bool> ClRecover(
92 "hwasan-recover",
93 cl::desc("Enable recovery mode (continue-after-error)."),
94 cl::Hidden, cl::init(false));
95
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +000096static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
97 cl::desc("instrument stack (allocas)"),
98 cl::Hidden, cl::init(true));
99
Alex Shlyapnikov788764c2018-06-29 20:20:17 +0000100static cl::opt<bool> ClUARRetagToZero(
101 "hwasan-uar-retag-to-zero",
102 cl::desc("Clear alloca tags before returning from the function to allow "
103 "non-instrumented and instrumented function calls mix. When set "
104 "to false, allocas are retagged before returning from the "
105 "function to detect use after return."),
106 cl::Hidden, cl::init(true));
107
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000108static cl::opt<bool> ClGenerateTagsWithCalls(
109 "hwasan-generate-tags-with-calls",
110 cl::desc("generate new tags with runtime library calls"), cl::Hidden,
111 cl::init(false));
112
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000113static cl::opt<int> ClMatchAllTag(
114 "hwasan-match-all-tag",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000115 cl::desc("don't report bad accesses via pointers with this tag"),
116 cl::Hidden, cl::init(-1));
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000117
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000118static cl::opt<bool> ClEnableKhwasan(
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000119 "hwasan-kernel",
120 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000121 cl::Hidden, cl::init(false));
122
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000123// These flags allow to change the shadow mapping and control how shadow memory
124// is accessed. The shadow mapping looks like:
125// Shadow = (Mem >> scale) + offset
126
Fangrui Songb5f39842019-04-24 02:40:20 +0000127static cl::opt<uint64_t>
128 ClMappingOffset("hwasan-mapping-offset",
129 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
130 cl::Hidden, cl::init(0));
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000131
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +0000132static cl::opt<bool>
133 ClWithIfunc("hwasan-with-ifunc",
134 cl::desc("Access dynamic shadow through an ifunc global on "
135 "platforms that support this"),
136 cl::Hidden, cl::init(false));
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000137
138static cl::opt<bool> ClWithTls(
139 "hwasan-with-tls",
140 cl::desc("Access dynamic shadow through an thread-local pointer on "
141 "platforms that support this"),
142 cl::Hidden, cl::init(true));
143
144static cl::opt<bool>
145 ClRecordStackHistory("hwasan-record-stack-history",
146 cl::desc("Record stack frames with tagged allocations "
147 "in a thread-local ring buffer"),
148 cl::Hidden, cl::init(true));
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000149static cl::opt<bool>
150 ClCreateFrameDescriptions("hwasan-create-frame-descriptions",
151 cl::desc("create static frame descriptions"),
152 cl::Hidden, cl::init(true));
153
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000154static cl::opt<bool>
155 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
156 cl::desc("instrument memory intrinsics"),
Eugene Leviant4dc3a3f2018-12-24 16:02:48 +0000157 cl::Hidden, cl::init(true));
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000158
159static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
160 cl::desc("inline all checks"),
161 cl::Hidden, cl::init(false));
162
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000163namespace {
164
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000165/// An instrumentation pass implementing detection of addressability bugs
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000166/// using tagged pointers.
167class HWAddressSanitizer : public FunctionPass {
168public:
169 // Pass identification, replacement for typeid.
170 static char ID;
171
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000172 explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false)
173 : FunctionPass(ID) {
174 this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover;
175 this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ?
176 ClEnableKhwasan : CompileKernel;
177 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000178
179 StringRef getPassName() const override { return "HWAddressSanitizer"; }
180
181 bool runOnFunction(Function &F) override;
182 bool doInitialization(Module &M) override;
183
184 void initializeCallbacks(Module &M);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000185
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000186 Value *getDynamicShadowIfunc(IRBuilder<> &IRB);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000187 Value *getDynamicShadowNonTls(IRBuilder<> &IRB);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000188
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000189 void untagPointerOperand(Instruction *I, Value *Addr);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000190 Value *shadowBase();
191 Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
192 void instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000193 unsigned AccessSizeIndex,
194 Instruction *InsertBefore);
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000195 void instrumentMemIntrinsic(MemIntrinsic *MI);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000196 bool instrumentMemAccess(Instruction *I);
197 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
198 uint64_t *TypeSize, unsigned *Alignment,
199 Value **MaybeMask);
200
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000201 bool isInterestingAlloca(const AllocaInst &AI);
202 bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000203 Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000204 Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000205 bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas,
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000206 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000207 Value *getNextTagWithCall(IRBuilder<> &IRB);
208 Value *getStackBaseTag(IRBuilder<> &IRB);
209 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI,
210 unsigned AllocaNo);
211 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000212
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000213 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
214 Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
215
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000216private:
217 LLVMContext *C;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000218 std::string CurModuleUniqueId;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000219 Triple TargetTriple;
James Y Knight13680222019-02-01 02:28:03 +0000220 FunctionCallee HWAsanMemmove, HWAsanMemcpy, HWAsanMemset;
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000221
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000222 // Frame description is a way to pass names/sizes of local variables
223 // to the run-time w/o adding extra executable code in every function.
224 // We do this by creating a separate section with {PC,Descr} pairs and passing
225 // the section beg/end to __hwasan_init_frames() at module init time.
226 std::string createFrameString(ArrayRef<AllocaInst*> Allocas);
227 void createFrameGlobal(Function &F, const std::string &FrameString);
228 // Get the section name for frame descriptions. Currently ELF-only.
229 const char *getFrameSection() { return "__hwasan_frames"; }
230 const char *getFrameSectionBeg() { return "__start___hwasan_frames"; }
231 const char *getFrameSectionEnd() { return "__stop___hwasan_frames"; }
232 GlobalVariable *createFrameSectionBound(Module &M, Type *Ty,
233 const char *Name) {
234 auto GV = new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
235 nullptr, Name);
236 GV->setVisibility(GlobalValue::HiddenVisibility);
237 return GV;
238 }
239
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000240 /// This struct defines the shadow mapping using the rule:
241 /// shadow = (mem >> Scale) + Offset.
242 /// If InGlobal is true, then
243 /// extern char __hwasan_shadow[];
244 /// shadow = (mem >> Scale) + &__hwasan_shadow
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000245 /// If InTls is true, then
246 /// extern char *__hwasan_tls;
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000247 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000248 struct ShadowMapping {
249 int Scale;
250 uint64_t Offset;
251 bool InGlobal;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000252 bool InTls;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000253
254 void init(Triple &TargetTriple);
255 unsigned getAllocaAlignment() const { return 1U << Scale; }
256 };
257 ShadowMapping Mapping;
258
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000259 Type *IntptrTy;
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000260 Type *Int8PtrTy;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000261 Type *Int8Ty;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000262 Type *Int32Ty;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000263
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000264 bool CompileKernel;
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000265 bool Recover;
266
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000267 Function *HwasanCtorFunction;
268
James Y Knight13680222019-02-01 02:28:03 +0000269 FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
270 FunctionCallee HwasanMemoryAccessCallbackSized[2];
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000271
James Y Knight13680222019-02-01 02:28:03 +0000272 FunctionCallee HwasanTagMemoryFunc;
273 FunctionCallee HwasanGenerateTagFunc;
274 FunctionCallee HwasanThreadEnterFunc;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000275
276 Constant *ShadowGlobal;
277
278 Value *LocalDynamicShadow = nullptr;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000279 GlobalValue *ThreadPtrGlobal = nullptr;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000280};
281
282} // end anonymous namespace
283
284char HWAddressSanitizer::ID = 0;
285
286INITIALIZE_PASS_BEGIN(
287 HWAddressSanitizer, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000288 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
289 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000290INITIALIZE_PASS_END(
291 HWAddressSanitizer, "hwasan",
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000292 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
293 false)
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000294
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000295FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel,
296 bool Recover) {
297 assert(!CompileKernel || Recover);
298 return new HWAddressSanitizer(CompileKernel, Recover);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000299}
300
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000301/// Module-level initialization.
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000302///
303/// inserts a call to __hwasan_init to the module's constructor list.
304bool HWAddressSanitizer::doInitialization(Module &M) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000305 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000306 auto &DL = M.getDataLayout();
307
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000308 TargetTriple = Triple(M.getTargetTriple());
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000309
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000310 Mapping.init(TargetTriple);
311
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000312 C = &(M.getContext());
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000313 CurModuleUniqueId = getUniqueModuleId(&M);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000314 IRBuilder<> IRB(*C);
315 IntptrTy = IRB.getIntPtrTy(DL);
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000316 Int8PtrTy = IRB.getInt8PtrTy();
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000317 Int8Ty = IRB.getInt8Ty();
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000318 Int32Ty = IRB.getInt32Ty();
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000319
Benjamin Kramerbfc1d972018-01-18 14:19:04 +0000320 HwasanCtorFunction = nullptr;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000321 if (!CompileKernel) {
Evgeniy Stepanov5bd669d2018-01-17 23:24:38 +0000322 std::tie(HwasanCtorFunction, std::ignore) =
323 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName,
324 kHwasanInitName,
325 /*InitArgTypes=*/{},
326 /*InitArgs=*/{});
Peter Collingbourned3a3e4b2018-12-17 22:56:34 +0000327 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
328 HwasanCtorFunction->setComdat(CtorComdat);
329 appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction);
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000330
Peter Collingbourned3a3e4b2018-12-17 22:56:34 +0000331 // Create a zero-length global in __hwasan_frame so that the linker will
332 // always create start and stop symbols.
333 //
334 // N.B. If we ever start creating associated metadata in this pass this
335 // global will need to be associated with the ctor.
336 Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
337 auto GV =
338 new GlobalVariable(M, Int8Arr0Ty, /*isConstantGlobal*/ true,
339 GlobalVariable::PrivateLinkage,
340 Constant::getNullValue(Int8Arr0Ty), "__hwasan");
341 GV->setSection(getFrameSection());
342 GV->setComdat(CtorComdat);
343 appendToCompilerUsed(M, GV);
344
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000345 IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator());
346 IRBCtor.CreateCall(
347 declareSanitizerInitFunction(M, "__hwasan_init_frames",
348 {Int8PtrTy, Int8PtrTy}),
349 {createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()),
350 createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())});
351 }
352
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000353 if (!TargetTriple.isAndroid())
354 appendToCompilerUsed(
355 M, ThreadPtrGlobal = new GlobalVariable(
356 M, IntptrTy, false, GlobalVariable::ExternalLinkage, nullptr,
357 "__hwasan_tls", nullptr, GlobalVariable::InitialExecTLSModel));
358
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000359 return true;
360}
361
362void HWAddressSanitizer::initializeCallbacks(Module &M) {
363 IRBuilder<> IRB(*C);
364 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
365 const std::string TypeStr = AccessIsWrite ? "store" : "load";
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000366 const std::string EndingStr = Recover ? "_noabort" : "";
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000367
James Y Knight13680222019-02-01 02:28:03 +0000368 HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(
369 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr,
370 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000371
372 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
373 AccessSizeIndex++) {
374 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
James Y Knight13680222019-02-01 02:28:03 +0000375 M.getOrInsertFunction(
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000376 ClMemoryAccessCallbackPrefix + TypeStr +
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000377 itostr(1ULL << AccessSizeIndex) + EndingStr,
James Y Knight13680222019-02-01 02:28:03 +0000378 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false));
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000379 }
380 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000381
James Y Knight13680222019-02-01 02:28:03 +0000382 HwasanTagMemoryFunc = M.getOrInsertFunction(
383 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy);
384 HwasanGenerateTagFunc =
385 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000386
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000387 ShadowGlobal = M.getOrInsertGlobal("__hwasan_shadow",
388 ArrayType::get(IRB.getInt8Ty(), 0));
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000389
390 const std::string MemIntrinCallbackPrefix =
391 CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix;
James Y Knight13680222019-02-01 02:28:03 +0000392 HWAsanMemmove = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memmove",
393 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
394 IRB.getInt8PtrTy(), IntptrTy);
395 HWAsanMemcpy = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memcpy",
396 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
397 IRB.getInt8PtrTy(), IntptrTy);
398 HWAsanMemset = M.getOrInsertFunction(MemIntrinCallbackPrefix + "memset",
399 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
400 IRB.getInt32Ty(), IntptrTy);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000401
James Y Knight13680222019-02-01 02:28:03 +0000402 HwasanThreadEnterFunc =
403 M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy());
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000404}
405
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000406Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {
407 // An empty inline asm with input reg == output reg.
408 // An opaque no-op cast, basically.
409 InlineAsm *Asm = InlineAsm::get(
410 FunctionType::get(Int8PtrTy, {ShadowGlobal->getType()}, false),
411 StringRef(""), StringRef("=r,0"),
412 /*hasSideEffects=*/false);
413 return IRB.CreateCall(Asm, {ShadowGlobal}, ".hwasan.shadow");
414}
415
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000416Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000417 // Generate code only when dynamic addressing is needed.
418 if (Mapping.Offset != kDynamicShadowSentinel)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000419 return nullptr;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000420
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000421 if (Mapping.InGlobal) {
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000422 return getDynamicShadowIfunc(IRB);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000423 } else {
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000424 Value *GlobalDynamicAddress =
425 IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000426 kHwasanShadowMemoryDynamicAddress, Int8PtrTy);
James Y Knight14359ef2019-02-01 20:44:24 +0000427 return IRB.CreateLoad(Int8PtrTy, GlobalDynamicAddress);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000428 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000429}
430
431Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I,
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000432 bool *IsWrite,
433 uint64_t *TypeSize,
434 unsigned *Alignment,
435 Value **MaybeMask) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000436 // Skip memory accesses inserted by another instrumentation.
437 if (I->getMetadata("nosanitize")) return nullptr;
438
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000439 // Do not instrument the load fetching the dynamic shadow address.
440 if (LocalDynamicShadow == I)
441 return nullptr;
442
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000443 Value *PtrOperand = nullptr;
444 const DataLayout &DL = I->getModule()->getDataLayout();
445 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
446 if (!ClInstrumentReads) return nullptr;
447 *IsWrite = false;
448 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType());
449 *Alignment = LI->getAlignment();
450 PtrOperand = LI->getPointerOperand();
451 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
452 if (!ClInstrumentWrites) return nullptr;
453 *IsWrite = true;
454 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType());
455 *Alignment = SI->getAlignment();
456 PtrOperand = SI->getPointerOperand();
457 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
458 if (!ClInstrumentAtomics) return nullptr;
459 *IsWrite = true;
460 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType());
461 *Alignment = 0;
462 PtrOperand = RMW->getPointerOperand();
463 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
464 if (!ClInstrumentAtomics) return nullptr;
465 *IsWrite = true;
466 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType());
467 *Alignment = 0;
468 PtrOperand = XCHG->getPointerOperand();
469 }
470
471 if (PtrOperand) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000472 // Do not instrument accesses from different address spaces; we cannot deal
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000473 // with them.
474 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType());
475 if (PtrTy->getPointerAddressSpace() != 0)
476 return nullptr;
477
478 // Ignore swifterror addresses.
479 // swifterror memory addresses are mem2reg promoted by instruction
480 // selection. As such they cannot have regular uses like an instrumentation
481 // function and it makes no sense to track them as memory.
482 if (PtrOperand->isSwiftError())
483 return nullptr;
484 }
485
486 return PtrOperand;
487}
488
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000489static unsigned getPointerOperandIndex(Instruction *I) {
490 if (LoadInst *LI = dyn_cast<LoadInst>(I))
491 return LI->getPointerOperandIndex();
492 if (StoreInst *SI = dyn_cast<StoreInst>(I))
493 return SI->getPointerOperandIndex();
494 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I))
495 return RMW->getPointerOperandIndex();
496 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I))
497 return XCHG->getPointerOperandIndex();
498 report_fatal_error("Unexpected instruction");
499 return -1;
500}
501
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000502static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
503 size_t Res = countTrailingZeros(TypeSize / 8);
504 assert(Res < kNumberOfAccessSizes);
505 return Res;
506}
507
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000508void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
509 if (TargetTriple.isAArch64())
510 return;
511
512 IRBuilder<> IRB(I);
513 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
514 Value *UntaggedPtr =
515 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType());
516 I->setOperand(getPointerOperandIndex(I), UntaggedPtr);
517}
518
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000519Value *HWAddressSanitizer::shadowBase() {
520 if (LocalDynamicShadow)
521 return LocalDynamicShadow;
522 return ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy, Mapping.Offset),
523 Int8PtrTy);
524}
525
526Value *HWAddressSanitizer::memToShadow(Value *Mem, IRBuilder<> &IRB) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000527 // Mem >> Scale
528 Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale);
529 if (Mapping.Offset == 0)
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000530 return IRB.CreateIntToPtr(Shadow, Int8PtrTy);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000531 // (Mem >> Scale) + Offset
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000532 return IRB.CreateGEP(Int8Ty, shadowBase(), Shadow);
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000533}
534
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000535void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000536 unsigned AccessSizeIndex,
537 Instruction *InsertBefore) {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000538 const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex;
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000539 IRBuilder<> IRB(InsertBefore);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000540
541 if (!ClInlineAllChecks && TargetTriple.isAArch64() &&
542 TargetTriple.isOSBinFormatELF() && !Recover) {
543 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
544 Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy);
545 IRB.CreateCall(
546 Intrinsic::getDeclaration(M, Intrinsic::hwasan_check_memaccess),
547 {shadowBase(), Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
548 return;
549 }
550
551 Value *PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000552 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift),
553 IRB.getInt8Ty());
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000554 Value *AddrLong = untagPointer(IRB, PtrLong);
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000555 Value *Shadow = memToShadow(AddrLong, IRB);
James Y Knight14359ef2019-02-01 20:44:24 +0000556 Value *MemTag = IRB.CreateLoad(Int8Ty, Shadow);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000557 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag);
558
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000559 int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ?
560 ClMatchAllTag : (CompileKernel ? 0xFF : -1);
561 if (matchAllTag != -1) {
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000562 Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag,
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000563 ConstantInt::get(PtrTag->getType(), matchAllTag));
Evgeniy Stepanov1f1a7a72018-04-04 20:44:59 +0000564 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);
565 }
566
Chandler Carruth4a2d58e2018-10-15 09:34:05 +0000567 Instruction *CheckTerm =
Evgeniy Stepanov3fd1b1a2017-12-20 19:05:44 +0000568 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover,
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000569 MDBuilder(*C).createBranchWeights(1, 100000));
570
571 IRB.SetInsertPoint(CheckTerm);
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000572 InlineAsm *Asm;
573 switch (TargetTriple.getArch()) {
574 case Triple::x86_64:
575 // The signal handler will find the data address in rdi.
576 Asm = InlineAsm::get(
577 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
578 "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)",
579 "{rdi}",
580 /*hasSideEffects=*/true);
581 break;
582 case Triple::aarch64:
583 case Triple::aarch64_be:
584 // The signal handler will find the data address in x0.
585 Asm = InlineAsm::get(
586 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false),
587 "brk #" + itostr(0x900 + AccessInfo),
588 "{x0}",
589 /*hasSideEffects=*/true);
590 break;
591 default:
592 report_fatal_error("unsupported architecture");
593 }
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000594 IRB.CreateCall(Asm, PtrLong);
595}
596
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000597void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
598 IRBuilder<> IRB(MI);
599 if (isa<MemTransferInst>(MI)) {
600 IRB.CreateCall(
601 isa<MemMoveInst>(MI) ? HWAsanMemmove : HWAsanMemcpy,
602 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
603 IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()),
604 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
605 } else if (isa<MemSetInst>(MI)) {
606 IRB.CreateCall(
607 HWAsanMemset,
608 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()),
609 IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
610 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)});
611 }
612 MI->eraseFromParent();
613}
614
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000615bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000616 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000617 bool IsWrite = false;
618 unsigned Alignment = 0;
619 uint64_t TypeSize = 0;
620 Value *MaybeMask = nullptr;
Eugene Leviant2d98eb12018-12-20 09:04:33 +0000621
622 if (ClInstrumentMemIntrinsics && isa<MemIntrinsic>(I)) {
623 instrumentMemIntrinsic(cast<MemIntrinsic>(I));
624 return true;
625 }
626
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000627 Value *Addr =
628 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask);
629
630 if (!Addr)
631 return false;
632
633 if (MaybeMask)
634 return false; //FIXME
635
636 IRBuilder<> IRB(I);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000637 if (isPowerOf2_64(TypeSize) &&
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000638 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) &&
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000639 (Alignment >= (1UL << Mapping.Scale) || Alignment == 0 ||
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000640 Alignment >= TypeSize / 8)) {
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000641 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000642 if (ClInstrumentWithCalls) {
643 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000644 IRB.CreatePointerCast(Addr, IntptrTy));
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000645 } else {
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000646 instrumentMemAccessInline(Addr, IsWrite, AccessSizeIndex, I);
Evgeniy Stepanovecb48e52017-12-13 01:16:34 +0000647 }
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000648 } else {
649 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite],
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000650 {IRB.CreatePointerCast(Addr, IntptrTy),
651 ConstantInt::get(IntptrTy, TypeSize / 8)});
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000652 }
Alex Shlyapnikov83e78412018-03-23 17:57:54 +0000653 untagPointerOperand(I, Addr);
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000654
655 return true;
656}
657
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000658static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) {
659 uint64_t ArraySize = 1;
660 if (AI.isArrayAllocation()) {
661 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize());
662 assert(CI && "non-constant array size");
663 ArraySize = CI->getZExtValue();
664 }
665 Type *Ty = AI.getAllocatedType();
666 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty);
667 return SizeInBytes * ArraySize;
668}
669
670bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI,
671 Value *Tag) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000672 size_t Size = (getAllocaSizeInBytes(*AI) + Mapping.getAllocaAlignment() - 1) &
673 ~(Mapping.getAllocaAlignment() - 1);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000674
675 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty());
676 if (ClInstrumentWithCalls) {
677 IRB.CreateCall(HwasanTagMemoryFunc,
Evgeniy Stepanova265a132018-08-15 00:39:35 +0000678 {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag,
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000679 ConstantInt::get(IntptrTy, Size)});
680 } else {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000681 size_t ShadowSize = Size >> Mapping.Scale;
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000682 Value *ShadowPtr = memToShadow(IRB.CreatePointerCast(AI, IntptrTy), IRB);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000683 // If this memset is not inlined, it will be intercepted in the hwasan
684 // runtime library. That's OK, because the interceptor skips the checks if
685 // the address is in the shadow region.
686 // FIXME: the interceptor is not as fast as real memset. Consider lowering
687 // llvm.memset right here into either a sequence of stores, or a call to
688 // hwasan_tag_memory.
689 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1);
690 }
691 return true;
692}
693
694static unsigned RetagMask(unsigned AllocaNo) {
695 // A list of 8-bit numbers that have at most one run of non-zero bits.
696 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
697 // masks.
698 // The list does not include the value 255, which is used for UAR.
699 static unsigned FastMasks[] = {
700 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24,
701 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120,
702 124, 126, 127, 128, 192, 224, 240, 248, 252, 254};
703 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
704}
705
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000706Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
707 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
708}
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000709
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000710Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
711 if (ClGenerateTagsWithCalls)
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000712 return getNextTagWithCall(IRB);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000713 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
714 // first).
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000715 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
716 auto GetStackPointerFn =
717 Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
718 Value *StackPointer = IRB.CreateCall(
719 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())});
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000720
721 // Extract some entropy from the stack pointer for the tags.
722 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
723 // between functions).
724 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy);
725 Value *StackTag =
726 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20),
727 "hwasan.stack.base.tag");
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000728 return StackTag;
729}
730
731Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
732 AllocaInst *AI, unsigned AllocaNo) {
733 if (ClGenerateTagsWithCalls)
734 return getNextTagWithCall(IRB);
735 return IRB.CreateXor(StackTag,
736 ConstantInt::get(IntptrTy, RetagMask(AllocaNo)));
737}
738
739Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
Alex Shlyapnikov788764c2018-06-29 20:20:17 +0000740 if (ClUARRetagToZero)
741 return ConstantInt::get(IntptrTy, 0);
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000742 if (ClGenerateTagsWithCalls)
743 return getNextTagWithCall(IRB);
744 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
745}
746
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000747// Add a tag to an address.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000748Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
749 Value *PtrLong, Value *Tag) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000750 Value *TaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000751 if (CompileKernel) {
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000752 // Kernel addresses have 0xFF in the most significant byte.
753 Value *ShiftedTag = IRB.CreateOr(
754 IRB.CreateShl(Tag, kPointerTagShift),
755 ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1));
756 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
757 } else {
758 // Userspace can simply do OR (tag << 56);
759 Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift);
760 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
761 }
762 return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
763}
764
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000765// Remove tag from an address.
766Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
767 Value *UntaggedPtrLong;
Andrey Konovalov1ba9d9c2018-04-13 18:05:21 +0000768 if (CompileKernel) {
Evgeniy Stepanov43271b12018-02-21 19:52:23 +0000769 // Kernel addresses have 0xFF in the most significant byte.
770 UntaggedPtrLong = IRB.CreateOr(PtrLong,
771 ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift));
772 } else {
773 // Userspace addresses have 0x00.
774 UntaggedPtrLong = IRB.CreateAnd(PtrLong,
775 ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift)));
776 }
777 return UntaggedPtrLong;
778}
779
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000780Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) {
781 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
782 if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) {
Evgeniy Stepanov0184c532019-01-05 00:44:58 +0000783 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
784 // in Bionic's libc/private/bionic_tls.h.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000785 Function *ThreadPointerFunc =
786 Intrinsic::getDeclaration(M, Intrinsic::thread_pointer);
787 Value *SlotPtr = IRB.CreatePointerCast(
James Y Knight77160752019-02-01 20:44:47 +0000788 IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
789 IRB.CreateCall(ThreadPointerFunc), 0x30),
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000790 Ty->getPointerTo(0));
791 return SlotPtr;
792 }
793 if (ThreadPtrGlobal)
794 return ThreadPtrGlobal;
795
796
797 return nullptr;
798}
799
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000800// Creates a string with a description of the stack frame (set of Allocas).
801// The string is intended to be human readable.
802// The current form is: Size1 Name1; Size2 Name2; ...
803std::string
804HWAddressSanitizer::createFrameString(ArrayRef<AllocaInst *> Allocas) {
805 std::ostringstream Descr;
806 for (auto AI : Allocas)
807 Descr << getAllocaSizeInBytes(*AI) << " " << AI->getName().str() << "; ";
808 return Descr.str();
809}
810
811// Creates a global in the frame section which consists of two pointers:
812// the function PC and the frame string constant.
813void HWAddressSanitizer::createFrameGlobal(Function &F,
814 const std::string &FrameString) {
815 Module &M = *F.getParent();
816 auto DescrGV = createPrivateGlobalForString(M, FrameString, true);
817 auto PtrPairTy = StructType::get(F.getType(), DescrGV->getType());
818 auto GV = new GlobalVariable(
819 M, PtrPairTy, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage,
820 ConstantStruct::get(PtrPairTy, (Constant *)&F, (Constant *)DescrGV),
821 "__hwasan");
822 GV->setSection(getFrameSection());
823 appendToCompilerUsed(M, GV);
824 // 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 +0000825 if (auto Comdat =
826 GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId))
827 GV->setComdat(Comdat);
Kostya Serebryanyaf955972018-10-23 00:50:40 +0000828}
829
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000830Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
831 bool WithFrameRecord) {
832 if (!Mapping.InTls)
833 return getDynamicShadowNonTls(IRB);
834
Peter Collingbournedf579792019-04-09 00:25:59 +0000835 if (!WithFrameRecord && TargetTriple.isAndroid())
Peter Collingbourne020ce3f2019-01-23 22:39:11 +0000836 return getDynamicShadowIfunc(IRB);
837
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000838 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
839 assert(SlotPtr);
840
James Y Knight14359ef2019-02-01 20:44:24 +0000841 Instruction *ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000842
843 Function *F = IRB.GetInsertBlock()->getParent();
844 if (F->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") {
845 Value *ThreadLongEqZero =
846 IRB.CreateICmpEQ(ThreadLong, ConstantInt::get(IntptrTy, 0));
847 auto *Br = cast<BranchInst>(SplitBlockAndInsertIfThen(
848 ThreadLongEqZero, cast<Instruction>(ThreadLongEqZero)->getNextNode(),
849 false, MDBuilder(*C).createBranchWeights(1, 100000)));
850
851 IRB.SetInsertPoint(Br);
852 // FIXME: This should call a new runtime function with a custom calling
853 // convention to avoid needing to spill all arguments here.
854 IRB.CreateCall(HwasanThreadEnterFunc);
James Y Knight14359ef2019-02-01 20:44:24 +0000855 LoadInst *ReloadThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
Peter Collingbourne87f477b2019-01-04 19:27:04 +0000856
857 IRB.SetInsertPoint(&*Br->getSuccessor(0)->begin());
858 PHINode *ThreadLongPhi = IRB.CreatePHI(IntptrTy, 2);
859 ThreadLongPhi->addIncoming(ThreadLong, ThreadLong->getParent());
860 ThreadLongPhi->addIncoming(ReloadThreadLong, ReloadThreadLong->getParent());
861 ThreadLong = ThreadLongPhi;
862 }
863
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000864 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI.
865 Value *ThreadLongMaybeUntagged =
866 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong);
867
868 if (WithFrameRecord) {
869 // Prepare ring buffer data.
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000870 auto PC = IRB.CreatePtrToInt(F, IntptrTy);
871 auto GetStackPointerFn =
872 Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress);
873 Value *SP = IRB.CreatePtrToInt(
874 IRB.CreateCall(GetStackPointerFn,
875 {Constant::getNullValue(IRB.getInt32Ty())}),
876 IntptrTy);
877 // Mix SP and PC. TODO: also add the tag to the mix.
878 // Assumptions:
879 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
880 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
881 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this:
882 // 0xSSSSPPPPPPPPPPPP
883 SP = IRB.CreateShl(SP, 44);
884
885 // Store data to ring buffer.
886 Value *RecordPtr =
887 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IntptrTy->getPointerTo(0));
888 IRB.CreateStore(IRB.CreateOr(PC, SP), RecordPtr);
889
890 // Update the ring buffer. Top byte of ThreadLong defines the size of the
891 // buffer in pages, it must be a power of two, and the start of the buffer
892 // must be aligned by twice that much. Therefore wrap around of the ring
893 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
894 // The use of AShr instead of LShr is due to
895 // https://bugs.llvm.org/show_bug.cgi?id=39030
896 // Runtime library makes sure not to use the highest bit.
897 Value *WrapMask = IRB.CreateXor(
898 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
899 ConstantInt::get(IntptrTy, (uint64_t)-1));
900 Value *ThreadLongNew = IRB.CreateAnd(
901 IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
902 IRB.CreateStore(ThreadLongNew, SlotPtr);
903 }
904
905 // Get shadow base address by aligning RecordPtr up.
906 // Note: this is not correct if the pointer is already aligned.
907 // Runtime library will make sure this never happens.
908 Value *ShadowBase = IRB.CreateAdd(
909 IRB.CreateOr(
910 ThreadLongMaybeUntagged,
911 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
912 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
Peter Collingbourne73078ec2019-01-23 02:20:10 +0000913 ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy);
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000914 return ShadowBase;
915}
916
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000917bool HWAddressSanitizer::instrumentStack(
918 SmallVectorImpl<AllocaInst *> &Allocas,
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000919 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000920 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
921 // alloca addresses using that. Unfortunately, offsets are not known yet
922 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
923 // temp, shift-OR it into each alloca address and xor with the retag mask.
924 // This generates one extra instruction per alloca use.
925 for (unsigned N = 0; N < Allocas.size(); ++N) {
926 auto *AI = Allocas[N];
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +0000927 IRBuilder<> IRB(AI->getNextNode());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000928
929 // Replace uses of the alloca with tagged address.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000930 Value *Tag = getAllocaTag(IRB, StackTag, AI, N);
931 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000932 Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000933 std::string Name =
934 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
Evgeniy Stepanov80ccda22018-02-09 00:59:10 +0000935 Replacement->setName(Name + ".hwasan");
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000936
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000937 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000938 Use &U = *UI++;
939 if (U.getUser() != AILong)
940 U.set(Replacement);
941 }
942
943 tagAlloca(IRB, AI, Tag);
944
945 for (auto RI : RetVec) {
946 IRB.SetInsertPoint(RI);
947
948 // Re-tag alloca memory with the special UAR tag.
Evgeniy Stepanov080e0d42018-01-13 01:32:15 +0000949 Value *Tag = getUARTag(IRB, StackTag);
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000950 tagAlloca(IRB, AI, Tag);
951 }
952 }
953
954 return true;
955}
956
957bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
958 return (AI.getAllocatedType()->isSized() &&
959 // FIXME: instrument dynamic allocas, too
960 AI.isStaticAlloca() &&
961 // alloca() may be called with 0 size, ignore it.
962 getAllocaSizeInBytes(AI) > 0 &&
963 // We are only interested in allocas not promotable to registers.
964 // Promotable allocas are common under -O0.
965 !isAllocaPromotable(&AI) &&
966 // inalloca allocas are not treated as static, and we don't want
967 // dynamic alloca instrumentation for them as well.
968 !AI.isUsedWithInAlloca() &&
969 // swifterror allocas are register promoted by ISel
970 !AI.isSwiftError());
971}
972
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000973bool HWAddressSanitizer::runOnFunction(Function &F) {
974 if (&F == HwasanCtorFunction)
975 return false;
976
977 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
978 return false;
979
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000980 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000981
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000982 SmallVector<Instruction*, 16> ToInstrument;
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000983 SmallVector<AllocaInst*, 8> AllocasToInstrument;
984 SmallVector<Instruction*, 8> RetVec;
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +0000985 for (auto &BB : F) {
986 for (auto &Inst : BB) {
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000987 if (ClInstrumentStack)
988 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
989 // Realign all allocas. We don't want small uninteresting allocas to
990 // hide in instrumented alloca's padding.
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000991 if (AI->getAlignment() < Mapping.getAllocaAlignment())
992 AI->setAlignment(Mapping.getAllocaAlignment());
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +0000993 // Instrument some of them.
994 if (isInterestingAlloca(*AI))
995 AllocasToInstrument.push_back(AI);
996 continue;
997 }
998
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +0000999 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) ||
1000 isa<CleanupReturnInst>(Inst))
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001001 RetVec.push_back(&Inst);
1002
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001003 Value *MaybeMask = nullptr;
1004 bool IsWrite;
1005 unsigned Alignment;
1006 uint64_t TypeSize;
1007 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize,
1008 &Alignment, &MaybeMask);
1009 if (Addr || isa<MemIntrinsic>(Inst))
1010 ToInstrument.push_back(&Inst);
1011 }
1012 }
1013
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001014 if (AllocasToInstrument.empty() && ToInstrument.empty())
1015 return false;
1016
Kostya Serebryanyaf955972018-10-23 00:50:40 +00001017 if (ClCreateFrameDescriptions && !AllocasToInstrument.empty())
1018 createFrameGlobal(F, createFrameString(AllocasToInstrument));
1019
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001020 initializeCallbacks(*F.getParent());
1021
1022 assert(!LocalDynamicShadow);
1023
1024 Instruction *InsertPt = &*F.getEntryBlock().begin();
1025 IRBuilder<> EntryIRB(InsertPt);
1026 LocalDynamicShadow = emitPrologue(EntryIRB,
1027 /*WithFrameRecord*/ ClRecordStackHistory &&
1028 !AllocasToInstrument.empty());
1029
1030 bool Changed = false;
1031 if (!AllocasToInstrument.empty()) {
1032 Value *StackTag =
1033 ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB);
1034 Changed |= instrumentStack(AllocasToInstrument, RetVec, StackTag);
1035 }
Evgeniy Stepanov99fa3e72018-01-11 22:53:30 +00001036
Peter Collingbourne1a8acfb2019-01-25 02:08:46 +00001037 // If we split the entry block, move any allocas that were originally in the
1038 // entry block back into the entry block so that they aren't treated as
1039 // dynamic allocas.
1040 if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {
1041 InsertPt = &*F.getEntryBlock().begin();
1042 for (auto II = EntryIRB.GetInsertBlock()->begin(),
1043 IE = EntryIRB.GetInsertBlock()->end();
1044 II != IE;) {
1045 Instruction *I = &*II++;
1046 if (auto *AI = dyn_cast<AllocaInst>(I))
1047 if (isa<ConstantInt>(AI->getArraySize()))
1048 I->moveBefore(InsertPt);
1049 }
1050 }
1051
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001052 for (auto Inst : ToInstrument)
1053 Changed |= instrumentMemAccess(Inst);
1054
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001055 LocalDynamicShadow = nullptr;
1056
Evgeniy Stepanovc667c1f2017-12-09 00:21:41 +00001057 return Changed;
1058}
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001059
1060void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) {
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001061 Scale = kDefaultShadowScale;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001062 if (ClMappingOffset.getNumOccurrences() > 0) {
1063 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001064 InTls = false;
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001065 Offset = ClMappingOffset;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001066 } else if (ClEnableKhwasan || ClInstrumentWithCalls) {
1067 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001068 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001069 Offset = 0;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001070 } else if (ClWithIfunc) {
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001071 InGlobal = true;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001072 InTls = false;
1073 Offset = kDynamicShadowSentinel;
1074 } else if (ClWithTls) {
1075 InGlobal = false;
1076 InTls = true;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001077 Offset = kDynamicShadowSentinel;
1078 } else {
1079 InGlobal = false;
Evgeniy Stepanov090f0f92018-09-24 23:03:34 +00001080 InTls = false;
Evgeniy Stepanov453e7ac2018-08-10 16:21:37 +00001081 Offset = kDynamicShadowSentinel;
1082 }
Alex Shlyapnikov99cf54b2018-04-20 20:04:04 +00001083}