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/Analysis/PostDominators.h"
21 #include "llvm/Analysis/StackSafetyAnalysis.h"
22 #include "llvm/Analysis/ValueTracking.h"
23 #include "llvm/BinaryFormat/ELF.h"
24 #include "llvm/IR/Attributes.h"
25 #include "llvm/IR/BasicBlock.h"
26 #include "llvm/IR/Constant.h"
27 #include "llvm/IR/Constants.h"
28 #include "llvm/IR/DataLayout.h"
29 #include "llvm/IR/DebugInfoMetadata.h"
30 #include "llvm/IR/DerivedTypes.h"
31 #include "llvm/IR/Dominators.h"
32 #include "llvm/IR/Function.h"
33 #include "llvm/IR/IRBuilder.h"
34 #include "llvm/IR/InlineAsm.h"
35 #include "llvm/IR/InstVisitor.h"
36 #include "llvm/IR/Instruction.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/IR/IntrinsicInst.h"
39 #include "llvm/IR/Intrinsics.h"
40 #include "llvm/IR/LLVMContext.h"
41 #include "llvm/IR/MDBuilder.h"
42 #include "llvm/IR/Module.h"
43 #include "llvm/IR/Type.h"
44 #include "llvm/IR/Value.h"
45 #include "llvm/InitializePasses.h"
46 #include "llvm/Pass.h"
47 #include "llvm/PassRegistry.h"
48 #include "llvm/Support/Casting.h"
49 #include "llvm/Support/CommandLine.h"
50 #include "llvm/Support/Debug.h"
51 #include "llvm/Support/raw_ostream.h"
52 #include "llvm/Transforms/Instrumentation.h"
53 #include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
54 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
55 #include "llvm/Transforms/Utils/ModuleUtils.h"
56 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
61 #define DEBUG_TYPE "hwasan"
63 const char kHwasanModuleCtorName
[] = "hwasan.module_ctor";
64 const char kHwasanNoteName
[] = "hwasan.note";
65 const char kHwasanInitName
[] = "__hwasan_init";
66 const char kHwasanPersonalityThunkName
[] = "__hwasan_personality_thunk";
68 const char kHwasanShadowMemoryDynamicAddress
[] =
69 "__hwasan_shadow_memory_dynamic_address";
71 // Accesses sizes are powers of two: 1, 2, 4, 8, 16.
72 static const size_t kNumberOfAccessSizes
= 5;
74 static const size_t kDefaultShadowScale
= 4;
75 static const uint64_t kDynamicShadowSentinel
=
76 std::numeric_limits
<uint64_t>::max();
78 static const unsigned kShadowBaseAlignment
= 32;
80 static cl::opt
<std::string
>
81 ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix",
82 cl::desc("Prefix for memory access callbacks"),
83 cl::Hidden
, cl::init("__hwasan_"));
85 static cl::opt
<bool> ClInstrumentWithCalls(
86 "hwasan-instrument-with-calls",
87 cl::desc("instrument reads and writes with callbacks"), cl::Hidden
,
90 static cl::opt
<bool> ClInstrumentReads("hwasan-instrument-reads",
91 cl::desc("instrument read instructions"),
92 cl::Hidden
, cl::init(true));
95 ClInstrumentWrites("hwasan-instrument-writes",
96 cl::desc("instrument write instructions"), cl::Hidden
,
99 static cl::opt
<bool> ClInstrumentAtomics(
100 "hwasan-instrument-atomics",
101 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden
,
104 static cl::opt
<bool> ClInstrumentByval("hwasan-instrument-byval",
105 cl::desc("instrument byval arguments"),
106 cl::Hidden
, cl::init(true));
109 ClRecover("hwasan-recover",
110 cl::desc("Enable recovery mode (continue-after-error)."),
111 cl::Hidden
, cl::init(false));
113 static cl::opt
<bool> ClInstrumentStack("hwasan-instrument-stack",
114 cl::desc("instrument stack (allocas)"),
115 cl::Hidden
, cl::init(true));
118 ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden
, cl::init(true),
119 cl::Hidden
, cl::desc("Use Stack Safety analysis results"),
123 ClUseAfterScope("hwasan-use-after-scope",
124 cl::desc("detect use after scope within function"),
125 cl::Hidden
, cl::init(false));
127 static cl::opt
<bool> ClUARRetagToZero(
128 "hwasan-uar-retag-to-zero",
129 cl::desc("Clear alloca tags before returning from the function to allow "
130 "non-instrumented and instrumented function calls mix. When set "
131 "to false, allocas are retagged before returning from the "
132 "function to detect use after return."),
133 cl::Hidden
, cl::init(true));
135 static cl::opt
<bool> ClGenerateTagsWithCalls(
136 "hwasan-generate-tags-with-calls",
137 cl::desc("generate new tags with runtime library calls"), cl::Hidden
,
140 static cl::opt
<bool> ClGlobals("hwasan-globals", cl::desc("Instrument globals"),
141 cl::Hidden
, cl::init(false), cl::ZeroOrMore
);
143 static cl::opt
<int> ClMatchAllTag(
144 "hwasan-match-all-tag",
145 cl::desc("don't report bad accesses via pointers with this tag"),
146 cl::Hidden
, cl::init(-1));
149 ClEnableKhwasan("hwasan-kernel",
150 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
151 cl::Hidden
, cl::init(false));
153 // These flags allow to change the shadow mapping and control how shadow memory
154 // is accessed. The shadow mapping looks like:
155 // Shadow = (Mem >> scale) + offset
157 static cl::opt
<uint64_t>
158 ClMappingOffset("hwasan-mapping-offset",
159 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
160 cl::Hidden
, cl::init(0));
163 ClWithIfunc("hwasan-with-ifunc",
164 cl::desc("Access dynamic shadow through an ifunc global on "
165 "platforms that support this"),
166 cl::Hidden
, cl::init(false));
168 static cl::opt
<bool> ClWithTls(
170 cl::desc("Access dynamic shadow through an thread-local pointer on "
171 "platforms that support this"),
172 cl::Hidden
, cl::init(true));
175 ClRecordStackHistory("hwasan-record-stack-history",
176 cl::desc("Record stack frames with tagged allocations "
177 "in a thread-local ring buffer"),
178 cl::Hidden
, cl::init(true));
180 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
181 cl::desc("instrument memory intrinsics"),
182 cl::Hidden
, cl::init(true));
185 ClInstrumentLandingPads("hwasan-instrument-landing-pads",
186 cl::desc("instrument landing pads"), cl::Hidden
,
187 cl::init(false), cl::ZeroOrMore
);
189 static cl::opt
<bool> ClUseShortGranules(
190 "hwasan-use-short-granules",
191 cl::desc("use short granules in allocas and outlined checks"), cl::Hidden
,
192 cl::init(false), cl::ZeroOrMore
);
194 static cl::opt
<bool> ClInstrumentPersonalityFunctions(
195 "hwasan-instrument-personality-functions",
196 cl::desc("instrument personality functions"), cl::Hidden
, cl::init(false),
199 static cl::opt
<bool> ClInlineAllChecks("hwasan-inline-all-checks",
200 cl::desc("inline all checks"),
201 cl::Hidden
, cl::init(false));
203 // Enabled from clang by "-fsanitize-hwaddress-experimental-aliasing".
204 static cl::opt
<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
205 cl::desc("Use page aliasing in HWASan"),
206 cl::Hidden
, cl::init(false));
210 bool shouldUsePageAliases(const Triple
&TargetTriple
) {
211 return ClUsePageAliases
&& TargetTriple
.getArch() == Triple::x86_64
;
214 bool shouldInstrumentStack(const Triple
&TargetTriple
) {
215 return !shouldUsePageAliases(TargetTriple
) && ClInstrumentStack
;
218 bool shouldInstrumentWithCalls(const Triple
&TargetTriple
) {
219 return ClInstrumentWithCalls
|| TargetTriple
.getArch() == Triple::x86_64
;
222 bool mightUseStackSafetyAnalysis(bool DisableOptimization
) {
223 return ClUseStackSafety
.getNumOccurrences() ? ClUseStackSafety
224 : !DisableOptimization
;
227 bool shouldUseStackSafetyAnalysis(const Triple
&TargetTriple
,
228 bool DisableOptimization
) {
229 return shouldInstrumentStack(TargetTriple
) &&
230 mightUseStackSafetyAnalysis(DisableOptimization
);
233 bool shouldDetectUseAfterScope(const Triple
&TargetTriple
) {
234 return ClUseAfterScope
&& shouldInstrumentStack(TargetTriple
);
237 /// An instrumentation pass implementing detection of addressability bugs
238 /// using tagged pointers.
239 class HWAddressSanitizer
{
243 SmallVector
<IntrinsicInst
*, 2> LifetimeStart
;
244 SmallVector
<IntrinsicInst
*, 2> LifetimeEnd
;
248 HWAddressSanitizer(Module
&M
, bool CompileKernel
, bool Recover
,
249 const StackSafetyGlobalInfo
*SSI
)
251 this->Recover
= ClRecover
.getNumOccurrences() > 0 ? ClRecover
: Recover
;
252 this->CompileKernel
= ClEnableKhwasan
.getNumOccurrences() > 0
259 void setSSI(const StackSafetyGlobalInfo
*S
) { SSI
= S
; }
261 DenseMap
<AllocaInst
*, AllocaInst
*> padInterestingAllocas(
262 const MapVector
<AllocaInst
*, AllocaInfo
> &AllocasToInstrument
);
263 bool sanitizeFunction(Function
&F
,
264 llvm::function_ref
<const DominatorTree
&()> GetDT
,
265 llvm::function_ref
<const PostDominatorTree
&()> GetPDT
);
266 void initializeModule();
267 void createHwasanCtorComdat();
269 void initializeCallbacks(Module
&M
);
271 Value
*getOpaqueNoopCast(IRBuilder
<> &IRB
, Value
*Val
);
273 Value
*getDynamicShadowIfunc(IRBuilder
<> &IRB
);
274 Value
*getShadowNonTls(IRBuilder
<> &IRB
);
276 void untagPointerOperand(Instruction
*I
, Value
*Addr
);
277 Value
*memToShadow(Value
*Shadow
, IRBuilder
<> &IRB
);
278 void instrumentMemAccessInline(Value
*Ptr
, bool IsWrite
,
279 unsigned AccessSizeIndex
,
280 Instruction
*InsertBefore
);
281 void instrumentMemIntrinsic(MemIntrinsic
*MI
);
282 bool instrumentMemAccess(InterestingMemoryOperand
&O
);
283 bool ignoreAccess(Value
*Ptr
);
284 void getInterestingMemoryOperands(
285 Instruction
*I
, SmallVectorImpl
<InterestingMemoryOperand
> &Interesting
);
287 bool isInterestingAlloca(const AllocaInst
&AI
);
288 void tagAlloca(IRBuilder
<> &IRB
, AllocaInst
*AI
, Value
*Tag
, size_t Size
);
289 Value
*tagPointer(IRBuilder
<> &IRB
, Type
*Ty
, Value
*PtrLong
, Value
*Tag
);
290 Value
*untagPointer(IRBuilder
<> &IRB
, Value
*PtrLong
);
291 bool instrumentStack(
292 MapVector
<AllocaInst
*, AllocaInfo
> &AllocasToInstrument
,
293 SmallVector
<Instruction
*, 4> &UnrecognizedLifetimes
,
294 DenseMap
<AllocaInst
*, std::vector
<DbgVariableIntrinsic
*>> &AllocaDbgMap
,
295 SmallVectorImpl
<Instruction
*> &RetVec
, Value
*StackTag
,
296 llvm::function_ref
<const DominatorTree
&()> GetDT
,
297 llvm::function_ref
<const PostDominatorTree
&()> GetPDT
);
298 Value
*readRegister(IRBuilder
<> &IRB
, StringRef Name
);
299 bool instrumentLandingPads(SmallVectorImpl
<Instruction
*> &RetVec
);
300 Value
*getNextTagWithCall(IRBuilder
<> &IRB
);
301 Value
*getStackBaseTag(IRBuilder
<> &IRB
);
302 Value
*getAllocaTag(IRBuilder
<> &IRB
, Value
*StackTag
, AllocaInst
*AI
,
304 Value
*getUARTag(IRBuilder
<> &IRB
, Value
*StackTag
);
306 Value
*getHwasanThreadSlotPtr(IRBuilder
<> &IRB
, Type
*Ty
);
307 Value
*applyTagMask(IRBuilder
<> &IRB
, Value
*OldTag
);
308 unsigned retagMask(unsigned AllocaNo
);
310 void emitPrologue(IRBuilder
<> &IRB
, bool WithFrameRecord
);
312 void instrumentGlobal(GlobalVariable
*GV
, uint8_t Tag
);
313 void instrumentGlobals();
315 void instrumentPersonalityFunctions();
320 const StackSafetyGlobalInfo
*SSI
;
322 FunctionCallee HWAsanMemmove
, HWAsanMemcpy
, HWAsanMemset
;
323 FunctionCallee HWAsanHandleVfork
;
325 /// This struct defines the shadow mapping using the rule:
326 /// shadow = (mem >> Scale) + Offset.
327 /// If InGlobal is true, then
328 /// extern char __hwasan_shadow[];
329 /// shadow = (mem >> Scale) + &__hwasan_shadow
330 /// If InTls is true, then
331 /// extern char *__hwasan_tls;
332 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
334 /// If WithFrameRecord is true, then __hwasan_tls will be used to access the
335 /// ring buffer for storing stack allocations on targets that support it.
336 struct ShadowMapping
{
341 bool WithFrameRecord
;
343 void init(Triple
&TargetTriple
, bool InstrumentWithCalls
);
344 unsigned getObjectAlignment() const { return 1U << Scale
; }
347 ShadowMapping Mapping
;
349 Type
*VoidTy
= Type::getVoidTy(M
.getContext());
354 Type
*Int64Ty
= Type::getInt64Ty(M
.getContext());
359 bool UseShortGranules
;
360 bool InstrumentLandingPads
;
361 bool InstrumentWithCalls
;
362 bool InstrumentStack
;
363 bool DetectUseAfterScope
;
366 bool HasMatchAllTag
= false;
367 uint8_t MatchAllTag
= 0;
369 unsigned PointerTagShift
;
370 uint64_t TagMaskByte
;
372 Function
*HwasanCtorFunction
;
374 FunctionCallee HwasanMemoryAccessCallback
[2][kNumberOfAccessSizes
];
375 FunctionCallee HwasanMemoryAccessCallbackSized
[2];
377 FunctionCallee HwasanTagMemoryFunc
;
378 FunctionCallee HwasanGenerateTagFunc
;
380 Constant
*ShadowGlobal
;
382 Value
*ShadowBase
= nullptr;
383 Value
*StackBaseTag
= nullptr;
384 GlobalValue
*ThreadPtrGlobal
= nullptr;
387 class HWAddressSanitizerLegacyPass
: public FunctionPass
{
389 // Pass identification, replacement for typeid.
392 explicit HWAddressSanitizerLegacyPass(bool CompileKernel
= false,
393 bool Recover
= false,
394 bool DisableOptimization
= false)
395 : FunctionPass(ID
), CompileKernel(CompileKernel
), Recover(Recover
),
396 DisableOptimization(DisableOptimization
) {
397 initializeHWAddressSanitizerLegacyPassPass(
398 *PassRegistry::getPassRegistry());
401 StringRef
getPassName() const override
{ return "HWAddressSanitizer"; }
403 bool doInitialization(Module
&M
) override
{
404 HWASan
= std::make_unique
<HWAddressSanitizer
>(M
, CompileKernel
, Recover
,
409 bool runOnFunction(Function
&F
) override
{
410 auto TargetTriple
= Triple(F
.getParent()->getTargetTriple());
411 if (shouldUseStackSafetyAnalysis(TargetTriple
, DisableOptimization
)) {
412 // We cannot call getAnalysis in doInitialization, that would cause a
413 // crash as the required analyses are not initialized yet.
415 &getAnalysis
<StackSafetyGlobalInfoWrapperPass
>().getResult());
417 return HWASan
->sanitizeFunction(
419 [&]() -> const DominatorTree
& {
420 return getAnalysis
<DominatorTreeWrapperPass
>().getDomTree();
422 [&]() -> const PostDominatorTree
& {
423 return getAnalysis
<PostDominatorTreeWrapperPass
>().getPostDomTree();
427 bool doFinalization(Module
&M
) override
{
432 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
433 // This is an over-estimation of, in case we are building for an
434 // architecture that doesn't allow stack tagging we will still load the
436 // This is so we don't need to plumb TargetTriple all the way to here.
437 if (mightUseStackSafetyAnalysis(DisableOptimization
))
438 AU
.addRequired
<StackSafetyGlobalInfoWrapperPass
>();
439 AU
.addRequired
<DominatorTreeWrapperPass
>();
440 AU
.addRequired
<PostDominatorTreeWrapperPass
>();
444 std::unique_ptr
<HWAddressSanitizer
> HWASan
;
447 bool DisableOptimization
;
450 } // end anonymous namespace
452 char HWAddressSanitizerLegacyPass::ID
= 0;
454 INITIALIZE_PASS_BEGIN(
455 HWAddressSanitizerLegacyPass
, "hwasan",
456 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
458 INITIALIZE_PASS_DEPENDENCY(StackSafetyGlobalInfoWrapperPass
)
459 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass
)
460 INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass
)
462 HWAddressSanitizerLegacyPass
, "hwasan",
463 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false,
467 llvm::createHWAddressSanitizerLegacyPassPass(bool CompileKernel
, bool Recover
,
468 bool DisableOptimization
) {
469 assert(!CompileKernel
|| Recover
);
470 return new HWAddressSanitizerLegacyPass(CompileKernel
, Recover
,
471 DisableOptimization
);
474 PreservedAnalyses
HWAddressSanitizerPass::run(Module
&M
,
475 ModuleAnalysisManager
&MAM
) {
476 const StackSafetyGlobalInfo
*SSI
= nullptr;
477 auto TargetTriple
= llvm::Triple(M
.getTargetTriple());
478 if (shouldUseStackSafetyAnalysis(TargetTriple
, Options
.DisableOptimization
))
479 SSI
= &MAM
.getResult
<StackSafetyGlobalAnalysis
>(M
);
481 HWAddressSanitizer
HWASan(M
, Options
.CompileKernel
, Options
.Recover
, SSI
);
482 bool Modified
= false;
483 auto &FAM
= MAM
.getResult
<FunctionAnalysisManagerModuleProxy
>(M
).getManager();
484 for (Function
&F
: M
) {
485 Modified
|= HWASan
.sanitizeFunction(
487 [&]() -> const DominatorTree
& {
488 return FAM
.getResult
<DominatorTreeAnalysis
>(F
);
490 [&]() -> const PostDominatorTree
& {
491 return FAM
.getResult
<PostDominatorTreeAnalysis
>(F
);
495 return PreservedAnalyses::none();
496 return PreservedAnalyses::all();
499 void HWAddressSanitizer::createHwasanCtorComdat() {
500 std::tie(HwasanCtorFunction
, std::ignore
) =
501 getOrCreateSanitizerCtorAndInitFunctions(
502 M
, kHwasanModuleCtorName
, kHwasanInitName
,
505 // This callback is invoked when the functions are created the first
506 // time. Hook them into the global ctors list in that case:
507 [&](Function
*Ctor
, FunctionCallee
) {
508 Comdat
*CtorComdat
= M
.getOrInsertComdat(kHwasanModuleCtorName
);
509 Ctor
->setComdat(CtorComdat
);
510 appendToGlobalCtors(M
, Ctor
, 0, Ctor
);
513 // Create a note that contains pointers to the list of global
514 // descriptors. Adding a note to the output file will cause the linker to
515 // create a PT_NOTE program header pointing to the note that we can use to
516 // find the descriptor list starting from the program headers. A function
517 // provided by the runtime initializes the shadow memory for the globals by
518 // accessing the descriptor list via the note. The dynamic loader needs to
519 // call this function whenever a library is loaded.
521 // The reason why we use a note for this instead of a more conventional
522 // approach of having a global constructor pass a descriptor list pointer to
523 // the runtime is because of an order of initialization problem. With
524 // constructors we can encounter the following problematic scenario:
526 // 1) library A depends on library B and also interposes one of B's symbols
527 // 2) B's constructors are called before A's (as required for correctness)
528 // 3) during construction, B accesses one of its "own" globals (actually
529 // interposed by A) and triggers a HWASAN failure due to the initialization
530 // for A not having happened yet
532 // Even without interposition it is possible to run into similar situations in
533 // cases where two libraries mutually depend on each other.
535 // We only need one note per binary, so put everything for the note in a
536 // comdat. This needs to be a comdat with an .init_array section to prevent
537 // newer versions of lld from discarding the note.
539 // Create the note even if we aren't instrumenting globals. This ensures that
540 // binaries linked from object files with both instrumented and
541 // non-instrumented globals will end up with a note, even if a comdat from an
542 // object file with non-instrumented globals is selected. The note is harmless
543 // if the runtime doesn't support it, since it will just be ignored.
544 Comdat
*NoteComdat
= M
.getOrInsertComdat(kHwasanModuleCtorName
);
546 Type
*Int8Arr0Ty
= ArrayType::get(Int8Ty
, 0);
548 new GlobalVariable(M
, Int8Arr0Ty
, true, GlobalVariable::ExternalLinkage
,
549 nullptr, "__start_hwasan_globals");
550 Start
->setVisibility(GlobalValue::HiddenVisibility
);
551 Start
->setDSOLocal(true);
553 new GlobalVariable(M
, Int8Arr0Ty
, true, GlobalVariable::ExternalLinkage
,
554 nullptr, "__stop_hwasan_globals");
555 Stop
->setVisibility(GlobalValue::HiddenVisibility
);
556 Stop
->setDSOLocal(true);
558 // Null-terminated so actually 8 bytes, which are required in order to align
559 // the note properly.
560 auto *Name
= ConstantDataArray::get(*C
, "LLVM\0\0\0");
562 auto *NoteTy
= StructType::get(Int32Ty
, Int32Ty
, Int32Ty
, Name
->getType(),
565 new GlobalVariable(M
, NoteTy
, /*isConstant=*/true,
566 GlobalValue::PrivateLinkage
, nullptr, kHwasanNoteName
);
567 Note
->setSection(".note.hwasan.globals");
568 Note
->setComdat(NoteComdat
);
569 Note
->setAlignment(Align(4));
570 Note
->setDSOLocal(true);
572 // The pointers in the note need to be relative so that the note ends up being
573 // placed in rodata, which is the standard location for notes.
574 auto CreateRelPtr
= [&](Constant
*Ptr
) {
575 return ConstantExpr::getTrunc(
576 ConstantExpr::getSub(ConstantExpr::getPtrToInt(Ptr
, Int64Ty
),
577 ConstantExpr::getPtrToInt(Note
, Int64Ty
)),
580 Note
->setInitializer(ConstantStruct::getAnon(
581 {ConstantInt::get(Int32Ty
, 8), // n_namesz
582 ConstantInt::get(Int32Ty
, 8), // n_descsz
583 ConstantInt::get(Int32Ty
, ELF::NT_LLVM_HWASAN_GLOBALS
), // n_type
584 Name
, CreateRelPtr(Start
), CreateRelPtr(Stop
)}));
585 appendToCompilerUsed(M
, Note
);
587 // Create a zero-length global in hwasan_globals so that the linker will
588 // always create start and stop symbols.
589 auto Dummy
= new GlobalVariable(
590 M
, Int8Arr0Ty
, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage
,
591 Constant::getNullValue(Int8Arr0Ty
), "hwasan.dummy.global");
592 Dummy
->setSection("hwasan_globals");
593 Dummy
->setComdat(NoteComdat
);
594 Dummy
->setMetadata(LLVMContext::MD_associated
,
595 MDNode::get(*C
, ValueAsMetadata::get(Note
)));
596 appendToCompilerUsed(M
, Dummy
);
599 /// Module-level initialization.
601 /// inserts a call to __hwasan_init to the module's constructor list.
602 void HWAddressSanitizer::initializeModule() {
603 LLVM_DEBUG(dbgs() << "Init " << M
.getName() << "\n");
604 auto &DL
= M
.getDataLayout();
606 TargetTriple
= Triple(M
.getTargetTriple());
608 // x86_64 currently has two modes:
609 // - Intel LAM (default)
610 // - pointer aliasing (heap only)
611 bool IsX86_64
= TargetTriple
.getArch() == Triple::x86_64
;
612 UsePageAliases
= shouldUsePageAliases(TargetTriple
);
613 InstrumentWithCalls
= shouldInstrumentWithCalls(TargetTriple
);
614 InstrumentStack
= shouldInstrumentStack(TargetTriple
);
615 DetectUseAfterScope
= shouldDetectUseAfterScope(TargetTriple
);
616 PointerTagShift
= IsX86_64
? 57 : 56;
617 TagMaskByte
= IsX86_64
? 0x3F : 0xFF;
619 Mapping
.init(TargetTriple
, InstrumentWithCalls
);
621 C
= &(M
.getContext());
623 IntptrTy
= IRB
.getIntPtrTy(DL
);
624 Int8PtrTy
= IRB
.getInt8PtrTy();
625 Int8Ty
= IRB
.getInt8Ty();
626 Int32Ty
= IRB
.getInt32Ty();
628 HwasanCtorFunction
= nullptr;
630 // Older versions of Android do not have the required runtime support for
631 // short granules, global or personality function instrumentation. On other
632 // platforms we currently require using the latest version of the runtime.
634 !TargetTriple
.isAndroid() || !TargetTriple
.isAndroidVersionLT(30);
637 ClUseShortGranules
.getNumOccurrences() ? ClUseShortGranules
: NewRuntime
;
639 TargetTriple
.isAArch64() && TargetTriple
.isOSBinFormatELF() &&
640 (ClInlineAllChecks
.getNumOccurrences() ? !ClInlineAllChecks
: !Recover
);
642 if (ClMatchAllTag
.getNumOccurrences()) {
643 if (ClMatchAllTag
!= -1) {
644 HasMatchAllTag
= true;
645 MatchAllTag
= ClMatchAllTag
& 0xFF;
647 } else if (CompileKernel
) {
648 HasMatchAllTag
= true;
652 // If we don't have personality function support, fall back to landing pads.
653 InstrumentLandingPads
= ClInstrumentLandingPads
.getNumOccurrences()
654 ? ClInstrumentLandingPads
657 if (!CompileKernel
) {
658 createHwasanCtorComdat();
659 bool InstrumentGlobals
=
660 ClGlobals
.getNumOccurrences() ? ClGlobals
: NewRuntime
;
662 if (InstrumentGlobals
&& !UsePageAliases
)
665 bool InstrumentPersonalityFunctions
=
666 ClInstrumentPersonalityFunctions
.getNumOccurrences()
667 ? ClInstrumentPersonalityFunctions
669 if (InstrumentPersonalityFunctions
)
670 instrumentPersonalityFunctions();
673 if (!TargetTriple
.isAndroid()) {
674 Constant
*C
= M
.getOrInsertGlobal("__hwasan_tls", IntptrTy
, [&] {
675 auto *GV
= new GlobalVariable(M
, IntptrTy
, /*isConstant=*/false,
676 GlobalValue::ExternalLinkage
, nullptr,
677 "__hwasan_tls", nullptr,
678 GlobalVariable::InitialExecTLSModel
);
679 appendToCompilerUsed(M
, GV
);
682 ThreadPtrGlobal
= cast
<GlobalVariable
>(C
);
686 void HWAddressSanitizer::initializeCallbacks(Module
&M
) {
688 for (size_t AccessIsWrite
= 0; AccessIsWrite
<= 1; AccessIsWrite
++) {
689 const std::string TypeStr
= AccessIsWrite
? "store" : "load";
690 const std::string EndingStr
= Recover
? "_noabort" : "";
692 HwasanMemoryAccessCallbackSized
[AccessIsWrite
] = M
.getOrInsertFunction(
693 ClMemoryAccessCallbackPrefix
+ TypeStr
+ "N" + EndingStr
,
694 FunctionType::get(IRB
.getVoidTy(), {IntptrTy
, IntptrTy
}, false));
696 for (size_t AccessSizeIndex
= 0; AccessSizeIndex
< kNumberOfAccessSizes
;
698 HwasanMemoryAccessCallback
[AccessIsWrite
][AccessSizeIndex
] =
699 M
.getOrInsertFunction(
700 ClMemoryAccessCallbackPrefix
+ TypeStr
+
701 itostr(1ULL << AccessSizeIndex
) + EndingStr
,
702 FunctionType::get(IRB
.getVoidTy(), {IntptrTy
}, false));
706 HwasanTagMemoryFunc
= M
.getOrInsertFunction(
707 "__hwasan_tag_memory", IRB
.getVoidTy(), Int8PtrTy
, Int8Ty
, IntptrTy
);
708 HwasanGenerateTagFunc
=
709 M
.getOrInsertFunction("__hwasan_generate_tag", Int8Ty
);
711 ShadowGlobal
= M
.getOrInsertGlobal("__hwasan_shadow",
712 ArrayType::get(IRB
.getInt8Ty(), 0));
714 const std::string MemIntrinCallbackPrefix
=
715 CompileKernel
? std::string("") : ClMemoryAccessCallbackPrefix
;
716 HWAsanMemmove
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memmove",
717 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
718 IRB
.getInt8PtrTy(), IntptrTy
);
719 HWAsanMemcpy
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memcpy",
720 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
721 IRB
.getInt8PtrTy(), IntptrTy
);
722 HWAsanMemset
= M
.getOrInsertFunction(MemIntrinCallbackPrefix
+ "memset",
723 IRB
.getInt8PtrTy(), IRB
.getInt8PtrTy(),
724 IRB
.getInt32Ty(), IntptrTy
);
727 M
.getOrInsertFunction("__hwasan_handle_vfork", IRB
.getVoidTy(), IntptrTy
);
730 Value
*HWAddressSanitizer::getOpaqueNoopCast(IRBuilder
<> &IRB
, Value
*Val
) {
731 // An empty inline asm with input reg == output reg.
732 // An opaque no-op cast, basically.
733 // This prevents code bloat as a result of rematerializing trivial definitions
734 // such as constants or global addresses at every load and store.
736 InlineAsm::get(FunctionType::get(Int8PtrTy
, {Val
->getType()}, false),
737 StringRef(""), StringRef("=r,0"),
738 /*hasSideEffects=*/false);
739 return IRB
.CreateCall(Asm
, {Val
}, ".hwasan.shadow");
742 Value
*HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder
<> &IRB
) {
743 return getOpaqueNoopCast(IRB
, ShadowGlobal
);
746 Value
*HWAddressSanitizer::getShadowNonTls(IRBuilder
<> &IRB
) {
747 if (Mapping
.Offset
!= kDynamicShadowSentinel
)
748 return getOpaqueNoopCast(
749 IRB
, ConstantExpr::getIntToPtr(
750 ConstantInt::get(IntptrTy
, Mapping
.Offset
), Int8PtrTy
));
752 if (Mapping
.InGlobal
) {
753 return getDynamicShadowIfunc(IRB
);
755 Value
*GlobalDynamicAddress
=
756 IRB
.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal(
757 kHwasanShadowMemoryDynamicAddress
, Int8PtrTy
);
758 return IRB
.CreateLoad(Int8PtrTy
, GlobalDynamicAddress
);
762 bool HWAddressSanitizer::ignoreAccess(Value
*Ptr
) {
763 // Do not instrument acesses from different address spaces; we cannot deal
765 Type
*PtrTy
= cast
<PointerType
>(Ptr
->getType()->getScalarType());
766 if (PtrTy
->getPointerAddressSpace() != 0)
769 // Ignore swifterror addresses.
770 // swifterror memory addresses are mem2reg promoted by instruction
771 // selection. As such they cannot have regular uses like an instrumentation
772 // function and it makes no sense to track them as memory.
773 if (Ptr
->isSwiftError())
779 void HWAddressSanitizer::getInterestingMemoryOperands(
780 Instruction
*I
, SmallVectorImpl
<InterestingMemoryOperand
> &Interesting
) {
781 // Skip memory accesses inserted by another instrumentation.
782 if (I
->hasMetadata("nosanitize"))
785 // Do not instrument the load fetching the dynamic shadow address.
789 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
)) {
790 if (!ClInstrumentReads
|| ignoreAccess(LI
->getPointerOperand()))
792 Interesting
.emplace_back(I
, LI
->getPointerOperandIndex(), false,
793 LI
->getType(), LI
->getAlign());
794 } else if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
)) {
795 if (!ClInstrumentWrites
|| ignoreAccess(SI
->getPointerOperand()))
797 Interesting
.emplace_back(I
, SI
->getPointerOperandIndex(), true,
798 SI
->getValueOperand()->getType(), SI
->getAlign());
799 } else if (AtomicRMWInst
*RMW
= dyn_cast
<AtomicRMWInst
>(I
)) {
800 if (!ClInstrumentAtomics
|| ignoreAccess(RMW
->getPointerOperand()))
802 Interesting
.emplace_back(I
, RMW
->getPointerOperandIndex(), true,
803 RMW
->getValOperand()->getType(), None
);
804 } else if (AtomicCmpXchgInst
*XCHG
= dyn_cast
<AtomicCmpXchgInst
>(I
)) {
805 if (!ClInstrumentAtomics
|| ignoreAccess(XCHG
->getPointerOperand()))
807 Interesting
.emplace_back(I
, XCHG
->getPointerOperandIndex(), true,
808 XCHG
->getCompareOperand()->getType(), None
);
809 } else if (auto CI
= dyn_cast
<CallInst
>(I
)) {
810 for (unsigned ArgNo
= 0; ArgNo
< CI
->getNumArgOperands(); ArgNo
++) {
811 if (!ClInstrumentByval
|| !CI
->isByValArgument(ArgNo
) ||
812 ignoreAccess(CI
->getArgOperand(ArgNo
)))
814 Type
*Ty
= CI
->getParamByValType(ArgNo
);
815 Interesting
.emplace_back(I
, ArgNo
, false, Ty
, Align(1));
820 static unsigned getPointerOperandIndex(Instruction
*I
) {
821 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
))
822 return LI
->getPointerOperandIndex();
823 if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
))
824 return SI
->getPointerOperandIndex();
825 if (AtomicRMWInst
*RMW
= dyn_cast
<AtomicRMWInst
>(I
))
826 return RMW
->getPointerOperandIndex();
827 if (AtomicCmpXchgInst
*XCHG
= dyn_cast
<AtomicCmpXchgInst
>(I
))
828 return XCHG
->getPointerOperandIndex();
829 report_fatal_error("Unexpected instruction");
833 static size_t TypeSizeToSizeIndex(uint32_t TypeSize
) {
834 size_t Res
= countTrailingZeros(TypeSize
/ 8);
835 assert(Res
< kNumberOfAccessSizes
);
839 void HWAddressSanitizer::untagPointerOperand(Instruction
*I
, Value
*Addr
) {
840 if (TargetTriple
.isAArch64() || TargetTriple
.getArch() == Triple::x86_64
)
844 Value
*AddrLong
= IRB
.CreatePointerCast(Addr
, IntptrTy
);
846 IRB
.CreateIntToPtr(untagPointer(IRB
, AddrLong
), Addr
->getType());
847 I
->setOperand(getPointerOperandIndex(I
), UntaggedPtr
);
850 Value
*HWAddressSanitizer::memToShadow(Value
*Mem
, IRBuilder
<> &IRB
) {
852 Value
*Shadow
= IRB
.CreateLShr(Mem
, Mapping
.Scale
);
853 if (Mapping
.Offset
== 0)
854 return IRB
.CreateIntToPtr(Shadow
, Int8PtrTy
);
855 // (Mem >> Scale) + Offset
856 return IRB
.CreateGEP(Int8Ty
, ShadowBase
, Shadow
);
859 void HWAddressSanitizer::instrumentMemAccessInline(Value
*Ptr
, bool IsWrite
,
860 unsigned AccessSizeIndex
,
861 Instruction
*InsertBefore
) {
862 assert(!UsePageAliases
);
863 const int64_t AccessInfo
=
864 (CompileKernel
<< HWASanAccessInfo::CompileKernelShift
) +
865 (HasMatchAllTag
<< HWASanAccessInfo::HasMatchAllShift
) +
866 (MatchAllTag
<< HWASanAccessInfo::MatchAllShift
) +
867 (Recover
<< HWASanAccessInfo::RecoverShift
) +
868 (IsWrite
<< HWASanAccessInfo::IsWriteShift
) +
869 (AccessSizeIndex
<< HWASanAccessInfo::AccessSizeShift
);
870 IRBuilder
<> IRB(InsertBefore
);
872 if (OutlinedChecks
) {
873 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
874 Ptr
= IRB
.CreateBitCast(Ptr
, Int8PtrTy
);
875 IRB
.CreateCall(Intrinsic::getDeclaration(
877 ? Intrinsic::hwasan_check_memaccess_shortgranules
878 : Intrinsic::hwasan_check_memaccess
),
879 {ShadowBase
, Ptr
, ConstantInt::get(Int32Ty
, AccessInfo
)});
883 Value
*PtrLong
= IRB
.CreatePointerCast(Ptr
, IntptrTy
);
884 Value
*PtrTag
= IRB
.CreateTrunc(IRB
.CreateLShr(PtrLong
, PointerTagShift
),
886 Value
*AddrLong
= untagPointer(IRB
, PtrLong
);
887 Value
*Shadow
= memToShadow(AddrLong
, IRB
);
888 Value
*MemTag
= IRB
.CreateLoad(Int8Ty
, Shadow
);
889 Value
*TagMismatch
= IRB
.CreateICmpNE(PtrTag
, MemTag
);
891 if (HasMatchAllTag
) {
892 Value
*TagNotIgnored
= IRB
.CreateICmpNE(
893 PtrTag
, ConstantInt::get(PtrTag
->getType(), MatchAllTag
));
894 TagMismatch
= IRB
.CreateAnd(TagMismatch
, TagNotIgnored
);
897 Instruction
*CheckTerm
=
898 SplitBlockAndInsertIfThen(TagMismatch
, InsertBefore
, false,
899 MDBuilder(*C
).createBranchWeights(1, 100000));
901 IRB
.SetInsertPoint(CheckTerm
);
902 Value
*OutOfShortGranuleTagRange
=
903 IRB
.CreateICmpUGT(MemTag
, ConstantInt::get(Int8Ty
, 15));
904 Instruction
*CheckFailTerm
=
905 SplitBlockAndInsertIfThen(OutOfShortGranuleTagRange
, CheckTerm
, !Recover
,
906 MDBuilder(*C
).createBranchWeights(1, 100000));
908 IRB
.SetInsertPoint(CheckTerm
);
909 Value
*PtrLowBits
= IRB
.CreateTrunc(IRB
.CreateAnd(PtrLong
, 15), Int8Ty
);
910 PtrLowBits
= IRB
.CreateAdd(
911 PtrLowBits
, ConstantInt::get(Int8Ty
, (1 << AccessSizeIndex
) - 1));
912 Value
*PtrLowBitsOOB
= IRB
.CreateICmpUGE(PtrLowBits
, MemTag
);
913 SplitBlockAndInsertIfThen(PtrLowBitsOOB
, CheckTerm
, false,
914 MDBuilder(*C
).createBranchWeights(1, 100000),
915 (DomTreeUpdater
*)nullptr, nullptr,
916 CheckFailTerm
->getParent());
918 IRB
.SetInsertPoint(CheckTerm
);
919 Value
*InlineTagAddr
= IRB
.CreateOr(AddrLong
, 15);
920 InlineTagAddr
= IRB
.CreateIntToPtr(InlineTagAddr
, Int8PtrTy
);
921 Value
*InlineTag
= IRB
.CreateLoad(Int8Ty
, InlineTagAddr
);
922 Value
*InlineTagMismatch
= IRB
.CreateICmpNE(PtrTag
, InlineTag
);
923 SplitBlockAndInsertIfThen(InlineTagMismatch
, CheckTerm
, false,
924 MDBuilder(*C
).createBranchWeights(1, 100000),
925 (DomTreeUpdater
*)nullptr, nullptr,
926 CheckFailTerm
->getParent());
928 IRB
.SetInsertPoint(CheckFailTerm
);
930 switch (TargetTriple
.getArch()) {
932 // The signal handler will find the data address in rdi.
933 Asm
= InlineAsm::get(
934 FunctionType::get(IRB
.getVoidTy(), {PtrLong
->getType()}, false),
936 itostr(0x40 + (AccessInfo
& HWASanAccessInfo::RuntimeMask
)) +
939 /*hasSideEffects=*/true);
941 case Triple::aarch64
:
942 case Triple::aarch64_be
:
943 // The signal handler will find the data address in x0.
944 Asm
= InlineAsm::get(
945 FunctionType::get(IRB
.getVoidTy(), {PtrLong
->getType()}, false),
946 "brk #" + itostr(0x900 + (AccessInfo
& HWASanAccessInfo::RuntimeMask
)),
948 /*hasSideEffects=*/true);
951 report_fatal_error("unsupported architecture");
953 IRB
.CreateCall(Asm
, PtrLong
);
955 cast
<BranchInst
>(CheckFailTerm
)->setSuccessor(0, CheckTerm
->getParent());
958 void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic
*MI
) {
960 if (isa
<MemTransferInst
>(MI
)) {
962 isa
<MemMoveInst
>(MI
) ? HWAsanMemmove
: HWAsanMemcpy
,
963 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
964 IRB
.CreatePointerCast(MI
->getOperand(1), IRB
.getInt8PtrTy()),
965 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
966 } else if (isa
<MemSetInst
>(MI
)) {
969 {IRB
.CreatePointerCast(MI
->getOperand(0), IRB
.getInt8PtrTy()),
970 IRB
.CreateIntCast(MI
->getOperand(1), IRB
.getInt32Ty(), false),
971 IRB
.CreateIntCast(MI
->getOperand(2), IntptrTy
, false)});
973 MI
->eraseFromParent();
976 bool HWAddressSanitizer::instrumentMemAccess(InterestingMemoryOperand
&O
) {
977 Value
*Addr
= O
.getPtr();
979 LLVM_DEBUG(dbgs() << "Instrumenting: " << O
.getInsn() << "\n");
982 return false; // FIXME
984 IRBuilder
<> IRB(O
.getInsn());
985 if (isPowerOf2_64(O
.TypeSize
) &&
986 (O
.TypeSize
/ 8 <= (1ULL << (kNumberOfAccessSizes
- 1))) &&
987 (!O
.Alignment
|| *O
.Alignment
>= (1ULL << Mapping
.Scale
) ||
988 *O
.Alignment
>= O
.TypeSize
/ 8)) {
989 size_t AccessSizeIndex
= TypeSizeToSizeIndex(O
.TypeSize
);
990 if (InstrumentWithCalls
) {
991 IRB
.CreateCall(HwasanMemoryAccessCallback
[O
.IsWrite
][AccessSizeIndex
],
992 IRB
.CreatePointerCast(Addr
, IntptrTy
));
994 instrumentMemAccessInline(Addr
, O
.IsWrite
, AccessSizeIndex
, O
.getInsn());
997 IRB
.CreateCall(HwasanMemoryAccessCallbackSized
[O
.IsWrite
],
998 {IRB
.CreatePointerCast(Addr
, IntptrTy
),
999 ConstantInt::get(IntptrTy
, O
.TypeSize
/ 8)});
1001 untagPointerOperand(O
.getInsn(), Addr
);
1006 static uint64_t getAllocaSizeInBytes(const AllocaInst
&AI
) {
1007 uint64_t ArraySize
= 1;
1008 if (AI
.isArrayAllocation()) {
1009 const ConstantInt
*CI
= dyn_cast
<ConstantInt
>(AI
.getArraySize());
1010 assert(CI
&& "non-constant array size");
1011 ArraySize
= CI
->getZExtValue();
1013 Type
*Ty
= AI
.getAllocatedType();
1014 uint64_t SizeInBytes
= AI
.getModule()->getDataLayout().getTypeAllocSize(Ty
);
1015 return SizeInBytes
* ArraySize
;
1018 void HWAddressSanitizer::tagAlloca(IRBuilder
<> &IRB
, AllocaInst
*AI
, Value
*Tag
,
1020 size_t AlignedSize
= alignTo(Size
, Mapping
.getObjectAlignment());
1021 if (!UseShortGranules
)
1024 Value
*JustTag
= IRB
.CreateTrunc(Tag
, IRB
.getInt8Ty());
1025 if (InstrumentWithCalls
) {
1026 IRB
.CreateCall(HwasanTagMemoryFunc
,
1027 {IRB
.CreatePointerCast(AI
, Int8PtrTy
), JustTag
,
1028 ConstantInt::get(IntptrTy
, AlignedSize
)});
1030 size_t ShadowSize
= Size
>> Mapping
.Scale
;
1031 Value
*ShadowPtr
= memToShadow(IRB
.CreatePointerCast(AI
, IntptrTy
), IRB
);
1032 // If this memset is not inlined, it will be intercepted in the hwasan
1033 // runtime library. That's OK, because the interceptor skips the checks if
1034 // the address is in the shadow region.
1035 // FIXME: the interceptor is not as fast as real memset. Consider lowering
1036 // llvm.memset right here into either a sequence of stores, or a call to
1037 // hwasan_tag_memory.
1039 IRB
.CreateMemSet(ShadowPtr
, JustTag
, ShadowSize
, Align(1));
1040 if (Size
!= AlignedSize
) {
1042 ConstantInt::get(Int8Ty
, Size
% Mapping
.getObjectAlignment()),
1043 IRB
.CreateConstGEP1_32(Int8Ty
, ShadowPtr
, ShadowSize
));
1044 IRB
.CreateStore(JustTag
, IRB
.CreateConstGEP1_32(
1045 Int8Ty
, IRB
.CreateBitCast(AI
, Int8PtrTy
),
1051 unsigned HWAddressSanitizer::retagMask(unsigned AllocaNo
) {
1052 if (TargetTriple
.getArch() == Triple::x86_64
)
1053 return AllocaNo
& TagMaskByte
;
1055 // A list of 8-bit numbers that have at most one run of non-zero bits.
1056 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
1058 // The list does not include the value 255, which is used for UAR.
1060 // Because we are more likely to use earlier elements of this list than later
1061 // ones, it is sorted in increasing order of probability of collision with a
1062 // mask allocated (temporally) nearby. The program that generated this list
1064 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
1065 static unsigned FastMasks
[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
1066 48, 16, 120, 248, 56, 24, 8, 124, 252,
1067 60, 28, 12, 4, 126, 254, 62, 30, 14,
1068 6, 2, 127, 63, 31, 15, 7, 3, 1};
1069 return FastMasks
[AllocaNo
% (sizeof(FastMasks
) / sizeof(FastMasks
[0]))];
1072 Value
*HWAddressSanitizer::applyTagMask(IRBuilder
<> &IRB
, Value
*OldTag
) {
1073 if (TargetTriple
.getArch() == Triple::x86_64
) {
1074 Constant
*TagMask
= ConstantInt::get(IntptrTy
, TagMaskByte
);
1075 Value
*NewTag
= IRB
.CreateAnd(OldTag
, TagMask
);
1078 // aarch64 uses 8-bit tags, so no mask is needed.
1082 Value
*HWAddressSanitizer::getNextTagWithCall(IRBuilder
<> &IRB
) {
1083 return IRB
.CreateZExt(IRB
.CreateCall(HwasanGenerateTagFunc
), IntptrTy
);
1086 Value
*HWAddressSanitizer::getStackBaseTag(IRBuilder
<> &IRB
) {
1087 if (ClGenerateTagsWithCalls
)
1088 return getNextTagWithCall(IRB
);
1090 return StackBaseTag
;
1091 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
1093 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
1094 auto GetStackPointerFn
= Intrinsic::getDeclaration(
1095 M
, Intrinsic::frameaddress
,
1096 IRB
.getInt8PtrTy(M
->getDataLayout().getAllocaAddrSpace()));
1097 Value
*StackPointer
= IRB
.CreateCall(
1098 GetStackPointerFn
, {Constant::getNullValue(IRB
.getInt32Ty())});
1100 // Extract some entropy from the stack pointer for the tags.
1101 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
1102 // between functions).
1103 Value
*StackPointerLong
= IRB
.CreatePointerCast(StackPointer
, IntptrTy
);
1105 applyTagMask(IRB
, IRB
.CreateXor(StackPointerLong
,
1106 IRB
.CreateLShr(StackPointerLong
, 20)));
1107 StackTag
->setName("hwasan.stack.base.tag");
1111 Value
*HWAddressSanitizer::getAllocaTag(IRBuilder
<> &IRB
, Value
*StackTag
,
1112 AllocaInst
*AI
, unsigned AllocaNo
) {
1113 if (ClGenerateTagsWithCalls
)
1114 return getNextTagWithCall(IRB
);
1115 return IRB
.CreateXor(StackTag
,
1116 ConstantInt::get(IntptrTy
, retagMask(AllocaNo
)));
1119 Value
*HWAddressSanitizer::getUARTag(IRBuilder
<> &IRB
, Value
*StackTag
) {
1120 if (ClUARRetagToZero
)
1121 return ConstantInt::get(IntptrTy
, 0);
1122 if (ClGenerateTagsWithCalls
)
1123 return getNextTagWithCall(IRB
);
1124 return IRB
.CreateXor(StackTag
, ConstantInt::get(IntptrTy
, TagMaskByte
));
1127 // Add a tag to an address.
1128 Value
*HWAddressSanitizer::tagPointer(IRBuilder
<> &IRB
, Type
*Ty
,
1129 Value
*PtrLong
, Value
*Tag
) {
1130 assert(!UsePageAliases
);
1131 Value
*TaggedPtrLong
;
1132 if (CompileKernel
) {
1133 // Kernel addresses have 0xFF in the most significant byte.
1135 IRB
.CreateOr(IRB
.CreateShl(Tag
, PointerTagShift
),
1136 ConstantInt::get(IntptrTy
, (1ULL << PointerTagShift
) - 1));
1137 TaggedPtrLong
= IRB
.CreateAnd(PtrLong
, ShiftedTag
);
1139 // Userspace can simply do OR (tag << PointerTagShift);
1140 Value
*ShiftedTag
= IRB
.CreateShl(Tag
, PointerTagShift
);
1141 TaggedPtrLong
= IRB
.CreateOr(PtrLong
, ShiftedTag
);
1143 return IRB
.CreateIntToPtr(TaggedPtrLong
, Ty
);
1146 // Remove tag from an address.
1147 Value
*HWAddressSanitizer::untagPointer(IRBuilder
<> &IRB
, Value
*PtrLong
) {
1148 assert(!UsePageAliases
);
1149 Value
*UntaggedPtrLong
;
1150 if (CompileKernel
) {
1151 // Kernel addresses have 0xFF in the most significant byte.
1153 IRB
.CreateOr(PtrLong
, ConstantInt::get(PtrLong
->getType(),
1154 0xFFULL
<< PointerTagShift
));
1156 // Userspace addresses have 0x00.
1158 IRB
.CreateAnd(PtrLong
, ConstantInt::get(PtrLong
->getType(),
1159 ~(0xFFULL
<< PointerTagShift
)));
1161 return UntaggedPtrLong
;
1164 Value
*HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder
<> &IRB
, Type
*Ty
) {
1165 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
1166 if (TargetTriple
.isAArch64() && TargetTriple
.isAndroid()) {
1167 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
1168 // in Bionic's libc/private/bionic_tls.h.
1169 Function
*ThreadPointerFunc
=
1170 Intrinsic::getDeclaration(M
, Intrinsic::thread_pointer
);
1171 Value
*SlotPtr
= IRB
.CreatePointerCast(
1172 IRB
.CreateConstGEP1_32(IRB
.getInt8Ty(),
1173 IRB
.CreateCall(ThreadPointerFunc
), 0x30),
1174 Ty
->getPointerTo(0));
1177 if (ThreadPtrGlobal
)
1178 return ThreadPtrGlobal
;
1183 void HWAddressSanitizer::emitPrologue(IRBuilder
<> &IRB
, bool WithFrameRecord
) {
1185 ShadowBase
= getShadowNonTls(IRB
);
1186 else if (!WithFrameRecord
&& TargetTriple
.isAndroid())
1187 ShadowBase
= getDynamicShadowIfunc(IRB
);
1189 if (!WithFrameRecord
&& ShadowBase
)
1192 Value
*SlotPtr
= getHwasanThreadSlotPtr(IRB
, IntptrTy
);
1195 Value
*ThreadLong
= IRB
.CreateLoad(IntptrTy
, SlotPtr
);
1196 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI.
1197 Value
*ThreadLongMaybeUntagged
=
1198 TargetTriple
.isAArch64() ? ThreadLong
: untagPointer(IRB
, ThreadLong
);
1200 if (WithFrameRecord
) {
1201 Function
*F
= IRB
.GetInsertBlock()->getParent();
1202 StackBaseTag
= IRB
.CreateAShr(ThreadLong
, 3);
1204 // Prepare ring buffer data.
1206 if (TargetTriple
.getArch() == Triple::aarch64
)
1207 PC
= readRegister(IRB
, "pc");
1209 PC
= IRB
.CreatePtrToInt(F
, IntptrTy
);
1210 Module
*M
= F
->getParent();
1211 auto GetStackPointerFn
= Intrinsic::getDeclaration(
1212 M
, Intrinsic::frameaddress
,
1213 IRB
.getInt8PtrTy(M
->getDataLayout().getAllocaAddrSpace()));
1214 Value
*SP
= IRB
.CreatePtrToInt(
1215 IRB
.CreateCall(GetStackPointerFn
,
1216 {Constant::getNullValue(IRB
.getInt32Ty())}),
1220 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
1221 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
1222 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this:
1223 // 0xSSSSPPPPPPPPPPPP
1224 SP
= IRB
.CreateShl(SP
, 44);
1226 // Store data to ring buffer.
1228 IRB
.CreateIntToPtr(ThreadLongMaybeUntagged
, IntptrTy
->getPointerTo(0));
1229 IRB
.CreateStore(IRB
.CreateOr(PC
, SP
), RecordPtr
);
1231 // Update the ring buffer. Top byte of ThreadLong defines the size of the
1232 // buffer in pages, it must be a power of two, and the start of the buffer
1233 // must be aligned by twice that much. Therefore wrap around of the ring
1234 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
1235 // The use of AShr instead of LShr is due to
1236 // https://bugs.llvm.org/show_bug.cgi?id=39030
1237 // Runtime library makes sure not to use the highest bit.
1238 Value
*WrapMask
= IRB
.CreateXor(
1239 IRB
.CreateShl(IRB
.CreateAShr(ThreadLong
, 56), 12, "", true, true),
1240 ConstantInt::get(IntptrTy
, (uint64_t)-1));
1241 Value
*ThreadLongNew
= IRB
.CreateAnd(
1242 IRB
.CreateAdd(ThreadLong
, ConstantInt::get(IntptrTy
, 8)), WrapMask
);
1243 IRB
.CreateStore(ThreadLongNew
, SlotPtr
);
1247 // Get shadow base address by aligning RecordPtr up.
1248 // Note: this is not correct if the pointer is already aligned.
1249 // Runtime library will make sure this never happens.
1250 ShadowBase
= IRB
.CreateAdd(
1252 ThreadLongMaybeUntagged
,
1253 ConstantInt::get(IntptrTy
, (1ULL << kShadowBaseAlignment
) - 1)),
1254 ConstantInt::get(IntptrTy
, 1), "hwasan.shadow");
1255 ShadowBase
= IRB
.CreateIntToPtr(ShadowBase
, Int8PtrTy
);
1259 Value
*HWAddressSanitizer::readRegister(IRBuilder
<> &IRB
, StringRef Name
) {
1260 Module
*M
= IRB
.GetInsertBlock()->getParent()->getParent();
1261 Function
*ReadRegister
=
1262 Intrinsic::getDeclaration(M
, Intrinsic::read_register
, IntptrTy
);
1263 MDNode
*MD
= MDNode::get(*C
, {MDString::get(*C
, Name
)});
1264 Value
*Args
[] = {MetadataAsValue::get(*C
, MD
)};
1265 return IRB
.CreateCall(ReadRegister
, Args
);
1268 bool HWAddressSanitizer::instrumentLandingPads(
1269 SmallVectorImpl
<Instruction
*> &LandingPadVec
) {
1270 for (auto *LP
: LandingPadVec
) {
1271 IRBuilder
<> IRB(LP
->getNextNode());
1274 {readRegister(IRB
, (TargetTriple
.getArch() == Triple::x86_64
) ? "rsp"
1280 bool HWAddressSanitizer::instrumentStack(
1281 MapVector
<AllocaInst
*, AllocaInfo
> &AllocasToInstrument
,
1282 SmallVector
<Instruction
*, 4> &UnrecognizedLifetimes
,
1283 DenseMap
<AllocaInst
*, std::vector
<DbgVariableIntrinsic
*>> &AllocaDbgMap
,
1284 SmallVectorImpl
<Instruction
*> &RetVec
, Value
*StackTag
,
1285 llvm::function_ref
<const DominatorTree
&()> GetDT
,
1286 llvm::function_ref
<const PostDominatorTree
&()> GetPDT
) {
1287 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
1288 // alloca addresses using that. Unfortunately, offsets are not known yet
1289 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
1290 // temp, shift-OR it into each alloca address and xor with the retag mask.
1291 // This generates one extra instruction per alloca use.
1294 for (auto &KV
: AllocasToInstrument
) {
1296 auto *AI
= KV
.first
;
1297 AllocaInfo
&Info
= KV
.second
;
1298 IRBuilder
<> IRB(AI
->getNextNode());
1300 // Replace uses of the alloca with tagged address.
1301 Value
*Tag
= getAllocaTag(IRB
, StackTag
, AI
, N
);
1302 Value
*AILong
= IRB
.CreatePointerCast(AI
, IntptrTy
);
1303 Value
*Replacement
= tagPointer(IRB
, AI
->getType(), AILong
, Tag
);
1305 AI
->hasName() ? AI
->getName().str() : "alloca." + itostr(N
);
1306 Replacement
->setName(Name
+ ".hwasan");
1308 AI
->replaceUsesWithIf(Replacement
,
1309 [AILong
](Use
&U
) { return U
.getUser() != AILong
; });
1311 for (auto *DDI
: AllocaDbgMap
.lookup(AI
)) {
1312 // Prepend "tag_offset, N" to the dwarf expression.
1313 // Tag offset logically applies to the alloca pointer, and it makes sense
1314 // to put it at the beginning of the expression.
1315 SmallVector
<uint64_t, 8> NewOps
= {dwarf::DW_OP_LLVM_tag_offset
,
1317 for (size_t LocNo
= 0; LocNo
< DDI
->getNumVariableLocationOps(); ++LocNo
)
1318 if (DDI
->getVariableLocationOp(LocNo
) == AI
)
1319 DDI
->setExpression(DIExpression::appendOpsToArg(DDI
->getExpression(),
1323 size_t Size
= getAllocaSizeInBytes(*AI
);
1324 size_t AlignedSize
= alignTo(Size
, Mapping
.getObjectAlignment());
1325 bool StandardLifetime
= UnrecognizedLifetimes
.empty() &&
1326 Info
.LifetimeStart
.size() == 1 &&
1327 Info
.LifetimeEnd
.size() == 1;
1328 if (DetectUseAfterScope
&& StandardLifetime
) {
1329 IntrinsicInst
*Start
= Info
.LifetimeStart
[0];
1330 IntrinsicInst
*End
= Info
.LifetimeEnd
[0];
1331 IRB
.SetInsertPoint(Start
->getNextNode());
1332 auto TagEnd
= [&](Instruction
*Node
) {
1333 IRB
.SetInsertPoint(Node
);
1334 Value
*UARTag
= getUARTag(IRB
, StackTag
);
1335 tagAlloca(IRB
, AI
, UARTag
, AlignedSize
);
1337 tagAlloca(IRB
, AI
, Tag
, Size
);
1338 if (!forAllReachableExits(GetDT(), GetPDT(), Start
, End
, RetVec
, TagEnd
))
1339 End
->eraseFromParent();
1341 tagAlloca(IRB
, AI
, Tag
, Size
);
1342 for (auto *RI
: RetVec
) {
1343 IRB
.SetInsertPoint(RI
);
1344 Value
*UARTag
= getUARTag(IRB
, StackTag
);
1345 tagAlloca(IRB
, AI
, UARTag
, AlignedSize
);
1347 if (!StandardLifetime
) {
1348 for (auto &II
: Info
.LifetimeStart
)
1349 II
->eraseFromParent();
1350 for (auto &II
: Info
.LifetimeEnd
)
1351 II
->eraseFromParent();
1355 for (auto &I
: UnrecognizedLifetimes
)
1356 I
->eraseFromParent();
1360 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst
&AI
) {
1361 return (AI
.getAllocatedType()->isSized() &&
1362 // FIXME: instrument dynamic allocas, too
1363 AI
.isStaticAlloca() &&
1364 // alloca() may be called with 0 size, ignore it.
1365 getAllocaSizeInBytes(AI
) > 0 &&
1366 // We are only interested in allocas not promotable to registers.
1367 // Promotable allocas are common under -O0.
1368 !isAllocaPromotable(&AI
) &&
1369 // inalloca allocas are not treated as static, and we don't want
1370 // dynamic alloca instrumentation for them as well.
1371 !AI
.isUsedWithInAlloca() &&
1372 // swifterror allocas are register promoted by ISel
1373 !AI
.isSwiftError()) &&
1374 // safe allocas are not interesting
1375 !(SSI
&& SSI
->isSafe(AI
));
1378 DenseMap
<AllocaInst
*, AllocaInst
*> HWAddressSanitizer::padInterestingAllocas(
1379 const MapVector
<AllocaInst
*, AllocaInfo
> &AllocasToInstrument
) {
1380 DenseMap
<AllocaInst
*, AllocaInst
*> AllocaToPaddedAllocaMap
;
1381 for (auto &KV
: AllocasToInstrument
) {
1382 AllocaInst
*AI
= KV
.first
;
1383 uint64_t Size
= getAllocaSizeInBytes(*AI
);
1384 uint64_t AlignedSize
= alignTo(Size
, Mapping
.getObjectAlignment());
1386 Align(std::max(AI
->getAlignment(), Mapping
.getObjectAlignment())));
1387 if (Size
!= AlignedSize
) {
1388 Type
*AllocatedType
= AI
->getAllocatedType();
1389 if (AI
->isArrayAllocation()) {
1390 uint64_t ArraySize
=
1391 cast
<ConstantInt
>(AI
->getArraySize())->getZExtValue();
1392 AllocatedType
= ArrayType::get(AllocatedType
, ArraySize
);
1394 Type
*TypeWithPadding
= StructType::get(
1395 AllocatedType
, ArrayType::get(Int8Ty
, AlignedSize
- Size
));
1396 auto *NewAI
= new AllocaInst(
1397 TypeWithPadding
, AI
->getType()->getAddressSpace(), nullptr, "", AI
);
1398 NewAI
->takeName(AI
);
1399 NewAI
->setAlignment(AI
->getAlign());
1400 NewAI
->setUsedWithInAlloca(AI
->isUsedWithInAlloca());
1401 NewAI
->setSwiftError(AI
->isSwiftError());
1402 NewAI
->copyMetadata(*AI
);
1403 auto *Bitcast
= new BitCastInst(NewAI
, AI
->getType(), "", AI
);
1404 AI
->replaceAllUsesWith(Bitcast
);
1405 AllocaToPaddedAllocaMap
[AI
] = NewAI
;
1408 return AllocaToPaddedAllocaMap
;
1411 bool HWAddressSanitizer::sanitizeFunction(
1412 Function
&F
, llvm::function_ref
<const DominatorTree
&()> GetDT
,
1413 llvm::function_ref
<const PostDominatorTree
&()> GetPDT
) {
1414 if (&F
== HwasanCtorFunction
)
1417 if (!F
.hasFnAttribute(Attribute::SanitizeHWAddress
))
1420 LLVM_DEBUG(dbgs() << "Function: " << F
.getName() << "\n");
1422 SmallVector
<InterestingMemoryOperand
, 16> OperandsToInstrument
;
1423 SmallVector
<MemIntrinsic
*, 16> IntrinToInstrument
;
1424 MapVector
<AllocaInst
*, AllocaInfo
> AllocasToInstrument
;
1425 SmallVector
<Instruction
*, 8> RetVec
;
1426 SmallVector
<Instruction
*, 8> LandingPadVec
;
1427 SmallVector
<Instruction
*, 4> UnrecognizedLifetimes
;
1428 DenseMap
<AllocaInst
*, std::vector
<DbgVariableIntrinsic
*>> AllocaDbgMap
;
1429 for (auto &BB
: F
) {
1430 for (auto &Inst
: BB
) {
1431 if (InstrumentStack
) {
1432 if (AllocaInst
*AI
= dyn_cast
<AllocaInst
>(&Inst
)) {
1433 if (isInterestingAlloca(*AI
))
1434 AllocasToInstrument
.insert({AI
, {}});
1437 auto *II
= dyn_cast
<IntrinsicInst
>(&Inst
);
1438 if (II
&& (II
->getIntrinsicID() == Intrinsic::lifetime_start
||
1439 II
->getIntrinsicID() == Intrinsic::lifetime_end
)) {
1440 AllocaInst
*AI
= findAllocaForValue(II
->getArgOperand(1));
1442 UnrecognizedLifetimes
.push_back(&Inst
);
1445 if (!isInterestingAlloca(*AI
))
1447 if (II
->getIntrinsicID() == Intrinsic::lifetime_start
)
1448 AllocasToInstrument
[AI
].LifetimeStart
.push_back(II
);
1450 AllocasToInstrument
[AI
].LifetimeEnd
.push_back(II
);
1455 if (isa
<ReturnInst
>(Inst
) || isa
<ResumeInst
>(Inst
) ||
1456 isa
<CleanupReturnInst
>(Inst
))
1457 RetVec
.push_back(&Inst
);
1459 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&Inst
)) {
1460 for (Value
*V
: DVI
->location_ops()) {
1461 if (auto *Alloca
= dyn_cast_or_null
<AllocaInst
>(V
))
1462 if (!AllocaDbgMap
.count(Alloca
) ||
1463 AllocaDbgMap
[Alloca
].back() != DVI
)
1464 AllocaDbgMap
[Alloca
].push_back(DVI
);
1468 if (InstrumentLandingPads
&& isa
<LandingPadInst
>(Inst
))
1469 LandingPadVec
.push_back(&Inst
);
1471 getInterestingMemoryOperands(&Inst
, OperandsToInstrument
);
1473 if (MemIntrinsic
*MI
= dyn_cast
<MemIntrinsic
>(&Inst
))
1474 IntrinToInstrument
.push_back(MI
);
1478 initializeCallbacks(*F
.getParent());
1480 bool Changed
= false;
1482 if (!LandingPadVec
.empty())
1483 Changed
|= instrumentLandingPads(LandingPadVec
);
1485 if (AllocasToInstrument
.empty() && F
.hasPersonalityFn() &&
1486 F
.getPersonalityFn()->getName() == kHwasanPersonalityThunkName
) {
1487 // __hwasan_personality_thunk is a no-op for functions without an
1488 // instrumented stack, so we can drop it.
1489 F
.setPersonalityFn(nullptr);
1493 if (AllocasToInstrument
.empty() && OperandsToInstrument
.empty() &&
1494 IntrinToInstrument
.empty())
1497 assert(!ShadowBase
);
1499 Instruction
*InsertPt
= &*F
.getEntryBlock().begin();
1500 IRBuilder
<> EntryIRB(InsertPt
);
1501 emitPrologue(EntryIRB
,
1502 /*WithFrameRecord*/ ClRecordStackHistory
&&
1503 Mapping
.WithFrameRecord
&& !AllocasToInstrument
.empty());
1505 if (!AllocasToInstrument
.empty()) {
1507 ClGenerateTagsWithCalls
? nullptr : getStackBaseTag(EntryIRB
);
1508 instrumentStack(AllocasToInstrument
, UnrecognizedLifetimes
, AllocaDbgMap
,
1509 RetVec
, StackTag
, GetDT
, GetPDT
);
1511 // Pad and align each of the allocas that we instrumented to stop small
1512 // uninteresting allocas from hiding in instrumented alloca's padding and so
1513 // that we have enough space to store real tags for short granules.
1514 DenseMap
<AllocaInst
*, AllocaInst
*> AllocaToPaddedAllocaMap
=
1515 padInterestingAllocas(AllocasToInstrument
);
1517 if (!AllocaToPaddedAllocaMap
.empty()) {
1518 for (auto &BB
: F
) {
1519 for (auto &Inst
: BB
) {
1520 if (auto *DVI
= dyn_cast
<DbgVariableIntrinsic
>(&Inst
)) {
1521 SmallDenseSet
<Value
*> LocationOps(DVI
->location_ops().begin(),
1522 DVI
->location_ops().end());
1523 for (Value
*V
: LocationOps
) {
1524 if (auto *AI
= dyn_cast_or_null
<AllocaInst
>(V
)) {
1525 if (auto *NewAI
= AllocaToPaddedAllocaMap
.lookup(AI
))
1526 DVI
->replaceVariableLocationOp(V
, NewAI
);
1532 for (auto &P
: AllocaToPaddedAllocaMap
)
1533 P
.first
->eraseFromParent();
1536 // If we split the entry block, move any allocas that were originally in the
1537 // entry block back into the entry block so that they aren't treated as
1539 if (EntryIRB
.GetInsertBlock() != &F
.getEntryBlock()) {
1540 InsertPt
= &*F
.getEntryBlock().begin();
1541 for (auto II
= EntryIRB
.GetInsertBlock()->begin(),
1542 IE
= EntryIRB
.GetInsertBlock()->end();
1544 Instruction
*I
= &*II
++;
1545 if (auto *AI
= dyn_cast
<AllocaInst
>(I
))
1546 if (isa
<ConstantInt
>(AI
->getArraySize()))
1547 I
->moveBefore(InsertPt
);
1551 for (auto &Operand
: OperandsToInstrument
)
1552 instrumentMemAccess(Operand
);
1554 if (ClInstrumentMemIntrinsics
&& !IntrinToInstrument
.empty()) {
1555 for (auto Inst
: IntrinToInstrument
)
1556 instrumentMemIntrinsic(cast
<MemIntrinsic
>(Inst
));
1559 ShadowBase
= nullptr;
1560 StackBaseTag
= nullptr;
1565 void HWAddressSanitizer::instrumentGlobal(GlobalVariable
*GV
, uint8_t Tag
) {
1566 assert(!UsePageAliases
);
1567 Constant
*Initializer
= GV
->getInitializer();
1568 uint64_t SizeInBytes
=
1569 M
.getDataLayout().getTypeAllocSize(Initializer
->getType());
1570 uint64_t NewSize
= alignTo(SizeInBytes
, Mapping
.getObjectAlignment());
1571 if (SizeInBytes
!= NewSize
) {
1572 // Pad the initializer out to the next multiple of 16 bytes and add the
1573 // required short granule tag.
1574 std::vector
<uint8_t> Init(NewSize
- SizeInBytes
, 0);
1576 Constant
*Padding
= ConstantDataArray::get(*C
, Init
);
1577 Initializer
= ConstantStruct::getAnon({Initializer
, Padding
});
1580 auto *NewGV
= new GlobalVariable(M
, Initializer
->getType(), GV
->isConstant(),
1581 GlobalValue::ExternalLinkage
, Initializer
,
1582 GV
->getName() + ".hwasan");
1583 NewGV
->copyAttributesFrom(GV
);
1584 NewGV
->setLinkage(GlobalValue::PrivateLinkage
);
1585 NewGV
->copyMetadata(GV
, 0);
1586 NewGV
->setAlignment(
1587 MaybeAlign(std::max(GV
->getAlignment(), Mapping
.getObjectAlignment())));
1589 // It is invalid to ICF two globals that have different tags. In the case
1590 // where the size of the global is a multiple of the tag granularity the
1591 // contents of the globals may be the same but the tags (i.e. symbol values)
1592 // may be different, and the symbols are not considered during ICF. In the
1593 // case where the size is not a multiple of the granularity, the short granule
1594 // tags would discriminate two globals with different tags, but there would
1595 // otherwise be nothing stopping such a global from being incorrectly ICF'd
1596 // with an uninstrumented (i.e. tag 0) global that happened to have the short
1597 // granule tag in the last byte.
1598 NewGV
->setUnnamedAddr(GlobalValue::UnnamedAddr::None
);
1600 // Descriptor format (assuming little-endian):
1601 // bytes 0-3: relative address of global
1602 // bytes 4-6: size of global (16MB ought to be enough for anyone, but in case
1603 // it isn't, we create multiple descriptors)
1605 auto *DescriptorTy
= StructType::get(Int32Ty
, Int32Ty
);
1606 const uint64_t MaxDescriptorSize
= 0xfffff0;
1607 for (uint64_t DescriptorPos
= 0; DescriptorPos
< SizeInBytes
;
1608 DescriptorPos
+= MaxDescriptorSize
) {
1610 new GlobalVariable(M
, DescriptorTy
, true, GlobalValue::PrivateLinkage
,
1611 nullptr, GV
->getName() + ".hwasan.descriptor");
1612 auto *GVRelPtr
= ConstantExpr::getTrunc(
1613 ConstantExpr::getAdd(
1614 ConstantExpr::getSub(
1615 ConstantExpr::getPtrToInt(NewGV
, Int64Ty
),
1616 ConstantExpr::getPtrToInt(Descriptor
, Int64Ty
)),
1617 ConstantInt::get(Int64Ty
, DescriptorPos
)),
1619 uint32_t Size
= std::min(SizeInBytes
- DescriptorPos
, MaxDescriptorSize
);
1620 auto *SizeAndTag
= ConstantInt::get(Int32Ty
, Size
| (uint32_t(Tag
) << 24));
1621 Descriptor
->setComdat(NewGV
->getComdat());
1622 Descriptor
->setInitializer(ConstantStruct::getAnon({GVRelPtr
, SizeAndTag
}));
1623 Descriptor
->setSection("hwasan_globals");
1624 Descriptor
->setMetadata(LLVMContext::MD_associated
,
1625 MDNode::get(*C
, ValueAsMetadata::get(NewGV
)));
1626 appendToCompilerUsed(M
, Descriptor
);
1629 Constant
*Aliasee
= ConstantExpr::getIntToPtr(
1630 ConstantExpr::getAdd(
1631 ConstantExpr::getPtrToInt(NewGV
, Int64Ty
),
1632 ConstantInt::get(Int64Ty
, uint64_t(Tag
) << PointerTagShift
)),
1634 auto *Alias
= GlobalAlias::create(GV
->getValueType(), GV
->getAddressSpace(),
1635 GV
->getLinkage(), "", Aliasee
, &M
);
1636 Alias
->setVisibility(GV
->getVisibility());
1637 Alias
->takeName(GV
);
1638 GV
->replaceAllUsesWith(Alias
);
1639 GV
->eraseFromParent();
1642 static DenseSet
<GlobalVariable
*> getExcludedGlobals(Module
&M
) {
1643 NamedMDNode
*Globals
= M
.getNamedMetadata("llvm.asan.globals");
1645 return DenseSet
<GlobalVariable
*>();
1646 DenseSet
<GlobalVariable
*> Excluded(Globals
->getNumOperands());
1647 for (auto MDN
: Globals
->operands()) {
1648 // Metadata node contains the global and the fields of "Entry".
1649 assert(MDN
->getNumOperands() == 5);
1650 auto *V
= mdconst::extract_or_null
<Constant
>(MDN
->getOperand(0));
1651 // The optimizer may optimize away a global entirely.
1654 auto *StrippedV
= V
->stripPointerCasts();
1655 auto *GV
= dyn_cast
<GlobalVariable
>(StrippedV
);
1658 ConstantInt
*IsExcluded
= mdconst::extract
<ConstantInt
>(MDN
->getOperand(4));
1659 if (IsExcluded
->isOne())
1660 Excluded
.insert(GV
);
1665 void HWAddressSanitizer::instrumentGlobals() {
1666 std::vector
<GlobalVariable
*> Globals
;
1667 auto ExcludedGlobals
= getExcludedGlobals(M
);
1668 for (GlobalVariable
&GV
: M
.globals()) {
1669 if (ExcludedGlobals
.count(&GV
))
1672 if (GV
.isDeclarationForLinker() || GV
.getName().startswith("llvm.") ||
1676 // Common symbols can't have aliases point to them, so they can't be tagged.
1677 if (GV
.hasCommonLinkage())
1680 // Globals with custom sections may be used in __start_/__stop_ enumeration,
1681 // which would be broken both by adding tags and potentially by the extra
1682 // padding/alignment that we insert.
1683 if (GV
.hasSection())
1686 Globals
.push_back(&GV
);
1690 Hasher
.update(M
.getSourceFileName());
1691 MD5::MD5Result Hash
;
1693 uint8_t Tag
= Hash
[0] & TagMaskByte
;
1695 for (GlobalVariable
*GV
: Globals
) {
1696 // Skip tag 0 in order to avoid collisions with untagged memory.
1699 instrumentGlobal(GV
, Tag
++);
1703 void HWAddressSanitizer::instrumentPersonalityFunctions() {
1704 // We need to untag stack frames as we unwind past them. That is the job of
1705 // the personality function wrapper, which either wraps an existing
1706 // personality function or acts as a personality function on its own. Each
1707 // function that has a personality function or that can be unwound past has
1708 // its personality function changed to a thunk that calls the personality
1709 // function wrapper in the runtime.
1710 MapVector
<Constant
*, std::vector
<Function
*>> PersonalityFns
;
1711 for (Function
&F
: M
) {
1712 if (F
.isDeclaration() || !F
.hasFnAttribute(Attribute::SanitizeHWAddress
))
1715 if (F
.hasPersonalityFn()) {
1716 PersonalityFns
[F
.getPersonalityFn()->stripPointerCasts()].push_back(&F
);
1717 } else if (!F
.hasFnAttribute(Attribute::NoUnwind
)) {
1718 PersonalityFns
[nullptr].push_back(&F
);
1722 if (PersonalityFns
.empty())
1725 FunctionCallee HwasanPersonalityWrapper
= M
.getOrInsertFunction(
1726 "__hwasan_personality_wrapper", Int32Ty
, Int32Ty
, Int32Ty
, Int64Ty
,
1727 Int8PtrTy
, Int8PtrTy
, Int8PtrTy
, Int8PtrTy
, Int8PtrTy
);
1728 FunctionCallee UnwindGetGR
= M
.getOrInsertFunction("_Unwind_GetGR", VoidTy
);
1729 FunctionCallee UnwindGetCFA
= M
.getOrInsertFunction("_Unwind_GetCFA", VoidTy
);
1731 for (auto &P
: PersonalityFns
) {
1732 std::string ThunkName
= kHwasanPersonalityThunkName
;
1734 ThunkName
+= ("." + P
.first
->getName()).str();
1735 FunctionType
*ThunkFnTy
= FunctionType::get(
1736 Int32Ty
, {Int32Ty
, Int32Ty
, Int64Ty
, Int8PtrTy
, Int8PtrTy
}, false);
1737 bool IsLocal
= P
.first
&& (!isa
<GlobalValue
>(P
.first
) ||
1738 cast
<GlobalValue
>(P
.first
)->hasLocalLinkage());
1739 auto *ThunkFn
= Function::Create(ThunkFnTy
,
1740 IsLocal
? GlobalValue::InternalLinkage
1741 : GlobalValue::LinkOnceODRLinkage
,
1744 ThunkFn
->setVisibility(GlobalValue::HiddenVisibility
);
1745 ThunkFn
->setComdat(M
.getOrInsertComdat(ThunkName
));
1748 auto *BB
= BasicBlock::Create(*C
, "entry", ThunkFn
);
1749 IRBuilder
<> IRB(BB
);
1750 CallInst
*WrapperCall
= IRB
.CreateCall(
1751 HwasanPersonalityWrapper
,
1752 {ThunkFn
->getArg(0), ThunkFn
->getArg(1), ThunkFn
->getArg(2),
1753 ThunkFn
->getArg(3), ThunkFn
->getArg(4),
1754 P
.first
? IRB
.CreateBitCast(P
.first
, Int8PtrTy
)
1755 : Constant::getNullValue(Int8PtrTy
),
1756 IRB
.CreateBitCast(UnwindGetGR
.getCallee(), Int8PtrTy
),
1757 IRB
.CreateBitCast(UnwindGetCFA
.getCallee(), Int8PtrTy
)});
1758 WrapperCall
->setTailCall();
1759 IRB
.CreateRet(WrapperCall
);
1761 for (Function
*F
: P
.second
)
1762 F
->setPersonalityFn(ThunkFn
);
1766 void HWAddressSanitizer::ShadowMapping::init(Triple
&TargetTriple
,
1767 bool InstrumentWithCalls
) {
1768 Scale
= kDefaultShadowScale
;
1769 if (TargetTriple
.isOSFuchsia()) {
1770 // Fuchsia is always PIE, which means that the beginning of the address
1771 // space is always available.
1775 WithFrameRecord
= true;
1776 } else if (ClMappingOffset
.getNumOccurrences() > 0) {
1779 Offset
= ClMappingOffset
;
1780 WithFrameRecord
= false;
1781 } else if (ClEnableKhwasan
|| InstrumentWithCalls
) {
1785 WithFrameRecord
= false;
1786 } else if (ClWithIfunc
) {
1789 Offset
= kDynamicShadowSentinel
;
1790 WithFrameRecord
= false;
1791 } else if (ClWithTls
) {
1794 Offset
= kDynamicShadowSentinel
;
1795 WithFrameRecord
= true;
1799 Offset
= kDynamicShadowSentinel
;
1800 WithFrameRecord
= false;