LLVM 24.0.0git
HWAddressSanitizer.cpp
Go to the documentation of this file.
1//===- HWAddressSanitizer.cpp - memory access error detector --------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file is a part of HWAddressSanitizer, an address basic correctness
11/// checker based on tagged addressing.
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/MapVector.h"
16#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/Statistic.h"
20#include "llvm/ADT/StringRef.h"
32#include "llvm/IR/Attributes.h"
33#include "llvm/IR/BasicBlock.h"
34#include "llvm/IR/Constant.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DataLayout.h"
38#include "llvm/IR/Dominators.h"
39#include "llvm/IR/Function.h"
40#include "llvm/IR/IRBuilder.h"
41#include "llvm/IR/InlineAsm.h"
43#include "llvm/IR/Instruction.h"
46#include "llvm/IR/Intrinsics.h"
47#include "llvm/IR/LLVMContext.h"
48#include "llvm/IR/MDBuilder.h"
49#include "llvm/IR/Module.h"
50#include "llvm/IR/Type.h"
51#include "llvm/IR/Value.h"
54#include "llvm/Support/Debug.h"
56#include "llvm/Support/MD5.h"
67#include <optional>
68#include <random>
69
70using namespace llvm;
71
72#define DEBUG_TYPE "hwasan"
73
74const char kHwasanModuleCtorName[] = "hwasan.module_ctor";
75const char kHwasanNoteName[] = "hwasan.note";
76const char kHwasanInitName[] = "__hwasan_init";
77const char kHwasanPersonalityThunkName[] = "__hwasan_personality_thunk";
78
80 "__hwasan_shadow_memory_dynamic_address";
81
82// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
83static const size_t kNumberOfAccessSizes = 5;
84
85static const size_t kDefaultShadowScale = 4;
86
87static const unsigned kShadowBaseAlignment = 32;
88
89namespace {
90enum class OffsetKind {
91 kFixed = 0,
92 kGlobal,
93 kIfunc,
94 kTls,
95};
96}
97
99 ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix",
100 cl::desc("Prefix for memory access callbacks"),
101 cl::Hidden, cl::init("__hwasan_"));
102
104 "hwasan-kernel-mem-intrinsic-prefix",
105 cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden,
106 cl::init(false));
107
109 "hwasan-instrument-with-calls",
110 cl::desc("instrument reads and writes with callbacks"), cl::Hidden,
111 cl::init(false));
112
113static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads",
114 cl::desc("instrument read instructions"),
115 cl::Hidden, cl::init(true));
116
117static cl::opt<bool>
118 ClInstrumentWrites("hwasan-instrument-writes",
119 cl::desc("instrument write instructions"), cl::Hidden,
120 cl::init(true));
121
123 "hwasan-instrument-atomics",
124 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,
125 cl::init(true));
126
127static cl::opt<bool> ClInstrumentByval("hwasan-instrument-byval",
128 cl::desc("instrument byval arguments"),
129 cl::Hidden, cl::init(true));
130
131static cl::opt<bool>
132 ClRecover("hwasan-recover",
133 cl::desc("Enable recovery mode (continue-after-error)."),
134 cl::Hidden, cl::init(false));
135
136static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack",
137 cl::desc("instrument stack (allocas)"),
138 cl::Hidden, cl::init(true));
139
140static cl::opt<bool>
141 ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true),
142 cl::Hidden, cl::desc("Use Stack Safety analysis results"));
143
145 "hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3),
147 cl::desc("How many lifetime ends to handle for a single alloca."));
148
149static cl::opt<bool>
150 ClUseAfterScope("hwasan-use-after-scope",
151 cl::desc("detect use after scope within function"),
152 cl::Hidden, cl::init(true));
153
155 "hwasan-strict-use-after-scope",
156 cl::desc("for complicated lifetimes, tag both on end and return"),
157 cl::Hidden, cl::init(true));
158
160 "hwasan-generate-tags-with-calls",
161 cl::desc("generate new tags with runtime library calls"), cl::Hidden,
162 cl::init(false));
163
164static cl::opt<bool> ClGlobals("hwasan-globals", cl::desc("Instrument globals"),
165 cl::Hidden, cl::init(false));
166
168 "hwasan-all-globals",
169 cl::desc(
170 "Instrument globals, even those within user-defined sections. Warning: "
171 "This may break existing code which walks globals via linker-generated "
172 "symbols, expects certain globals to be contiguous with each other, or "
173 "makes other assumptions which are invalidated by HWASan "
174 "instrumentation."),
175 cl::Hidden, cl::init(false));
176
178 "hwasan-match-all-tag",
179 cl::desc("don't report bad accesses via pointers with this tag"),
180 cl::Hidden, cl::init(-1));
181
182static cl::opt<bool>
183 ClEnableKhwasan("hwasan-kernel",
184 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),
185 cl::Hidden, cl::init(false));
186
187// These flags allow to change the shadow mapping and control how shadow memory
188// is accessed. The shadow mapping looks like:
189// Shadow = (Mem >> scale) + offset
190
192 ClMappingOffset("hwasan-mapping-offset",
193 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),
194 cl::Hidden);
195
197 "hwasan-mapping-offset-dynamic",
198 cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden,
199 cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"),
200 clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"),
201 clEnumValN(OffsetKind::kTls, "tls", "Use TLS")));
202
203static cl::opt<bool>
204 ClFrameRecords("hwasan-with-frame-record",
205 cl::desc("Use ring buffer for stack allocations"),
206 cl::Hidden);
207
208static cl::opt<int> ClHotPercentileCutoff("hwasan-percentile-cutoff-hot",
209 cl::desc("Hot percentile cutoff."));
210
211static cl::opt<float>
212 ClRandomKeepRate("hwasan-random-rate",
213 cl::desc("Probability value in the range [0.0, 1.0] "
214 "to keep instrumentation of a function. "
215 "Note: instrumentation can be skipped randomly "
216 "OR because of the hot percentile cutoff, if "
217 "both are supplied."));
218
220 "hwasan-static-linking",
221 cl::desc("Don't use .note.hwasan.globals section to instrument globals "
222 "from loadable libraries. "
223 "Note: in static binaries, the global variables section can be "
224 "accessed directly via linker-provided "
225 "__start_hwasan_globals and __stop_hwasan_globals symbols"),
226 cl::Hidden, cl::init(false));
227
228// Mode for selecting how to insert frame record info into the stack ring
229// buffer.
231 // Do not record frame record info.
233
234 // Insert instructions into the prologue for storing into the stack ring
235 // buffer directly.
237
238 // Add a call to __hwasan_add_frame_record in the runtime.
240};
241
243 "hwasan-record-stack-history",
244 cl::desc("Record stack frames with tagged allocations in a thread-local "
245 "ring buffer"),
246 cl::values(clEnumVal(none, "Do not record stack ring history"),
247 clEnumVal(instr, "Insert instructions into the prologue for "
248 "storing into the stack ring buffer directly"),
249 clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for "
250 "storing into the stack ring buffer")),
252
253static cl::opt<bool>
254 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics",
255 cl::desc("instrument memory intrinsics"),
256 cl::Hidden, cl::init(true));
257
258static cl::opt<bool>
259 ClInstrumentLandingPads("hwasan-instrument-landing-pads",
260 cl::desc("instrument landing pads"), cl::Hidden,
261 cl::init(false));
262
264 "hwasan-use-short-granules",
265 cl::desc("use short granules in allocas and outlined checks"), cl::Hidden,
266 cl::init(false));
267
269 "hwasan-instrument-personality-functions",
270 cl::desc("instrument personality functions"), cl::Hidden);
271
272static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
273 cl::desc("inline all checks"),
274 cl::Hidden, cl::init(false));
275
276static cl::opt<bool> ClInlineFastPathChecks("hwasan-inline-fast-path-checks",
277 cl::desc("inline all checks"),
278 cl::Hidden, cl::init(false));
279
280// Enabled from clang by "-fsanitize-hwaddress-experimental-aliasing".
281static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
282 cl::desc("Use page aliasing in HWASan"),
283 cl::Hidden, cl::init(false));
284
286 ClTagBits("hwasan-tag-bits",
287 cl::desc("Restrict tag to at most N bits. Needs to be > 4."),
288 cl::Hidden, cl::init(0));
289
290STATISTIC(NumTotalFuncs, "Number of total funcs");
291STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");
292STATISTIC(NumNoProfileSummaryFuncs, "Number of funcs without PS");
293
294namespace {
295
296template <typename T> T optOr(cl::opt<T> &Opt, T Other) {
297 return Opt.getNumOccurrences() ? Opt : Other;
298}
299
300bool shouldUsePageAliases(const Triple &TargetTriple) {
301 return ClUsePageAliases && TargetTriple.getArch() == Triple::x86_64;
302}
303
304bool shouldInstrumentStack(const Triple &TargetTriple) {
305 return !shouldUsePageAliases(TargetTriple) && ClInstrumentStack;
306}
307
308bool shouldInstrumentWithCalls(const Triple &TargetTriple) {
309 return optOr(ClInstrumentWithCalls, TargetTriple.getArch() == Triple::x86_64);
310}
311
312bool mightUseStackSafetyAnalysis(bool DisableOptimization) {
313 return optOr(ClUseStackSafety, !DisableOptimization);
314}
315
316bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple,
317 bool DisableOptimization) {
318 return shouldInstrumentStack(TargetTriple) &&
319 mightUseStackSafetyAnalysis(DisableOptimization);
320}
321
322bool shouldDetectUseAfterScope(const Triple &TargetTriple) {
323 return ClUseAfterScope && shouldInstrumentStack(TargetTriple);
324}
325
326/// An instrumentation pass implementing detection of addressability bugs
327/// using tagged pointers.
328class HWAddressSanitizer {
329public:
330 HWAddressSanitizer(Module &M, bool CompileKernel, bool Recover,
331 const StackSafetyGlobalInfo *SSI)
332 : M(M), SSI(SSI) {
333 this->Recover = optOr(ClRecover, Recover);
334 this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel);
335 this->Rng = ClRandomKeepRate.getNumOccurrences() ? M.createRNG(DEBUG_TYPE)
336 : nullptr;
337
338 initializeModule();
339 }
340
341 void sanitizeFunction(Function &F, FunctionAnalysisManager &FAM);
342
343private:
344 struct ShadowTagCheckInfo {
345 Instruction *TagMismatchTerm = nullptr;
346 Value *PtrLong = nullptr;
347 Value *AddrLong = nullptr;
348 Value *PtrTag = nullptr;
349 Value *MemTag = nullptr;
350 };
351
352 bool selectiveInstrumentationShouldSkip(Function &F,
354 void initializeModule();
355 void createHwasanCtorComdat();
356 void createHwasanNote();
357
358 void initializeCallbacks(Module &M);
359
360 Value *getOpaqueNoopCast(IRBuilder<> &IRB, Value *Val);
361
362 Value *getDynamicShadowIfunc(IRBuilder<> &IRB);
363 Value *getShadowNonTls(IRBuilder<> &IRB);
364
365 void untagPointerOperand(Instruction *I, Value *Addr);
366 Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
367
368 int64_t getAccessInfo(bool IsWrite, unsigned AccessSizeIndex);
369 ShadowTagCheckInfo insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,
370 DomTreeUpdater &DTU, LoopInfo *LI);
371 void instrumentMemAccessOutline(Value *Ptr, bool IsWrite,
372 unsigned AccessSizeIndex,
373 Instruction *InsertBefore,
374 DomTreeUpdater &DTU, LoopInfo *LI);
375 void instrumentMemAccessInline(Value *Ptr, bool IsWrite,
376 unsigned AccessSizeIndex,
377 Instruction *InsertBefore, DomTreeUpdater &DTU,
378 LoopInfo *LI);
379 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *MI);
380 void instrumentMemIntrinsic(MemIntrinsic *MI);
381 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
382 LoopInfo *LI, const DataLayout &DL);
383 bool ignoreAccessWithoutRemark(Instruction *Inst, Value *Ptr);
384 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
385 Value *Ptr);
386
388 OptimizationRemarkEmitter &ORE, Instruction *I,
389 const TargetLibraryInfo &TLI,
390 SmallVectorImpl<InterestingMemoryOperand> &Interesting);
391
392 void tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, size_t Size);
393 Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
394 Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
395 void instrumentStack(OptimizationRemarkEmitter &ORE, memtag::StackInfo &Info,
396 Value *StackTag, Value *UARTag, const DominatorTree &DT,
397 const PostDominatorTree &PDT, const LoopInfo &LI);
398 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
399 Value *getNextTagWithCall(IRBuilder<> &IRB);
400 Value *getStackBaseTag(IRBuilder<> &IRB);
401 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, unsigned AllocaNo);
402 Value *getUARTag(IRBuilder<> &IRB);
403
404 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB);
405 Value *applyTagMask(IRBuilder<> &IRB, Value *OldTag);
406 unsigned retagMask(unsigned AllocaNo);
407
408 void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
409
410 void instrumentGlobal(GlobalVariable *GV, uint8_t Tag);
411 void instrumentGlobals();
412
413 Value *getCachedFP(IRBuilder<> &IRB);
414 Value *getFrameRecordInfo(IRBuilder<> &IRB);
415
416 void instrumentPersonalityFunctions();
417
418 LLVMContext *C;
419 Module &M;
420 const StackSafetyGlobalInfo *SSI;
421 Triple TargetTriple;
422 std::unique_ptr<RandomNumberGenerator> Rng;
423
424 /// This struct defines the shadow mapping using the rule:
425 /// If `kFixed`, then
426 /// shadow = (mem >> Scale) + Offset.
427 /// If `kGlobal`, then
428 /// extern char* __hwasan_shadow_memory_dynamic_address;
429 /// shadow = (mem >> Scale) + __hwasan_shadow_memory_dynamic_address
430 /// If `kIfunc`, then
431 /// extern char __hwasan_shadow[];
432 /// shadow = (mem >> Scale) + &__hwasan_shadow
433 /// If `kTls`, then
434 /// extern char *__hwasan_tls;
435 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment)
436 ///
437 /// If WithFrameRecord is true, then __hwasan_tls will be used to access the
438 /// ring buffer for storing stack allocations on targets that support it.
439 class ShadowMapping {
440 OffsetKind Kind;
441 uint64_t Offset;
442 uint8_t Scale;
443 bool WithFrameRecord;
444
445 void SetFixed(uint64_t O) {
446 Kind = OffsetKind::kFixed;
447 Offset = O;
448 }
449
450 public:
451 void init(Triple &TargetTriple, bool InstrumentWithCalls,
452 bool CompileKernel);
453 Align getObjectAlignment() const { return Align(1ULL << Scale); }
454 bool isInGlobal() const { return Kind == OffsetKind::kGlobal; }
455 bool isInIfunc() const { return Kind == OffsetKind::kIfunc; }
456 bool isInTls() const { return Kind == OffsetKind::kTls; }
457 bool isFixed() const { return Kind == OffsetKind::kFixed; }
458 uint8_t scale() const { return Scale; };
459 uint64_t offset() const {
460 assert(isFixed());
461 return Offset;
462 };
463 bool withFrameRecord() const { return WithFrameRecord; };
464 };
465
466 ShadowMapping Mapping;
467
468 Type *VoidTy = Type::getVoidTy(M.getContext());
469 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
470 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
471 Type *Int8Ty = Type::getInt8Ty(M.getContext());
472 Type *Int32Ty = Type::getInt32Ty(M.getContext());
473 Type *Int64Ty = Type::getInt64Ty(M.getContext());
474
475 bool CompileKernel;
476 bool Recover;
477 bool OutlinedChecks;
478 bool InlineFastPath;
479 bool UseShortGranules;
480 bool InstrumentLandingPads;
481 bool InstrumentWithCalls;
482 bool InstrumentStack;
483 bool InstrumentGlobals;
484 bool DetectUseAfterScope;
485 bool UsePageAliases;
486 bool UseMatchAllCallback;
487
488 std::optional<uint8_t> MatchAllTag;
489
490 unsigned PointerTagShift;
491 uint64_t TagMaskByte;
492
493 Function *HwasanCtorFunction;
494
495 FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
496 FunctionCallee HwasanMemoryAccessCallbackSized[2];
497
498 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
499 FunctionCallee HwasanHandleVfork;
500
501 FunctionCallee HwasanTagMemoryFunc;
502 FunctionCallee HwasanGenerateTagFunc;
503 FunctionCallee HwasanRecordFrameRecordFunc;
504
505 Constant *ShadowGlobal;
506
507 Value *ShadowBase = nullptr;
508 Value *StackBaseTag = nullptr;
509 Value *CachedFP = nullptr;
510 GlobalValue *ThreadPtrGlobal = nullptr;
511};
512
513} // end anonymous namespace
514
517 // Return early if nosanitize_hwaddress module flag is present for the module.
518 if (checkIfAlreadyInstrumented(M, "nosanitize_hwaddress"))
519 return PreservedAnalyses::all();
520 const StackSafetyGlobalInfo *SSI = nullptr;
521 const Triple &TargetTriple = M.getTargetTriple();
522 if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
523 SSI = &MAM.getResult<StackSafetyGlobalAnalysis>(M);
524
525 HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
526 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
527 for (Function &F : M)
528 HWASan.sanitizeFunction(F, FAM);
529
531 // DominatorTreeAnalysis, PostDominatorTreeAnalysis, and LoopAnalysis
532 // are incrementally updated throughout this pass whenever
533 // SplitBlockAndInsertIfThen is called.
537 // GlobalsAA is considered stateless and does not get invalidated unless
538 // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
539 // make changes that require GlobalsAA to be invalidated.
540 PA.abandon<GlobalsAA>();
541 return PA;
542}
544 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
545 static_cast<PassInfoMixin<HWAddressSanitizerPass> *>(this)->printPipeline(
546 OS, MapClassName2PassName);
547 OS << '<';
548 if (Options.CompileKernel)
549 OS << "kernel;";
550 if (Options.Recover)
551 OS << "recover";
552 OS << '>';
553}
554
555void HWAddressSanitizer::createHwasanNote() {
556 // Create a note that contains pointers to the list of global
557 // descriptors. Adding a note to the output file will cause the linker to
558 // create a PT_NOTE program header pointing to the note that we can use to
559 // find the descriptor list starting from the program headers. A function
560 // provided by the runtime initializes the shadow memory for the globals by
561 // accessing the descriptor list via the note. The dynamic loader needs to
562 // call this function whenever a library is loaded.
563 //
564 // The reason why we use a note for this instead of a more conventional
565 // approach of having a global constructor pass a descriptor list pointer to
566 // the runtime is because of an order of initialization problem. With
567 // constructors we can encounter the following problematic scenario:
568 //
569 // 1) library A depends on library B and also interposes one of B's symbols
570 // 2) B's constructors are called before A's (as required for correctness)
571 // 3) during construction, B accesses one of its "own" globals (actually
572 // interposed by A) and triggers a HWASAN failure due to the initialization
573 // for A not having happened yet
574 //
575 // Even without interposition it is possible to run into similar situations in
576 // cases where two libraries mutually depend on each other.
577 //
578 // We only need one note per binary, so put everything for the note in a
579 // comdat. This needs to be a comdat with an .init_array section to prevent
580 // newer versions of lld from discarding the note.
581 //
582 // Create the note even if we aren't instrumenting globals. This ensures that
583 // binaries linked from object files with both instrumented and
584 // non-instrumented globals will end up with a note, even if a comdat from an
585 // object file with non-instrumented globals is selected. The note is harmless
586 // if the runtime doesn't support it, since it will just be ignored.
587 Comdat *NoteComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
588
589 Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0);
590 auto *Start =
591 new GlobalVariable(M, Int8Arr0Ty, true, GlobalVariable::ExternalLinkage,
592 nullptr, "__start_hwasan_globals");
593 Start->setVisibility(GlobalValue::HiddenVisibility);
594 auto *Stop =
595 new GlobalVariable(M, Int8Arr0Ty, true, GlobalVariable::ExternalLinkage,
596 nullptr, "__stop_hwasan_globals");
597 Stop->setVisibility(GlobalValue::HiddenVisibility);
598
599 // Null-terminated so actually 8 bytes, which are required in order to align
600 // the note properly.
601 auto *Name = ConstantDataArray::get(*C, "LLVM\0\0\0");
602
603 auto *NoteTy = StructType::get(Int32Ty, Int32Ty, Int32Ty, Name->getType(),
604 Int32Ty, Int32Ty);
605 auto *Note =
606 new GlobalVariable(M, NoteTy, /*isConstant=*/true,
608 Note->setSection(".note.hwasan.globals");
609 Note->setComdat(NoteComdat);
610 Note->setAlignment(Align(4));
611
612 // The pointers in the note need to be relative so that the note ends up being
613 // placed in rodata, which is the standard location for notes.
614 auto CreateRelPtr = [&](Constant *Ptr) {
618 Int32Ty);
619 };
620 Note->setInitializer(ConstantStruct::getAnon(
621 {ConstantInt::get(Int32Ty, 8), // n_namesz
622 ConstantInt::get(Int32Ty, 8), // n_descsz
623 ConstantInt::get(Int32Ty, ELF::NT_LLVM_HWASAN_GLOBALS), // n_type
624 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
626
627 // Create a zero-length global in hwasan_globals so that the linker will
628 // always create start and stop symbols.
629 auto *Dummy = new GlobalVariable(
630 M, Int8Arr0Ty, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage,
631 Constant::getNullValue(Int8Arr0Ty), "hwasan.dummy.global");
632 Dummy->setSection("hwasan_globals");
633 Dummy->setComdat(NoteComdat);
634 Dummy->setMetadata(LLVMContext::MD_associated,
636 appendToCompilerUsed(M, Dummy);
637}
638
639void HWAddressSanitizer::createHwasanCtorComdat() {
640 std::tie(HwasanCtorFunction, std::ignore) =
643 /*InitArgTypes=*/{},
644 /*InitArgs=*/{},
645 // This callback is invoked when the functions are created the first
646 // time. Hook them into the global ctors list in that case:
647 [&](Function *Ctor, FunctionCallee) {
648 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName);
649 Ctor->setComdat(CtorComdat);
650 appendToGlobalCtors(M, Ctor, 0, Ctor);
651 });
652
653 // Do not create .note.hwasan.globals for static binaries, as it is only
654 // needed for instrumenting globals from dynamic libraries. In static
655 // binaries, the global variables section can be accessed directly via the
656 // __start_hwasan_globals and __stop_hwasan_globals symbols inserted by the
657 // linker.
658 if (!ClStaticLinking)
659 createHwasanNote();
660}
661
662/// Module-level initialization.
663///
664/// inserts a call to __hwasan_init to the module's constructor list.
665void HWAddressSanitizer::initializeModule() {
666 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
667 TargetTriple = M.getTargetTriple();
668
669 // HWASan may do short granule checks on function arguments read from the
670 // argument memory (last byte of the granule), which invalidates writeonly.
671 for (Function &F : M.functions())
672 removeASanIncompatibleFnAttributes(F, /*ReadsArgMem=*/true);
673
674 // x86_64 currently has two modes:
675 // - Intel LAM (default)
676 // - pointer aliasing (heap only)
677 bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
678 UsePageAliases = shouldUsePageAliases(TargetTriple);
679 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
680 InstrumentStack = shouldInstrumentStack(TargetTriple);
681 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
682 PointerTagShift = IsX86_64 ? 57 : 56;
683 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
684 if (ClTagBits) {
685 if (TagMaskByte < 4)
687 "need more than 4 bits of tag to have non-short-granule tags");
688 TagMaskByte &= (1ULL << ClTagBits) - 1;
689 }
690
691 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
692
693 C = &(M.getContext());
694 IRBuilder<> IRB(*C);
695
696 HwasanCtorFunction = nullptr;
697
698 // Older versions of Android do not have the required runtime support for
699 // short granules, global or personality function instrumentation. On other
700 // platforms we currently require using the latest version of the runtime.
701 bool NewRuntime =
702 !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30);
703
704 UseShortGranules = optOr(ClUseShortGranules, NewRuntime);
705 OutlinedChecks = (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) &&
706 TargetTriple.isOSBinFormatELF() &&
707 !optOr(ClInlineAllChecks, Recover);
708
709 // These platforms may prefer less inlining to reduce binary size.
710 InlineFastPath = optOr(ClInlineFastPathChecks, !(TargetTriple.isAndroid() ||
711 TargetTriple.isOSFuchsia()));
712
713 if (ClMatchAllTag.getNumOccurrences()) {
714 if (ClMatchAllTag != -1) {
715 MatchAllTag = ClMatchAllTag & 0xFF;
716 }
717 } else if (CompileKernel) {
718 MatchAllTag = 0xFF;
719 }
720 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
721
722 // If we don't have personality function support, fall back to landing pads.
723 InstrumentLandingPads = optOr(ClInstrumentLandingPads, !NewRuntime);
724
725 InstrumentGlobals =
726 !CompileKernel && !UsePageAliases && optOr(ClGlobals, NewRuntime);
727
728 if (!CompileKernel) {
729 if (InstrumentGlobals)
730 instrumentGlobals();
731
732 createHwasanCtorComdat();
733
734 bool InstrumentPersonalityFunctions =
735 optOr(ClInstrumentPersonalityFunctions, NewRuntime);
736 if (InstrumentPersonalityFunctions)
737 instrumentPersonalityFunctions();
738 }
739
740 if (!TargetTriple.isAndroid()) {
741 ThreadPtrGlobal = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {
742 auto *GV = new GlobalVariable(M, IntptrTy, /*isConstant=*/false,
744 "__hwasan_tls", nullptr,
747 return GV;
748 });
749 }
750}
751
752void HWAddressSanitizer::initializeCallbacks(Module &M) {
753 IRBuilder<> IRB(*C);
754 const std::string MatchAllStr = UseMatchAllCallback ? "_match_all" : "";
755 FunctionType *HwasanMemoryAccessCallbackSizedFnTy,
756 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
757 *HwasanMemsetFnTy;
758 if (UseMatchAllCallback) {
759 HwasanMemoryAccessCallbackSizedFnTy =
760 FunctionType::get(VoidTy, {IntptrTy, IntptrTy, Int8Ty}, false);
761 HwasanMemoryAccessCallbackFnTy =
762 FunctionType::get(VoidTy, {IntptrTy, Int8Ty}, false);
763 HwasanMemTransferFnTy =
764 FunctionType::get(PtrTy, {PtrTy, PtrTy, IntptrTy, Int8Ty}, false);
765 HwasanMemsetFnTy =
766 FunctionType::get(PtrTy, {PtrTy, Int32Ty, IntptrTy, Int8Ty}, false);
767 } else {
768 HwasanMemoryAccessCallbackSizedFnTy =
769 FunctionType::get(VoidTy, {IntptrTy, IntptrTy}, false);
770 HwasanMemoryAccessCallbackFnTy =
771 FunctionType::get(VoidTy, {IntptrTy}, false);
772 HwasanMemTransferFnTy =
773 FunctionType::get(PtrTy, {PtrTy, PtrTy, IntptrTy}, false);
774 HwasanMemsetFnTy =
775 FunctionType::get(PtrTy, {PtrTy, Int32Ty, IntptrTy}, false);
776 }
777
778 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
779 const std::string TypeStr = AccessIsWrite ? "store" : "load";
780 const std::string EndingStr = Recover ? "_noabort" : "";
781
782 HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(
783 ClMemoryAccessCallbackPrefix + TypeStr + "N" + MatchAllStr + EndingStr,
784 HwasanMemoryAccessCallbackSizedFnTy);
785
786 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
787 AccessSizeIndex++) {
788 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
789 M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + TypeStr +
790 itostr(1ULL << AccessSizeIndex) +
791 MatchAllStr + EndingStr,
792 HwasanMemoryAccessCallbackFnTy);
793 }
794 }
795
796 const std::string MemIntrinCallbackPrefix =
797 (CompileKernel && !ClKasanMemIntrinCallbackPrefix)
798 ? std::string("")
800
801 HwasanMemmove = M.getOrInsertFunction(
802 MemIntrinCallbackPrefix + "memmove" + MatchAllStr, HwasanMemTransferFnTy);
803 HwasanMemcpy = M.getOrInsertFunction(
804 MemIntrinCallbackPrefix + "memcpy" + MatchAllStr, HwasanMemTransferFnTy);
805 HwasanMemset = M.getOrInsertFunction(
806 MemIntrinCallbackPrefix + "memset" + MatchAllStr, HwasanMemsetFnTy);
807
808 HwasanTagMemoryFunc = M.getOrInsertFunction("__hwasan_tag_memory", VoidTy,
809 PtrTy, Int8Ty, IntptrTy);
810 HwasanGenerateTagFunc =
811 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);
812
813 HwasanRecordFrameRecordFunc =
814 M.getOrInsertFunction("__hwasan_add_frame_record", VoidTy, Int64Ty);
815
816 ShadowGlobal =
817 M.getOrInsertGlobal("__hwasan_shadow", ArrayType::get(Int8Ty, 0));
818
819 HwasanHandleVfork =
820 M.getOrInsertFunction("__hwasan_handle_vfork", VoidTy, IntptrTy);
821}
822
823Value *HWAddressSanitizer::getOpaqueNoopCast(IRBuilder<> &IRB, Value *Val) {
824 // An empty inline asm with input reg == output reg.
825 // An opaque no-op cast, basically.
826 // This prevents code bloat as a result of rematerializing trivial definitions
827 // such as constants or global addresses at every load and store.
828 InlineAsm *Asm =
829 InlineAsm::get(FunctionType::get(PtrTy, {Val->getType()}, false),
830 StringRef(""), StringRef("=r,0"),
831 /*hasSideEffects=*/false);
832 return IRB.CreateCall(Asm, {Val}, ".hwasan.shadow");
833}
834
835Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {
836 return getOpaqueNoopCast(IRB, ShadowGlobal);
837}
838
839Value *HWAddressSanitizer::getShadowNonTls(IRBuilder<> &IRB) {
840 if (Mapping.isFixed()) {
841 return getOpaqueNoopCast(
843 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
844 }
845
846 if (Mapping.isInIfunc())
847 return getDynamicShadowIfunc(IRB);
848
849 Value *GlobalDynamicAddress =
852 return IRB.CreateLoad(PtrTy, GlobalDynamicAddress);
853}
854
855bool HWAddressSanitizer::ignoreAccessWithoutRemark(Instruction *Inst,
856 Value *Ptr) {
857 // Do not instrument accesses from different address spaces; we cannot deal
858 // with them.
859 Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType());
860 if (PtrTy->getPointerAddressSpace() != 0)
861 return true;
862
863 // Ignore swifterror addresses.
864 // swifterror memory addresses are mem2reg promoted by instruction
865 // selection. As such they cannot have regular uses like an instrumentation
866 // function and it makes no sense to track them as memory.
867 if (Ptr->isSwiftError())
868 return true;
869
870 if (findAllocaForValue(Ptr)) {
871 if (!InstrumentStack)
872 return true;
873 if (SSI && SSI->stackAccessIsSafe(*Inst))
874 return true;
875 }
876
878 if (!InstrumentGlobals)
879 return true;
880 // TODO: Optimize inbound global accesses, like Asan `instrumentMop`.
881 }
882
883 return false;
884}
885
886bool HWAddressSanitizer::ignoreAccess(OptimizationRemarkEmitter &ORE,
887 Instruction *Inst, Value *Ptr) {
888 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
889 if (Ignored) {
890 ORE.emit(
891 [&]() { return OptimizationRemark(DEBUG_TYPE, "ignoreAccess", Inst); });
892 } else {
893 ORE.emit([&]() {
894 return OptimizationRemarkMissed(DEBUG_TYPE, "ignoreAccess", Inst);
895 });
896 }
897 return Ignored;
898}
899
900void HWAddressSanitizer::getInterestingMemoryOperands(
902 const TargetLibraryInfo &TLI,
904 // Skip memory accesses inserted by another instrumentation.
905 if (I->hasMetadata(LLVMContext::MD_nosanitize))
906 return;
907
908 // Do not instrument the load fetching the dynamic shadow address.
909 if (ShadowBase == I)
910 return;
911
912 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
913 if (!ClInstrumentReads || ignoreAccess(ORE, I, LI->getPointerOperand()))
914 return;
915 Interesting.emplace_back(I, LI->getPointerOperandIndex(), false,
916 LI->getType(), LI->getAlign());
917 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
918 if (!ClInstrumentWrites || ignoreAccess(ORE, I, SI->getPointerOperand()))
919 return;
920 Interesting.emplace_back(I, SI->getPointerOperandIndex(), true,
921 SI->getValueOperand()->getType(), SI->getAlign());
922 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
923 if (!ClInstrumentAtomics || ignoreAccess(ORE, I, RMW->getPointerOperand()))
924 return;
925 Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true,
926 RMW->getValOperand()->getType(), std::nullopt);
927 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
928 if (!ClInstrumentAtomics || ignoreAccess(ORE, I, XCHG->getPointerOperand()))
929 return;
930 Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true,
931 XCHG->getCompareOperand()->getType(),
932 std::nullopt);
933 } else if (auto *CI = dyn_cast<CallInst>(I)) {
934 for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
935 if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) ||
936 ignoreAccess(ORE, I, CI->getArgOperand(ArgNo)))
937 continue;
938 Type *Ty = CI->getParamByValType(ArgNo);
939 Interesting.emplace_back(I, ArgNo, false, Ty, Align(1));
940 }
942 }
943}
944
946 if (LoadInst *LI = dyn_cast<LoadInst>(I))
947 return LI->getPointerOperandIndex();
949 return SI->getPointerOperandIndex();
951 return RMW->getPointerOperandIndex();
953 return XCHG->getPointerOperandIndex();
954 report_fatal_error("Unexpected instruction");
955 return -1;
956}
957
959 size_t Res = llvm::countr_zero(TypeSize / 8);
961 return Res;
962}
963
964void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {
965 if (TargetTriple.isAArch64() || TargetTriple.getArch() == Triple::x86_64 ||
966 TargetTriple.isRISCV64())
967 return;
968
969 IRBuilder<> IRB(I);
970 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
971 Value *UntaggedPtr =
972 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType());
973 I->setOperand(getPointerOperandIndex(I), UntaggedPtr);
974}
975
976Value *HWAddressSanitizer::memToShadow(Value *Mem, IRBuilder<> &IRB) {
977 // Mem >> Scale
978 Value *Shadow = IRB.CreateLShr(Mem, Mapping.scale());
979 if (Mapping.isFixed() && Mapping.offset() == 0)
980 return IRB.CreateIntToPtr(Shadow, PtrTy);
981 // (Mem >> Scale) + Offset
982 return IRB.CreatePtrAdd(ShadowBase, Shadow);
983}
984
985int64_t HWAddressSanitizer::getAccessInfo(bool IsWrite,
986 unsigned AccessSizeIndex) {
987 return (CompileKernel << HWASanAccessInfo::CompileKernelShift) |
988 (MatchAllTag.has_value() << HWASanAccessInfo::HasMatchAllShift) |
989 (MatchAllTag.value_or(0) << HWASanAccessInfo::MatchAllShift) |
990 (Recover << HWASanAccessInfo::RecoverShift) |
991 (IsWrite << HWASanAccessInfo::IsWriteShift) |
992 (AccessSizeIndex << HWASanAccessInfo::AccessSizeShift);
993}
994
995HWAddressSanitizer::ShadowTagCheckInfo
996HWAddressSanitizer::insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,
997 DomTreeUpdater &DTU, LoopInfo *LI) {
998 ShadowTagCheckInfo R;
999
1000 IRBuilder<> IRB(InsertBefore);
1001
1002 R.PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
1003 R.PtrTag =
1004 IRB.CreateTrunc(IRB.CreateLShr(R.PtrLong, PointerTagShift), Int8Ty);
1005 R.AddrLong = untagPointer(IRB, R.PtrLong);
1006 Value *Shadow = memToShadow(R.AddrLong, IRB);
1007 R.MemTag = IRB.CreateLoad(Int8Ty, Shadow);
1008 Value *TagMismatch = IRB.CreateICmpNE(R.PtrTag, R.MemTag);
1009
1010 if (MatchAllTag.has_value()) {
1011 Value *TagNotIgnored = IRB.CreateICmpNE(
1012 R.PtrTag, ConstantInt::get(R.PtrTag->getType(), *MatchAllTag));
1013 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);
1014 }
1015
1016 R.TagMismatchTerm = SplitBlockAndInsertIfThen(
1017 TagMismatch, InsertBefore, false,
1018 MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);
1019
1020 return R;
1021}
1022
1023void HWAddressSanitizer::instrumentMemAccessOutline(Value *Ptr, bool IsWrite,
1024 unsigned AccessSizeIndex,
1025 Instruction *InsertBefore,
1026 DomTreeUpdater &DTU,
1027 LoopInfo *LI) {
1028 assert(!UsePageAliases);
1029 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1030
1031 if (InlineFastPath)
1032 InsertBefore =
1033 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1034
1035 IRBuilder<> IRB(InsertBefore);
1036 bool UseFixedShadowIntrinsic = false;
1037 // The memaccess fixed shadow intrinsic is only supported on AArch64,
1038 // which allows a 16-bit immediate to be left-shifted by 32.
1039 // Since kShadowBaseAlignment == 32, and Linux by default will not
1040 // mmap above 48-bits, practically any valid shadow offset is
1041 // representable.
1042 // In particular, an offset of 4TB (1024 << 32) is representable, and
1043 // ought to be good enough for anybody.
1044 if (TargetTriple.isAArch64() && Mapping.isFixed()) {
1045 uint16_t OffsetShifted = Mapping.offset() >> 32;
1046 UseFixedShadowIntrinsic =
1047 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
1048 }
1049
1050 if (UseFixedShadowIntrinsic) {
1051 IRB.CreateIntrinsic(
1052 UseShortGranules
1053 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1054 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1055 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
1056 ConstantInt::get(Int64Ty, Mapping.offset())});
1057 } else {
1058 IRB.CreateIntrinsic(
1059 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1060 : Intrinsic::hwasan_check_memaccess,
1061 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
1062 }
1063}
1064
1065void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
1066 unsigned AccessSizeIndex,
1067 Instruction *InsertBefore,
1068 DomTreeUpdater &DTU,
1069 LoopInfo *LI) {
1070 assert(!UsePageAliases);
1071 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1072
1073 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
1074
1075 IRBuilder<> IRB(TCI.TagMismatchTerm);
1076 Value *OutOfShortGranuleTagRange =
1077 IRB.CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1078 Instruction *CheckFailTerm = SplitBlockAndInsertIfThen(
1079 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1080 MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);
1081
1082 IRB.SetInsertPoint(TCI.TagMismatchTerm);
1083 Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(TCI.PtrLong, 15), Int8Ty);
1084 PtrLowBits = IRB.CreateAdd(
1085 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1086 Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, TCI.MemTag);
1087 SplitBlockAndInsertIfThen(PtrLowBitsOOB, TCI.TagMismatchTerm, false,
1089 LI, CheckFailTerm->getParent());
1090
1091 IRB.SetInsertPoint(TCI.TagMismatchTerm);
1092 Value *InlineTagAddr = IRB.CreateOr(TCI.AddrLong, 15);
1093 InlineTagAddr = IRB.CreateIntToPtr(InlineTagAddr, PtrTy);
1094 Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr);
1095 Value *InlineTagMismatch = IRB.CreateICmpNE(TCI.PtrTag, InlineTag);
1096 SplitBlockAndInsertIfThen(InlineTagMismatch, TCI.TagMismatchTerm, false,
1098 LI, CheckFailTerm->getParent());
1099
1100 IRB.SetInsertPoint(CheckFailTerm);
1101 InlineAsm *Asm;
1102 switch (TargetTriple.getArch()) {
1103 case Triple::x86_64:
1104 // The signal handler will find the data address in rdi.
1106 FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1107 "int3\nnopl " +
1108 itostr(0x40 + (AccessInfo & HWASanAccessInfo::RuntimeMask)) +
1109 "(%rax)",
1110 "{rdi}",
1111 /*hasSideEffects=*/true);
1112 break;
1113 case Triple::aarch64:
1114 case Triple::aarch64_be:
1115 // The signal handler will find the data address in x0.
1117 FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1118 "brk #" + itostr(0x900 + (AccessInfo & HWASanAccessInfo::RuntimeMask)),
1119 "{x0}",
1120 /*hasSideEffects=*/true);
1121 break;
1122 case Triple::riscv64:
1123 // The signal handler will find the data address in x10.
1125 FunctionType::get(VoidTy, {TCI.PtrLong->getType()}, false),
1126 "ebreak\naddiw x0, x11, " +
1127 itostr(0x40 + (AccessInfo & HWASanAccessInfo::RuntimeMask)),
1128 "{x10}",
1129 /*hasSideEffects=*/true);
1130 break;
1131 default:
1132 report_fatal_error("unsupported architecture");
1133 }
1134 IRB.CreateCall(Asm, TCI.PtrLong);
1135 if (Recover)
1136 cast<UncondBrInst>(CheckFailTerm)
1137 ->setSuccessor(TCI.TagMismatchTerm->getParent());
1138}
1139
1140bool HWAddressSanitizer::ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE,
1141 MemIntrinsic *MI) {
1143 return (!ClInstrumentWrites || ignoreAccess(ORE, MTI, MTI->getDest())) &&
1144 (!ClInstrumentReads || ignoreAccess(ORE, MTI, MTI->getSource()));
1145 }
1146 if (isa<MemSetInst>(MI))
1147 return !ClInstrumentWrites || ignoreAccess(ORE, MI, MI->getDest());
1148 return false;
1149}
1150
1151void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
1152 IRBuilder<> IRB(MI);
1153 if (isa<MemTransferInst>(MI)) {
1155 MI->getOperand(0), MI->getOperand(1),
1156 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)};
1157
1158 if (UseMatchAllCallback)
1159 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1160 IRB.CreateCall(isa<MemMoveInst>(MI) ? HwasanMemmove : HwasanMemcpy, Args);
1161 } else if (isa<MemSetInst>(MI)) {
1163 MI->getOperand(0),
1164 IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false),
1165 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)};
1166 if (UseMatchAllCallback)
1167 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1168 IRB.CreateCall(HwasanMemset, Args);
1169 }
1170 MI->eraseFromParent();
1171}
1172
1173bool HWAddressSanitizer::instrumentMemAccess(InterestingMemoryOperand &O,
1174 DomTreeUpdater &DTU, LoopInfo *LI,
1175 const DataLayout &DL) {
1176 Value *Addr = O.getPtr();
1177
1178 LLVM_DEBUG(dbgs() << "Instrumenting: " << O.getInsn() << "\n");
1179
1180 // If the pointer is statically known to be zero, the tag check will pass
1181 // since:
1182 // 1) it has a zero tag
1183 // 2) the shadow memory corresponding to address 0 is initialized to zero and
1184 // never updated.
1185 // We can therefore elide the tag check.
1186 llvm::KnownBits Known(DL.getPointerTypeSizeInBits(Addr->getType()));
1188 if (Known.isZero())
1189 return false;
1190
1191 if (O.MaybeMask)
1192 return false; // FIXME
1193
1194 IRBuilder<> IRB(O.getInsn());
1195 if (!O.TypeStoreSize.isScalable() && isPowerOf2_64(O.TypeStoreSize) &&
1196 (O.TypeStoreSize / 8 <= (1ULL << (kNumberOfAccessSizes - 1))) &&
1197 (!O.Alignment || *O.Alignment >= Mapping.getObjectAlignment() ||
1198 *O.Alignment >= O.TypeStoreSize / 8)) {
1199 size_t AccessSizeIndex = TypeSizeToSizeIndex(O.TypeStoreSize);
1200 if (InstrumentWithCalls) {
1201 SmallVector<Value *, 2> Args{IRB.CreatePointerCast(Addr, IntptrTy)};
1202 if (UseMatchAllCallback)
1203 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1204 IRB.CreateCall(HwasanMemoryAccessCallback[O.IsWrite][AccessSizeIndex],
1205 Args);
1206 } else if (OutlinedChecks) {
1207 instrumentMemAccessOutline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),
1208 DTU, LI);
1209 } else {
1210 instrumentMemAccessInline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),
1211 DTU, LI);
1212 }
1213 } else {
1215 IRB.CreatePointerCast(Addr, IntptrTy),
1216 IRB.CreateUDiv(IRB.CreateTypeSize(IntptrTy, O.TypeStoreSize),
1217 ConstantInt::get(IntptrTy, 8))};
1218 if (UseMatchAllCallback)
1219 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1220 IRB.CreateCall(HwasanMemoryAccessCallbackSized[O.IsWrite], Args);
1221 }
1222 untagPointerOperand(O.getInsn(), Addr);
1223
1224 return true;
1225}
1226
1227void HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag,
1228 size_t Size) {
1229 size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());
1230 if (!UseShortGranules)
1231 Size = AlignedSize;
1232
1233 Tag = IRB.CreateTrunc(Tag, Int8Ty);
1234 if (InstrumentWithCalls) {
1235 IRB.CreateCall(HwasanTagMemoryFunc,
1236 {IRB.CreatePointerCast(AI, PtrTy), Tag,
1237 ConstantInt::get(IntptrTy, AlignedSize)});
1238 } else {
1239 size_t ShadowSize = Size >> Mapping.scale();
1240 Value *AddrLong = untagPointer(IRB, IRB.CreatePointerCast(AI, IntptrTy));
1241 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1242 // If this memset is not inlined, it will be intercepted in the hwasan
1243 // runtime library. That's OK, because the interceptor skips the checks if
1244 // the address is in the shadow region.
1245 // FIXME: the interceptor is not as fast as real memset. Consider lowering
1246 // llvm.memset right here into either a sequence of stores, or a call to
1247 // hwasan_tag_memory.
1248 if (ShadowSize)
1249 IRB.CreateMemSet(ShadowPtr, Tag, ShadowSize, Align(1));
1250 if (Size != AlignedSize) {
1251 const uint8_t SizeRemainder = Size % Mapping.getObjectAlignment().value();
1252 IRB.CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1253 IRB.CreateConstGEP1_32(Int8Ty, ShadowPtr, ShadowSize));
1254 IRB.CreateStore(
1255 Tag, IRB.CreateConstGEP1_32(Int8Ty, IRB.CreatePointerCast(AI, PtrTy),
1256 AlignedSize - 1));
1257 }
1258 }
1259}
1260
1261unsigned HWAddressSanitizer::retagMask(unsigned AllocaNo) {
1262 if (TargetTriple.getArch() == Triple::x86_64)
1263 return AllocaNo & TagMaskByte;
1264
1265 // A list of 8-bit numbers that have at most one run of non-zero bits.
1266 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
1267 // masks.
1268 // The list does not include the value 255, which is used for UAR.
1269 //
1270 // Because we are more likely to use earlier elements of this list than later
1271 // ones, it is sorted in increasing order of probability of collision with a
1272 // mask allocated (temporally) nearby. The program that generated this list
1273 // can be found at:
1274 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
1275 static const unsigned FastMasks[] = {
1276 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1277 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1278 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1279 return FastMasks[AllocaNo % std::size(FastMasks)];
1280}
1281
1282Value *HWAddressSanitizer::applyTagMask(IRBuilder<> &IRB, Value *OldTag) {
1283 if (TagMaskByte == 0xFF)
1284 return OldTag; // No need to clear the tag byte.
1285 return IRB.CreateAnd(OldTag,
1286 ConstantInt::get(OldTag->getType(), TagMaskByte));
1287}
1288
1289Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
1290 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
1291}
1292
1293Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
1295 return nullptr;
1296 if (StackBaseTag)
1297 return StackBaseTag;
1298 // Extract some entropy from the stack pointer for the tags.
1299 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ
1300 // between functions).
1301 Value *FramePointerLong = getCachedFP(IRB);
1302 Value *StackTag =
1303 applyTagMask(IRB, IRB.CreateXor(FramePointerLong,
1304 IRB.CreateLShr(FramePointerLong, 20)));
1305 StackTag->setName("hwasan.stack.base.tag");
1306 return StackTag;
1307}
1308
1309Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
1310 unsigned AllocaNo) {
1312 return getNextTagWithCall(IRB);
1313 return IRB.CreateXor(
1314 StackTag, ConstantInt::get(StackTag->getType(), retagMask(AllocaNo)));
1315}
1316
1317Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB) {
1318 Value *FramePointerLong = getCachedFP(IRB);
1319 Value *UARTag =
1320 applyTagMask(IRB, IRB.CreateLShr(FramePointerLong, PointerTagShift));
1321
1322 UARTag->setName("hwasan.uar.tag");
1323 return UARTag;
1324}
1325
1326// Add a tag to an address.
1327Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
1328 Value *PtrLong, Value *Tag) {
1329 assert(!UsePageAliases);
1330 Value *TaggedPtrLong;
1331 if (CompileKernel) {
1332 // Kernel addresses have 0xFF in the most significant byte.
1333 Value *ShiftedTag =
1334 IRB.CreateOr(IRB.CreateShl(Tag, PointerTagShift),
1335 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1336 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
1337 } else {
1338 // Userspace can simply do OR (tag << PointerTagShift);
1339 Value *ShiftedTag = IRB.CreateShl(Tag, PointerTagShift);
1340 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
1341 }
1342 return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
1343}
1344
1345// Remove tag from an address.
1346Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
1347 assert(!UsePageAliases);
1348 Value *UntaggedPtrLong;
1349 if (CompileKernel) {
1350 // Kernel addresses have 0xFF in the most significant byte.
1351 UntaggedPtrLong =
1352 IRB.CreateOr(PtrLong, ConstantInt::get(PtrLong->getType(),
1353 TagMaskByte << PointerTagShift));
1354 } else {
1355 // Userspace addresses have 0x00.
1356 UntaggedPtrLong = IRB.CreateAnd(
1357 PtrLong, ConstantInt::get(PtrLong->getType(),
1358 ~(TagMaskByte << PointerTagShift)));
1359 }
1360 return UntaggedPtrLong;
1361}
1362
1363Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB) {
1364 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
1365 // in Bionic's libc/platform/bionic/tls_defines.h.
1366 constexpr int SanitizerSlot = 6;
1367 if (TargetTriple.isAArch64() && TargetTriple.isAndroid())
1368 return memtag::getAndroidSlotPtr(IRB, SanitizerSlot);
1369 return ThreadPtrGlobal;
1370}
1371
1372Value *HWAddressSanitizer::getCachedFP(IRBuilder<> &IRB) {
1373 if (!CachedFP)
1374 CachedFP = memtag::getFP(IRB);
1375 return CachedFP;
1376}
1377
1378Value *HWAddressSanitizer::getFrameRecordInfo(IRBuilder<> &IRB) {
1379 // Prepare ring buffer data.
1380 Value *PC = memtag::getPC(TargetTriple, IRB);
1381 Value *FP = getCachedFP(IRB);
1382
1383 // Mix FP and PC.
1384 // Assumptions:
1385 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
1386 // FP is 0xfffffffffffFFFF0 (4 lower bits are zero)
1387 // We only really need ~20 lower non-zero bits (FFFF), so we mix like this:
1388 // 0xFFFFPPPPPPPPPPPP
1389 //
1390 // FP works because in AArch64FrameLowering::getFrameIndexReference, we
1391 // prefer FP-relative offsets for functions compiled with HWASan.
1392 FP = IRB.CreateShl(FP, 44);
1393 return IRB.CreateOr(PC, FP);
1394}
1395
1396void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
1397 if (!Mapping.isInTls())
1398 ShadowBase = getShadowNonTls(IRB);
1399 else if (!WithFrameRecord && TargetTriple.isAndroid())
1400 ShadowBase = getDynamicShadowIfunc(IRB);
1401
1402 if (!WithFrameRecord && ShadowBase)
1403 return;
1404
1405 Value *SlotPtr = nullptr;
1406 Value *ThreadLong = nullptr;
1407 Value *ThreadLongMaybeUntagged = nullptr;
1408
1409 auto getThreadLongMaybeUntagged = [&]() {
1410 if (!SlotPtr)
1411 SlotPtr = getHwasanThreadSlotPtr(IRB);
1412 if (!ThreadLong)
1413 ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
1414 // Extract the address field from ThreadLong. Unnecessary on AArch64 with
1415 // TBI.
1416 return TargetTriple.isAArch64() ? ThreadLong
1417 : untagPointer(IRB, ThreadLong);
1418 };
1419
1420 if (WithFrameRecord) {
1421 switch (ClRecordStackHistory) {
1422 case libcall: {
1423 // Emit a runtime call into hwasan rather than emitting instructions for
1424 // recording stack history.
1425 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1426 IRB.CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1427 break;
1428 }
1429 case instr: {
1430 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1431
1432 StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
1433
1434 // Store data to ring buffer.
1435 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1436 Value *RecordPtr =
1437 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IRB.getPtrTy(0));
1438 IRB.CreateStore(FrameRecordInfo, RecordPtr);
1439
1440 IRB.CreateStore(memtag::incrementThreadLong(IRB, ThreadLong, 8), SlotPtr);
1441 break;
1442 }
1443 case none: {
1445 "A stack history recording mode should've been selected.");
1446 }
1447 }
1448 }
1449
1450 if (!ShadowBase) {
1451 if (!ThreadLongMaybeUntagged)
1452 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1453
1454 // Get shadow base address by aligning RecordPtr up.
1455 // Note: this is not correct if the pointer is already aligned.
1456 // Runtime library will make sure this never happens.
1457 ShadowBase = IRB.CreateAdd(
1458 IRB.CreateOr(
1459 ThreadLongMaybeUntagged,
1460 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
1461 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
1462 ShadowBase = IRB.CreateIntToPtr(ShadowBase, PtrTy);
1463 }
1464}
1465
1466void HWAddressSanitizer::instrumentLandingPads(
1467 SmallVectorImpl<Instruction *> &LandingPadVec) {
1468 for (auto *LP : LandingPadVec) {
1469 IRBuilder<> IRB(LP->getNextNode());
1470 IRB.CreateCall(
1471 HwasanHandleVfork,
1473 IRB, (TargetTriple.getArch() == Triple::x86_64) ? "rsp" : "sp")});
1474 }
1475}
1476
1477void HWAddressSanitizer::instrumentStack(OptimizationRemarkEmitter &ORE,
1478 memtag::StackInfo &SInfo,
1479 Value *StackTag, Value *UARTag,
1480 const DominatorTree &DT,
1481 const PostDominatorTree &PDT,
1482 const LoopInfo &LI) {
1483 // Ideally, we want to calculate tagged stack base pointer, and rewrite all
1484 // alloca addresses using that. Unfortunately, offsets are not known yet
1485 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a
1486 // temp, shift-OR it into each alloca address and xor with the retag mask.
1487 // This generates one extra instruction per alloca use.
1488 unsigned int I = 0;
1489
1490 for (auto &KV : SInfo.AllocasToInstrument) {
1491 auto N = I++;
1492 auto *AI = KV.first;
1493 memtag::AllocaInfo &Info = KV.second;
1494 IRBuilder<> IRB(AI->getNextNode());
1495
1496 // Replace uses of the alloca with tagged address.
1497 Value *Tag = getAllocaTag(IRB, StackTag, N);
1498 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy);
1499 Value *AINoTagLong = untagPointer(IRB, AILong);
1500 Value *Replacement = tagPointer(IRB, AI->getType(), AINoTagLong, Tag);
1501 std::string Name =
1502 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N);
1503 Replacement->setName(Name + ".hwasan");
1504
1505 size_t Size = memtag::getAllocaSizeInBytes(*AI);
1506 size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());
1507
1508 AI->replaceUsesWithIf(Replacement, [AILong](const Use &U) {
1509 auto *User = U.getUser();
1510 return User != AILong && !isa<LifetimeIntrinsic>(User);
1511 });
1512
1513 memtag::annotateDebugRecords(Info, retagMask(N));
1514
1515 auto TagStarts = [&]() {
1516 for (IntrinsicInst *Start : Info.LifetimeStart) {
1517 IRB.SetInsertPoint(Start->getNextNode());
1518 tagAlloca(IRB, AI, Tag, Size);
1519 }
1520 };
1521 auto TagEnd = [&](Instruction *Node) {
1522 IRB.SetInsertPoint(Node);
1523 // When untagging, use the `AlignedSize` because we need to set the tags
1524 // for the entire alloca to original. If we used `Size` here, we would
1525 // keep the last granule tagged, and store zero in the last byte of the
1526 // last granule, due to how short granules are implemented.
1527 tagAlloca(IRB, AI, UARTag, AlignedSize);
1528 };
1529 auto EraseLifetimes = [&]() {
1530 for (auto &II : Info.LifetimeStart)
1531 II->eraseFromParent();
1532 for (auto &II : Info.LifetimeEnd)
1533 II->eraseFromParent();
1534 };
1535 // Calls to functions that may return twice (e.g. setjmp) confuse the
1536 // postdominator analysis, and will leave us to keep memory tagged after
1537 // function return. Work around this by always untagging at every return
1538 // statement if return_twice functions are called.
1539 if (DetectUseAfterScope && !SInfo.CallsReturnTwice &&
1540 memtag::isSupportedLifetime(Info, &DT, &LI)) {
1541 TagStarts();
1542 memtag::forAllReachableExits(DT, PDT, LI, Info, SInfo.RetVec, TagEnd);
1543 ORE.emit([&]() {
1544 return OptimizationRemark(DEBUG_TYPE, "supportedLifetime", AI);
1545 });
1546 } else if (DetectUseAfterScope && ClStrictUseAfterScope) {
1547 // SInfo.CallsReturnTwice || !isStandardLifetime
1548 ORE.emit([&]() {
1549 return OptimizationRemarkMissed(DEBUG_TYPE, "supportedLifetime", AI);
1550 });
1551
1552 tagAlloca(IRB, AI, Tag, Size);
1553 TagStarts();
1554 for_each(Info.LifetimeEnd, TagEnd);
1555 for_each(SInfo.RetVec, TagEnd);
1556 EraseLifetimes();
1557 } else {
1558 tagAlloca(IRB, AI, Tag, Size);
1559 for_each(SInfo.RetVec, TagEnd);
1560 EraseLifetimes();
1561 }
1562 memtag::alignAndPadAlloca(Info, Mapping.getObjectAlignment());
1563 }
1564}
1565
1567 bool Skip) {
1568 if (Skip) {
1569 ORE.emit([&]() {
1570 return OptimizationRemark(DEBUG_TYPE, "Skip", &F)
1571 << "Skipped: F=" << ore::NV("Function", &F);
1572 });
1573 } else {
1574 ORE.emit([&]() {
1575 return OptimizationRemarkMissed(DEBUG_TYPE, "Sanitize", &F)
1576 << "Sanitized: F=" << ore::NV("Function", &F);
1577 });
1578 }
1579}
1580
1581bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1583 auto SkipHot = [&]() {
1584 if (!ClHotPercentileCutoff.getNumOccurrences())
1585 return false;
1587 ProfileSummaryInfo *PSI =
1588 MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
1589 if (!PSI || !PSI->hasProfileSummary()) {
1590 ++NumNoProfileSummaryFuncs;
1591 return false;
1592 }
1593 return PSI->isFunctionHotInCallGraphNthPercentile(
1595 };
1596
1597 auto SkipRandom = [&]() {
1598 if (!ClRandomKeepRate.getNumOccurrences())
1599 return false;
1600 std::bernoulli_distribution D(ClRandomKeepRate);
1601 return !D(*Rng);
1602 };
1603
1604 bool Skip = SkipRandom() || SkipHot();
1606 return Skip;
1607}
1608
1609void HWAddressSanitizer::sanitizeFunction(Function &F,
1611 if (&F == HwasanCtorFunction)
1612 return;
1613
1614 // Do not apply any instrumentation for naked functions.
1615 if (F.hasFnAttribute(Attribute::Naked))
1616 return;
1617
1618 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress))
1619 return;
1620
1621 if (F.empty())
1622 return;
1623
1624 if (F.isPresplitCoroutine())
1625 return;
1626
1627 NumTotalFuncs++;
1628
1631
1632 if (selectiveInstrumentationShouldSkip(F, FAM))
1633 return;
1634
1635 NumInstrumentedFuncs++;
1636
1637 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
1638
1639 SmallVector<InterestingMemoryOperand, 16> OperandsToInstrument;
1640 SmallVector<MemIntrinsic *, 16> IntrinToInstrument;
1641 SmallVector<Instruction *, 8> LandingPadVec;
1643
1645 for (auto &Inst : instructions(F)) {
1646 if (InstrumentStack) {
1647 SIB.visit(ORE, Inst);
1648 }
1649
1650 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1651 LandingPadVec.push_back(&Inst);
1652
1653 getInterestingMemoryOperands(ORE, &Inst, TLI, OperandsToInstrument);
1654
1656 if (!ignoreMemIntrinsic(ORE, MI))
1657 IntrinToInstrument.push_back(MI);
1658 }
1659
1660 memtag::StackInfo &SInfo = SIB.get();
1661
1662 initializeCallbacks(*F.getParent());
1663
1664 if (!LandingPadVec.empty())
1665 instrumentLandingPads(LandingPadVec);
1666
1667 if (SInfo.AllocasToInstrument.empty() && F.hasPersonalityFn() &&
1668 F.getPersonalityFn()->getName() == kHwasanPersonalityThunkName) {
1669 // __hwasan_personality_thunk is a no-op for functions without an
1670 // instrumented stack, so we can drop it.
1671 F.setPersonalityFn(nullptr);
1672 }
1673
1674 if (SInfo.AllocasToInstrument.empty() && OperandsToInstrument.empty() &&
1675 IntrinToInstrument.empty())
1676 return;
1677
1678 assert(!ShadowBase);
1679
1680 BasicBlock::iterator InsertPt = F.getEntryBlock().begin();
1681 IRBuilder<> EntryIRB(&F.getEntryBlock(), InsertPt);
1682 emitPrologue(EntryIRB,
1683 /*WithFrameRecord*/ ClRecordStackHistory != none &&
1684 Mapping.withFrameRecord() &&
1685 !SInfo.AllocasToInstrument.empty());
1686
1687 if (!SInfo.AllocasToInstrument.empty()) {
1690 const LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
1691 Value *StackTag = getStackBaseTag(EntryIRB);
1692 Value *UARTag = getUARTag(EntryIRB);
1693 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1694 }
1695
1696 // If we split the entry block, move any allocas that were originally in the
1697 // entry block back into the entry block so that they aren't treated as
1698 // dynamic allocas.
1699 if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {
1700 InsertPt = F.getEntryBlock().begin();
1701 for (Instruction &I :
1702 llvm::make_early_inc_range(*EntryIRB.GetInsertBlock())) {
1703 if (auto *AI = dyn_cast<AllocaInst>(&I))
1704 if (isa<ConstantInt>(AI->getArraySize()))
1705 I.moveBefore(F.getEntryBlock(), InsertPt);
1706 }
1707 }
1708
1712 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1713 const DataLayout &DL = F.getDataLayout();
1714 for (auto &Operand : OperandsToInstrument)
1715 instrumentMemAccess(Operand, DTU, LI, DL);
1716 DTU.flush();
1717
1718 if (ClInstrumentMemIntrinsics && !IntrinToInstrument.empty()) {
1719 for (auto *Inst : IntrinToInstrument)
1720 instrumentMemIntrinsic(Inst);
1721 }
1722
1723 ShadowBase = nullptr;
1724 StackBaseTag = nullptr;
1725 CachedFP = nullptr;
1726}
1727
1728void HWAddressSanitizer::instrumentGlobal(GlobalVariable *GV, uint8_t Tag) {
1729 assert(!UsePageAliases);
1730 Constant *Initializer = GV->getInitializer();
1731 uint64_t SizeInBytes =
1732 M.getDataLayout().getTypeAllocSize(Initializer->getType());
1733 uint64_t NewSize = alignTo(SizeInBytes, Mapping.getObjectAlignment());
1734 if (SizeInBytes != NewSize) {
1735 // Pad the initializer out to the next multiple of 16 bytes and add the
1736 // required short granule tag.
1737 std::vector<uint8_t> Init(NewSize - SizeInBytes, 0);
1738 Init.back() = Tag;
1740 Initializer = ConstantStruct::getAnon({Initializer, Padding});
1741 }
1742
1743 auto *NewGV = new GlobalVariable(M, Initializer->getType(), GV->isConstant(),
1744 GlobalValue::ExternalLinkage, Initializer,
1745 GV->getName() + ".hwasan");
1746 NewGV->copyAttributesFrom(GV);
1747 NewGV->setLinkage(GlobalValue::PrivateLinkage);
1748 NewGV->copyMetadata(GV, 0);
1749 NewGV->setAlignment(
1750 std::max(GV->getAlign().valueOrOne(), Mapping.getObjectAlignment()));
1751
1752 // It is invalid to ICF two globals that have different tags. In the case
1753 // where the size of the global is a multiple of the tag granularity the
1754 // contents of the globals may be the same but the tags (i.e. symbol values)
1755 // may be different, and the symbols are not considered during ICF. In the
1756 // case where the size is not a multiple of the granularity, the short granule
1757 // tags would discriminate two globals with different tags, but there would
1758 // otherwise be nothing stopping such a global from being incorrectly ICF'd
1759 // with an uninstrumented (i.e. tag 0) global that happened to have the short
1760 // granule tag in the last byte.
1761 NewGV->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
1762
1763 // Descriptor format (assuming little-endian):
1764 // bytes 0-3: relative address of global
1765 // bytes 4-6: size of global (16MB ought to be enough for anyone, but in case
1766 // it isn't, we create multiple descriptors)
1767 // byte 7: tag
1768 auto *DescriptorTy = StructType::get(Int32Ty, Int32Ty);
1769 const uint64_t MaxDescriptorSize = 0xfffff0;
1770 for (uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1771 DescriptorPos += MaxDescriptorSize) {
1772 auto *Descriptor =
1773 new GlobalVariable(M, DescriptorTy, true, GlobalValue::PrivateLinkage,
1774 nullptr, GV->getName() + ".hwasan.descriptor");
1775 auto *GVRelPtr = ConstantExpr::getTrunc(
1778 ConstantExpr::getPtrToInt(NewGV, Int64Ty),
1779 ConstantExpr::getPtrToInt(Descriptor, Int64Ty)),
1780 ConstantInt::get(Int64Ty, DescriptorPos)),
1781 Int32Ty);
1782 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1783 auto *SizeAndTag = ConstantInt::get(Int32Ty, Size | (uint32_t(Tag) << 24));
1784 Descriptor->setComdat(NewGV->getComdat());
1785 Descriptor->setInitializer(ConstantStruct::getAnon({GVRelPtr, SizeAndTag}));
1786 Descriptor->setSection("hwasan_globals");
1787 Descriptor->setMetadata(LLVMContext::MD_associated,
1789 appendToCompilerUsed(M, Descriptor);
1790 }
1791
1794 ConstantExpr::getPtrToInt(NewGV, Int64Ty),
1795 ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)),
1796 GV->getType());
1797 auto *Alias = GlobalAlias::create(GV->getValueType(), GV->getAddressSpace(),
1798 GV->getLinkage(), "", Aliasee, &M);
1799 Alias->setVisibility(GV->getVisibility());
1800 Alias->takeName(GV);
1801 GV->replaceAllUsesWith(Alias);
1802 GV->eraseFromParent();
1803}
1804
1805void HWAddressSanitizer::instrumentGlobals() {
1806 std::vector<GlobalVariable *> Globals;
1807 for (GlobalVariable &GV : M.globals()) {
1809 continue;
1810
1811 if (GV.isDeclarationForLinker() || GV.getName().starts_with("llvm.") ||
1812 GV.isThreadLocal())
1813 continue;
1814
1815 // Common symbols can't have aliases point to them, so they can't be tagged.
1816 if (GV.hasCommonLinkage())
1817 continue;
1818
1819 if (ClAllGlobals) {
1820 // Avoid instrumenting intrinsic global variables.
1821 if (GV.getSection() == "llvm.metadata")
1822 continue;
1823 } else {
1824 // Globals with custom sections may be used in __start_/__stop_
1825 // enumeration, which would be broken both by adding tags and potentially
1826 // by the extra padding/alignment that we insert.
1827 if (GV.hasSection())
1828 continue;
1829 }
1830
1831 Globals.push_back(&GV);
1832 }
1833
1834 MD5 Hasher;
1835 Hasher.update(M.getSourceFileName());
1836 MD5::MD5Result Hash;
1837 Hasher.final(Hash);
1838 uint8_t Tag = Hash[0];
1839
1840 assert(TagMaskByte >= 16);
1841
1842 for (GlobalVariable *GV : Globals) {
1843 // Don't allow globals to be tagged with something that looks like a
1844 // short-granule tag, otherwise we lose inter-granule overflow detection, as
1845 // the fast path shadow-vs-address check succeeds.
1846 if (Tag < 16 || Tag > TagMaskByte)
1847 Tag = 16;
1848 instrumentGlobal(GV, Tag++);
1849 }
1850}
1851
1852void HWAddressSanitizer::instrumentPersonalityFunctions() {
1853 // We need to untag stack frames as we unwind past them. That is the job of
1854 // the personality function wrapper, which either wraps an existing
1855 // personality function or acts as a personality function on its own. Each
1856 // function that has a personality function or that can be unwound past has
1857 // its personality function changed to a thunk that calls the personality
1858 // function wrapper in the runtime.
1860 for (Function &F : M) {
1861 if (F.isDeclaration() || !F.hasFnAttribute(Attribute::SanitizeHWAddress))
1862 continue;
1863
1864 if (F.hasPersonalityFn()) {
1865 PersonalityFns[F.getPersonalityFn()->stripPointerCasts()].push_back(&F);
1866 } else if (!F.hasFnAttribute(Attribute::NoUnwind)) {
1867 PersonalityFns[nullptr].push_back(&F);
1868 }
1869 }
1870
1871 if (PersonalityFns.empty())
1872 return;
1873
1874 FunctionCallee HwasanPersonalityWrapper = M.getOrInsertFunction(
1875 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1876 PtrTy, PtrTy, PtrTy, PtrTy);
1877 FunctionCallee UnwindGetGR = M.getOrInsertFunction("_Unwind_GetGR", VoidTy);
1878 FunctionCallee UnwindGetCFA = M.getOrInsertFunction("_Unwind_GetCFA", VoidTy);
1879
1880 for (auto &P : PersonalityFns) {
1881 std::string ThunkName = kHwasanPersonalityThunkName;
1882 if (P.first)
1883 ThunkName += ("." + P.first->getName()).str();
1884 FunctionType *ThunkFnTy = FunctionType::get(
1885 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy}, false);
1886 bool IsLocal = P.first && (!isa<GlobalValue>(P.first) ||
1887 cast<GlobalValue>(P.first)->hasLocalLinkage());
1888 auto *ThunkFn = Function::Create(ThunkFnTy,
1891 ThunkName, &M);
1892 // TODO: think about other attributes as well.
1893 if (any_of(P.second, [](const Function *F) {
1894 return F->hasFnAttribute("branch-target-enforcement");
1895 })) {
1896 ThunkFn->addFnAttr("branch-target-enforcement");
1897 }
1898 if (!IsLocal) {
1899 ThunkFn->setVisibility(GlobalValue::HiddenVisibility);
1900 ThunkFn->setComdat(M.getOrInsertComdat(ThunkName));
1901 }
1902
1903 auto *BB = BasicBlock::Create(*C, "entry", ThunkFn);
1904 IRBuilder<> IRB(BB);
1905 CallInst *WrapperCall = IRB.CreateCall(
1906 HwasanPersonalityWrapper,
1907 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1908 ThunkFn->getArg(3), ThunkFn->getArg(4),
1909 P.first ? P.first : Constant::getNullValue(PtrTy),
1910 UnwindGetGR.getCallee(), UnwindGetCFA.getCallee()});
1911 WrapperCall->setTailCall();
1912 IRB.CreateRet(WrapperCall);
1913
1914 for (Function *F : P.second)
1915 F->setPersonalityFn(ThunkFn);
1916 }
1917}
1918
1919void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple,
1920 bool InstrumentWithCalls,
1921 bool CompileKernel) {
1922 // Start with defaults.
1923 Scale = kDefaultShadowScale;
1924 Kind = OffsetKind::kTls;
1925 WithFrameRecord = true;
1926
1927 // Tune for the target.
1928 if (TargetTriple.isOSFuchsia()) {
1929 // Fuchsia is always PIE, which means that the beginning of the address
1930 // space is always available.
1931 Kind = OffsetKind::kGlobal;
1932 } else if (CompileKernel || InstrumentWithCalls) {
1933 SetFixed(0);
1934 WithFrameRecord = false;
1935 }
1936
1937 WithFrameRecord = optOr(ClFrameRecords, WithFrameRecord);
1938
1939 // Apply the last of ClMappingOffset and ClMappingOffsetDynamic.
1940 Kind = optOr(ClMappingOffsetDynamic, Kind);
1941 if (ClMappingOffset.getNumOccurrences() > 0 &&
1942 !(ClMappingOffsetDynamic.getNumOccurrences() > 0 &&
1943 ClMappingOffsetDynamic.getPosition() > ClMappingOffset.getPosition())) {
1944 SetFixed(ClMappingOffset);
1945 }
1946}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))
static cl::opt< StackTaggingRecordStackHistoryMode > ClRecordStackHistory("stack-tagging-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer")), cl::Hidden, cl::init(none))
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const uint64_t kDefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClUseAfterScope("asan-use-after-scope", cl::desc("Check stack-use-after-scope"), cl::Hidden, cl::init(false))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define clEnumVal(ENUMVAL, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
#define DEBUG_TYPE
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
static cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)
static cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))
const char kHwasanModuleCtorName[]
static cl::opt< bool > ClFrameRecords("hwasan-with-frame-record", cl::desc("Use ring buffer for stack allocations"), cl::Hidden)
static cl::opt< int > ClMatchAllTag("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true))
const char kHwasanNoteName[]
static cl::opt< uint64_t > ClTagBits("hwasan-tag-bits", cl::desc("Restrict tag to at most N bits. Needs to be > 4."), cl::Hidden, cl::init(0))
static const unsigned kShadowBaseAlignment
static cl::opt< bool > ClGenerateTagsWithCalls("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentReads("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< float > ClRandomKeepRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function. " "Note: instrumentation can be skipped randomly " "OR because of the hot percentile cutoff, if " "both are supplied."))
static cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentAtomics("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentStack("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClStrictUseAfterScope("hwasan-strict-use-after-scope", cl::desc("for complicated lifetimes, tag both on end and return"), cl::Hidden, cl::init(true))
static cl::opt< OffsetKind > ClMappingOffsetDynamic("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS")))
static cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static cl::opt< size_t > ClMaxLifetimes("hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."))
static cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))
static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClGlobals("hwasan-globals", cl::desc("Instrument globals"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("hwasan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentByval("hwasan-instrument-byval", cl::desc("instrument byval arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClUseShortGranules("hwasan-use-short-granules", cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"))
const char kHwasanShadowMemoryDynamicAddress[]
static unsigned getPointerOperandIndex(Instruction *I)
#define DEBUG_TYPE
static cl::opt< bool > ClInlineFastPathChecks("hwasan-inline-fast-path-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentPersonalityFunctions("hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden)
const char kHwasanInitName[]
static cl::opt< bool > ClAllGlobals("hwasan-all-globals", cl::desc("Instrument globals, even those within user-defined sections. Warning: " "This may break existing code which walks globals via linker-generated " "symbols, expects certain globals to be contiguous with each other, or " "makes other assumptions which are invalidated by HWASan " "instrumentation."), cl::Hidden, cl::init(false))
RecordStackHistoryMode
static cl::opt< bool > ClInstrumentLandingPads("hwasan-instrument-landing-pads", cl::desc("instrument landing pads"), cl::Hidden, cl::init(false))
const char kHwasanPersonalityThunkName[]
static cl::opt< bool > ClStaticLinking("hwasan-static-linking", cl::desc("Don't use .note.hwasan.globals section to instrument globals " "from loadable libraries. " "Note: in static binaries, the global variables section can be " "accessed directly via linker-provided " "__start_hwasan_globals and __stop_hwasan_globals symbols"), cl::Hidden, cl::init(false))
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
static cl::opt< int > ClHotPercentileCutoff("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cutoff."))
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file implements a map that provides insertion order iteration.
#define T
uint64_t IntrinsicInst * II
#define P(N)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
an instruction to allocate memory on the stack
PointerType * getType() const
Overload to return most specific pointer type.
const Value * getArraySize() const
Get the number of elements allocated.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
Analysis pass which computes BlockFrequencyInfo.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
Definition Constants.h:878
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition Constants.h:643
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:169
void flush()
Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
Definition Globals.cpp:692
StringRef getSection() const
Get the custom section of this global if it has one.
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:287
bool hasSection() const
Check if this global has a custom object file section.
LLVM_ABI const SanitizerMetadata & getSanitizerMetadata() const
Definition Globals.cpp:318
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
LinkageTypes getLinkage() const
bool isDeclarationForLinker() const
bool hasSanitizerMetadata() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
Definition GlobalValue.h:69
bool hasCommonLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:56
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:609
Analysis pass providing a never-invalidated alias analysis result.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition IRBuilder.h:2032
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2305
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2246
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1540
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:534
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2100
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1200
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1481
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2394
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2398
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1914
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1519
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Definition IRBuilder.h:608
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2129
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1578
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1933
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1430
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2569
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Definition IRBuilder.h:2115
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:577
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2402
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition IRBuilder.h:2331
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1559
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1630
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1600
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2903
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
Definition InlineAsm.cpp:43
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:594
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition MD5.cpp:188
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition MD5.cpp:233
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
Definition MDBuilder.cpp:48
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
bool empty() const
Definition MapVector.h:79
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Definition Module.cpp:262
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
Diagnostic information for applied optimization remarks.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Definition Analysis.h:171
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
LLVM_ABI bool stackAccessIsSafe(const Instruction &I) const
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:467
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
bool isAndroidVersionLT(unsigned Major) const
Definition Triple.h:912
bool isAndroid() const
Tests whether the target is Android.
Definition Triple.h:910
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:514
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
Definition Triple.h:1175
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
Definition Triple.h:1095
bool isOSFuchsia() const
Definition Triple.h:750
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition Triple.h:866
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:514
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
Definition Value.cpp:1164
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
Definition Value.cpp:561
bool hasName() const
Definition Value.h:263
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
int getNumOccurrences() const
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
@ NT_LLVM_HWASAN_GLOBALS
Definition ELF.h:1812
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI Value * getFP(IRBuilder<> &IRB)
LLVM_ABI void forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
LLVM_ABI bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, const LoopInfo *LI)
LLVM_ABI uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
LLVM_ABI Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
LLVM_ABI Value * readRegister(IRBuilder<> &IRB, StringRef Name)
LLVM_ABI void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
LLVM_ABI void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
LLVM_ABI Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
LLVM_ABI Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc, bool IsMemtagDarwin=false)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1748
@ Known
Known to have no common set bits.
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
LLVM_ABI void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)
Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
Definition Local.cpp:3898
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:130
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 8 > RetVec