1 //===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===//
3 // 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
7 //===----------------------------------------------------------------------===//
10 /// This file is a part of HWAddressSanitizer, an address sanity checker
11 /// based on tagged addressing.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/BinaryFormat/ELF.h"
21 #include "llvm/IR/Attributes.h"
22 #include "llvm/IR/BasicBlock.h"
23 #include "llvm/IR/Constant.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/DebugInfoMetadata.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/IRBuilder.h"
30 #include "llvm/IR/InlineAsm.h"
31 #include "llvm/IR/InstVisitor.h"
32 #include "llvm/IR/Instruction.h"
33 #include "llvm/IR/Instructions.h"
34 #include "llvm/IR/IntrinsicInst.h"
35 #include "llvm/IR/Intrinsics.h"
36 #include "llvm/IR/LLVMContext.h"
37 #include "llvm/IR/MDBuilder.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/IR/Type.h"
40 #include "llvm/IR/Value.h"
41 #include "llvm/Pass.h"
42 #include "llvm/Support/Casting.h"
43 #include "llvm/Support/CommandLine.h"
44 #include "llvm/Support/Debug.h"
45 #include "llvm/Support/raw_ostream.h"
46 #include "llvm/Transforms/Instrumentation.h"
47 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
48 #include "llvm/Transforms/Utils/ModuleUtils.h"
49 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
54 #define DEBUG_TYPE "hwasan"
56 static const char *const kHwasanModuleCtorName
= "hwasan.module_ctor";
57 static const char *const kHwasanNoteName
= "hwasan.note";
58 static const char *const kHwasanInitName
= "__hwasan_init";
59 static const char *const kHwasanPersonalityThunkName
=
60 "__hwasan_personality_thunk";
62 static const char *const kHwasanShadowMemoryDynamicAddress
=
63 "__hwasan_shadow_memory_dynamic_address";
65 // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
66 static const size_t kNumberOfAccessSizes
= 5;
68 static const size_t kDefaultShadowScale
= 4;
69 static const uint64_t kDynamicShadowSentinel
=
70 std::numeric_limits
<uint64_t>::max();
71 static const unsigned kPointerTagShift
= 56;
73 static const unsigned kShadowBaseAlignment
= 32;
75 static cl::opt
<std::string
> ClMemoryAccessCallbackPrefix(
76 "hwasan-memory-access-callback-prefix",
77 cl::desc("Prefix for memory access callbacks"), cl::Hidden
,
78 cl::init("__hwasan_"));
81 ClInstrumentWithCalls("hwasan-instrument-with-calls",
82 cl::desc("instrument reads and writes with callbacks"),
83 cl::Hidden
, cl::init(false));
85 static cl::opt
<bool> ClInstrumentReads("hwasan-instrument-reads",
86 cl::desc("instrument read instructions"),
87 cl::Hidden
, cl::init(true));
89 static cl::opt
<bool> ClInstrumentWrites(
90 "hwasan-instrument-writes", cl::desc("instrument write instructions"),
91 cl::Hidden
, cl::init(true));
93 static cl::opt
<bool> ClInstrumentAtomics(
94 "hwasan-instrument-atomics",
95 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden
,
98 static cl::opt
<bool> ClRecover(
100 cl::desc("Enable recovery mode (continue-after-error)."),
101 cl::Hidden
, cl::init(false));
103 static cl::opt
<bool> ClInstrumentStack("hwasan-instrument-stack",
104 cl::desc("instrument stack (allocas)"),
105 cl::Hidden
, cl::init(true));
107 static cl::opt
<bool> ClUARRetagToZero(
108 "hwasan-uar-retag-to-zero",
109 cl::desc("Clear alloca tags before returning from the function to allow "
110 "non-instrumented and instrumented function calls mix. When set "
111 "to false, allocas are retagged before returning from the "
112 "function to detect use after return."),
113 cl::Hidden
, cl::init(true));
115 static cl::opt
<bool> ClGenerateTagsWithCalls(
116 "hwasan-generate-tags-with-calls",
117 cl::desc("generate new tags with runtime library calls"), cl::Hidden
,
120 static cl::opt
<bool> ClGlobals("hwasan-globals", cl::desc("Instrument globals"),
121 cl::Hidden
, cl::init(false));
123 static cl::opt
<int> ClMatchAllTag(
124 "hwasan-match-all-tag",
125 cl::desc("don't report bad accesses via pointers with this tag"),
126 cl::Hidden
, cl::init(-1));
128 static cl::opt
<bool> ClEnableKhwasan(
130 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
131 cl::Hidden
, cl::init(false));
133 // These flags allow to change the shadow mapping and control how shadow memory
134 // is accessed. The shadow mapping looks like:
135 // Shadow = (Mem >> scale) + offset
137 static cl::opt
<uint64_t>
138 ClMappingOffset("hwasan-mapping-offset",
139 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
140 cl::Hidden
, cl::init(0));
143 ClWithIfunc("hwasan-with-ifunc",
144 cl::desc("Access dynamic shadow through an ifunc global on "
145 "platforms that support this"),
146 cl::Hidden
, cl::init(false));
148 static cl::opt
<bool> ClWithTls(
150 cl::desc("Access dynamic shadow through an thread-local pointer on "
151 "platforms that support this"),
152 cl::Hidden
, cl::init(true));
155 ClRecordStackHistory("hwasan-record-stack-history",
156 cl::desc("Record stack frames with tagged allocations "
157 "in a thread-local ring buffer"),
158 cl::Hidden
, cl::init(true));
160 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
161 cl::desc("instrument memory intrinsics"),
162 cl::Hidden
, cl::init(true));
165 ClInstrumentLandingPads("hwasan-instrument-landing-pads",
166 cl::desc("instrument landing pads"), cl::Hidden
,
167 cl::init(false), cl::ZeroOrMore
);
169 static cl::opt
<bool> ClInstrumentPersonalityFunctions(
170 "hwasan-instrument-personality-functions",
171 cl::desc("instrument personality functions"), cl::Hidden
, cl::init(false),
174 static cl::opt
<bool> ClInlineAllChecks("hwasan-inline-all-checks",
175 cl::desc("inline all checks"),
176 cl::Hidden
, cl::init(false));
180 /// An instrumentation pass implementing detection of addressability bugs
181 /// using tagged pointers.
182 class HWAddressSanitizer
{
184 explicit HWAddressSanitizer(Module
&M
, bool CompileKernel
= false,
185 bool Recover
= false) : M(M
) {
186 this->Recover
= ClRecover
.getNumOccurrences() > 0 ? ClRecover
: Recover
;
187 this->CompileKernel
= ClEnableKhwasan
.getNumOccurrences() > 0 ?
188 ClEnableKhwasan
: CompileKernel
;
193 bool sanitizeFunction(Function
&F
);
194 void initializeModule();
196 void initializeCallbacks(Module
&M
);
198 Value
*getDynamicShadowIfunc(IRBuilder
<> &IRB
);
199 Value
*getDynamicShadowNonTls(IRBuilder
<> &IRB
);
201 void untagPointerOperand(Instruction
*I
, Value
*Addr
);
203 Value
*memToShadow(Value
*Shadow
, IRBuilder
<> &IRB
);
204 void instrumentMemAccessInline(Value
*Ptr
, bool IsWrite
,
205 unsigned AccessSizeIndex
,
206 Instruction
*InsertBefore
);
207 void instrumentMemIntrinsic(MemIntrinsic
*MI
);
208 bool instrumentMemAccess(Instruction
*I
);
209 Value
*isInterestingMemoryAccess(Instruction
*I
, bool *IsWrite
,
210 uint64_t *TypeSize
, unsigned *Alignment
,
213 bool isInterestingAlloca(const AllocaInst
&AI
);
214 bool tagAlloca(IRBuilder
<> &IRB
, AllocaInst
*AI
, Value
*Tag
, size_t Size
);
215 Value
*tagPointer(IRBuilder
<> &IRB
, Type
*Ty
, Value
*PtrLong
, Value
*Tag
);
216 Value
*untagPointer(IRBuilder
<> &IRB
, Value
*PtrLong
);
217 bool instrumentStack(
218 SmallVectorImpl
<AllocaInst
*> &Allocas
,
219 DenseMap
<AllocaInst
*, std::vector
<DbgDeclareInst
*>> &AllocaDeclareMap
,
220 SmallVectorImpl
<Instruction
*> &RetVec
, Value
*StackTag
);
221 Value
*readRegister(IRBuilder
<> &IRB
, StringRef Name
);
222 bool instrumentLandingPads(SmallVectorImpl
<Instruction
*> &RetVec
);
223 Value
*getNextTagWithCall(IRBuilder
<> &IRB
);
224 Value
*getStackBaseTag(IRBuilder
<> &IRB
);
225 Value
*getAllocaTag(IRBuilder
<> &IRB
, Value
*StackTag
, AllocaInst
*AI
,
227 Value
*getUARTag(IRBuilder
<> &IRB
, Value
*StackTag
);
229 Value
*getHwasanThreadSlotPtr(IRBuilder
<> &IRB
, Type
*Ty
);
230 void emitPrologue(IRBuilder
<> &IRB
, bool WithFrameRecord
);
232 void instrumentGlobal(GlobalVariable
*GV
, uint8_t Tag
);
233 void instrumentGlobals();
235 void instrumentPersonalityFunctions();
241 FunctionCallee HWAsanMemmove
, HWAsanMemcpy
, HWAsanMemset
;
242 FunctionCallee HWAsanHandleVfork
;
244 /// This struct defines the shadow mapping using the rule:
245 /// shadow = (mem >> Scale) + Offset.
246 /// If InGlobal is true, then
247 /// extern char __hwasan_shadow[];
248 /// shadow = (mem >> Scale) + &__hwasan_shadow
249 /// If InTls is true, then
250 /// extern char *__hwasan_tls;
251 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
252 struct ShadowMapping
{
258 void init(Triple
&TargetTriple
);
259 unsigned getObjectAlignment() const { return 1U << Scale
; }
261 ShadowMapping Mapping
;
263 Type
*VoidTy
= Type::getVoidTy(M
.getContext());
268 Type
*Int64Ty
= Type::getInt64Ty(M
.getContext());
272 bool InstrumentLandingPads
;
274 Function
*HwasanCtorFunction
;
276 FunctionCallee HwasanMemoryAccessCallback
[2][kNumberOfAccessSizes
];
277 FunctionCallee HwasanMemoryAccessCallbackSized
[2];
279 FunctionCallee HwasanTagMemoryFunc
;
280 FunctionCallee HwasanGenerateTagFunc
;
281 FunctionCallee HwasanThreadEnterFunc
;
283 Constant
*ShadowGlobal
;
285 Value
*LocalDynamicShadow
= nullptr;
286 Value
*StackBaseTag
= nullptr;
287 GlobalValue
*ThreadPtrGlobal
= nullptr;
290 class HWAddressSanitizerLegacyPass
: public FunctionPass
{
292 // Pass identification, replacement for typeid.
295 explicit HWAddressSanitizerLegacyPass(bool CompileKernel
= false,
296 bool Recover
= false)
297 : FunctionPass(ID
), CompileKernel(CompileKernel
), Recover(Recover
) {}
299 StringRef
getPassName() const override
{ return "HWAddressSanitizer"; }
301 bool doInitialization(Module
&M
) override
{
302 HWASan
= std::make_unique
<HWAddressSanitizer
>(M
, CompileKernel
, Recover
);
306 bool runOnFunction(Function
&F
) override
{
307 return HWASan
->sanitizeFunction(F
);
310 bool doFinalization(Module
&M
) override
{
316 std::unique_ptr
<HWAddressSanitizer
> HWASan
;
321 } // end anonymous namespace
323 char HWAddressSanitizerLegacyPass::ID
= 0;
325 INITIALIZE_PASS_BEGIN(
326 HWAddressSanitizerLegacyPass
, "hwasan",
327 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
330 HWAddressSanitizerLegacyPass
, "hwasan",
331 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
334 FunctionPass
*llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel
,
336 assert(!CompileKernel
|| Recover
);
337 return new HWAddressSanitizerLegacyPass(CompileKernel
, Recover
);
340 HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel
, bool Recover
)
341 : CompileKernel(CompileKernel
), Recover(Recover
) {}
343 PreservedAnalyses
HWAddressSanitizerPass::run(Module
&M
,
344 ModuleAnalysisManager
&MAM
) {
345 HWAddressSanitizer
HWASan(M
, CompileKernel
, Recover
);
346 bool Modified
= false;
347 for (Function
&F
: M
)
348 Modified
|= HWASan
.sanitizeFunction(F
);
350 return PreservedAnalyses::none();
351 return PreservedAnalyses::all();
354 /// Module-level initialization.
356 /// inserts a call to __hwasan_init to the module's constructor list.
357 void HWAddressSanitizer::initializeModule() {
358 LLVM_DEBUG(dbgs() << "Init " << M
.getName() << "\n");
359 auto &DL
= M
.getDataLayout();
361 TargetTriple
= Triple(M
.getTargetTriple());
363 Mapping
.init(TargetTriple
);
365 C
= &(M
.getContext());
367 IntptrTy
= IRB
.getIntPtrTy(DL
);
368 Int8PtrTy
= IRB
.getInt8PtrTy();
369 Int8Ty
= IRB
.getInt8Ty();
370 Int32Ty
= IRB
.getInt32Ty();
372 HwasanCtorFunction
= nullptr;
374 // Older versions of Android do not have the required runtime support for
375 // global or personality function instrumentation. On other platforms we
376 // currently require using the latest version of the runtime.
378 !TargetTriple
.isAndroid() || !TargetTriple
.isAndroidVersionLT(30);
380 // If we don't have personality function support, fall back to landing pads.
381 InstrumentLandingPads
= ClInstrumentLandingPads
.getNumOccurrences()
382 ? ClInstrumentLandingPads
385 if (!CompileKernel
) {
386 std::tie(HwasanCtorFunction
, std::ignore
) =
387 getOrCreateSanitizerCtorAndInitFunctions(
388 M
, kHwasanModuleCtorName
, kHwasanInitName
,
391 // This callback is invoked when the functions are created the first
392 // time. Hook them into the global ctors list in that case:
393 [&](Function
*Ctor
, FunctionCallee
) {
394 Comdat
*CtorComdat
= M
.getOrInsertComdat(kHwasanModuleCtorName
);
395 Ctor
->setComdat(CtorComdat
);
396 appendToGlobalCtors(M
, Ctor
, 0, Ctor
);
399 bool InstrumentGlobals
=
400 ClGlobals
.getNumOccurrences() ? ClGlobals
: NewRuntime
;
401 if (InstrumentGlobals
)
404 bool InstrumentPersonalityFunctions
=
405 ClInstrumentPersonalityFunctions
.getNumOccurrences()
406 ? ClInstrumentPersonalityFunctions
408 if (InstrumentPersonalityFunctions
)
409 instrumentPersonalityFunctions();
412 if (!TargetTriple
.isAndroid()) {
413 Constant
*C
= M
.getOrInsertGlobal("__hwasan_tls", IntptrTy
, [&] {
414 auto *GV
= new GlobalVariable(M
, IntptrTy
, /*isConstant=*/false,
415 GlobalValue::ExternalLinkage
, nullptr,
416 "__hwasan_tls", nullptr,
417 GlobalVariable::InitialExecTLSModel
);
418 appendToCompilerUsed(M
, GV
);
421 ThreadPtrGlobal
= cast
<GlobalVariable
>(C
);
425 void HWAddressSanitizer::initializeCallbacks(Module
&M
) {
427 for (size_t AccessIsWrite
= 0; AccessIsWrite
<= 1; AccessIsWrite
++) {
428 const std::string TypeStr
= AccessIsWrite
? "store" : "load";
429 const std::string EndingStr
= Recover
? "_noabort" : "";
431 HwasanMemoryAccessCallbackSized
[AccessIsWrite
] = M
.getOrInsertFunction(
432 ClMemoryAccessCallbackPrefix
+ TypeStr
+ "N" + EndingStr
,
433 FunctionType::get(IRB
.getVoidTy(), {IntptrTy
, IntptrTy
}, false));
435 for (size_t AccessSizeIndex
= 0; AccessSizeIndex
< kNumberOfAccessSizes
;
437 HwasanMemoryAccessCallback
[AccessIsWrite
][AccessSizeIndex
] =
438 M
.getOrInsertFunction(
439 ClMemoryAccessCallbackPrefix
+ TypeStr
+
440 itostr(1ULL << AccessSizeIndex
) + EndingStr
,
441 FunctionType::get(IRB
.getVoidTy(), {IntptrTy
}, false));
445 HwasanTagMemoryFunc
= M
.getOrInsertFunction(
446 "__hwasan_tag_memory", IRB
.getVoidTy(), Int8PtrTy
, Int8Ty
, IntptrTy
);
447 HwasanGenerateTagFunc
=
448 M
.getOrInsertFunction("__hwasan_generate_tag", Int8Ty
);
450 ShadowGlobal
= M
.getOrInsertGlobal("__hwasan_shadow",
451 ArrayType::get(IRB
.getInt8Ty(), 0));
453 const std::string MemIntrinCallbackPrefix
=
454 CompileKernel
? std::string("") : ClMemoryAccessCallbackPrefix
;
455 HWAsanMemmove
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memmove",
456 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
457 IRB
.getInt8PtrTy(), IntptrTy
);
458 HWAsanMemcpy
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memcpy",
459 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
460 IRB
.getInt8PtrTy(), IntptrTy
);
461 HWAsanMemset
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memset",
462 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
463 IRB
.getInt32Ty(), IntptrTy
);
466 M
.getOrInsertFunction("__hwasan_handle_vfork", IRB
.getVoidTy(), IntptrTy
);
468 HwasanThreadEnterFunc
=
469 M
.getOrInsertFunction("__hwasan_thread_enter", IRB
.getVoidTy());
472 Value
*HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder
<> &IRB
) {
473 // An empty inline asm with input reg == output reg.
474 // An opaque no-op cast, basically.
475 InlineAsm
*Asm
= InlineAsm::get(
476 FunctionType::get(Int8PtrTy
, {ShadowGlobal
->getType()}, false),
477 StringRef(""), StringRef("=r,0"),
478 /*hasSideEffects=*/false);
479 return IRB
.CreateCall(Asm
, {ShadowGlobal
}, ".hwasan.shadow");
482 Value
*HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder
<> &IRB
) {
483 // Generate code only when dynamic addressing is needed.
484 if (Mapping
.Offset
!= kDynamicShadowSentinel
)
487 if (Mapping
.InGlobal
) {
488 return getDynamicShadowIfunc(IRB
);
490 Value
*GlobalDynamicAddress
=
491 IRB
.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
492 kHwasanShadowMemoryDynamicAddress
, Int8PtrTy
);
493 return IRB
.CreateLoad(Int8PtrTy
, GlobalDynamicAddress
);
497 Value
*HWAddressSanitizer::isInterestingMemoryAccess(Instruction
*I
,
502 // Skip memory accesses inserted by another instrumentation.
503 if (I
->getMetadata("nosanitize")) return nullptr;
505 // Do not instrument the load fetching the dynamic shadow address.
506 if (LocalDynamicShadow
== I
)
509 Value
*PtrOperand
= nullptr;
510 const DataLayout
&DL
= I
->getModule()->getDataLayout();
511 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
)) {
512 if (!ClInstrumentReads
) return nullptr;
514 *TypeSize
= DL
.getTypeStoreSizeInBits(LI
->getType());
515 *Alignment
= LI
->getAlignment();
516 PtrOperand
= LI
->getPointerOperand();
517 } else if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
)) {
518 if (!ClInstrumentWrites
) return nullptr;
520 *TypeSize
= DL
.getTypeStoreSizeInBits(SI
->getValueOperand()->getType());
521 *Alignment
= SI
->getAlignment();
522 PtrOperand
= SI
->getPointerOperand();
523 } else if (AtomicRMWInst
*RMW
= dyn_cast
<AtomicRMWInst
>(I
)) {
524 if (!ClInstrumentAtomics
) return nullptr;
526 *TypeSize
= DL
.getTypeStoreSizeInBits(RMW
->getValOperand()->getType());
528 PtrOperand
= RMW
->getPointerOperand();
529 } else if (AtomicCmpXchgInst
*XCHG
= dyn_cast
<AtomicCmpXchgInst
>(I
)) {
530 if (!ClInstrumentAtomics
) return nullptr;
532 *TypeSize
= DL
.getTypeStoreSizeInBits(XCHG
->getCompareOperand()->getType());
534 PtrOperand
= XCHG
->getPointerOperand();
538 // Do not instrument accesses from different address spaces; we cannot deal
540 Type
*PtrTy
= cast
<PointerType
>(PtrOperand
->getType()->getScalarType());
541 if (PtrTy
->getPointerAddressSpace() != 0)
544 // Ignore swifterror addresses.
545 // swifterror memory addresses are mem2reg promoted by instruction
546 // selection. As such they cannot have regular uses like an instrumentation
547 // function and it makes no sense to track them as memory.
548 if (PtrOperand
->isSwiftError())
555 static unsigned getPointerOperandIndex(Instruction
*I
) {
556 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
))
557 return LI
->getPointerOperandIndex();
558 if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
))
559 return SI
->getPointerOperandIndex();
560 if (AtomicRMWInst
*RMW
= dyn_cast
<AtomicRMWInst
>(I
))
561 return RMW
->getPointerOperandIndex();
562 if (AtomicCmpXchgInst
*XCHG
= dyn_cast
<AtomicCmpXchgInst
>(I
))
563 return XCHG
->getPointerOperandIndex();
564 report_fatal_error("Unexpected instruction");
568 static size_t TypeSizeToSizeIndex(uint32_t TypeSize
) {
569 size_t Res
= countTrailingZeros(TypeSize
/ 8);
570 assert(Res
< kNumberOfAccessSizes
);
574 void HWAddressSanitizer::untagPointerOperand(Instruction
*I
, Value
*Addr
) {
575 if (TargetTriple
.isAArch64())
579 Value
*AddrLong
= IRB
.CreatePointerCast(Addr
, IntptrTy
);
581 IRB
.CreateIntToPtr(untagPointer(IRB
, AddrLong
), Addr
->getType());
582 I
->setOperand(getPointerOperandIndex(I
), UntaggedPtr
);
585 Value
*HWAddressSanitizer::shadowBase() {
586 if (LocalDynamicShadow
)
587 return LocalDynamicShadow
;
588 return ConstantExpr::getIntToPtr(ConstantInt::get(IntptrTy
, Mapping
.Offset
),
592 Value
*HWAddressSanitizer::memToShadow(Value
*Mem
, IRBuilder
<> &IRB
) {
594 Value
*Shadow
= IRB
.CreateLShr(Mem
, Mapping
.Scale
);
595 if (Mapping
.Offset
== 0)
596 return IRB
.CreateIntToPtr(Shadow
, Int8PtrTy
);
597 // (Mem >> Scale) + Offset
598 return IRB
.CreateGEP(Int8Ty
, shadowBase(), Shadow
);
601 void HWAddressSanitizer::instrumentMemAccessInline(Value
*Ptr
, bool IsWrite
,
602 unsigned AccessSizeIndex
,
603 Instruction
*InsertBefore
) {
604 const int64_t AccessInfo
= Recover
* 0x20 + IsWrite
* 0x10 + AccessSizeIndex
;
605 IRBuilder
<> IRB(InsertBefore
);
607 if (!ClInlineAllChecks
&& TargetTriple
.isAArch64() &&
608 TargetTriple
.isOSBinFormatELF() && !Recover
) {
609 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
610 Ptr
= IRB
.CreateBitCast(Ptr
, Int8PtrTy
);
612 Intrinsic::getDeclaration(M
, Intrinsic::hwasan_check_memaccess
),
613 {shadowBase(), Ptr
, ConstantInt::get(Int32Ty
, AccessInfo
)});
617 Value
*PtrLong
= IRB
.CreatePointerCast(Ptr
, IntptrTy
);
618 Value
*PtrTag
= IRB
.CreateTrunc(IRB
.CreateLShr(PtrLong
, kPointerTagShift
),
620 Value
*AddrLong
= untagPointer(IRB
, PtrLong
);
621 Value
*Shadow
= memToShadow(AddrLong
, IRB
);
622 Value
*MemTag
= IRB
.CreateLoad(Int8Ty
, Shadow
);
623 Value
*TagMismatch
= IRB
.CreateICmpNE(PtrTag
, MemTag
);
625 int matchAllTag
= ClMatchAllTag
.getNumOccurrences() > 0 ?
626 ClMatchAllTag
: (CompileKernel
? 0xFF : -1);
627 if (matchAllTag
!= -1) {
628 Value
*TagNotIgnored
= IRB
.CreateICmpNE(PtrTag
,
629 ConstantInt::get(PtrTag
->getType(), matchAllTag
));
630 TagMismatch
= IRB
.CreateAnd(TagMismatch
, TagNotIgnored
);
633 Instruction
*CheckTerm
=
634 SplitBlockAndInsertIfThen(TagMismatch
, InsertBefore
, false,
635 MDBuilder(*C
).createBranchWeights(1, 100000));
637 IRB
.SetInsertPoint(CheckTerm
);
638 Value
*OutOfShortGranuleTagRange
=
639 IRB
.CreateICmpUGT(MemTag
, ConstantInt::get(Int8Ty
, 15));
640 Instruction
*CheckFailTerm
=
641 SplitBlockAndInsertIfThen(OutOfShortGranuleTagRange
, CheckTerm
, !Recover
,
642 MDBuilder(*C
).createBranchWeights(1, 100000));
644 IRB
.SetInsertPoint(CheckTerm
);
645 Value
*PtrLowBits
= IRB
.CreateTrunc(IRB
.CreateAnd(PtrLong
, 15), Int8Ty
);
646 PtrLowBits
= IRB
.CreateAdd(
647 PtrLowBits
, ConstantInt::get(Int8Ty
, (1 << AccessSizeIndex
) - 1));
648 Value
*PtrLowBitsOOB
= IRB
.CreateICmpUGE(PtrLowBits
, MemTag
);
649 SplitBlockAndInsertIfThen(PtrLowBitsOOB
, CheckTerm
, false,
650 MDBuilder(*C
).createBranchWeights(1, 100000),
651 nullptr, nullptr, CheckFailTerm
->getParent());
653 IRB
.SetInsertPoint(CheckTerm
);
654 Value
*InlineTagAddr
= IRB
.CreateOr(AddrLong
, 15);
655 InlineTagAddr
= IRB
.CreateIntToPtr(InlineTagAddr
, Int8PtrTy
);
656 Value
*InlineTag
= IRB
.CreateLoad(Int8Ty
, InlineTagAddr
);
657 Value
*InlineTagMismatch
= IRB
.CreateICmpNE(PtrTag
, InlineTag
);
658 SplitBlockAndInsertIfThen(InlineTagMismatch
, CheckTerm
, false,
659 MDBuilder(*C
).createBranchWeights(1, 100000),
660 nullptr, nullptr, CheckFailTerm
->getParent());
662 IRB
.SetInsertPoint(CheckFailTerm
);
664 switch (TargetTriple
.getArch()) {
666 // The signal handler will find the data address in rdi.
667 Asm
= InlineAsm::get(
668 FunctionType::get(IRB
.getVoidTy(), {PtrLong
->getType()}, false),
669 "int3\nnopl " + itostr(0x40 + AccessInfo
) + "(%rax)",
671 /*hasSideEffects=*/true);
673 case Triple::aarch64
:
674 case Triple::aarch64_be
:
675 // The signal handler will find the data address in x0.
676 Asm
= InlineAsm::get(
677 FunctionType::get(IRB
.getVoidTy(), {PtrLong
->getType()}, false),
678 "brk #" + itostr(0x900 + AccessInfo
),
680 /*hasSideEffects=*/true);
683 report_fatal_error("unsupported architecture");
685 IRB
.CreateCall(Asm
, PtrLong
);
687 cast
<BranchInst
>(CheckFailTerm
)->setSuccessor(0, CheckTerm
->getParent());
690 void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic
*MI
) {
692 if (isa
<MemTransferInst
>(MI
)) {
694 isa
<MemMoveInst
>(MI
) ? HWAsanMemmove
: HWAsanMemcpy
,
695 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
696 IRB
.CreatePointerCast(MI
->getOperand(1), IRB
.getInt8PtrTy()),
697 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
698 } else if (isa
<MemSetInst
>(MI
)) {
701 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
702 IRB
.CreateIntCast(MI
->getOperand(1), IRB
.getInt32Ty(), false),
703 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
705 MI
->eraseFromParent();
708 bool HWAddressSanitizer::instrumentMemAccess(Instruction
*I
) {
709 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I
<< "\n");
710 bool IsWrite
= false;
711 unsigned Alignment
= 0;
712 uint64_t TypeSize
= 0;
713 Value
*MaybeMask
= nullptr;
715 if (ClInstrumentMemIntrinsics
&& isa
<MemIntrinsic
>(I
)) {
716 instrumentMemIntrinsic(cast
<MemIntrinsic
>(I
));
721 isInterestingMemoryAccess(I
, &IsWrite
, &TypeSize
, &Alignment
, &MaybeMask
);
727 return false; //FIXME
730 if (isPowerOf2_64(TypeSize
) &&
731 (TypeSize
/ 8 <= (1UL << (kNumberOfAccessSizes
- 1))) &&
732 (Alignment
>= (1UL << Mapping
.Scale
) || Alignment
== 0 ||
733 Alignment
>= TypeSize
/ 8)) {
734 size_t AccessSizeIndex
= TypeSizeToSizeIndex(TypeSize
);
735 if (ClInstrumentWithCalls
) {
736 IRB
.CreateCall(HwasanMemoryAccessCallback
[IsWrite
][AccessSizeIndex
],
737 IRB
.CreatePointerCast(Addr
, IntptrTy
));
739 instrumentMemAccessInline(Addr
, IsWrite
, AccessSizeIndex
, I
);
742 IRB
.CreateCall(HwasanMemoryAccessCallbackSized
[IsWrite
],
743 {IRB
.CreatePointerCast(Addr
, IntptrTy
),
744 ConstantInt::get(IntptrTy
, TypeSize
/ 8)});
746 untagPointerOperand(I
, Addr
);
751 static uint64_t getAllocaSizeInBytes(const AllocaInst
&AI
) {
752 uint64_t ArraySize
= 1;
753 if (AI
.isArrayAllocation()) {
754 const ConstantInt
*CI
= dyn_cast
<ConstantInt
>(AI
.getArraySize());
755 assert(CI
&& "non-constant array size");
756 ArraySize
= CI
->getZExtValue();
758 Type
*Ty
= AI
.getAllocatedType();
759 uint64_t SizeInBytes
= AI
.getModule()->getDataLayout().getTypeAllocSize(Ty
);
760 return SizeInBytes
* ArraySize
;
763 bool HWAddressSanitizer::tagAlloca(IRBuilder
<> &IRB
, AllocaInst
*AI
,
764 Value
*Tag
, size_t Size
) {
765 size_t AlignedSize
= alignTo(Size
, Mapping
.getObjectAlignment());
767 Value
*JustTag
= IRB
.CreateTrunc(Tag
, IRB
.getInt8Ty());
768 if (ClInstrumentWithCalls
) {
769 IRB
.CreateCall(HwasanTagMemoryFunc
,
770 {IRB
.CreatePointerCast(AI
, Int8PtrTy
), JustTag
,
771 ConstantInt::get(IntptrTy
, AlignedSize
)});
773 size_t ShadowSize
= Size
>> Mapping
.Scale
;
774 Value
*ShadowPtr
= memToShadow(IRB
.CreatePointerCast(AI
, IntptrTy
), IRB
);
775 // If this memset is not inlined, it will be intercepted in the hwasan
776 // runtime library. That's OK, because the interceptor skips the checks if
777 // the address is in the shadow region.
778 // FIXME: the interceptor is not as fast as real memset. Consider lowering
779 // llvm.memset right here into either a sequence of stores, or a call to
780 // hwasan_tag_memory.
782 IRB
.CreateMemSet(ShadowPtr
, JustTag
, ShadowSize
, /*Align=*/1);
783 if (Size
!= AlignedSize
) {
785 ConstantInt::get(Int8Ty
, Size
% Mapping
.getObjectAlignment()),
786 IRB
.CreateConstGEP1_32(Int8Ty
, ShadowPtr
, ShadowSize
));
787 IRB
.CreateStore(JustTag
, IRB
.CreateConstGEP1_32(
788 Int8Ty
, IRB
.CreateBitCast(AI
, Int8PtrTy
),
795 static unsigned RetagMask(unsigned AllocaNo
) {
796 // A list of 8-bit numbers that have at most one run of non-zero bits.
797 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
799 // The list does not include the value 255, which is used for UAR.
801 // Because we are more likely to use earlier elements of this list than later
802 // ones, it is sorted in increasing order of probability of collision with a
803 // mask allocated (temporally) nearby. The program that generated this list
805 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
806 static unsigned FastMasks
[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
807 48, 16, 120, 248, 56, 24, 8, 124, 252,
808 60, 28, 12, 4, 126, 254, 62, 30, 14,
809 6, 2, 127, 63, 31, 15, 7, 3, 1};
810 return FastMasks
[AllocaNo
% (sizeof(FastMasks
) / sizeof(FastMasks
[0]))];
813 Value
*HWAddressSanitizer::getNextTagWithCall(IRBuilder
<> &IRB
) {
814 return IRB
.CreateZExt(IRB
.CreateCall(HwasanGenerateTagFunc
), IntptrTy
);
817 Value
*HWAddressSanitizer::getStackBaseTag(IRBuilder
<> &IRB
) {
818 if (ClGenerateTagsWithCalls
)
819 return getNextTagWithCall(IRB
);
822 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
824 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
825 auto GetStackPointerFn
= Intrinsic::getDeclaration(
826 M
, Intrinsic::frameaddress
,
827 IRB
.getInt8PtrTy(M
->getDataLayout().getAllocaAddrSpace()));
828 Value
*StackPointer
= IRB
.CreateCall(
829 GetStackPointerFn
, {Constant::getNullValue(IRB
.getInt32Ty())});
831 // Extract some entropy from the stack pointer for the tags.
832 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
833 // between functions).
834 Value
*StackPointerLong
= IRB
.CreatePointerCast(StackPointer
, IntptrTy
);
836 IRB
.CreateXor(StackPointerLong
, IRB
.CreateLShr(StackPointerLong
, 20),
837 "hwasan.stack.base.tag");
841 Value
*HWAddressSanitizer::getAllocaTag(IRBuilder
<> &IRB
, Value
*StackTag
,
842 AllocaInst
*AI
, unsigned AllocaNo
) {
843 if (ClGenerateTagsWithCalls
)
844 return getNextTagWithCall(IRB
);
845 return IRB
.CreateXor(StackTag
,
846 ConstantInt::get(IntptrTy
, RetagMask(AllocaNo
)));
849 Value
*HWAddressSanitizer::getUARTag(IRBuilder
<> &IRB
, Value
*StackTag
) {
850 if (ClUARRetagToZero
)
851 return ConstantInt::get(IntptrTy
, 0);
852 if (ClGenerateTagsWithCalls
)
853 return getNextTagWithCall(IRB
);
854 return IRB
.CreateXor(StackTag
, ConstantInt::get(IntptrTy
, 0xFFU
));
857 // Add a tag to an address.
858 Value
*HWAddressSanitizer::tagPointer(IRBuilder
<> &IRB
, Type
*Ty
,
859 Value
*PtrLong
, Value
*Tag
) {
860 Value
*TaggedPtrLong
;
862 // Kernel addresses have 0xFF in the most significant byte.
863 Value
*ShiftedTag
= IRB
.CreateOr(
864 IRB
.CreateShl(Tag
, kPointerTagShift
),
865 ConstantInt::get(IntptrTy
, (1ULL << kPointerTagShift
) - 1));
866 TaggedPtrLong
= IRB
.CreateAnd(PtrLong
, ShiftedTag
);
868 // Userspace can simply do OR (tag << 56);
869 Value
*ShiftedTag
= IRB
.CreateShl(Tag
, kPointerTagShift
);
870 TaggedPtrLong
= IRB
.CreateOr(PtrLong
, ShiftedTag
);
872 return IRB
.CreateIntToPtr(TaggedPtrLong
, Ty
);
875 // Remove tag from an address.
876 Value
*HWAddressSanitizer::untagPointer(IRBuilder
<> &IRB
, Value
*PtrLong
) {
877 Value
*UntaggedPtrLong
;
879 // Kernel addresses have 0xFF in the most significant byte.
880 UntaggedPtrLong
= IRB
.CreateOr(PtrLong
,
881 ConstantInt::get(PtrLong
->getType(), 0xFFULL
<< kPointerTagShift
));
883 // Userspace addresses have 0x00.
884 UntaggedPtrLong
= IRB
.CreateAnd(PtrLong
,
885 ConstantInt::get(PtrLong
->getType(), ~(0xFFULL
<< kPointerTagShift
)));
887 return UntaggedPtrLong
;
890 Value
*HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder
<> &IRB
, Type
*Ty
) {
891 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
892 if (TargetTriple
.isAArch64() && TargetTriple
.isAndroid()) {
893 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
894 // in Bionic's libc/private/bionic_tls.h.
895 Function
*ThreadPointerFunc
=
896 Intrinsic::getDeclaration(M
, Intrinsic::thread_pointer
);
897 Value
*SlotPtr
= IRB
.CreatePointerCast(
898 IRB
.CreateConstGEP1_32(IRB
.getInt8Ty(),
899 IRB
.CreateCall(ThreadPointerFunc
), 0x30),
900 Ty
->getPointerTo(0));
904 return ThreadPtrGlobal
;
910 void HWAddressSanitizer::emitPrologue(IRBuilder
<> &IRB
, bool WithFrameRecord
) {
911 if (!Mapping
.InTls
) {
912 LocalDynamicShadow
= getDynamicShadowNonTls(IRB
);
916 if (!WithFrameRecord
&& TargetTriple
.isAndroid()) {
917 LocalDynamicShadow
= getDynamicShadowIfunc(IRB
);
921 Value
*SlotPtr
= getHwasanThreadSlotPtr(IRB
, IntptrTy
);
924 Instruction
*ThreadLong
= IRB
.CreateLoad(IntptrTy
, SlotPtr
);
926 Function
*F
= IRB
.GetInsertBlock()->getParent();
927 if (F
->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") {
928 Value
*ThreadLongEqZero
=
929 IRB
.CreateICmpEQ(ThreadLong
, ConstantInt::get(IntptrTy
, 0));
930 auto *Br
= cast
<BranchInst
>(SplitBlockAndInsertIfThen(
931 ThreadLongEqZero
, cast
<Instruction
>(ThreadLongEqZero
)->getNextNode(),
932 false, MDBuilder(*C
).createBranchWeights(1, 100000)));
934 IRB
.SetInsertPoint(Br
);
935 // FIXME: This should call a new runtime function with a custom calling
936 // convention to avoid needing to spill all arguments here.
937 IRB
.CreateCall(HwasanThreadEnterFunc
);
938 LoadInst
*ReloadThreadLong
= IRB
.CreateLoad(IntptrTy
, SlotPtr
);
940 IRB
.SetInsertPoint(&*Br
->getSuccessor(0)->begin());
941 PHINode
*ThreadLongPhi
= IRB
.CreatePHI(IntptrTy
, 2);
942 ThreadLongPhi
->addIncoming(ThreadLong
, ThreadLong
->getParent());
943 ThreadLongPhi
->addIncoming(ReloadThreadLong
, ReloadThreadLong
->getParent());
944 ThreadLong
= ThreadLongPhi
;
947 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI.
948 Value
*ThreadLongMaybeUntagged
=
949 TargetTriple
.isAArch64() ? ThreadLong
: untagPointer(IRB
, ThreadLong
);
951 if (WithFrameRecord
) {
952 StackBaseTag
= IRB
.CreateAShr(ThreadLong
, 3);
954 // Prepare ring buffer data.
956 if (TargetTriple
.getArch() == Triple::aarch64
)
957 PC
= readRegister(IRB
, "pc");
959 PC
= IRB
.CreatePtrToInt(F
, IntptrTy
);
960 Module
*M
= F
->getParent();
961 auto GetStackPointerFn
= Intrinsic::getDeclaration(
962 M
, Intrinsic::frameaddress
,
963 IRB
.getInt8PtrTy(M
->getDataLayout().getAllocaAddrSpace()));
964 Value
*SP
= IRB
.CreatePtrToInt(
965 IRB
.CreateCall(GetStackPointerFn
,
966 {Constant::getNullValue(IRB
.getInt32Ty())}),
970 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
971 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
972 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this:
973 // 0xSSSSPPPPPPPPPPPP
974 SP
= IRB
.CreateShl(SP
, 44);
976 // Store data to ring buffer.
978 IRB
.CreateIntToPtr(ThreadLongMaybeUntagged
, IntptrTy
->getPointerTo(0));
979 IRB
.CreateStore(IRB
.CreateOr(PC
, SP
), RecordPtr
);
981 // Update the ring buffer. Top byte of ThreadLong defines the size of the
982 // buffer in pages, it must be a power of two, and the start of the buffer
983 // must be aligned by twice that much. Therefore wrap around of the ring
984 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
985 // The use of AShr instead of LShr is due to
986 // https://bugs.llvm.org/show_bug.cgi?id=39030
987 // Runtime library makes sure not to use the highest bit.
988 Value
*WrapMask
= IRB
.CreateXor(
989 IRB
.CreateShl(IRB
.CreateAShr(ThreadLong
, 56), 12, "", true, true),
990 ConstantInt::get(IntptrTy
, (uint64_t)-1));
991 Value
*ThreadLongNew
= IRB
.CreateAnd(
992 IRB
.CreateAdd(ThreadLong
, ConstantInt::get(IntptrTy
, 8)), WrapMask
);
993 IRB
.CreateStore(ThreadLongNew
, SlotPtr
);
996 // Get shadow base address by aligning RecordPtr up.
997 // Note: this is not correct if the pointer is already aligned.
998 // Runtime library will make sure this never happens.
999 LocalDynamicShadow
= IRB
.CreateAdd(
1001 ThreadLongMaybeUntagged
,
1002 ConstantInt::get(IntptrTy
, (1ULL << kShadowBaseAlignment
) - 1)),
1003 ConstantInt::get(IntptrTy
, 1), "hwasan.shadow");
1004 LocalDynamicShadow
= IRB
.CreateIntToPtr(LocalDynamicShadow
, Int8PtrTy
);
1007 Value
*HWAddressSanitizer::readRegister(IRBuilder
<> &IRB
, StringRef Name
) {
1008 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
1009 Function
*ReadRegister
=
1010 Intrinsic::getDeclaration(M
, Intrinsic::read_register
, IntptrTy
);
1011 MDNode
*MD
= MDNode::get(*C
, {MDString::get(*C
, Name
)});
1012 Value
*Args
[] = {MetadataAsValue::get(*C
, MD
)};
1013 return IRB
.CreateCall(ReadRegister
, Args
);
1016 bool HWAddressSanitizer::instrumentLandingPads(
1017 SmallVectorImpl
<Instruction
*> &LandingPadVec
) {
1018 for (auto *LP
: LandingPadVec
) {
1019 IRBuilder
<> IRB(LP
->getNextNode());
1022 {readRegister(IRB
, (TargetTriple
.getArch() == Triple::x86_64
) ? "rsp"
1028 bool HWAddressSanitizer::instrumentStack(
1029 SmallVectorImpl
<AllocaInst
*> &Allocas
,
1030 DenseMap
<AllocaInst
*, std::vector
<DbgDeclareInst
*>> &AllocaDeclareMap
,
1031 SmallVectorImpl
<Instruction
*> &RetVec
, Value
*StackTag
) {
1032 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
1033 // alloca addresses using that. Unfortunately, offsets are not known yet
1034 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
1035 // temp, shift-OR it into each alloca address and xor with the retag mask.
1036 // This generates one extra instruction per alloca use.
1037 for (unsigned N
= 0; N
< Allocas
.size(); ++N
) {
1038 auto *AI
= Allocas
[N
];
1039 IRBuilder
<> IRB(AI
->getNextNode());
1041 // Replace uses of the alloca with tagged address.
1042 Value
*Tag
= getAllocaTag(IRB
, StackTag
, AI
, N
);
1043 Value
*AILong
= IRB
.CreatePointerCast(AI
, IntptrTy
);
1044 Value
*Replacement
= tagPointer(IRB
, AI
->getType(), AILong
, Tag
);
1046 AI
->hasName() ? AI
->getName().str() : "alloca." + itostr(N
);
1047 Replacement
->setName(Name
+ ".hwasan");
1049 AI
->replaceUsesWithIf(Replacement
,
1050 [AILong
](Use
&U
) { return U
.getUser() != AILong
; });
1052 for (auto *DDI
: AllocaDeclareMap
.lookup(AI
)) {
1053 DIExpression
*OldExpr
= DDI
->getExpression();
1054 DIExpression
*NewExpr
= DIExpression::append(
1055 OldExpr
, {dwarf::DW_OP_LLVM_tag_offset
, RetagMask(N
)});
1056 DDI
->setArgOperand(2, MetadataAsValue::get(*C
, NewExpr
));
1059 size_t Size
= getAllocaSizeInBytes(*AI
);
1060 tagAlloca(IRB
, AI
, Tag
, Size
);
1062 for (auto RI
: RetVec
) {
1063 IRB
.SetInsertPoint(RI
);
1065 // Re-tag alloca memory with the special UAR tag.
1066 Value
*Tag
= getUARTag(IRB
, StackTag
);
1067 tagAlloca(IRB
, AI
, Tag
, alignTo(Size
, Mapping
.getObjectAlignment()));
1074 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst
&AI
) {
1075 return (AI
.getAllocatedType()->isSized() &&
1076 // FIXME: instrument dynamic allocas, too
1077 AI
.isStaticAlloca() &&
1078 // alloca() may be called with 0 size, ignore it.
1079 getAllocaSizeInBytes(AI
) > 0 &&
1080 // We are only interested in allocas not promotable to registers.
1081 // Promotable allocas are common under -O0.
1082 !isAllocaPromotable(&AI
) &&
1083 // inalloca allocas are not treated as static, and we don't want
1084 // dynamic alloca instrumentation for them as well.
1085 !AI
.isUsedWithInAlloca() &&
1086 // swifterror allocas are register promoted by ISel
1087 !AI
.isSwiftError());
1090 bool HWAddressSanitizer::sanitizeFunction(Function
&F
) {
1091 if (&F
== HwasanCtorFunction
)
1094 if (!F
.hasFnAttribute(Attribute::SanitizeHWAddress
))
1097 LLVM_DEBUG(dbgs() << "Function: " << F
.getName() << "\n");
1099 SmallVector
<Instruction
*, 16> ToInstrument
;
1100 SmallVector
<AllocaInst
*, 8> AllocasToInstrument
;
1101 SmallVector
<Instruction
*, 8> RetVec
;
1102 SmallVector
<Instruction
*, 8> LandingPadVec
;
1103 DenseMap
<AllocaInst
*, std::vector
<DbgDeclareInst
*>> AllocaDeclareMap
;
1104 for (auto &BB
: F
) {
1105 for (auto &Inst
: BB
) {
1106 if (ClInstrumentStack
)
1107 if (AllocaInst
*AI
= dyn_cast
<AllocaInst
>(&Inst
)) {
1108 if (isInterestingAlloca(*AI
))
1109 AllocasToInstrument
.push_back(AI
);
1113 if (isa
<ReturnInst
>(Inst
) || isa
<ResumeInst
>(Inst
) ||
1114 isa
<CleanupReturnInst
>(Inst
))
1115 RetVec
.push_back(&Inst
);
1117 if (auto *DDI
= dyn_cast
<DbgDeclareInst
>(&Inst
))
1118 if (auto *Alloca
= dyn_cast_or_null
<AllocaInst
>(DDI
->getAddress()))
1119 AllocaDeclareMap
[Alloca
].push_back(DDI
);
1121 if (InstrumentLandingPads
&& isa
<LandingPadInst
>(Inst
))
1122 LandingPadVec
.push_back(&Inst
);
1124 Value
*MaybeMask
= nullptr;
1128 Value
*Addr
= isInterestingMemoryAccess(&Inst
, &IsWrite
, &TypeSize
,
1129 &Alignment
, &MaybeMask
);
1130 if (Addr
|| isa
<MemIntrinsic
>(Inst
))
1131 ToInstrument
.push_back(&Inst
);
1135 initializeCallbacks(*F
.getParent());
1137 if (!LandingPadVec
.empty())
1138 instrumentLandingPads(LandingPadVec
);
1140 if (AllocasToInstrument
.empty() && F
.hasPersonalityFn() &&
1141 F
.getPersonalityFn()->getName() == kHwasanPersonalityThunkName
) {
1142 // __hwasan_personality_thunk is a no-op for functions without an
1143 // instrumented stack, so we can drop it.
1144 F
.setPersonalityFn(nullptr);
1147 if (AllocasToInstrument
.empty() && ToInstrument
.empty())
1150 assert(!LocalDynamicShadow
);
1152 Instruction
*InsertPt
= &*F
.getEntryBlock().begin();
1153 IRBuilder
<> EntryIRB(InsertPt
);
1154 emitPrologue(EntryIRB
,
1155 /*WithFrameRecord*/ ClRecordStackHistory
&&
1156 !AllocasToInstrument
.empty());
1158 bool Changed
= false;
1159 if (!AllocasToInstrument
.empty()) {
1161 ClGenerateTagsWithCalls
? nullptr : getStackBaseTag(EntryIRB
);
1162 Changed
|= instrumentStack(AllocasToInstrument
, AllocaDeclareMap
, RetVec
,
1166 // Pad and align each of the allocas that we instrumented to stop small
1167 // uninteresting allocas from hiding in instrumented alloca's padding and so
1168 // that we have enough space to store real tags for short granules.
1169 DenseMap
<AllocaInst
*, AllocaInst
*> AllocaToPaddedAllocaMap
;
1170 for (AllocaInst
*AI
: AllocasToInstrument
) {
1171 uint64_t Size
= getAllocaSizeInBytes(*AI
);
1172 uint64_t AlignedSize
= alignTo(Size
, Mapping
.getObjectAlignment());
1174 std::max(AI
->getAlignment(), Mapping
.getObjectAlignment()));
1175 if (Size
!= AlignedSize
) {
1176 Type
*AllocatedType
= AI
->getAllocatedType();
1177 if (AI
->isArrayAllocation()) {
1178 uint64_t ArraySize
=
1179 cast
<ConstantInt
>(AI
->getArraySize())->getZExtValue();
1180 AllocatedType
= ArrayType::get(AllocatedType
, ArraySize
);
1182 Type
*TypeWithPadding
= StructType::get(
1183 AllocatedType
, ArrayType::get(Int8Ty
, AlignedSize
- Size
));
1184 auto *NewAI
= new AllocaInst(
1185 TypeWithPadding
, AI
->getType()->getAddressSpace(), nullptr, "", AI
);
1186 NewAI
->takeName(AI
);
1187 NewAI
->setAlignment(AI
->getAlignment());
1188 NewAI
->setUsedWithInAlloca(AI
->isUsedWithInAlloca());
1189 NewAI
->setSwiftError(AI
->isSwiftError());
1190 NewAI
->copyMetadata(*AI
);
1191 auto *Bitcast
= new BitCastInst(NewAI
, AI
->getType(), "", AI
);
1192 AI
->replaceAllUsesWith(Bitcast
);
1193 AllocaToPaddedAllocaMap
[AI
] = NewAI
;
1197 if (!AllocaToPaddedAllocaMap
.empty()) {
1199 for (auto &Inst
: BB
)
1200 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&Inst
))
1202 dyn_cast_or_null
<AllocaInst
>(DVI
->getVariableLocation()))
1203 if (auto *NewAI
= AllocaToPaddedAllocaMap
.lookup(AI
))
1205 0, MetadataAsValue::get(*C
, LocalAsMetadata::get(NewAI
)));
1206 for (auto &P
: AllocaToPaddedAllocaMap
)
1207 P
.first
->eraseFromParent();
1210 // If we split the entry block, move any allocas that were originally in the
1211 // entry block back into the entry block so that they aren't treated as
1213 if (EntryIRB
.GetInsertBlock() != &F
.getEntryBlock()) {
1214 InsertPt
= &*F
.getEntryBlock().begin();
1215 for (auto II
= EntryIRB
.GetInsertBlock()->begin(),
1216 IE
= EntryIRB
.GetInsertBlock()->end();
1218 Instruction
*I
= &*II
++;
1219 if (auto *AI
= dyn_cast
<AllocaInst
>(I
))
1220 if (isa
<ConstantInt
>(AI
->getArraySize()))
1221 I
->moveBefore(InsertPt
);
1225 for (auto Inst
: ToInstrument
)
1226 Changed
|= instrumentMemAccess(Inst
);
1228 LocalDynamicShadow
= nullptr;
1229 StackBaseTag
= nullptr;
1234 void HWAddressSanitizer::instrumentGlobal(GlobalVariable
*GV
, uint8_t Tag
) {
1235 Constant
*Initializer
= GV
->getInitializer();
1236 uint64_t SizeInBytes
=
1237 M
.getDataLayout().getTypeAllocSize(Initializer
->getType());
1238 uint64_t NewSize
= alignTo(SizeInBytes
, Mapping
.getObjectAlignment());
1239 if (SizeInBytes
!= NewSize
) {
1240 // Pad the initializer out to the next multiple of 16 bytes and add the
1241 // required short granule tag.
1242 std::vector
<uint8_t> Init(NewSize
- SizeInBytes
, 0);
1244 Constant
*Padding
= ConstantDataArray::get(*C
, Init
);
1245 Initializer
= ConstantStruct::getAnon({Initializer
, Padding
});
1248 auto *NewGV
= new GlobalVariable(M
, Initializer
->getType(), GV
->isConstant(),
1249 GlobalValue::ExternalLinkage
, Initializer
,
1250 GV
->getName() + ".hwasan");
1251 NewGV
->copyAttributesFrom(GV
);
1252 NewGV
->setLinkage(GlobalValue::PrivateLinkage
);
1253 NewGV
->copyMetadata(GV
, 0);
1254 NewGV
->setAlignment(
1255 std::max(GV
->getAlignment(), Mapping
.getObjectAlignment()));
1257 // It is invalid to ICF two globals that have different tags. In the case
1258 // where the size of the global is a multiple of the tag granularity the
1259 // contents of the globals may be the same but the tags (i.e. symbol values)
1260 // may be different, and the symbols are not considered during ICF. In the
1261 // case where the size is not a multiple of the granularity, the short granule
1262 // tags would discriminate two globals with different tags, but there would
1263 // otherwise be nothing stopping such a global from being incorrectly ICF'd
1264 // with an uninstrumented (i.e. tag 0) global that happened to have the short
1265 // granule tag in the last byte.
1266 NewGV
->setUnnamedAddr(GlobalValue::UnnamedAddr::None
);
1268 // Descriptor format (assuming little-endian):
1269 // bytes 0-3: relative address of global
1270 // bytes 4-6: size of global (16MB ought to be enough for anyone, but in case
1271 // it isn't, we create multiple descriptors)
1273 auto *DescriptorTy
= StructType::get(Int32Ty
, Int32Ty
);
1274 const uint64_t MaxDescriptorSize
= 0xfffff0;
1275 for (uint64_t DescriptorPos
= 0; DescriptorPos
< SizeInBytes
;
1276 DescriptorPos
+= MaxDescriptorSize
) {
1278 new GlobalVariable(M
, DescriptorTy
, true, GlobalValue::PrivateLinkage
,
1279 nullptr, GV
->getName() + ".hwasan.descriptor");
1280 auto *GVRelPtr
= ConstantExpr::getTrunc(
1281 ConstantExpr::getAdd(
1282 ConstantExpr::getSub(
1283 ConstantExpr::getPtrToInt(NewGV
, Int64Ty
),
1284 ConstantExpr::getPtrToInt(Descriptor
, Int64Ty
)),
1285 ConstantInt::get(Int64Ty
, DescriptorPos
)),
1287 uint32_t Size
= std::min(SizeInBytes
- DescriptorPos
, MaxDescriptorSize
);
1288 auto *SizeAndTag
= ConstantInt::get(Int32Ty
, Size
| (uint32_t(Tag
) << 24));
1289 Descriptor
->setComdat(NewGV
->getComdat());
1290 Descriptor
->setInitializer(ConstantStruct::getAnon({GVRelPtr
, SizeAndTag
}));
1291 Descriptor
->setSection("hwasan_globals");
1292 Descriptor
->setMetadata(LLVMContext::MD_associated
,
1293 MDNode::get(*C
, ValueAsMetadata::get(NewGV
)));
1294 appendToCompilerUsed(M
, Descriptor
);
1297 Constant
*Aliasee
= ConstantExpr::getIntToPtr(
1298 ConstantExpr::getAdd(
1299 ConstantExpr::getPtrToInt(NewGV
, Int64Ty
),
1300 ConstantInt::get(Int64Ty
, uint64_t(Tag
) << kPointerTagShift
)),
1302 auto *Alias
= GlobalAlias::create(GV
->getValueType(), GV
->getAddressSpace(),
1303 GV
->getLinkage(), "", Aliasee
, &M
);
1304 Alias
->setVisibility(GV
->getVisibility());
1305 Alias
->takeName(GV
);
1306 GV
->replaceAllUsesWith(Alias
);
1307 GV
->eraseFromParent();
1310 void HWAddressSanitizer::instrumentGlobals() {
1311 // Start by creating a note that contains pointers to the list of global
1312 // descriptors. Adding a note to the output file will cause the linker to
1313 // create a PT_NOTE program header pointing to the note that we can use to
1314 // find the descriptor list starting from the program headers. A function
1315 // provided by the runtime initializes the shadow memory for the globals by
1316 // accessing the descriptor list via the note. The dynamic loader needs to
1317 // call this function whenever a library is loaded.
1319 // The reason why we use a note for this instead of a more conventional
1320 // approach of having a global constructor pass a descriptor list pointer to
1321 // the runtime is because of an order of initialization problem. With
1322 // constructors we can encounter the following problematic scenario:
1324 // 1) library A depends on library B and also interposes one of B's symbols
1325 // 2) B's constructors are called before A's (as required for correctness)
1326 // 3) during construction, B accesses one of its "own" globals (actually
1327 // interposed by A) and triggers a HWASAN failure due to the initialization
1328 // for A not having happened yet
1330 // Even without interposition it is possible to run into similar situations in
1331 // cases where two libraries mutually depend on each other.
1333 // We only need one note per binary, so put everything for the note in a
1335 Comdat
*NoteComdat
= M
.getOrInsertComdat(kHwasanNoteName
);
1337 Type
*Int8Arr0Ty
= ArrayType::get(Int8Ty
, 0);
1339 new GlobalVariable(M
, Int8Arr0Ty
, true, GlobalVariable::ExternalLinkage
,
1340 nullptr, "__start_hwasan_globals");
1341 Start
->setVisibility(GlobalValue::HiddenVisibility
);
1342 Start
->setDSOLocal(true);
1344 new GlobalVariable(M
, Int8Arr0Ty
, true, GlobalVariable::ExternalLinkage
,
1345 nullptr, "__stop_hwasan_globals");
1346 Stop
->setVisibility(GlobalValue::HiddenVisibility
);
1347 Stop
->setDSOLocal(true);
1349 // Null-terminated so actually 8 bytes, which are required in order to align
1350 // the note properly.
1351 auto *Name
= ConstantDataArray::get(*C
, "LLVM\0\0\0");
1353 auto *NoteTy
= StructType::get(Int32Ty
, Int32Ty
, Int32Ty
, Name
->getType(),
1356 new GlobalVariable(M
, NoteTy
, /*isConstantGlobal=*/true,
1357 GlobalValue::PrivateLinkage
, nullptr, kHwasanNoteName
);
1358 Note
->setSection(".note.hwasan.globals");
1359 Note
->setComdat(NoteComdat
);
1360 Note
->setAlignment(4);
1361 Note
->setDSOLocal(true);
1363 // The pointers in the note need to be relative so that the note ends up being
1364 // placed in rodata, which is the standard location for notes.
1365 auto CreateRelPtr
= [&](Constant
*Ptr
) {
1366 return ConstantExpr::getTrunc(
1367 ConstantExpr::getSub(ConstantExpr::getPtrToInt(Ptr
, Int64Ty
),
1368 ConstantExpr::getPtrToInt(Note
, Int64Ty
)),
1371 Note
->setInitializer(ConstantStruct::getAnon(
1372 {ConstantInt::get(Int32Ty
, 8), // n_namesz
1373 ConstantInt::get(Int32Ty
, 8), // n_descsz
1374 ConstantInt::get(Int32Ty
, ELF::NT_LLVM_HWASAN_GLOBALS
), // n_type
1375 Name
, CreateRelPtr(Start
), CreateRelPtr(Stop
)}));
1376 appendToCompilerUsed(M
, Note
);
1378 // Create a zero-length global in hwasan_globals so that the linker will
1379 // always create start and stop symbols.
1380 auto Dummy
= new GlobalVariable(
1381 M
, Int8Arr0Ty
, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage
,
1382 Constant::getNullValue(Int8Arr0Ty
), "hwasan.dummy.global");
1383 Dummy
->setSection("hwasan_globals");
1384 Dummy
->setComdat(NoteComdat
);
1385 Dummy
->setMetadata(LLVMContext::MD_associated
,
1386 MDNode::get(*C
, ValueAsMetadata::get(Note
)));
1387 appendToCompilerUsed(M
, Dummy
);
1389 std::vector
<GlobalVariable
*> Globals
;
1390 for (GlobalVariable
&GV
: M
.globals()) {
1391 if (GV
.isDeclarationForLinker() || GV
.getName().startswith("llvm.") ||
1395 // Common symbols can't have aliases point to them, so they can't be tagged.
1396 if (GV
.hasCommonLinkage())
1399 // Globals with custom sections may be used in __start_/__stop_ enumeration,
1400 // which would be broken both by adding tags and potentially by the extra
1401 // padding/alignment that we insert.
1402 if (GV
.hasSection())
1405 Globals
.push_back(&GV
);
1409 Hasher
.update(M
.getSourceFileName());
1410 MD5::MD5Result Hash
;
1412 uint8_t Tag
= Hash
[0];
1414 for (GlobalVariable
*GV
: Globals
) {
1415 // Skip tag 0 in order to avoid collisions with untagged memory.
1418 instrumentGlobal(GV
, Tag
++);
1422 void HWAddressSanitizer::instrumentPersonalityFunctions() {
1423 // We need to untag stack frames as we unwind past them. That is the job of
1424 // the personality function wrapper, which either wraps an existing
1425 // personality function or acts as a personality function on its own. Each
1426 // function that has a personality function or that can be unwound past has
1427 // its personality function changed to a thunk that calls the personality
1428 // function wrapper in the runtime.
1429 MapVector
<Constant
*, std::vector
<Function
*>> PersonalityFns
;
1430 for (Function
&F
: M
) {
1431 if (F
.isDeclaration() || !F
.hasFnAttribute(Attribute::SanitizeHWAddress
))
1434 if (F
.hasPersonalityFn()) {
1435 PersonalityFns
[F
.getPersonalityFn()->stripPointerCasts()].push_back(&F
);
1436 } else if (!F
.hasFnAttribute(Attribute::NoUnwind
)) {
1437 PersonalityFns
[nullptr].push_back(&F
);
1441 if (PersonalityFns
.empty())
1444 FunctionCallee HwasanPersonalityWrapper
= M
.getOrInsertFunction(
1445 "__hwasan_personality_wrapper", Int32Ty
, Int32Ty
, Int32Ty
, Int64Ty
,
1446 Int8PtrTy
, Int8PtrTy
, Int8PtrTy
, Int8PtrTy
, Int8PtrTy
);
1447 FunctionCallee UnwindGetGR
= M
.getOrInsertFunction("_Unwind_GetGR", VoidTy
);
1448 FunctionCallee UnwindGetCFA
= M
.getOrInsertFunction("_Unwind_GetCFA", VoidTy
);
1450 for (auto &P
: PersonalityFns
) {
1451 std::string ThunkName
= kHwasanPersonalityThunkName
;
1453 ThunkName
+= ("." + P
.first
->getName()).str();
1454 FunctionType
*ThunkFnTy
= FunctionType::get(
1455 Int32Ty
, {Int32Ty
, Int32Ty
, Int64Ty
, Int8PtrTy
, Int8PtrTy
}, false);
1456 bool IsLocal
= P
.first
&& (!isa
<GlobalValue
>(P
.first
) ||
1457 cast
<GlobalValue
>(P
.first
)->hasLocalLinkage());
1458 auto *ThunkFn
= Function::Create(ThunkFnTy
,
1459 IsLocal
? GlobalValue::InternalLinkage
1460 : GlobalValue::LinkOnceODRLinkage
,
1463 ThunkFn
->setVisibility(GlobalValue::HiddenVisibility
);
1464 ThunkFn
->setComdat(M
.getOrInsertComdat(ThunkName
));
1467 auto *BB
= BasicBlock::Create(*C
, "entry", ThunkFn
);
1468 IRBuilder
<> IRB(BB
);
1469 CallInst
*WrapperCall
= IRB
.CreateCall(
1470 HwasanPersonalityWrapper
,
1471 {ThunkFn
->getArg(0), ThunkFn
->getArg(1), ThunkFn
->getArg(2),
1472 ThunkFn
->getArg(3), ThunkFn
->getArg(4),
1473 P
.first
? IRB
.CreateBitCast(P
.first
, Int8PtrTy
)
1474 : Constant::getNullValue(Int8PtrTy
),
1475 IRB
.CreateBitCast(UnwindGetGR
.getCallee(), Int8PtrTy
),
1476 IRB
.CreateBitCast(UnwindGetCFA
.getCallee(), Int8PtrTy
)});
1477 WrapperCall
->setTailCall();
1478 IRB
.CreateRet(WrapperCall
);
1480 for (Function
*F
: P
.second
)
1481 F
->setPersonalityFn(ThunkFn
);
1485 void HWAddressSanitizer::ShadowMapping::init(Triple
&TargetTriple
) {
1486 Scale
= kDefaultShadowScale
;
1487 if (ClMappingOffset
.getNumOccurrences() > 0) {
1490 Offset
= ClMappingOffset
;
1491 } else if (ClEnableKhwasan
|| ClInstrumentWithCalls
) {
1495 } else if (ClWithIfunc
) {
1498 Offset
= kDynamicShadowSentinel
;
1499 } else if (ClWithTls
) {
1502 Offset
= kDynamicShadowSentinel
;
1506 Offset
= kDynamicShadowSentinel
;