1//===- AddressSanitizer.cpp - memory 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// This file is a part of AddressSanitizer, an address basic correctness
10// checker.
11// Details of the algorithm:
12// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
13//
14// FIXME: This sanitizer does not yet handle scalable vectors
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
19#include "InstrumentationOptions.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/DepthFirstIterator.h"
23#include "llvm/ADT/SmallPtrSet.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/Statistic.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/Twine.h"
29#include "llvm/Analysis/GlobalsModRef.h"
30#include "llvm/Analysis/MemoryBuiltins.h"
31#include "llvm/Analysis/StackSafetyAnalysis.h"
32#include "llvm/Analysis/TargetLibraryInfo.h"
33#include "llvm/Analysis/TargetTransformInfo.h"
34#include "llvm/Analysis/ValueTracking.h"
35#include "llvm/BinaryFormat/MachO.h"
36#include "llvm/Demangle/Demangle.h"
37#include "llvm/IR/Argument.h"
38#include "llvm/IR/Attributes.h"
39#include "llvm/IR/BasicBlock.h"
40#include "llvm/IR/Comdat.h"
41#include "llvm/IR/Constant.h"
42#include "llvm/IR/Constants.h"
43#include "llvm/IR/DIBuilder.h"
44#include "llvm/IR/DataLayout.h"
45#include "llvm/IR/DebugInfoMetadata.h"
46#include "llvm/IR/DebugLoc.h"
47#include "llvm/IR/DerivedTypes.h"
48#include "llvm/IR/EHPersonalities.h"
49#include "llvm/IR/Function.h"
50#include "llvm/IR/GlobalAlias.h"
51#include "llvm/IR/GlobalValue.h"
52#include "llvm/IR/GlobalVariable.h"
53#include "llvm/IR/IRBuilder.h"
54#include "llvm/IR/InlineAsm.h"
55#include "llvm/IR/InstVisitor.h"
56#include "llvm/IR/InstrTypes.h"
57#include "llvm/IR/Instruction.h"
58#include "llvm/IR/Instructions.h"
59#include "llvm/IR/IntrinsicInst.h"
60#include "llvm/IR/Intrinsics.h"
61#include "llvm/IR/LLVMContext.h"
62#include "llvm/IR/MDBuilder.h"
63#include "llvm/IR/Metadata.h"
64#include "llvm/IR/Module.h"
65#include "llvm/IR/Type.h"
66#include "llvm/IR/Use.h"
67#include "llvm/IR/Value.h"
68#include "llvm/MC/MCSectionMachO.h"
69#include "llvm/Support/Casting.h"
70#include "llvm/Support/Debug.h"
71#include "llvm/Support/ErrorHandling.h"
72#include "llvm/Support/MathExtras.h"
73#include "llvm/Support/ModRef.h"
74#include "llvm/Support/raw_ostream.h"
75#include "llvm/TargetParser/Triple.h"
76#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
77#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
78#include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
79#include "llvm/Transforms/Utils/BasicBlockUtils.h"
80#include "llvm/Transforms/Utils/Instrumentation.h"
81#include "llvm/Transforms/Utils/Local.h"
82#include "llvm/Transforms/Utils/ModuleUtils.h"
83#include "llvm/Transforms/Utils/PromoteMemToReg.h"
84#include <algorithm>
85#include <cassert>
86#include <cstddef>
87#include <cstdint>
88#include <iomanip>
89#include <limits>
90#include <sstream>
91#include <string>
92#include <tuple>
93#include <utility>
94
95using namespace llvm;
96
97#define DEBUG_TYPE "asan"
98
99static const uint64_t kDefaultShadowScale = 3;
100static const uint64_t kDefaultShadowOffset32 = 1ULL << 29;
101static const uint64_t kDefaultShadowOffset64 = 1ULL << 44;
102static const uint64_t kDynamicShadowSentinel =
103 std::numeric_limits<uint64_t>::max();
104static const uint64_t kSmallX86_64ShadowOffsetBase = 0x7FFFFFFF; // < 2G.
105static const uint64_t kSmallX86_64ShadowOffsetAlignMask = ~0xFFFULL;
106static const uint64_t kLinuxKasan_ShadowOffset64 = 0xdffffc0000000000;
107static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 44;
108static const uint64_t kSystemZ_ShadowOffset64 = 1ULL << 52;
109static const uint64_t kMIPS_ShadowOffsetN32 = 1ULL << 29;
110static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000;
111static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37;
112static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36;
113static const uint64_t kLoongArch64_ShadowOffset64 = 1ULL << 46;
114static const uint64_t kRISCV64_ShadowOffset64 = kDynamicShadowSentinel;
115static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30;
116static const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46;
117static const uint64_t kFreeBSDAArch64_ShadowOffset64 = 1ULL << 47;
118static const uint64_t kFreeBSDKasan_ShadowOffset64 = 0xdffff7c000000000;
119static const uint64_t kNetBSD_ShadowOffset32 = 1ULL << 30;
120static const uint64_t kNetBSD_ShadowOffset64 = 1ULL << 46;
121static const uint64_t kNetBSDKasan_ShadowOffset64 = 0xdfff900000000000;
122static const uint64_t kPS_ShadowOffset64 = 1ULL << 40;
123static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
124static const uint64_t kWebAssemblyShadowOffset = 0;
125
126// The shadow memory space is dynamically allocated.
127static const uint64_t kWindowsShadowOffset64 = kDynamicShadowSentinel;
128
129static const size_t kMinStackMallocSize = 1 << 6; // 64B
130static const size_t kMaxStackMallocSize = 1 << 16; // 64K
131static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
132static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E;
133
134const char kAsanModuleCtorName[] = "asan.module_ctor";
135const char kAsanModuleDtorName[] = "asan.module_dtor";
136static const uint64_t kAsanCtorAndDtorPriority = 1;
137// On Emscripten, the system needs more than one priorities for constructors.
138static const uint64_t kAsanEmscriptenCtorAndDtorPriority = 50;
139const char kAsanReportErrorTemplate[] = "__asan_report_";
140const char kAsanRegisterGlobalsName[] = "__asan_register_globals";
141const char kAsanUnregisterGlobalsName[] = "__asan_unregister_globals";
142const char kAsanRegisterImageGlobalsName[] = "__asan_register_image_globals";
143const char kAsanUnregisterImageGlobalsName[] =
144 "__asan_unregister_image_globals";
145const char kAsanRegisterElfGlobalsName[] = "__asan_register_elf_globals";
146const char kAsanUnregisterElfGlobalsName[] = "__asan_unregister_elf_globals";
147const char kAsanPoisonGlobalsName[] = "__asan_before_dynamic_init";
148const char kAsanUnpoisonGlobalsName[] = "__asan_after_dynamic_init";
149const char kAsanInitName[] = "__asan_init";
150const char kAsanVersionCheckNamePrefix[] = "__asan_version_mismatch_check_v";
151const char kAsanPtrCmp[] = "__sanitizer_ptr_cmp";
152const char kAsanPtrSub[] = "__sanitizer_ptr_sub";
153const char kAsanHandleNoReturnName[] = "__asan_handle_no_return";
154static const int kMaxAsanStackMallocSizeClass = 10;
155const char kAsanStackMallocNameTemplate[] = "__asan_stack_malloc_";
156const char kAsanStackMallocAlwaysNameTemplate[] =
157 "__asan_stack_malloc_always_";
158const char kAsanStackFreeNameTemplate[] = "__asan_stack_free_";
159const char kAsanGenPrefix[] = "___asan_gen_";
160const char kODRGenPrefix[] = "__odr_asan_gen_";
161const char kSanCovGenPrefix[] = "__sancov_gen_";
162const char kAsanSetShadowPrefix[] = "__asan_set_shadow_";
163const char kAsanPoisonStackMemoryName[] = "__asan_poison_stack_memory";
164const char kAsanUnpoisonStackMemoryName[] = "__asan_unpoison_stack_memory";
165
166// ASan version script has __asan_* wildcard. Triple underscore prevents a
167// linker (gold) warning about attempting to export a local symbol.
168const char kAsanGlobalsRegisteredFlagName[] = "___asan_globals_registered";
169
170const char kAsanOptionDetectUseAfterReturn[] =
171 "__asan_option_detect_stack_use_after_return";
172
173const char kAsanShadowMemoryDynamicAddress[] =
174 "__asan_shadow_memory_dynamic_address";
175
176const char kAsanAllocaPoison[] = "__asan_alloca_poison";
177const char kAsanAllocasUnpoison[] = "__asan_allocas_unpoison";
178
179const char kAMDGPUAddressSharedName[] = "llvm.amdgcn.is.shared";
180const char kAMDGPUAddressPrivateName[] = "llvm.amdgcn.is.private";
181const char kAMDGPUBallotName[] = "llvm.amdgcn.ballot.i64";
182const char kAMDGPUUnreachableName[] = "llvm.amdgcn.unreachable";
183
184// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
185static const size_t kNumberOfAccessSizes = 5;
186
187static const uint64_t kAllocaRzSize = 32;
188
189// ASanAccessInfo implementation constants.
190constexpr size_t kCompileKernelShift = 0;
191constexpr size_t kCompileKernelMask = 0x1;
192constexpr size_t kAccessSizeIndexShift = 1;
193constexpr size_t kAccessSizeIndexMask = 0xf;
194constexpr size_t kIsWriteShift = 5;
195constexpr size_t kIsWriteMask = 0x1;
196
197STATISTIC(NumInstrumentedReads, "Number of instrumented reads");
198STATISTIC(NumInstrumentedWrites, "Number of instrumented writes");
199STATISTIC(NumOptimizedAccessesToGlobalVar,
200 "Number of optimized accesses to global vars");
201STATISTIC(NumOptimizedAccessesToStackVar,
202 "Number of optimized accesses to stack vars");
203
204namespace {
205
206/// This struct defines the shadow mapping using the rule:
207/// shadow = (mem >> Scale) ADD-or-OR Offset.
208/// If InGlobal is true, then
209/// extern char __asan_shadow[];
210/// shadow = (mem >> Scale) + &__asan_shadow
211struct ShadowMapping {
212 int Scale;
213 uint64_t Offset;
214 bool OrShadowOffset;
215 bool InGlobal;
216};
217
218} // end anonymous namespace
219
220static ShadowMapping getShadowMapping(const InstrumentationOptions &Opts,
221 const Triple &TargetTriple, int LongSize,
222 bool IsKasan) {
223 bool IsAndroid = TargetTriple.isAndroid();
224 bool IsIOS = TargetTriple.isiOS() || TargetTriple.isWatchOS() ||
225 TargetTriple.isDriverKit();
226 bool IsMacOS = TargetTriple.isMacOSX();
227 bool IsFreeBSD = TargetTriple.isOSFreeBSD();
228 bool IsNetBSD = TargetTriple.isOSNetBSD();
229 bool IsPS = TargetTriple.isPS();
230 bool IsLinux = TargetTriple.isOSLinux();
231 bool IsPPC64 = TargetTriple.getArch() == Triple::ppc64 ||
232 TargetTriple.getArch() == Triple::ppc64le;
233 bool IsSystemZ = TargetTriple.getArch() == Triple::systemz;
234 bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
235 bool IsMIPSN32ABI = TargetTriple.isABIN32();
236 bool IsMIPS32 = TargetTriple.isMIPS32();
237 bool IsMIPS64 = TargetTriple.isMIPS64();
238 bool IsArmOrThumb = TargetTriple.isARM() || TargetTriple.isThumb();
239 bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 ||
240 TargetTriple.getArch() == Triple::aarch64_be;
241 bool IsLoongArch64 = TargetTriple.isLoongArch64();
242 bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64;
243 bool IsWindows = TargetTriple.isOSWindows();
244 bool IsFuchsia = TargetTriple.isOSFuchsia();
245 bool IsAMDGPU = TargetTriple.isAMDGPU();
246 bool IsHaiku = TargetTriple.isOSHaiku();
247 bool IsWasm = TargetTriple.isWasm();
248 bool IsBPF = TargetTriple.isBPF();
249
250 ShadowMapping Mapping;
251
252 Mapping.Scale = Opts.asan_mapping_scale.value_or(u: kDefaultShadowScale);
253
254 if (LongSize == 32) {
255 if (IsAndroid)
256 Mapping.Offset = kDynamicShadowSentinel;
257 else if (IsMIPSN32ABI)
258 Mapping.Offset = kMIPS_ShadowOffsetN32;
259 else if (IsMIPS32)
260 Mapping.Offset = kMIPS32_ShadowOffset32;
261 else if (IsFreeBSD)
262 Mapping.Offset = kFreeBSD_ShadowOffset32;
263 else if (IsNetBSD)
264 Mapping.Offset = kNetBSD_ShadowOffset32;
265 else if (IsIOS)
266 Mapping.Offset = kDynamicShadowSentinel;
267 else if (IsWindows)
268 Mapping.Offset = kWindowsShadowOffset32;
269 else if (IsWasm)
270 Mapping.Offset = kWebAssemblyShadowOffset;
271 else
272 Mapping.Offset = kDefaultShadowOffset32;
273 } else { // LongSize == 64
274 // Fuchsia is always PIE, which means that the beginning of the address
275 // space is always available.
276 if (IsFuchsia) {
277 // kDynamicShadowSentinel tells instrumentation to use the dynamic shadow.
278 Mapping.Offset = kDynamicShadowSentinel;
279 } else if (IsPPC64)
280 Mapping.Offset = kPPC64_ShadowOffset64;
281 else if (IsSystemZ)
282 Mapping.Offset = kSystemZ_ShadowOffset64;
283 else if (IsFreeBSD && IsAArch64)
284 Mapping.Offset = kFreeBSDAArch64_ShadowOffset64;
285 else if (IsFreeBSD && !IsMIPS64) {
286 if (IsKasan)
287 Mapping.Offset = kFreeBSDKasan_ShadowOffset64;
288 else
289 Mapping.Offset = kFreeBSD_ShadowOffset64;
290 } else if (IsNetBSD) {
291 if (IsKasan)
292 Mapping.Offset = kNetBSDKasan_ShadowOffset64;
293 else
294 Mapping.Offset = kNetBSD_ShadowOffset64;
295 } else if (IsPS)
296 Mapping.Offset = kPS_ShadowOffset64;
297 else if (IsLinux && IsX86_64) {
298 if (IsKasan)
299 Mapping.Offset = kLinuxKasan_ShadowOffset64;
300 else
301 Mapping.Offset = (kSmallX86_64ShadowOffsetBase &
302 (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale));
303 } else if (IsWindows && (IsX86_64 || IsAArch64)) {
304 Mapping.Offset = kWindowsShadowOffset64;
305 } else if (IsMIPS64)
306 Mapping.Offset = kMIPS64_ShadowOffset64;
307 else if (IsIOS)
308 Mapping.Offset = kDynamicShadowSentinel;
309 else if (IsMacOS && IsAArch64)
310 Mapping.Offset = kDynamicShadowSentinel;
311 else if (IsAArch64)
312 Mapping.Offset = kAArch64_ShadowOffset64;
313 else if (IsLoongArch64)
314 Mapping.Offset = kLoongArch64_ShadowOffset64;
315 else if (IsRISCV64)
316 Mapping.Offset = kRISCV64_ShadowOffset64;
317 else if (IsAMDGPU)
318 Mapping.Offset = (kSmallX86_64ShadowOffsetBase &
319 (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale));
320 else if (IsHaiku && IsX86_64)
321 Mapping.Offset = (kSmallX86_64ShadowOffsetBase &
322 (kSmallX86_64ShadowOffsetAlignMask << Mapping.Scale));
323 else if (IsBPF)
324 Mapping.Offset = kDynamicShadowSentinel;
325 else if (IsWasm)
326 Mapping.Offset = kWebAssemblyShadowOffset;
327 else
328 Mapping.Offset = kDefaultShadowOffset64;
329 }
330
331 if (Opts.asan_force_dynamic_shadow) {
332 Mapping.Offset = kDynamicShadowSentinel;
333 }
334
335 if (Opts.asan_mapping_offset) {
336 Mapping.Offset = *Opts.asan_mapping_offset;
337 }
338
339 // OR-ing shadow offset if more efficient (at least on x86) if the offset
340 // is a power of two, but on ppc64 and loongarch64 we have to use add since
341 // the shadow offset is not necessarily 1/8-th of the address space. On
342 // SystemZ, we could OR the constant in a single instruction, but it's more
343 // efficient to load it once and use indexed addressing.
344 Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS &&
345 !IsRISCV64 && !IsLoongArch64 &&
346 !(Mapping.Offset & (Mapping.Offset - 1)) &&
347 Mapping.Offset != kDynamicShadowSentinel;
348 Mapping.InGlobal = Opts.asan_with_ifunc && IsAndroid && IsArmOrThumb;
349
350 return Mapping;
351}
352
353void llvm::getAddressSanitizerParams(const LLVMContext &Ctx,
354 const Triple &TargetTriple, int LongSize,
355 bool IsKasan, uint64_t *ShadowBase,
356 int *MappingScale, bool *OrShadowOffset) {
357 auto Mapping =
358 getShadowMapping(Opts: Ctx.getLibraryOptions().get<InstrumentationOptions>(),
359 TargetTriple, LongSize, IsKasan);
360 *ShadowBase = Mapping.Offset;
361 *MappingScale = Mapping.Scale;
362 *OrShadowOffset = Mapping.OrShadowOffset;
363}
364
365void llvm::removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem) {
366 // Adding sanitizer checks invalidates previously inferred memory attributes.
367 //
368 // This is not only true for sanitized functions, because AttrInfer can
369 // infer those attributes on libc functions, which is not true if those
370 // are instrumented (Android) or intercepted.
371 //
372 // We might want to model ASan shadow memory more opaquely to get rid of
373 // this problem altogether, by hiding the shadow memory write in an
374 // intrinsic, essentially like in the AArch64StackTagging pass. But that's
375 // for another day.
376
377 bool Changed = false;
378 // We add memory(readwrite) to functions that don't already have that set and
379 // can access any non-inaccessible memory. Sanitizer instrumentation can
380 // read/write shadow memory, which is IRMemLocation::Other. Sanitizer
381 // instrumentation can instrument any memory accesses to non-inaccessible
382 // memory.
383 if (!F.getMemoryEffects()
384 .getWithoutLoc(Loc: IRMemLocation::InaccessibleMem)
385 .doesNotAccessMemory() &&
386 !isModAndRefSet(MRI: F.getMemoryEffects().getModRef(Loc: IRMemLocation::Other))) {
387 F.setMemoryEffects(F.getMemoryEffects() |
388 MemoryEffects::otherMemOnly(MR: ModRefInfo::ModRef));
389 Changed = true;
390 }
391 // HWASan reads from argument memory even for previously write-only accesses.
392 if (ReadsArgMem) {
393 if (F.getMemoryEffects().getModRef(Loc: IRMemLocation::ArgMem) ==
394 ModRefInfo::Mod) {
395 F.setMemoryEffects(F.getMemoryEffects() |
396 MemoryEffects::argMemOnly(MR: ModRefInfo::Ref));
397 Changed = true;
398 }
399 for (Argument &A : F.args()) {
400 if (A.hasAttribute(Kind: Attribute::WriteOnly)) {
401 A.removeAttr(Kind: Attribute::WriteOnly);
402 Changed = true;
403 }
404 }
405 }
406 if (Changed) {
407 // nobuiltin makes sure later passes don't restore assumptions about
408 // the function.
409 F.addFnAttr(Kind: Attribute::NoBuiltin);
410 }
411}
412
413ASanAccessInfo::ASanAccessInfo(int32_t Packed)
414 : Packed(Packed),
415 AccessSizeIndex((Packed >> kAccessSizeIndexShift) & kAccessSizeIndexMask),
416 IsWrite((Packed >> kIsWriteShift) & kIsWriteMask),
417 CompileKernel((Packed >> kCompileKernelShift) & kCompileKernelMask) {}
418
419ASanAccessInfo::ASanAccessInfo(bool IsWrite, bool CompileKernel,
420 uint8_t AccessSizeIndex)
421 : Packed((IsWrite << kIsWriteShift) +
422 (CompileKernel << kCompileKernelShift) +
423 (AccessSizeIndex << kAccessSizeIndexShift)),
424 AccessSizeIndex(AccessSizeIndex), IsWrite(IsWrite),
425 CompileKernel(CompileKernel) {}
426
427static uint64_t getRedzoneSizeForScale(int MappingScale) {
428 // Redzone used for stack and globals is at least 32 bytes.
429 // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively.
430 return std::max(a: 32U, b: 1U << MappingScale);
431}
432
433static uint64_t GetCtorAndDtorPriority(Triple &TargetTriple) {
434 if (TargetTriple.isOSEmscripten())
435 return kAsanEmscriptenCtorAndDtorPriority;
436 else
437 return kAsanCtorAndDtorPriority;
438}
439
440static Twine genName(StringRef suffix) {
441 return Twine(kAsanGenPrefix) + suffix;
442}
443
444namespace {
445
446class AsanFunctionInserter {
447public:
448 AsanFunctionInserter(Module &M) : M(M) {}
449
450 template <typename... ArgTypes>
451 FunctionCallee insertFunction(StringRef Name, ArgTypes &&...Args) {
452 return M.getOrInsertFunction(Name, std::forward<ArgTypes>(Args)...);
453 }
454
455private:
456 Module &M;
457};
458
459} // end anonymous namespace
460
461namespace {
462/// Helper RAII class to post-process inserted asan runtime calls during a
463/// pass on a single Function. Upon end of scope, detects and applies the
464/// required funclet OpBundle.
465class RuntimeCallInserter {
466 Function *OwnerFn = nullptr;
467 bool TrackInsertedCalls = false;
468 SmallVector<CallInst *> InsertedCalls;
469
470public:
471 RuntimeCallInserter(Function &Fn) : OwnerFn(&Fn) {
472 if (Fn.hasPersonalityFn()) {
473 auto Personality = classifyEHPersonality(Pers: Fn.getPersonalityFn());
474 if (isScopedEHPersonality(Pers: Personality))
475 TrackInsertedCalls = true;
476 }
477 }
478
479 ~RuntimeCallInserter() {
480 if (InsertedCalls.empty())
481 return;
482 assert(TrackInsertedCalls && "Calls were wrongly tracked");
483
484 DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F&: *OwnerFn);
485 for (CallInst *CI : InsertedCalls) {
486 BasicBlock *BB = CI->getParent();
487 assert(BB && "Instruction doesn't belong to a BasicBlock");
488 assert(BB->getParent() == OwnerFn &&
489 "Instruction doesn't belong to the expected Function!");
490
491 ColorVector &Colors = BlockColors[BB];
492 // funclet opbundles are only valid in monochromatic BBs.
493 // Note that unreachable BBs are seen as colorless by colorEHFunclets()
494 // and will be DCE'ed later.
495 if (Colors.empty())
496 continue;
497 if (Colors.size() != 1) {
498 OwnerFn->getContext().emitError(
499 ErrorStr: "Instruction's BasicBlock is not monochromatic");
500 continue;
501 }
502
503 BasicBlock *Color = Colors.front();
504 BasicBlock::iterator EHPadIt = Color->getFirstNonPHIIt();
505
506 if (EHPadIt != Color->end() && EHPadIt->isEHPad()) {
507 // Replace CI with a clone with an added funclet OperandBundle
508 OperandBundleDef OB("funclet", &*EHPadIt);
509 auto *NewCall = CallBase::addOperandBundle(CB: CI, ID: LLVMContext::OB_funclet,
510 OB, InsertPt: CI->getIterator());
511 NewCall->copyMetadata(SrcInst: *CI);
512 CI->replaceAllUsesWith(V: NewCall);
513 CI->eraseFromParent();
514 }
515 }
516 }
517
518 CallInst *createRuntimeCall(IRBuilder<> &IRB, FunctionCallee Callee,
519 ArrayRef<Value *> Args = {},
520 const Twine &Name = "") {
521 assert(IRB.GetInsertBlock()->getParent() == OwnerFn);
522
523 CallInst *Inst = IRB.CreateCall(Callee, Args, Name, FPMathTag: nullptr);
524 if (TrackInsertedCalls)
525 InsertedCalls.push_back(Elt: Inst);
526 return Inst;
527 }
528};
529
530/// AddressSanitizer: instrument the code in module to find memory bugs.
531struct AddressSanitizer {
532 AddressSanitizer(const InstrumentationOptions &Opts, Module &M,
533 const StackSafetyGlobalInfo *SSGI,
534 int InstrumentationWithCallsThreshold,
535 uint32_t MaxInlinePoisoningSize, bool CompileKernel = false,
536 bool Recover = false, bool UseAfterScope = false,
537 AsanDetectStackUseAfterReturnMode UseAfterReturn =
538 AsanDetectStackUseAfterReturnMode::Runtime)
539 : Opts(Opts), M(M), Inserter(M),
540 CompileKernel(valueOr(X: Opts.asan_kernel, Default: CompileKernel)),
541 Recover(valueOr(X: Opts.asan_recover, Default: Recover)),
542 UseAfterScope(UseAfterScope || Opts.asan_use_after_scope),
543 UseAfterReturn(Opts.asan_use_after_return.value_or(u&: UseAfterReturn)),
544 SSGI(SSGI), InstrumentationWithCallsThreshold(
545 Opts.asan_instrumentation_with_call_threshold.value_or(
546 u&: InstrumentationWithCallsThreshold)),
547 MaxInlinePoisoningSize(Opts.asan_max_inline_poisoning_size.value_or(
548 u&: MaxInlinePoisoningSize)) {
549 C = &(M.getContext());
550 DL = &M.getDataLayout();
551 LongSize = M.getDataLayout().getPointerSizeInBits();
552 IntptrTy = Type::getIntNTy(C&: *C, N: LongSize);
553 PtrTy = PointerType::getUnqual(C&: *C);
554 Int32Ty = Type::getInt32Ty(C&: *C);
555 TargetTriple = M.getTargetTriple();
556
557 Mapping =
558 getShadowMapping(Opts, TargetTriple, LongSize, IsKasan: this->CompileKernel);
559
560 assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid);
561 }
562
563 TypeSize getAllocaSizeInBytes(const AllocaInst &AI) const {
564 return *AI.getAllocationSize(DL: AI.getDataLayout());
565 }
566
567 /// Check if we want (and can) handle this alloca.
568 bool isInterestingAlloca(const AllocaInst &AI);
569
570 bool ignoreAccess(Instruction *Inst, Value *Ptr);
571 void getInterestingMemoryOperands(
572 Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
573 const TargetTransformInfo *TTI);
574
575 void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
576 InterestingMemoryOperand &O, bool UseCalls,
577 const DataLayout &DL, RuntimeCallInserter &RTCI);
578 bool instrumentPointerComparisonOrSubtraction(Instruction *I,
579 RuntimeCallInserter &RTCI);
580 void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
581 Value *Addr, MaybeAlign Alignment,
582 uint32_t TypeStoreSize, bool IsWrite,
583 Value *SizeArgument, bool UseCalls, uint32_t Exp,
584 RuntimeCallInserter &RTCI);
585 Instruction *instrumentAMDGPUAddress(Instruction *OrigIns,
586 Instruction *InsertBefore, Value *Addr,
587 uint32_t TypeStoreSize, bool IsWrite,
588 Value *SizeArgument);
589 Instruction *genAMDGPUReportBlock(IRBuilder<> &IRB, Value *Cond,
590 bool Recover);
591 void instrumentUnusualSizeOrAlignment(Instruction *I,
592 Instruction *InsertBefore, Value *Addr,
593 TypeSize TypeStoreSize, bool IsWrite,
594 Value *SizeArgument, bool UseCalls,
595 uint32_t Exp,
596 RuntimeCallInserter &RTCI);
597 void instrumentMaskedLoadOrStore(AddressSanitizer *Pass, const DataLayout &DL,
598 Type *IntptrTy, Value *Mask, Value *EVL,
599 Value *Stride, Instruction *I, Value *Addr,
600 MaybeAlign Alignment, unsigned Granularity,
601 Type *OpType, bool IsWrite,
602 Value *SizeArgument, bool UseCalls,
603 uint32_t Exp, RuntimeCallInserter &RTCI);
604 Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
605 Value *ShadowValue, uint32_t TypeStoreSize);
606 Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr,
607 bool IsWrite, size_t AccessSizeIndex,
608 Value *SizeArgument, uint32_t Exp,
609 RuntimeCallInserter &RTCI);
610 void instrumentMemIntrinsic(MemIntrinsic *MI, RuntimeCallInserter &RTCI);
611 Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
612 bool suppressInstrumentationSiteForDebug(int &Instrumented);
613 bool instrumentFunction(Function &F, const TargetLibraryInfo *TLI,
614 const TargetTransformInfo *TTI);
615 bool maybeInsertAsanInitAtFunctionEntry(Function &F);
616 bool maybeInsertDynamicShadowAtFunctionEntry(Function &F);
617 void markEscapedLocalAllocas(Function &F);
618 void markCatchParametersAsUninteresting(Function &F);
619
620private:
621 friend struct FunctionStackPoisoner;
622
623 void initializeCallbacks(const TargetLibraryInfo *TLI);
624
625 bool LooksLikeCodeInBug11395(Instruction *I);
626 bool GlobalIsLinkerInitialized(GlobalVariable *G);
627 bool isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis, Value *Addr,
628 TypeSize TypeStoreSize) const;
629
630 /// Helper to cleanup per-function state.
631 struct FunctionStateRAII {
632 AddressSanitizer *Pass;
633
634 FunctionStateRAII(AddressSanitizer *Pass) : Pass(Pass) {
635 assert(Pass->ProcessedAllocas.empty() &&
636 "last pass forgot to clear cache");
637 assert(!Pass->LocalDynamicShadow);
638 }
639
640 ~FunctionStateRAII() {
641 Pass->LocalDynamicShadow = nullptr;
642 Pass->ProcessedAllocas.clear();
643 }
644 };
645
646 const InstrumentationOptions &Opts;
647 Module &M;
648 AsanFunctionInserter Inserter;
649 LLVMContext *C;
650 const DataLayout *DL;
651 Triple TargetTriple;
652 int LongSize;
653 bool CompileKernel;
654 bool Recover;
655 bool UseAfterScope;
656 AsanDetectStackUseAfterReturnMode UseAfterReturn;
657 Type *IntptrTy;
658 Type *Int32Ty;
659 PointerType *PtrTy;
660 ShadowMapping Mapping;
661 FunctionCallee AsanHandleNoReturnFunc;
662 FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction;
663 Constant *AsanShadowGlobal;
664
665 // These arrays is indexed by AccessIsWrite, Experiment and log2(AccessSize).
666 FunctionCallee AsanErrorCallback[2][2][kNumberOfAccessSizes];
667 FunctionCallee AsanMemoryAccessCallback[2][2][kNumberOfAccessSizes];
668
669 // These arrays is indexed by AccessIsWrite and Experiment.
670 FunctionCallee AsanErrorCallbackSized[2][2];
671 FunctionCallee AsanMemoryAccessCallbackSized[2][2];
672 FunctionCallee AsanAssumeDereferenceableCallback;
673
674 FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset;
675 Value *LocalDynamicShadow = nullptr;
676 const StackSafetyGlobalInfo *SSGI;
677 DenseMap<const AllocaInst *, bool> ProcessedAllocas;
678
679 FunctionCallee AMDGPUAddressShared;
680 FunctionCallee AMDGPUAddressPrivate;
681 int InstrumentationWithCallsThreshold;
682 uint32_t MaxInlinePoisoningSize;
683};
684
685class ModuleAddressSanitizer {
686public:
687 ModuleAddressSanitizer(const InstrumentationOptions &Opts, Module &M,
688 bool InsertVersionCheck, bool CompileKernel = false,
689 bool Recover = false, bool UseGlobalsGC = true,
690 bool UseOdrIndicator = true,
691 AsanDtorKind DestructorKind = AsanDtorKind::Global,
692 AsanCtorKind ConstructorKind = AsanCtorKind::Global)
693 : Opts(Opts), M(M), Inserter(M),
694 CompileKernel(valueOr(X: Opts.asan_kernel, Default: CompileKernel)),
695 InsertVersionCheck(valueOr(X: Opts.asan_guard_against_version_mismatch,
696 Default: InsertVersionCheck)),
697 Recover(valueOr(X: Opts.asan_recover, Default: Recover)),
698 UseGlobalsGC(UseGlobalsGC && Opts.asan_globals_live_support &&
699 !this->CompileKernel),
700 // Enable aliases as they should have no downside with ODR indicators.
701 UsePrivateAlias(valueOr(X: Opts.asan_use_private_alias, Default: UseOdrIndicator)),
702 UseOdrIndicator(valueOr(X: Opts.asan_use_odr_indicator, Default: UseOdrIndicator)),
703 // Not a typo: -asan-with-comdat is almost completely pointless without
704 // -asan-globals-live-support (because then it only works on modules
705 // without globals, which are rare); it is a prerequisite for
706 // -asan-globals-live-support; and both suffer from gold PR19002 for
707 // which UseGlobalsGC constructor argument is designed as workaround.
708 // Therefore, disable both -asan-with-comdat and
709 // -asan-globals-live-support unless the frontend says it's ok to do
710 // globals-gc.
711 UseCtorComdat(UseGlobalsGC && Opts.asan_with_comdat &&
712 !this->CompileKernel),
713 DestructorKind(Opts.asan_destructor_kind.value_or(u&: DestructorKind)),
714 ConstructorKind(Opts.asan_constructor_kind.value_or(u&: ConstructorKind)) {
715 C = &(M.getContext());
716 int LongSize = M.getDataLayout().getPointerSizeInBits();
717 IntptrTy = Type::getIntNTy(C&: *C, N: LongSize);
718 PtrTy = PointerType::getUnqual(C&: *C);
719 TargetTriple = M.getTargetTriple();
720 Mapping =
721 getShadowMapping(Opts, TargetTriple, LongSize, IsKasan: this->CompileKernel);
722
723 assert(this->DestructorKind != AsanDtorKind::Invalid);
724 }
725
726 bool instrumentModule();
727
728private:
729 void initializeCallbacks();
730
731 void instrumentGlobals(IRBuilder<> &IRB, bool *CtorComdat);
732 void InstrumentGlobalsCOFF(IRBuilder<> &IRB,
733 ArrayRef<GlobalVariable *> ExtendedGlobals,
734 ArrayRef<Constant *> MetadataInitializers);
735 void instrumentGlobalsELF(IRBuilder<> &IRB,
736 ArrayRef<GlobalVariable *> ExtendedGlobals,
737 ArrayRef<Constant *> MetadataInitializers,
738 const std::string &UniqueModuleId);
739 void InstrumentGlobalsMachO(IRBuilder<> &IRB,
740 ArrayRef<GlobalVariable *> ExtendedGlobals,
741 ArrayRef<Constant *> MetadataInitializers);
742 void
743 InstrumentGlobalsWithMetadataArray(IRBuilder<> &IRB,
744 ArrayRef<GlobalVariable *> ExtendedGlobals,
745 ArrayRef<Constant *> MetadataInitializers);
746
747 GlobalVariable *CreateMetadataGlobal(Constant *Initializer,
748 StringRef OriginalName);
749 void SetComdatForGlobalMetadata(GlobalVariable *G, GlobalVariable *Metadata,
750 StringRef InternalSuffix);
751 Instruction *CreateAsanModuleDtor();
752
753 const GlobalVariable *getExcludedAliasedGlobal(const GlobalAlias &GA) const;
754 bool shouldInstrumentGlobal(GlobalVariable *G) const;
755 bool ShouldUseMachOGlobalsSection() const;
756 StringRef getGlobalMetadataSection() const;
757 void poisonOneInitializer(Function &GlobalInit);
758 void createInitializerPoisonCalls();
759 uint64_t getMinRedzoneSizeForGlobal() const {
760 return getRedzoneSizeForScale(MappingScale: Mapping.Scale);
761 }
762 uint64_t getRedzoneSizeForGlobal(uint64_t SizeInBytes) const;
763 int GetAsanVersion() const;
764 GlobalVariable *getOrCreateModuleName();
765
766 const InstrumentationOptions &Opts;
767 Module &M;
768 AsanFunctionInserter Inserter;
769 bool CompileKernel;
770 bool InsertVersionCheck;
771 bool Recover;
772 bool UseGlobalsGC;
773 bool UsePrivateAlias;
774 bool UseOdrIndicator;
775 bool UseCtorComdat;
776 AsanDtorKind DestructorKind;
777 AsanCtorKind ConstructorKind;
778 Type *IntptrTy;
779 PointerType *PtrTy;
780 LLVMContext *C;
781 Triple TargetTriple;
782 ShadowMapping Mapping;
783 FunctionCallee AsanPoisonGlobals;
784 FunctionCallee AsanUnpoisonGlobals;
785 FunctionCallee AsanRegisterGlobals;
786 FunctionCallee AsanUnregisterGlobals;
787 FunctionCallee AsanRegisterImageGlobals;
788 FunctionCallee AsanUnregisterImageGlobals;
789 FunctionCallee AsanRegisterElfGlobals;
790 FunctionCallee AsanUnregisterElfGlobals;
791
792 Function *AsanCtorFunction = nullptr;
793 Function *AsanDtorFunction = nullptr;
794 GlobalVariable *ModuleName = nullptr;
795};
796
797// Stack poisoning does not play well with exception handling.
798// When an exception is thrown, we essentially bypass the code
799// that unpoisones the stack. This is why the run-time library has
800// to intercept __cxa_throw (as well as longjmp, etc) and unpoison the entire
801// stack in the interceptor. This however does not work inside the
802// actual function which catches the exception. Most likely because the
803// compiler hoists the load of the shadow value somewhere too high.
804// This causes asan to report a non-existing bug on 453.povray.
805// It sounds like an LLVM bug.
806struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
807 const InstrumentationOptions &Opts;
808 Function &F;
809 AddressSanitizer &ASan;
810 RuntimeCallInserter &RTCI;
811 DIBuilder DIB;
812 LLVMContext *C;
813 Type *IntptrTy;
814 Type *IntptrPtrTy;
815 ShadowMapping Mapping;
816
817 SmallVector<AllocaInst *, 16> AllocaVec;
818 SmallVector<AllocaInst *, 16> StaticAllocasToMoveUp;
819 SmallVector<Instruction *, 8> RetVec;
820
821 FunctionCallee AsanStackMallocFunc[kMaxAsanStackMallocSizeClass + 1],
822 AsanStackFreeFunc[kMaxAsanStackMallocSizeClass + 1];
823 FunctionCallee AsanSetShadowFunc[0x100] = {};
824 FunctionCallee AsanPoisonStackMemoryFunc, AsanUnpoisonStackMemoryFunc;
825 FunctionCallee AsanAllocaPoisonFunc, AsanAllocasUnpoisonFunc;
826
827 // Stores a place and arguments of poisoning/unpoisoning call for alloca.
828 struct AllocaPoisonCall {
829 IntrinsicInst *InsBefore;
830 AllocaInst *AI;
831 uint64_t Size;
832 bool DoPoison;
833 };
834 SmallVector<AllocaPoisonCall, 8> DynamicAllocaPoisonCallVec;
835 SmallVector<AllocaPoisonCall, 8> StaticAllocaPoisonCallVec;
836
837 SmallVector<AllocaInst *, 1> DynamicAllocaVec;
838 SmallVector<IntrinsicInst *, 1> StackRestoreVec;
839 AllocaInst *DynamicAllocaLayout = nullptr;
840 IntrinsicInst *LocalEscapeCall = nullptr;
841
842 bool HasInlineAsm = false;
843 bool HasReturnsTwiceCall = false;
844 bool PoisonStack;
845
846 FunctionStackPoisoner(Function &F, AddressSanitizer &ASan,
847 RuntimeCallInserter &RTCI)
848 : Opts(ASan.Opts), F(F), ASan(ASan), RTCI(RTCI),
849 DIB(*F.getParent(), /*AllowUnresolved*/ false), C(ASan.C),
850 IntptrTy(ASan.IntptrTy),
851 IntptrPtrTy(PointerType::get(C&: IntptrTy->getContext(), AddressSpace: 0)),
852 Mapping(ASan.Mapping),
853 PoisonStack(Opts.asan_stack &&
854 !F.getParent()->getTargetTriple().isAMDGPU()) {}
855
856 bool runOnFunction() {
857 if (!PoisonStack)
858 return false;
859
860 if (Opts.asan_redzone_byval_args)
861 copyArgsPassedByValToAllocas();
862
863 // Collect alloca, ret, lifetime instructions etc.
864 for (BasicBlock *BB : depth_first(G: &F.getEntryBlock())) visit(BB&: *BB);
865
866 if (AllocaVec.empty() && DynamicAllocaVec.empty()) return false;
867
868 initializeCallbacks(M&: *F.getParent());
869
870 processDynamicAllocas();
871 processStaticAllocas();
872
873 if (Opts.asan_debug_stack) {
874 LLVM_DEBUG(dbgs() << F);
875 }
876 return true;
877 }
878
879 // Arguments marked with the "byval" attribute are implicitly copied without
880 // using an alloca instruction. To produce redzones for those arguments, we
881 // copy them a second time into memory allocated with an alloca instruction.
882 void copyArgsPassedByValToAllocas();
883
884 // Finds all Alloca instructions and puts
885 // poisoned red zones around all of them.
886 // Then unpoison everything back before the function returns.
887 void processStaticAllocas();
888 void processDynamicAllocas();
889
890 void createDynamicAllocasInitStorage();
891
892 // ----------------------- Visitors.
893 /// Collect all Ret instructions, or the musttail call instruction if it
894 /// precedes the return instruction.
895 void visitReturnInst(ReturnInst &RI) {
896 if (CallInst *CI = RI.getParent()->getTerminatingMustTailCall())
897 RetVec.push_back(Elt: CI);
898 else
899 RetVec.push_back(Elt: &RI);
900 }
901
902 /// Collect all Resume instructions.
903 void visitResumeInst(ResumeInst &RI) { RetVec.push_back(Elt: &RI); }
904
905 /// Collect all CatchReturnInst instructions.
906 void visitCleanupReturnInst(CleanupReturnInst &CRI) { RetVec.push_back(Elt: &CRI); }
907
908 void unpoisonDynamicAllocasBeforeInst(Instruction *InstBefore,
909 Value *SavedStack) {
910 IRBuilder<> IRB(InstBefore);
911 Value *DynamicAreaPtr = IRB.CreatePtrToInt(V: SavedStack, DestTy: IntptrTy);
912 // When we insert _asan_allocas_unpoison before @llvm.stackrestore, we
913 // need to adjust extracted SP to compute the address of the most recent
914 // alloca. We have a special @llvm.get.dynamic.area.offset intrinsic for
915 // this purpose.
916 if (!isa<ReturnInst>(Val: InstBefore)) {
917 Value *DynamicAreaOffset = IRB.CreateIntrinsic(
918 ID: Intrinsic::get_dynamic_area_offset, OverloadTypes: {IntptrTy}, Args: {});
919
920 DynamicAreaPtr = IRB.CreateAdd(LHS: IRB.CreatePtrToInt(V: SavedStack, DestTy: IntptrTy),
921 RHS: DynamicAreaOffset);
922 }
923
924 RTCI.createRuntimeCall(
925 IRB, Callee: AsanAllocasUnpoisonFunc,
926 Args: {IRB.CreateLoad(Ty: IntptrTy, Ptr: DynamicAllocaLayout), DynamicAreaPtr});
927 }
928
929 // Unpoison dynamic allocas redzones.
930 void unpoisonDynamicAllocas() {
931 for (Instruction *Ret : RetVec)
932 unpoisonDynamicAllocasBeforeInst(InstBefore: Ret, SavedStack: DynamicAllocaLayout);
933
934 for (Instruction *StackRestoreInst : StackRestoreVec)
935 unpoisonDynamicAllocasBeforeInst(InstBefore: StackRestoreInst,
936 SavedStack: StackRestoreInst->getOperand(i: 0));
937 }
938
939 // Deploy and poison redzones around dynamic alloca call. To do this, we
940 // should replace this call with another one with changed parameters and
941 // replace all its uses with new address, so
942 // addr = alloca type, old_size, align
943 // is replaced by
944 // new_size = (old_size + additional_size) * sizeof(type)
945 // tmp = alloca i8, new_size, max(align, 32)
946 // addr = tmp + 32 (first 32 bytes are for the left redzone).
947 // Additional_size is added to make new memory allocation contain not only
948 // requested memory, but also left, partial and right redzones.
949 void handleDynamicAllocaCall(AllocaInst *AI);
950
951 /// Collect Alloca instructions we want (and can) handle.
952 void visitAllocaInst(AllocaInst &AI) {
953 // FIXME: Handle scalable vectors instead of ignoring them.
954 if (!ASan.isInterestingAlloca(AI) || AI.isScalable()) {
955 if (AI.isStaticAlloca()) {
956 // Skip over allocas that are present *before* the first instrumented
957 // alloca, we don't want to move those around.
958 if (AllocaVec.empty())
959 return;
960
961 StaticAllocasToMoveUp.push_back(Elt: &AI);
962 }
963 return;
964 }
965
966 if (!AI.isStaticAlloca())
967 DynamicAllocaVec.push_back(Elt: &AI);
968 else
969 AllocaVec.push_back(Elt: &AI);
970 }
971
972 /// Collect lifetime intrinsic calls to check for use-after-scope
973 /// errors.
974 void visitIntrinsicInst(IntrinsicInst &II) {
975 Intrinsic::ID ID = II.getIntrinsicID();
976 if (ID == Intrinsic::stackrestore) StackRestoreVec.push_back(Elt: &II);
977 if (ID == Intrinsic::localescape) LocalEscapeCall = &II;
978 if (!ASan.UseAfterScope)
979 return;
980 if (!II.isLifetimeStartOrEnd())
981 return;
982 // Find alloca instruction that corresponds to llvm.lifetime argument.
983 AllocaInst *AI = dyn_cast<AllocaInst>(Val: II.getArgOperand(i: 0));
984 // We're interested only in allocas we can handle.
985 if (!AI || !ASan.isInterestingAlloca(AI: *AI))
986 return;
987
988 std::optional<TypeSize> Size = AI->getAllocationSize(DL: AI->getDataLayout());
989 // Check that size is known and can be stored in IntptrTy.
990 // TODO: Add support for scalable vectors if possible.
991 if (!Size || Size->isScalable() ||
992 !ConstantInt::isValueValidForType(Ty: IntptrTy, V: *Size))
993 return;
994
995 bool DoPoison = (ID == Intrinsic::lifetime_end);
996 AllocaPoisonCall APC = {.InsBefore: &II, .AI: AI, .Size: *Size, .DoPoison: DoPoison};
997 if (AI->isStaticAlloca())
998 StaticAllocaPoisonCallVec.push_back(Elt: APC);
999 else if (Opts.asan_instrument_dynamic_allocas)
1000 DynamicAllocaPoisonCallVec.push_back(Elt: APC);
1001 }
1002
1003 void visitCallBase(CallBase &CB) {
1004 if (CallInst *CI = dyn_cast<CallInst>(Val: &CB)) {
1005 HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
1006 HasReturnsTwiceCall |= CI->canReturnTwice();
1007 }
1008 }
1009
1010 // ---------------------- Helpers.
1011 void initializeCallbacks(Module &M);
1012
1013 // Copies bytes from ShadowBytes into shadow memory for indexes where
1014 // ShadowMask is not zero. If ShadowMask[i] is zero, we assume that
1015 // ShadowBytes[i] is constantly zero and doesn't need to be overwritten.
1016 void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
1017 IRBuilder<> &IRB, Value *ShadowBase);
1018 void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
1019 size_t Begin, size_t End, IRBuilder<> &IRB,
1020 Value *ShadowBase);
1021 void copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
1022 ArrayRef<uint8_t> ShadowBytes, size_t Begin,
1023 size_t End, IRBuilder<> &IRB, Value *ShadowBase);
1024
1025 void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison);
1026
1027 Value *createAllocaForLayout(IRBuilder<> &IRB, const ASanStackFrameLayout &L,
1028 bool Dynamic);
1029 PHINode *createPHI(IRBuilder<> &IRB, Value *Cond, Value *ValueIfTrue,
1030 Instruction *ThenTerm, Value *ValueIfFalse);
1031};
1032
1033} // end anonymous namespace
1034
1035void AddressSanitizerPass::printPipeline(
1036 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
1037 static_cast<PassInfoMixin<AddressSanitizerPass> *>(this)->printPipeline(
1038 OS, MapClassName2PassName);
1039 OS << '<';
1040 if (Options.CompileKernel)
1041 OS << "kernel;";
1042 if (Options.UseAfterScope)
1043 OS << "use-after-scope";
1044 OS << '>';
1045}
1046
1047AddressSanitizerPass::AddressSanitizerPass(
1048 const AddressSanitizerOptions &Options, bool UseGlobalGC,
1049 bool UseOdrIndicator, AsanDtorKind DestructorKind,
1050 AsanCtorKind ConstructorKind)
1051 : Options(Options), UseGlobalGC(UseGlobalGC),
1052 UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1053 ConstructorKind(ConstructorKind) {}
1054
1055PreservedAnalyses AddressSanitizerPass::run(Module &M,
1056 ModuleAnalysisManager &MAM) {
1057 // Return early if nosanitize_address module flag is present for the module.
1058 // This implies that asan pass has already run before.
1059 if (checkIfAlreadyInstrumented(M, Flag: "nosanitize_address"))
1060 return PreservedAnalyses::all();
1061
1062 const InstrumentationOptions &Opts =
1063 M.getContext().getLibraryOptions().get<InstrumentationOptions>();
1064 ModuleAddressSanitizer ModuleSanitizer(Opts, M, Options.InsertVersionCheck,
1065 Options.CompileKernel, Options.Recover,
1066 UseGlobalGC, UseOdrIndicator,
1067 DestructorKind, ConstructorKind);
1068 bool Modified = false;
1069 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager();
1070 const StackSafetyGlobalInfo *const SSGI =
1071 Opts.asan_use_stack_safety ? &MAM.getResult<StackSafetyGlobalAnalysis>(IR&: M)
1072 : nullptr;
1073 for (Function &F : M) {
1074 if (F.empty())
1075 continue;
1076 if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
1077 continue;
1078 if (!Opts.asan_debug_func.empty() && Opts.asan_debug_func == F.getName())
1079 continue;
1080 if (F.getName().starts_with(Prefix: "__asan_"))
1081 continue;
1082 if (F.isPresplitCoroutine())
1083 continue;
1084 AddressSanitizer FunctionSanitizer(
1085 Opts, M, SSGI, Options.InstrumentationWithCallsThreshold,
1086 Options.MaxInlinePoisoningSize, Options.CompileKernel, Options.Recover,
1087 Options.UseAfterScope, Options.UseAfterReturn);
1088 const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(IR&: F);
1089 const TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(IR&: F);
1090 Modified |= FunctionSanitizer.instrumentFunction(F, TLI: &TLI, TTI: &TTI);
1091 }
1092 Modified |= ModuleSanitizer.instrumentModule();
1093 if (!Modified)
1094 return PreservedAnalyses::all();
1095
1096 PreservedAnalyses PA = PreservedAnalyses::none();
1097 // GlobalsAA is considered stateless and does not get invalidated unless
1098 // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
1099 // make changes that require GlobalsAA to be invalidated.
1100 PA.abandon<GlobalsAA>();
1101 return PA;
1102}
1103
1104static size_t TypeStoreSizeToSizeIndex(uint32_t TypeSize) {
1105 size_t Res = llvm::countr_zero(Val: TypeSize / 8);
1106 assert(Res < kNumberOfAccessSizes);
1107 return Res;
1108}
1109
1110/// Check if \p G has been created by a trusted compiler pass.
1111static bool GlobalWasGeneratedByCompiler(GlobalVariable *G) {
1112 // Do not instrument @llvm.global_ctors, @llvm.used, etc.
1113 if (G->getName().starts_with(Prefix: "llvm.") ||
1114 // Do not instrument gcov counter arrays.
1115 G->getName().starts_with(Prefix: "__llvm_gcov_ctr") ||
1116 // Do not instrument rtti proxy symbols for function sanitizer.
1117 G->getName().starts_with(Prefix: "__llvm_rtti_proxy"))
1118 return true;
1119
1120 // Do not instrument asan globals.
1121 if (G->getName().starts_with(Prefix: kAsanGenPrefix) ||
1122 G->getName().starts_with(Prefix: kSanCovGenPrefix) ||
1123 G->getName().starts_with(Prefix: kODRGenPrefix))
1124 return true;
1125
1126 return false;
1127}
1128
1129static bool isUnsupportedAMDGPUAddrspace(Value *Addr) {
1130 Type *PtrTy = cast<PointerType>(Val: Addr->getType()->getScalarType());
1131 unsigned int AddrSpace = PtrTy->getPointerAddressSpace();
1132 // Globals in address space 1 and 4 are supported for AMDGPU.
1133 if (AddrSpace == 3 || AddrSpace == 5)
1134 return true;
1135 return false;
1136}
1137
1138static bool isSupportedAddrspace(const InstrumentationOptions &Opts,
1139 const Triple &TargetTriple, Value *Addr) {
1140 Type *PtrTy = cast<PointerType>(Val: Addr->getType()->getScalarType());
1141 unsigned int AddrSpace = PtrTy->getPointerAddressSpace();
1142
1143 if (!Opts.asan_instrument_address_spaces.empty())
1144 return is_contained(Range: Opts.asan_instrument_address_spaces, Element: AddrSpace);
1145
1146 if (TargetTriple.isAMDGPU())
1147 return !isUnsupportedAMDGPUAddrspace(Addr);
1148
1149 return AddrSpace == 0;
1150}
1151
1152Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
1153 if (TargetTriple.isOSDarwin() &&
1154 TargetTriple.getArch() == llvm::Triple::aarch64) {
1155 // Strip MTE-tag bits before translating to shadow address
1156 Shadow = IRB.CreateAnd(LHS: Shadow,
1157 RHS: ConstantInt::get(Ty: IntptrTy, V: ~(uint64_t(0x0f) << 56)));
1158 }
1159 // Shadow >> scale
1160 Shadow = IRB.CreateLShr(LHS: Shadow, RHS: Mapping.Scale);
1161 if (Mapping.Offset == 0) return Shadow;
1162 // (Shadow >> scale) | offset
1163 Value *ShadowBase;
1164 if (LocalDynamicShadow)
1165 ShadowBase = LocalDynamicShadow;
1166 else
1167 ShadowBase = ConstantInt::get(Ty: IntptrTy, V: Mapping.Offset);
1168 if (Mapping.OrShadowOffset)
1169 return IRB.CreateOr(LHS: Shadow, RHS: ShadowBase);
1170 else
1171 return IRB.CreateAdd(LHS: Shadow, RHS: ShadowBase);
1172}
1173
1174// Instrument memset/memmove/memcpy
1175void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI,
1176 RuntimeCallInserter &RTCI) {
1177 InstrumentationIRBuilder IRB(MI);
1178 if (isa<MemTransferInst>(Val: MI)) {
1179 RTCI.createRuntimeCall(
1180 IRB, Callee: isa<MemMoveInst>(Val: MI) ? AsanMemmove : AsanMemcpy,
1181 Args: {IRB.CreateAddrSpaceCast(V: MI->getOperand(i_nocapture: 0), DestTy: PtrTy),
1182 IRB.CreateAddrSpaceCast(V: MI->getOperand(i_nocapture: 1), DestTy: PtrTy),
1183 IRB.CreateIntCast(V: MI->getOperand(i_nocapture: 2), DestTy: IntptrTy, isSigned: false)});
1184 } else if (isa<MemSetInst>(Val: MI)) {
1185 RTCI.createRuntimeCall(
1186 IRB, Callee: AsanMemset,
1187 Args: {IRB.CreateAddrSpaceCast(V: MI->getOperand(i_nocapture: 0), DestTy: PtrTy),
1188 IRB.CreateIntCast(V: MI->getOperand(i_nocapture: 1), DestTy: IRB.getInt32Ty(), isSigned: false),
1189 IRB.CreateIntCast(V: MI->getOperand(i_nocapture: 2), DestTy: IntptrTy, isSigned: false)});
1190 }
1191 MI->eraseFromParent();
1192}
1193
1194/// Check if we want (and can) handle this alloca.
1195bool AddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
1196 auto [It, Inserted] = ProcessedAllocas.try_emplace(Key: &AI);
1197
1198 if (!Inserted)
1199 return It->getSecond();
1200
1201 bool IsInteresting = // alloca() may be called with 0 size, ignore it.
1202 (((!AI.isStaticAlloca()) || !getAllocaSizeInBytes(AI).isZero()) &&
1203 // We are only interested in allocas not promotable to registers.
1204 // Promotable allocas are common under -O0.
1205 (!Opts.asan_skip_promotable_allocas || !isAllocaPromotable(AI: &AI)) &&
1206 // inalloca allocas are not treated as static, and we don't want
1207 // dynamic alloca instrumentation for them as well.
1208 !AI.isUsedWithInAlloca() &&
1209 // swifterror allocas are register promoted by ISel
1210 !AI.isSwiftError() &&
1211 // safe allocas are not interesting
1212 !(SSGI && SSGI->isSafe(AI)));
1213
1214 It->second = IsInteresting;
1215 return IsInteresting;
1216}
1217
1218bool AddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {
1219 // Check whether the target supports sanitizing the address space
1220 // of the pointer.
1221 if (!isSupportedAddrspace(Opts, TargetTriple, Addr: Ptr))
1222 return true;
1223
1224 // Ignore swifterror addresses.
1225 // swifterror memory addresses are mem2reg promoted by instruction
1226 // selection. As such they cannot have regular uses like an instrumentation
1227 // function and it makes no sense to track them as memory.
1228 if (Ptr->isSwiftError())
1229 return true;
1230
1231 // Treat memory accesses to promotable allocas as non-interesting since they
1232 // will not cause memory violations. This greatly speeds up the instrumented
1233 // executable at -O0.
1234 if (auto AI = dyn_cast_or_null<AllocaInst>(Val: Ptr))
1235 if (Opts.asan_skip_promotable_allocas && !isInterestingAlloca(AI: *AI))
1236 return true;
1237
1238 if (SSGI != nullptr && SSGI->stackAccessIsSafe(I: *Inst) &&
1239 findAllocaForValue(V: Ptr))
1240 return true;
1241
1242 return false;
1243}
1244
1245void AddressSanitizer::getInterestingMemoryOperands(
1246 Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
1247 const TargetTransformInfo *TTI) {
1248 // Do not instrument the load fetching the dynamic shadow address.
1249 if (LocalDynamicShadow == I)
1250 return;
1251
1252 if (LoadInst *LI = dyn_cast<LoadInst>(Val: I)) {
1253 if (!Opts.asan_instrument_reads || ignoreAccess(Inst: I, Ptr: LI->getPointerOperand()))
1254 return;
1255 Interesting.emplace_back(Args&: I, Args: LI->getPointerOperandIndex(), Args: false,
1256 Args: LI->getType(), Args: LI->getAlign());
1257 } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: I)) {
1258 if (!Opts.asan_instrument_writes ||
1259 ignoreAccess(Inst: I, Ptr: SI->getPointerOperand()))
1260 return;
1261 Interesting.emplace_back(Args&: I, Args: SI->getPointerOperandIndex(), Args: true,
1262 Args: SI->getValueOperand()->getType(), Args: SI->getAlign());
1263 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(Val: I)) {
1264 if (!Opts.asan_instrument_atomics ||
1265 ignoreAccess(Inst: I, Ptr: RMW->getPointerOperand()))
1266 return;
1267 Interesting.emplace_back(Args&: I, Args: RMW->getPointerOperandIndex(), Args: true,
1268 Args: RMW->getValOperand()->getType(), Args: std::nullopt);
1269 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(Val: I)) {
1270 if (!Opts.asan_instrument_atomics ||
1271 ignoreAccess(Inst: I, Ptr: XCHG->getPointerOperand()))
1272 return;
1273 Interesting.emplace_back(Args&: I, Args: XCHG->getPointerOperandIndex(), Args: true,
1274 Args: XCHG->getCompareOperand()->getType(),
1275 Args: std::nullopt);
1276 } else if (auto CI = dyn_cast<CallInst>(Val: I)) {
1277 switch (CI->getIntrinsicID()) {
1278 case Intrinsic::masked_load:
1279 case Intrinsic::masked_store:
1280 case Intrinsic::masked_gather:
1281 case Intrinsic::masked_scatter: {
1282 bool IsWrite = CI->getType()->isVoidTy();
1283 // Masked store has an initial operand for the value.
1284 unsigned OpOffset = IsWrite ? 1 : 0;
1285 if (IsWrite ? !Opts.asan_instrument_writes : !Opts.asan_instrument_reads)
1286 return;
1287
1288 auto BasePtr = CI->getOperand(i_nocapture: OpOffset);
1289 if (ignoreAccess(Inst: I, Ptr: BasePtr))
1290 return;
1291 Type *Ty = IsWrite ? CI->getArgOperand(i: 0)->getType() : CI->getType();
1292 MaybeAlign Alignment = CI->getParamAlign(ArgNo: 0);
1293 Value *Mask = CI->getOperand(i_nocapture: 1 + OpOffset);
1294 Interesting.emplace_back(Args&: I, Args&: OpOffset, Args&: IsWrite, Args&: Ty, Args&: Alignment, Args&: Mask);
1295 break;
1296 }
1297 case Intrinsic::masked_expandload:
1298 case Intrinsic::masked_compressstore: {
1299 bool IsWrite = CI->getIntrinsicID() == Intrinsic::masked_compressstore;
1300 unsigned OpOffset = IsWrite ? 1 : 0;
1301 if (IsWrite ? !Opts.asan_instrument_writes : !Opts.asan_instrument_reads)
1302 return;
1303 auto BasePtr = CI->getOperand(i_nocapture: OpOffset);
1304 if (ignoreAccess(Inst: I, Ptr: BasePtr))
1305 return;
1306 MaybeAlign Alignment = BasePtr->getPointerAlignment(DL: *DL);
1307 Type *Ty = IsWrite ? CI->getArgOperand(i: 0)->getType() : CI->getType();
1308
1309 IRBuilder IB(I);
1310 Value *Mask = CI->getOperand(i_nocapture: 1 + OpOffset);
1311 // Use the popcount of Mask as the effective vector length.
1312 Type *ExtTy = VectorType::get(ElementType: IntptrTy, Other: cast<VectorType>(Val: Ty));
1313 Value *ExtMask = IB.CreateZExt(V: Mask, DestTy: ExtTy);
1314 Value *EVL = IB.CreateAddReduce(Src: ExtMask);
1315 Value *TrueMask = ConstantInt::get(Ty: Mask->getType(), V: 1);
1316 Interesting.emplace_back(Args&: I, Args&: OpOffset, Args&: IsWrite, Args&: Ty, Args&: Alignment, Args&: TrueMask,
1317 Args&: EVL);
1318 break;
1319 }
1320 case Intrinsic::vp_load:
1321 case Intrinsic::vp_store:
1322 case Intrinsic::experimental_vp_strided_load:
1323 case Intrinsic::experimental_vp_strided_store: {
1324 auto *VPI = cast<VPIntrinsic>(Val: CI);
1325 unsigned IID = CI->getIntrinsicID();
1326 bool IsWrite = CI->getType()->isVoidTy();
1327 if (IsWrite ? !Opts.asan_instrument_writes : !Opts.asan_instrument_reads)
1328 return;
1329 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1330 Type *Ty = IsWrite ? CI->getArgOperand(i: 0)->getType() : CI->getType();
1331 MaybeAlign Alignment = VPI->getOperand(i_nocapture: PtrOpNo)->getPointerAlignment(DL: *DL);
1332 Value *Stride = nullptr;
1333 if (IID == Intrinsic::experimental_vp_strided_store ||
1334 IID == Intrinsic::experimental_vp_strided_load) {
1335 Stride = VPI->getOperand(i_nocapture: PtrOpNo + 1);
1336 // Use the pointer alignment as the element alignment if the stride is a
1337 // multiple of the pointer alignment. Otherwise, the element alignment
1338 // should be Align(1).
1339 unsigned PointerAlign = Alignment.valueOrOne().value();
1340 if (!isa<ConstantInt>(Val: Stride) ||
1341 cast<ConstantInt>(Val: Stride)->getZExtValue() % PointerAlign != 0)
1342 Alignment = Align(1);
1343 }
1344 Interesting.emplace_back(Args&: I, Args&: PtrOpNo, Args&: IsWrite, Args&: Ty, Args&: Alignment,
1345 Args: VPI->getMaskParam(), Args: VPI->getVectorLengthParam(),
1346 Args&: Stride);
1347 break;
1348 }
1349 case Intrinsic::vp_gather:
1350 case Intrinsic::vp_scatter: {
1351 auto *VPI = cast<VPIntrinsic>(Val: CI);
1352 unsigned IID = CI->getIntrinsicID();
1353 bool IsWrite = IID == Intrinsic::vp_scatter;
1354 if (IsWrite ? !Opts.asan_instrument_writes : !Opts.asan_instrument_reads)
1355 return;
1356 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1357 Type *Ty = IsWrite ? CI->getArgOperand(i: 0)->getType() : CI->getType();
1358 MaybeAlign Alignment = VPI->getPointerAlignment();
1359 Interesting.emplace_back(Args&: I, Args&: PtrOpNo, Args&: IsWrite, Args&: Ty, Args&: Alignment,
1360 Args: VPI->getMaskParam(),
1361 Args: VPI->getVectorLengthParam());
1362 break;
1363 }
1364 default:
1365 if (auto *II = dyn_cast<IntrinsicInst>(Val: I)) {
1366 MemIntrinsicInfo IntrInfo;
1367 if (TTI->getTgtMemIntrinsic(Inst: II, Info&: IntrInfo))
1368 Interesting = IntrInfo.InterestingOperands;
1369 return;
1370 }
1371 for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
1372 if (!Opts.asan_instrument_byval || !CI->isByValArgument(ArgNo) ||
1373 ignoreAccess(Inst: I, Ptr: CI->getArgOperand(i: ArgNo)))
1374 continue;
1375 Type *Ty = CI->getParamByValType(ArgNo);
1376 Interesting.emplace_back(Args&: I, Args&: ArgNo, Args: false, Args&: Ty, Args: Align(1));
1377 }
1378 }
1379 }
1380}
1381
1382static bool isPointerOperand(Value *V) {
1383 return V->getType()->isPointerTy() || isa<PtrToIntInst, PtrToAddrInst>(Val: V);
1384}
1385
1386// This is a rough heuristic; it may cause both false positives and
1387// false negatives. The proper implementation requires cooperation with
1388// the frontend.
1389static bool isInterestingPointerComparison(Instruction *I) {
1390 if (ICmpInst *Cmp = dyn_cast<ICmpInst>(Val: I)) {
1391 if (!Cmp->isRelational())
1392 return false;
1393 } else {
1394 return false;
1395 }
1396 return isPointerOperand(V: I->getOperand(i: 0)) &&
1397 isPointerOperand(V: I->getOperand(i: 1));
1398}
1399
1400// This is a rough heuristic; it may cause both false positives and
1401// false negatives. The proper implementation requires cooperation with
1402// the frontend.
1403static bool isInterestingPointerSubtraction(Instruction *I) {
1404 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Val: I)) {
1405 if (BO->getOpcode() != Instruction::Sub)
1406 return false;
1407 } else {
1408 return false;
1409 }
1410 return isPointerOperand(V: I->getOperand(i: 0)) &&
1411 isPointerOperand(V: I->getOperand(i: 1));
1412}
1413
1414bool AddressSanitizer::GlobalIsLinkerInitialized(GlobalVariable *G) {
1415 // If a global variable does not have dynamic initialization we don't
1416 // have to instrument it. However, if a global does not have initializer
1417 // at all, we assume it has dynamic initializer (in other TU).
1418 if (!G->hasInitializer())
1419 return false;
1420
1421 if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().IsDynInit)
1422 return false;
1423
1424 return true;
1425}
1426
1427static bool isPointerPairOperand(Value *V, Type *IntptrTy) {
1428 Type *Ty = V->getType();
1429 if (Ty->isPtrOrPtrVectorTy())
1430 return true;
1431 return Ty->isIntOrIntVectorTy() &&
1432 Ty->getScalarSizeInBits() == IntptrTy->getScalarSizeInBits();
1433}
1434
1435bool AddressSanitizer::instrumentPointerComparisonOrSubtraction(
1436 Instruction *I, RuntimeCallInserter &RTCI) {
1437 Value *Param[2] = {I->getOperand(i: 0), I->getOperand(i: 1)};
1438 if (!isPointerPairOperand(V: Param[0], IntptrTy) ||
1439 !isPointerPairOperand(V: Param[1], IntptrTy))
1440 return false;
1441
1442 IRBuilder<> IRB(I);
1443 FunctionCallee F = isa<ICmpInst>(Val: I) ? AsanPtrCmpFunction : AsanPtrSubFunction;
1444
1445 if (const auto *Ty = Param[0]->getType(); Ty->isVectorTy()) {
1446 const auto *VTy = dyn_cast<FixedVectorType>(Val: Ty);
1447 // TODO: Add support for scalable vectors if possible.
1448 if (!VTy)
1449 return false;
1450
1451 assert(Param[0]->getType() == Param[1]->getType() &&
1452 "invalid vector pointer pair instrumentation operands");
1453 for (unsigned Index = 0, NumElements = VTy->getNumElements();
1454 Index != NumElements; ++Index) {
1455 Value *ScalarParam[2] = {
1456 IRB.CreatePointerCast(
1457 V: IRB.CreateExtractElement(Vec: Param[0], Idx: IRB.getInt32(C: Index)),
1458 DestTy: IntptrTy),
1459 IRB.CreatePointerCast(
1460 V: IRB.CreateExtractElement(Vec: Param[1], Idx: IRB.getInt32(C: Index)),
1461 DestTy: IntptrTy)};
1462 RTCI.createRuntimeCall(IRB, Callee: F, Args: ScalarParam);
1463 }
1464 return true;
1465 }
1466
1467 for (Value *&P : Param)
1468 P = IRB.CreatePointerCast(V: P, DestTy: IntptrTy);
1469 RTCI.createRuntimeCall(IRB, Callee: F, Args: Param);
1470 return true;
1471}
1472
1473static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
1474 Instruction *InsertBefore, Value *Addr,
1475 MaybeAlign Alignment, unsigned Granularity,
1476 TypeSize TypeStoreSize, bool IsWrite,
1477 Value *SizeArgument, bool UseCalls,
1478 uint32_t Exp, RuntimeCallInserter &RTCI) {
1479 // Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check
1480 // if the data is properly aligned.
1481 if (!TypeStoreSize.isScalable()) {
1482 const auto FixedSize = TypeStoreSize.getFixedValue();
1483 switch (FixedSize) {
1484 case 8:
1485 case 16:
1486 case 32:
1487 case 64:
1488 case 128:
1489 if (!Alignment || *Alignment >= Granularity ||
1490 *Alignment >= FixedSize / 8)
1491 return Pass->instrumentAddress(OrigIns: I, InsertBefore, Addr, Alignment,
1492 TypeStoreSize: FixedSize, IsWrite, SizeArgument: nullptr, UseCalls,
1493 Exp, RTCI);
1494 }
1495 }
1496 Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeStoreSize,
1497 IsWrite, SizeArgument: nullptr, UseCalls, Exp, RTCI);
1498}
1499
1500void AddressSanitizer::instrumentMaskedLoadOrStore(
1501 AddressSanitizer *Pass, const DataLayout &DL, Type *IntptrTy, Value *Mask,
1502 Value *EVL, Value *Stride, Instruction *I, Value *Addr,
1503 MaybeAlign Alignment, unsigned Granularity, Type *OpType, bool IsWrite,
1504 Value *SizeArgument, bool UseCalls, uint32_t Exp,
1505 RuntimeCallInserter &RTCI) {
1506 auto *VTy = cast<VectorType>(Val: OpType);
1507 TypeSize ElemTypeSize = DL.getTypeStoreSizeInBits(Ty: VTy->getScalarType());
1508 auto Zero = ConstantInt::get(Ty: IntptrTy, V: 0);
1509
1510 IRBuilder IB(I);
1511 Instruction *LoopInsertBefore = I;
1512 if (EVL) {
1513 // The end argument of SplitBlockAndInsertForLane is assumed bigger
1514 // than zero, so we should check whether EVL is zero here.
1515 Type *EVLType = EVL->getType();
1516 Value *IsEVLZero = IB.CreateICmpNE(LHS: EVL, RHS: ConstantInt::get(Ty: EVLType, V: 0));
1517 LoopInsertBefore = SplitBlockAndInsertIfThen(Cond: IsEVLZero, SplitBefore: I, Unreachable: false);
1518 IB.SetInsertPoint(LoopInsertBefore);
1519 // Cast EVL to IntptrTy.
1520 EVL = IB.CreateZExtOrTrunc(V: EVL, DestTy: IntptrTy);
1521 // To avoid undefined behavior for extracting with out of range index, use
1522 // the minimum of evl and element count as trip count.
1523 Value *EC = IB.CreateElementCount(Ty: IntptrTy, EC: VTy->getElementCount());
1524 EVL = IB.CreateBinaryIntrinsic(ID: Intrinsic::umin, LHS: EVL, RHS: EC);
1525 } else {
1526 EVL = IB.CreateElementCount(Ty: IntptrTy, EC: VTy->getElementCount());
1527 }
1528
1529 // Cast Stride to IntptrTy.
1530 if (Stride)
1531 Stride = IB.CreateZExtOrTrunc(V: Stride, DestTy: IntptrTy);
1532
1533 SplitBlockAndInsertForEachLane(End: EVL, InsertBefore: LoopInsertBefore->getIterator(),
1534 Func: [&](IRBuilderBase &IRB, Value *Index) {
1535 Value *MaskElem = IRB.CreateExtractElement(Vec: Mask, Idx: Index);
1536 if (auto *MaskElemC = dyn_cast<ConstantInt>(Val: MaskElem)) {
1537 if (MaskElemC->isZero())
1538 // No check
1539 return;
1540 // Unconditional check
1541 } else {
1542 // Conditional check
1543 Instruction *ThenTerm = SplitBlockAndInsertIfThen(
1544 Cond: MaskElem, SplitBefore: &*IRB.GetInsertPoint(), Unreachable: false);
1545 IRB.SetInsertPoint(ThenTerm);
1546 }
1547
1548 Value *InstrumentedAddress;
1549 if (isa<VectorType>(Val: Addr->getType())) {
1550 assert(
1551 cast<VectorType>(Addr->getType())->getElementType()->isPointerTy() &&
1552 "Expected vector of pointer.");
1553 InstrumentedAddress = IRB.CreateExtractElement(Vec: Addr, Idx: Index);
1554 } else if (Stride) {
1555 Index = IRB.CreateMul(LHS: Index, RHS: Stride);
1556 InstrumentedAddress = IRB.CreatePtrAdd(Ptr: Addr, Offset: Index);
1557 } else {
1558 InstrumentedAddress = IRB.CreateGEP(Ty: VTy, Ptr: Addr, IdxList: {Zero, Index});
1559 }
1560 doInstrumentAddress(Pass, I, InsertBefore: &*IRB.GetInsertPoint(), Addr: InstrumentedAddress,
1561 Alignment, Granularity, TypeStoreSize: ElemTypeSize, IsWrite,
1562 SizeArgument, UseCalls, Exp, RTCI);
1563 });
1564}
1565
1566void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
1567 InterestingMemoryOperand &O, bool UseCalls,
1568 const DataLayout &DL,
1569 RuntimeCallInserter &RTCI) {
1570 Value *Addr = O.getPtr();
1571
1572 // Optimization experiments.
1573 // The experiments can be used to evaluate potential optimizations that remove
1574 // instrumentation (assess false negatives). Instead of completely removing
1575 // some instrumentation, you set Exp to a non-zero value (mask of optimization
1576 // experiments that want to remove instrumentation of this instruction).
1577 // If Exp is non-zero, this pass will emit special calls into runtime
1578 // (e.g. __asan_report_exp_load1 instead of __asan_report_load1). These calls
1579 // make runtime terminate the program in a special way (with a different
1580 // exit status). Then you run the new compiler on a buggy corpus, collect
1581 // the special terminations (ideally, you don't see them at all -- no false
1582 // negatives) and make the decision on the optimization.
1583 uint32_t Exp = Opts.asan_force_experiment;
1584
1585 if (Opts.asan_opt && Opts.asan_opt_globals) {
1586 // If initialization order checking is disabled, a simple access to a
1587 // dynamically initialized global is always valid.
1588 GlobalVariable *G = dyn_cast<GlobalVariable>(Val: getUnderlyingObject(V: Addr));
1589 if (G &&
1590 (!Opts.asan_initialization_order || GlobalIsLinkerInitialized(G)) &&
1591 isSafeAccess(ObjSizeVis, Addr, TypeStoreSize: O.TypeStoreSize)) {
1592 NumOptimizedAccessesToGlobalVar++;
1593 return;
1594 }
1595 }
1596
1597 if (Opts.asan_opt && Opts.asan_opt_stack) {
1598 // A direct inbounds access to a stack variable is always valid.
1599 if (isa<AllocaInst>(Val: getUnderlyingObject(V: Addr)) &&
1600 isSafeAccess(ObjSizeVis, Addr, TypeStoreSize: O.TypeStoreSize)) {
1601 NumOptimizedAccessesToStackVar++;
1602 return;
1603 }
1604 }
1605
1606 if (O.IsWrite)
1607 NumInstrumentedWrites++;
1608 else
1609 NumInstrumentedReads++;
1610
1611 if (O.MaybeByteOffset) {
1612 Type *Ty = Type::getInt8Ty(C&: *C);
1613 IRBuilder IB(O.getInsn());
1614
1615 Value *OffsetOp = O.MaybeByteOffset;
1616 if (TargetTriple.isRISCV()) {
1617 Type *OffsetTy = OffsetOp->getType();
1618 // RVV indexed loads/stores zero-extend offset operands which are narrower
1619 // than XLEN to XLEN.
1620 if (OffsetTy->getScalarType()->getIntegerBitWidth() <
1621 static_cast<unsigned>(LongSize)) {
1622 VectorType *OrigType = cast<VectorType>(Val: OffsetTy);
1623 Type *ExtendTy = VectorType::get(ElementType: IntptrTy, Other: OrigType);
1624 OffsetOp = IB.CreateZExt(V: OffsetOp, DestTy: ExtendTy);
1625 }
1626 }
1627 Addr = IB.CreateGEP(Ty, Ptr: Addr, IdxList: {OffsetOp});
1628 }
1629
1630 unsigned Granularity = 1 << Mapping.Scale;
1631 if (O.MaybeMask) {
1632 instrumentMaskedLoadOrStore(Pass: this, DL, IntptrTy, Mask: O.MaybeMask, EVL: O.MaybeEVL,
1633 Stride: O.MaybeStride, I: O.getInsn(), Addr, Alignment: O.Alignment,
1634 Granularity, OpType: O.OpType, IsWrite: O.IsWrite, SizeArgument: nullptr,
1635 UseCalls, Exp, RTCI);
1636 } else {
1637 doInstrumentAddress(Pass: this, I: O.getInsn(), InsertBefore: O.getInsn(), Addr, Alignment: O.Alignment,
1638 Granularity, TypeStoreSize: O.TypeStoreSize, IsWrite: O.IsWrite, SizeArgument: nullptr,
1639 UseCalls, Exp, RTCI);
1640 }
1641}
1642
1643Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore,
1644 Value *Addr, bool IsWrite,
1645 size_t AccessSizeIndex,
1646 Value *SizeArgument,
1647 uint32_t Exp,
1648 RuntimeCallInserter &RTCI) {
1649 InstrumentationIRBuilder IRB(InsertBefore);
1650 Value *ExpVal = Exp == 0 ? nullptr : ConstantInt::get(Ty: IRB.getInt32Ty(), V: Exp);
1651 CallInst *Call = nullptr;
1652 if (SizeArgument) {
1653 if (Exp == 0)
1654 Call = RTCI.createRuntimeCall(IRB, Callee: AsanErrorCallbackSized[IsWrite][0],
1655 Args: {Addr, SizeArgument});
1656 else
1657 Call = RTCI.createRuntimeCall(IRB, Callee: AsanErrorCallbackSized[IsWrite][1],
1658 Args: {Addr, SizeArgument, ExpVal});
1659 } else {
1660 if (Exp == 0)
1661 Call = RTCI.createRuntimeCall(
1662 IRB, Callee: AsanErrorCallback[IsWrite][0][AccessSizeIndex], Args: Addr);
1663 else
1664 Call = RTCI.createRuntimeCall(
1665 IRB, Callee: AsanErrorCallback[IsWrite][1][AccessSizeIndex], Args: {Addr, ExpVal});
1666 }
1667
1668 Call->setCannotMerge();
1669 return Call;
1670}
1671
1672Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
1673 Value *ShadowValue,
1674 uint32_t TypeStoreSize) {
1675 size_t Granularity = static_cast<size_t>(1) << Mapping.Scale;
1676 // Addr & (Granularity - 1)
1677 Value *LastAccessedByte =
1678 IRB.CreateAnd(LHS: AddrLong, RHS: ConstantInt::get(Ty: IntptrTy, V: Granularity - 1));
1679 // (Addr & (Granularity - 1)) + size - 1
1680 if (TypeStoreSize / 8 > 1)
1681 LastAccessedByte = IRB.CreateAdd(
1682 LHS: LastAccessedByte, RHS: ConstantInt::get(Ty: IntptrTy, V: TypeStoreSize / 8 - 1));
1683 // (uint8_t) ((Addr & (Granularity-1)) + size - 1)
1684 LastAccessedByte =
1685 IRB.CreateIntCast(V: LastAccessedByte, DestTy: ShadowValue->getType(), isSigned: false);
1686 // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue
1687 return IRB.CreateICmpSGE(LHS: LastAccessedByte, RHS: ShadowValue);
1688}
1689
1690Instruction *AddressSanitizer::instrumentAMDGPUAddress(
1691 Instruction *OrigIns, Instruction *InsertBefore, Value *Addr,
1692 uint32_t TypeStoreSize, bool IsWrite, Value *SizeArgument) {
1693 // Do not instrument unsupported addrspaces.
1694 if (isUnsupportedAMDGPUAddrspace(Addr))
1695 return nullptr;
1696 Type *PtrTy = cast<PointerType>(Val: Addr->getType()->getScalarType());
1697 // Follow host instrumentation for global and constant addresses.
1698 if (PtrTy->getPointerAddressSpace() != 0)
1699 return InsertBefore;
1700 // Instrument generic addresses in supported addressspaces.
1701 IRBuilder<> IRB(InsertBefore);
1702 Value *IsShared = IRB.CreateCall(Callee: AMDGPUAddressShared, Args: {Addr});
1703 Value *IsPrivate = IRB.CreateCall(Callee: AMDGPUAddressPrivate, Args: {Addr});
1704 Value *IsSharedOrPrivate = IRB.CreateOr(LHS: IsShared, RHS: IsPrivate);
1705 Value *Cmp = IRB.CreateNot(V: IsSharedOrPrivate);
1706 Value *AddrSpaceZeroLanding =
1707 SplitBlockAndInsertIfThen(Cond: Cmp, SplitBefore: InsertBefore, Unreachable: false);
1708 InsertBefore = cast<Instruction>(Val: AddrSpaceZeroLanding);
1709 return InsertBefore;
1710}
1711
1712Instruction *AddressSanitizer::genAMDGPUReportBlock(IRBuilder<> &IRB,
1713 Value *Cond, bool Recover) {
1714 Value *ReportCond = Cond;
1715 if (!Recover) {
1716 auto Ballot = Inserter.insertFunction(Name: kAMDGPUBallotName, Args: IRB.getInt64Ty(),
1717 Args: IRB.getInt1Ty());
1718 ReportCond = IRB.CreateIsNotNull(Arg: IRB.CreateCall(Callee: Ballot, Args: {Cond}));
1719 }
1720
1721 auto *Trm =
1722 SplitBlockAndInsertIfThen(Cond: ReportCond, SplitBefore: &*IRB.GetInsertPoint(), Unreachable: false,
1723 BranchWeights: MDBuilder(*C).createUnlikelyBranchWeights());
1724 Trm->getParent()->setName("asan.report");
1725
1726 if (Recover)
1727 return Trm;
1728
1729 Trm = SplitBlockAndInsertIfThen(Cond, SplitBefore: Trm, Unreachable: false);
1730 IRB.SetInsertPoint(Trm);
1731 return IRB.CreateCall(
1732 Callee: Inserter.insertFunction(Name: kAMDGPUUnreachableName, Args: IRB.getVoidTy()), Args: {});
1733}
1734
1735void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
1736 Instruction *InsertBefore, Value *Addr,
1737 MaybeAlign Alignment,
1738 uint32_t TypeStoreSize, bool IsWrite,
1739 Value *SizeArgument, bool UseCalls,
1740 uint32_t Exp,
1741 RuntimeCallInserter &RTCI) {
1742 if (TargetTriple.isAMDGPU()) {
1743 InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore, Addr,
1744 TypeStoreSize, IsWrite, SizeArgument);
1745 if (!InsertBefore)
1746 return;
1747 }
1748
1749 InstrumentationIRBuilder IRB(InsertBefore);
1750 size_t AccessSizeIndex = TypeStoreSizeToSizeIndex(TypeSize: TypeStoreSize);
1751
1752 if (UseCalls && Opts.asan_optimize_callbacks) {
1753 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1754 IRB.CreateIntrinsic(ID: Intrinsic::asan_check_memaccess, OverloadTypes: {},
1755 Args: {IRB.CreatePointerCast(V: Addr, DestTy: PtrTy),
1756 ConstantInt::get(Ty: Int32Ty, V: AccessInfo.Packed)});
1757 return;
1758 }
1759
1760 Value *AddrLong = IRB.CreatePointerCast(V: Addr, DestTy: IntptrTy);
1761 if (UseCalls) {
1762 if (Exp == 0)
1763 RTCI.createRuntimeCall(
1764 IRB, Callee: AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], Args: AddrLong);
1765 else
1766 RTCI.createRuntimeCall(
1767 IRB, Callee: AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex],
1768 Args: {AddrLong, ConstantInt::get(Ty: IRB.getInt32Ty(), V: Exp)});
1769 return;
1770 }
1771
1772 Type *ShadowTy =
1773 IntegerType::get(C&: *C, NumBits: std::max(a: 8U, b: TypeStoreSize >> Mapping.Scale));
1774 Type *ShadowPtrTy = PointerType::get(C&: *C, AddressSpace: Opts.asan_shadow_addr_space);
1775 Value *ShadowPtr = memToShadow(Shadow: AddrLong, IRB);
1776 const uint64_t ShadowAlign =
1777 std::max<uint64_t>(a: Alignment.valueOrOne().value() >> Mapping.Scale, b: 1);
1778 Value *ShadowValue = IRB.CreateAlignedLoad(
1779 Ty: ShadowTy, Ptr: IRB.CreateIntToPtr(V: ShadowPtr, DestTy: ShadowPtrTy), Align: Align(ShadowAlign));
1780
1781 Value *Cmp = IRB.CreateIsNotNull(Arg: ShadowValue);
1782 size_t Granularity = 1ULL << Mapping.Scale;
1783 Instruction *CrashTerm = nullptr;
1784
1785 bool GenSlowPath =
1786 (Opts.asan_always_slow_path || (TypeStoreSize < 8 * Granularity));
1787
1788 if (TargetTriple.isAMDGCN()) {
1789 if (GenSlowPath) {
1790 auto *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1791 Cmp = IRB.CreateAnd(LHS: Cmp, RHS: Cmp2);
1792 }
1793 CrashTerm = genAMDGPUReportBlock(IRB, Cond: Cmp, Recover);
1794 } else if (GenSlowPath) {
1795 // We use branch weights for the slow path check, to indicate that the slow
1796 // path is rarely taken. This seems to be the case for SPEC benchmarks.
1797 Instruction *CheckTerm = SplitBlockAndInsertIfThen(
1798 Cond: Cmp, SplitBefore: InsertBefore, Unreachable: false, BranchWeights: MDBuilder(*C).createUnlikelyBranchWeights());
1799 BasicBlock *NextBB = cast<UncondBrInst>(Val: CheckTerm)->getSuccessor();
1800 IRB.SetInsertPoint(CheckTerm);
1801 Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1802 if (Recover) {
1803 CrashTerm = SplitBlockAndInsertIfThen(Cond: Cmp2, SplitBefore: CheckTerm, Unreachable: false);
1804 } else {
1805 BasicBlock *CrashBlock =
1806 BasicBlock::Create(Context&: *C, Name: "", Parent: NextBB->getParent(), InsertBefore: NextBB);
1807 CrashTerm = new UnreachableInst(*C, CrashBlock);
1808 CondBrInst *NewTerm = CondBrInst::Create(Cond: Cmp2, IfTrue: CrashBlock, IfFalse: NextBB);
1809 ReplaceInstWithInst(From: CheckTerm, To: NewTerm);
1810 }
1811 } else {
1812 CrashTerm = SplitBlockAndInsertIfThen(Cond: Cmp, SplitBefore: InsertBefore, Unreachable: !Recover);
1813 }
1814
1815 Instruction *Crash = generateCrashCode(
1816 InsertBefore: CrashTerm, Addr: AddrLong, IsWrite, AccessSizeIndex, SizeArgument, Exp, RTCI);
1817 if (OrigIns->getDebugLoc())
1818 Crash->setDebugLoc(OrigIns->getDebugLoc());
1819}
1820
1821// Instrument unusual size or unusual alignment.
1822// We can not do it with a single check, so we do 1-byte check for the first
1823// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
1824// to report the actual access size.
1825void AddressSanitizer::instrumentUnusualSizeOrAlignment(
1826 Instruction *I, Instruction *InsertBefore, Value *Addr,
1827 TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls,
1828 uint32_t Exp, RuntimeCallInserter &RTCI) {
1829 InstrumentationIRBuilder IRB(InsertBefore);
1830 Value *NumBits = IRB.CreateTypeSize(Ty: IntptrTy, Size: TypeStoreSize);
1831 Value *Size = IRB.CreateLShr(LHS: NumBits, RHS: ConstantInt::get(Ty: IntptrTy, V: 3));
1832
1833 Value *AddrLong = IRB.CreatePointerCast(V: Addr, DestTy: IntptrTy);
1834 if (UseCalls) {
1835 if (Exp == 0)
1836 RTCI.createRuntimeCall(IRB, Callee: AsanMemoryAccessCallbackSized[IsWrite][0],
1837 Args: {AddrLong, Size});
1838 else
1839 RTCI.createRuntimeCall(
1840 IRB, Callee: AsanMemoryAccessCallbackSized[IsWrite][1],
1841 Args: {AddrLong, Size, ConstantInt::get(Ty: IRB.getInt32Ty(), V: Exp)});
1842 } else {
1843 Value *SizeMinusOne = IRB.CreateSub(LHS: Size, RHS: ConstantInt::get(Ty: IntptrTy, V: 1));
1844 Value *LastByte = IRB.CreateIntToPtr(
1845 V: IRB.CreateAdd(LHS: AddrLong, RHS: SizeMinusOne),
1846 DestTy: Addr->getType());
1847 instrumentAddress(OrigIns: I, InsertBefore, Addr, Alignment: {}, TypeStoreSize: 8, IsWrite, SizeArgument: Size, UseCalls: false, Exp,
1848 RTCI);
1849 instrumentAddress(OrigIns: I, InsertBefore, Addr: LastByte, Alignment: {}, TypeStoreSize: 8, IsWrite, SizeArgument: Size, UseCalls: false,
1850 Exp, RTCI);
1851 }
1852}
1853
1854void ModuleAddressSanitizer::poisonOneInitializer(Function &GlobalInit) {
1855 // Set up the arguments to our poison/unpoison functions.
1856 IRBuilder<> IRB(GlobalInit.front().getFirstInsertionPt());
1857
1858 // Add a call to poison all external globals before the given function starts.
1859 Value *ModuleNameAddr =
1860 ConstantExpr::getPointerCast(C: getOrCreateModuleName(), Ty: IntptrTy);
1861 CallInst *CallBefore = IRB.CreateCall(Callee: AsanPoisonGlobals, Args: ModuleNameAddr);
1862 if (DISubprogram *SP = GlobalInit.getSubprogram())
1863 CallBefore->setDebugLoc(
1864 DILocation::get(Context&: SP->getContext(), Line: SP->getScopeLine(), Column: 0, Scope: SP));
1865
1866 // Add calls to unpoison all globals before each return instruction.
1867 for (auto &BB : GlobalInit)
1868 if (ReturnInst *RI = dyn_cast<ReturnInst>(Val: BB.getTerminator())) {
1869 CallInst *CallAfter =
1870 CallInst::Create(Func: AsanUnpoisonGlobals, NameStr: "", InsertBefore: RI->getIterator());
1871 if (RI->getDebugLoc())
1872 CallAfter->setDebugLoc(RI->getDebugLoc());
1873 else if (DISubprogram *SP = GlobalInit.getSubprogram())
1874 CallAfter->setDebugLoc(
1875 DILocation::get(Context&: SP->getContext(), Line: SP->getScopeLine(), Column: 0, Scope: SP));
1876 }
1877}
1878
1879void ModuleAddressSanitizer::createInitializerPoisonCalls() {
1880 GlobalVariable *GV = M.getGlobalVariable(Name: "llvm.global_ctors");
1881 if (!GV)
1882 return;
1883
1884 ConstantArray *CA = dyn_cast<ConstantArray>(Val: GV->getInitializer());
1885 if (!CA)
1886 return;
1887
1888 for (Use &OP : CA->operands()) {
1889 if (isa<ConstantAggregateZero>(Val: OP)) continue;
1890 ConstantStruct *CS = cast<ConstantStruct>(Val&: OP);
1891
1892 // Must have a function or null ptr.
1893 if (Function *F = dyn_cast<Function>(Val: CS->getOperand(i_nocapture: 1))) {
1894 if (F->getName() == kAsanModuleCtorName) continue;
1895 auto *Priority = cast<ConstantInt>(Val: CS->getOperand(i_nocapture: 0));
1896 // Don't instrument CTORs that will run before asan.module_ctor.
1897 if (Priority->getLimitedValue() <= GetCtorAndDtorPriority(TargetTriple))
1898 continue;
1899 poisonOneInitializer(GlobalInit&: *F);
1900 }
1901 }
1902}
1903
1904const GlobalVariable *
1905ModuleAddressSanitizer::getExcludedAliasedGlobal(const GlobalAlias &GA) const {
1906 // In case this function should be expanded to include rules that do not just
1907 // apply when CompileKernel is true, either guard all existing rules with an
1908 // 'if (CompileKernel) { ... }' or be absolutely sure that all these rules
1909 // should also apply to user space.
1910 assert(CompileKernel && "Only expecting to be called when compiling kernel");
1911
1912 const Constant *C = GA.getAliasee();
1913
1914 // When compiling the kernel, globals that are aliased by symbols prefixed
1915 // by "__" are special and cannot be padded with a redzone.
1916 if (GA.getName().starts_with(Prefix: "__"))
1917 return dyn_cast<GlobalVariable>(Val: C->stripPointerCastsAndAliases());
1918
1919 return nullptr;
1920}
1921
1922bool ModuleAddressSanitizer::shouldInstrumentGlobal(GlobalVariable *G) const {
1923 Type *Ty = G->getValueType();
1924 LLVM_DEBUG(dbgs() << "GLOBAL: " << *G << "\n");
1925
1926 if (G->hasSanitizerMetadata() && G->getSanitizerMetadata().NoAddress)
1927 return false;
1928 if (!Ty->isSized()) return false;
1929 if (!G->hasInitializer()) return false;
1930 if (!isSupportedAddrspace(Opts, TargetTriple, Addr: G))
1931 return false;
1932 if (GlobalWasGeneratedByCompiler(G)) return false; // Our own globals.
1933 // Two problems with thread-locals:
1934 // - The address of the main thread's copy can't be computed at link-time.
1935 // - Need to poison all copies, not just the main thread's one.
1936 if (G->isThreadLocal()) return false;
1937 // For now, just ignore this Global if the alignment is large.
1938 if (G->getAlign() && *G->getAlign() > getMinRedzoneSizeForGlobal()) return false;
1939
1940 // For non-COFF targets, only instrument globals known to be defined by this
1941 // TU.
1942 // FIXME: We can instrument comdat globals on ELF if we are using the
1943 // GC-friendly metadata scheme.
1944 if (!TargetTriple.isOSBinFormatCOFF()) {
1945 if (!G->hasExactDefinition() || G->hasComdat())
1946 return false;
1947 } else {
1948 // On COFF, don't instrument non-ODR linkages.
1949 if (G->isInterposable())
1950 return false;
1951 // If the global has AvailableExternally linkage, then it is not in this
1952 // module, which means it does not need to be instrumented.
1953 if (G->hasAvailableExternallyLinkage())
1954 return false;
1955 }
1956
1957 // If a comdat is present, it must have a selection kind that implies ODR
1958 // semantics: no duplicates, any, or exact match.
1959 if (Comdat *C = G->getComdat()) {
1960 switch (C->getSelectionKind()) {
1961 case Comdat::Any:
1962 case Comdat::ExactMatch:
1963 case Comdat::NoDeduplicate:
1964 break;
1965 case Comdat::Largest:
1966 case Comdat::SameSize:
1967 return false;
1968 }
1969 }
1970
1971 if (G->hasSection()) {
1972 // The kernel uses explicit sections for mostly special global variables
1973 // that we should not instrument. E.g. the kernel may rely on their layout
1974 // without redzones, or remove them at link time ("discard.*"), etc.
1975 if (CompileKernel)
1976 return false;
1977
1978 StringRef Section = G->getSection();
1979
1980 // Globals from llvm.metadata aren't emitted, do not instrument them.
1981 if (Section == "llvm.metadata") return false;
1982 // Do not instrument globals from special LLVM sections.
1983 if (Section.contains(Other: "__llvm") || Section.contains(Other: "__LLVM"))
1984 return false;
1985
1986 // Do not instrument function pointers to initialization and termination
1987 // routines: dynamic linker will not properly handle redzones.
1988 if (Section.starts_with(Prefix: ".preinit_array") ||
1989 Section.starts_with(Prefix: ".init_array") ||
1990 Section.starts_with(Prefix: ".fini_array")) {
1991 return false;
1992 }
1993
1994 // Do not instrument user-defined sections (with names resembling
1995 // valid C identifiers)
1996 if (TargetTriple.isOSBinFormatELF()) {
1997 if (llvm::all_of(Range&: Section,
1998 P: [](char c) { return llvm::isAlnum(C: c) || c == '_'; }))
1999 return false;
2000 }
2001
2002 // On COFF, if the section name contains '$', it is highly likely that the
2003 // user is using section sorting to create an array of globals similar to
2004 // the way initialization callbacks are registered in .init_array and
2005 // .CRT$XCU. The ATL also registers things in .ATL$__[azm]. Adding redzones
2006 // to such globals is counterproductive, because the intent is that they
2007 // will form an array, and out-of-bounds accesses are expected.
2008 // See https://github.com/google/sanitizers/issues/305
2009 // and http://msdn.microsoft.com/en-US/en-en/library/bb918180(v=vs.120).aspx
2010 if (TargetTriple.isOSBinFormatCOFF() && Section.contains(C: '$')) {
2011 LLVM_DEBUG(dbgs() << "Ignoring global in sorted section (contains '$'): "
2012 << *G << "\n");
2013 return false;
2014 }
2015
2016 if (TargetTriple.isOSBinFormatMachO()) {
2017 StringRef ParsedSegment, ParsedSection;
2018 unsigned TAA = 0, StubSize = 0;
2019 bool TAAParsed;
2020 cantFail(Err: MCSectionMachO::ParseSectionSpecifier(
2021 Spec: Section, Segment&: ParsedSegment, Section&: ParsedSection, TAA, TAAParsed, StubSize));
2022
2023 // Ignore the globals from the __OBJC section. The ObjC runtime assumes
2024 // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to
2025 // them.
2026 if (ParsedSegment == "__OBJC" ||
2027 (ParsedSegment == "__DATA" && ParsedSection.starts_with(Prefix: "__objc_"))) {
2028 LLVM_DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G << "\n");
2029 return false;
2030 }
2031 // See https://github.com/google/sanitizers/issues/32
2032 // Constant CFString instances are compiled in the following way:
2033 // -- the string buffer is emitted into
2034 // __TEXT,__cstring,cstring_literals
2035 // -- the constant NSConstantString structure referencing that buffer
2036 // is placed into __DATA,__cfstring
2037 // Therefore there's no point in placing redzones into __DATA,__cfstring.
2038 // Moreover, it causes the linker to crash on OS X 10.7
2039 if (ParsedSegment == "__DATA" && ParsedSection == "__cfstring") {
2040 LLVM_DEBUG(dbgs() << "Ignoring CFString: " << *G << "\n");
2041 return false;
2042 }
2043 // The linker merges the contents of cstring_literals and removes the
2044 // trailing zeroes.
2045 if (ParsedSegment == "__TEXT" && (TAA & MachO::S_CSTRING_LITERALS)) {
2046 LLVM_DEBUG(dbgs() << "Ignoring a cstring literal: " << *G << "\n");
2047 return false;
2048 }
2049 }
2050 }
2051
2052 if (CompileKernel) {
2053 // Globals that prefixed by "__" are special and cannot be padded with a
2054 // redzone.
2055 if (G->getName().starts_with(Prefix: "__"))
2056 return false;
2057 }
2058
2059 return true;
2060}
2061
2062// On Mach-O platforms, we emit global metadata in a separate section of the
2063// binary in order to allow the linker to properly dead strip. This is only
2064// supported on recent versions of ld64.
2065bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection() const {
2066 if (!TargetTriple.isOSBinFormatMachO())
2067 return false;
2068
2069 if (TargetTriple.isMacOSX() && !TargetTriple.isMacOSXVersionLT(Major: 10, Minor: 11))
2070 return true;
2071 if (TargetTriple.isiOS() /* or tvOS */ && !TargetTriple.isOSVersionLT(Major: 9))
2072 return true;
2073 if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(Major: 2))
2074 return true;
2075 if (TargetTriple.isDriverKit())
2076 return true;
2077 if (TargetTriple.isXROS())
2078 return true;
2079
2080 return false;
2081}
2082
2083StringRef ModuleAddressSanitizer::getGlobalMetadataSection() const {
2084 switch (TargetTriple.getObjectFormat()) {
2085 case Triple::COFF: return ".ASAN$GL";
2086 case Triple::ELF: return "asan_globals";
2087 case Triple::MachO: return "__DATA,__asan_globals,regular";
2088 case Triple::Wasm:
2089 case Triple::GOFF:
2090 case Triple::SPIRV:
2091 case Triple::XCOFF:
2092 case Triple::DXContainer:
2093 report_fatal_error(
2094 reason: "ModuleAddressSanitizer not implemented for object file format");
2095 case Triple::UnknownObjectFormat:
2096 break;
2097 }
2098 llvm_unreachable("unsupported object format");
2099}
2100
2101void ModuleAddressSanitizer::initializeCallbacks() {
2102 IRBuilder<> IRB(M);
2103
2104 // Declare our poisoning and unpoisoning functions.
2105 AsanPoisonGlobals = Inserter.insertFunction(Name: kAsanPoisonGlobalsName,
2106 Args: IRB.getVoidTy(), Args&: IntptrTy);
2107 AsanUnpoisonGlobals =
2108 Inserter.insertFunction(Name: kAsanUnpoisonGlobalsName, Args: IRB.getVoidTy());
2109
2110 // Declare functions that register/unregister globals.
2111 AsanRegisterGlobals = Inserter.insertFunction(
2112 Name: kAsanRegisterGlobalsName, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
2113 AsanUnregisterGlobals = Inserter.insertFunction(
2114 Name: kAsanUnregisterGlobalsName, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
2115
2116 // Declare the functions that find globals in a shared object and then invoke
2117 // the (un)register function on them.
2118 AsanRegisterImageGlobals = Inserter.insertFunction(
2119 Name: kAsanRegisterImageGlobalsName, Args: IRB.getVoidTy(), Args&: IntptrTy);
2120 AsanUnregisterImageGlobals = Inserter.insertFunction(
2121 Name: kAsanUnregisterImageGlobalsName, Args: IRB.getVoidTy(), Args&: IntptrTy);
2122
2123 AsanRegisterElfGlobals =
2124 Inserter.insertFunction(Name: kAsanRegisterElfGlobalsName, Args: IRB.getVoidTy(),
2125 Args&: IntptrTy, Args&: IntptrTy, Args&: IntptrTy);
2126 AsanUnregisterElfGlobals =
2127 Inserter.insertFunction(Name: kAsanUnregisterElfGlobalsName, Args: IRB.getVoidTy(),
2128 Args&: IntptrTy, Args&: IntptrTy, Args&: IntptrTy);
2129}
2130
2131// Put the metadata and the instrumented global in the same group. This ensures
2132// that the metadata is discarded if the instrumented global is discarded.
2133void ModuleAddressSanitizer::SetComdatForGlobalMetadata(
2134 GlobalVariable *G, GlobalVariable *Metadata, StringRef InternalSuffix) {
2135 Module &M = *G->getParent();
2136 Comdat *C = G->getComdat();
2137 if (!C) {
2138 if (!G->hasName()) {
2139 // If G is unnamed, it must be internal. Give it an artificial name
2140 // so we can put it in a comdat.
2141 assert(G->hasLocalLinkage());
2142 G->setName(genName(suffix: "anon_global"));
2143 }
2144
2145 if (!InternalSuffix.empty() && G->hasLocalLinkage()) {
2146 std::string Name = std::string(G->getName());
2147 Name += InternalSuffix;
2148 C = M.getOrInsertComdat(Name);
2149 } else {
2150 C = M.getOrInsertComdat(Name: G->getName());
2151 }
2152
2153 // Make this IMAGE_COMDAT_SELECT_NODUPLICATES on COFF. Also upgrade private
2154 // linkage to internal linkage so that a symbol table entry is emitted. This
2155 // is necessary in order to create the comdat group.
2156 if (TargetTriple.isOSBinFormatCOFF()) {
2157 C->setSelectionKind(Comdat::NoDeduplicate);
2158 if (G->hasPrivateLinkage())
2159 G->setLinkage(GlobalValue::InternalLinkage);
2160 }
2161 G->setComdat(C);
2162 }
2163
2164 assert(G->hasComdat());
2165 Metadata->setComdat(G->getComdat());
2166}
2167
2168// Create a separate metadata global and put it in the appropriate ASan
2169// global registration section.
2170GlobalVariable *
2171ModuleAddressSanitizer::CreateMetadataGlobal(Constant *Initializer,
2172 StringRef OriginalName) {
2173 auto Linkage = TargetTriple.isOSBinFormatMachO()
2174 ? GlobalVariable::InternalLinkage
2175 : GlobalVariable::PrivateLinkage;
2176 GlobalVariable *Metadata = new GlobalVariable(
2177 M, Initializer->getType(), false, Linkage, Initializer,
2178 Twine("__asan_global_") + GlobalValue::dropLLVMManglingEscape(Name: OriginalName));
2179 Metadata->setSection(getGlobalMetadataSection());
2180 // Place metadata in a large section for x86-64 ELF binaries to mitigate
2181 // relocation pressure.
2182 setGlobalVariableLargeSection(TargetTriple, GV&: *Metadata);
2183 return Metadata;
2184}
2185
2186Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor() {
2187 AsanDtorFunction = Function::createWithDefaultAttr(
2188 Ty: FunctionType::get(Result: Type::getVoidTy(C&: *C), isVarArg: false),
2189 Linkage: GlobalValue::InternalLinkage, AddrSpace: 0, N: kAsanModuleDtorName, M: &M);
2190 AsanDtorFunction->addFnAttr(Kind: Attribute::NoUnwind);
2191 // Ensure Dtor cannot be discarded, even if in a comdat.
2192 appendToUsed(M, Values: {AsanDtorFunction});
2193 BasicBlock *AsanDtorBB = BasicBlock::Create(Context&: *C, Name: "", Parent: AsanDtorFunction);
2194
2195 return ReturnInst::Create(C&: *C, InsertAtEnd: AsanDtorBB);
2196}
2197
2198void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
2199 IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
2200 ArrayRef<Constant *> MetadataInitializers) {
2201 assert(ExtendedGlobals.size() == MetadataInitializers.size());
2202 auto &DL = M.getDataLayout();
2203
2204 SmallVector<GlobalValue *, 16> MetadataGlobals(ExtendedGlobals.size());
2205 for (size_t i = 0; i < ExtendedGlobals.size(); i++) {
2206 Constant *Initializer = MetadataInitializers[i];
2207 GlobalVariable *G = ExtendedGlobals[i];
2208 GlobalVariable *Metadata = CreateMetadataGlobal(Initializer, OriginalName: G->getName());
2209 MDNode *MD = MDNode::get(Context&: M.getContext(), MDs: ValueAsMetadata::get(V: G));
2210 Metadata->setMetadata(KindID: LLVMContext::MD_associated, Node: MD);
2211 MetadataGlobals[i] = Metadata;
2212
2213 // The MSVC linker always inserts padding when linking incrementally. We
2214 // cope with that by aligning each struct to its size, which must be a power
2215 // of two.
2216 unsigned SizeOfGlobalStruct = DL.getTypeAllocSize(Ty: Initializer->getType());
2217 assert(isPowerOf2_32(SizeOfGlobalStruct) &&
2218 "global metadata will not be padded appropriately");
2219 Metadata->setAlignment(assumeAligned(Value: SizeOfGlobalStruct));
2220
2221 SetComdatForGlobalMetadata(G, Metadata, InternalSuffix: "");
2222 }
2223
2224 // Update llvm.compiler.used, adding the new metadata globals. This is
2225 // needed so that during LTO these variables stay alive.
2226 if (!MetadataGlobals.empty())
2227 appendToCompilerUsed(M, Values: MetadataGlobals);
2228}
2229
2230void ModuleAddressSanitizer::instrumentGlobalsELF(
2231 IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
2232 ArrayRef<Constant *> MetadataInitializers,
2233 const std::string &UniqueModuleId) {
2234 assert(ExtendedGlobals.size() == MetadataInitializers.size());
2235
2236 // Putting globals in a comdat changes the semantic and potentially cause
2237 // false negative odr violations at link time. If odr indicators are used, we
2238 // keep the comdat sections, as link time odr violations will be detected on
2239 // the odr indicator symbols.
2240 bool UseComdatForGlobalsGC = UseOdrIndicator && !UniqueModuleId.empty();
2241
2242 SmallVector<GlobalValue *, 16> MetadataGlobals(ExtendedGlobals.size());
2243 for (size_t i = 0; i < ExtendedGlobals.size(); i++) {
2244 GlobalVariable *G = ExtendedGlobals[i];
2245 GlobalVariable *Metadata =
2246 CreateMetadataGlobal(Initializer: MetadataInitializers[i], OriginalName: G->getName());
2247 MDNode *MD = MDNode::get(Context&: M.getContext(), MDs: ValueAsMetadata::get(V: G));
2248 Metadata->setMetadata(KindID: LLVMContext::MD_associated, Node: MD);
2249 MetadataGlobals[i] = Metadata;
2250
2251 if (UseComdatForGlobalsGC)
2252 SetComdatForGlobalMetadata(G, Metadata, InternalSuffix: UniqueModuleId);
2253 }
2254
2255 // Update llvm.compiler.used, adding the new metadata globals. This is
2256 // needed so that during LTO these variables stay alive.
2257 if (!MetadataGlobals.empty())
2258 appendToCompilerUsed(M, Values: MetadataGlobals);
2259
2260 // RegisteredFlag serves two purposes. First, we can pass it to dladdr()
2261 // to look up the loaded image that contains it. Second, we can store in it
2262 // whether registration has already occurred, to prevent duplicate
2263 // registration.
2264 //
2265 // Common linkage ensures that there is only one global per shared library.
2266 GlobalVariable *RegisteredFlag = new GlobalVariable(
2267 M, IntptrTy, false, GlobalVariable::CommonLinkage,
2268 ConstantInt::get(Ty: IntptrTy, V: 0), kAsanGlobalsRegisteredFlagName);
2269 RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
2270
2271 // Create start and stop symbols.
2272 GlobalVariable *StartELFMetadata = new GlobalVariable(
2273 M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr,
2274 "__start_" + getGlobalMetadataSection());
2275 StartELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
2276 GlobalVariable *StopELFMetadata = new GlobalVariable(
2277 M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr,
2278 "__stop_" + getGlobalMetadataSection());
2279 StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
2280
2281 // Create a call to register the globals with the runtime.
2282 if (ConstructorKind == AsanCtorKind::Global)
2283 IRB.CreateCall(Callee: AsanRegisterElfGlobals,
2284 Args: {IRB.CreatePointerCast(V: RegisteredFlag, DestTy: IntptrTy),
2285 IRB.CreatePointerCast(V: StartELFMetadata, DestTy: IntptrTy),
2286 IRB.CreatePointerCast(V: StopELFMetadata, DestTy: IntptrTy)});
2287
2288 // We also need to unregister globals at the end, e.g., when a shared library
2289 // gets closed.
2290 if (DestructorKind != AsanDtorKind::None && !MetadataGlobals.empty()) {
2291 IRBuilder<> IrbDtor(CreateAsanModuleDtor());
2292 IrbDtor.CreateCall(Callee: AsanUnregisterElfGlobals,
2293 Args: {IRB.CreatePointerCast(V: RegisteredFlag, DestTy: IntptrTy),
2294 IRB.CreatePointerCast(V: StartELFMetadata, DestTy: IntptrTy),
2295 IRB.CreatePointerCast(V: StopELFMetadata, DestTy: IntptrTy)});
2296 }
2297}
2298
2299void ModuleAddressSanitizer::InstrumentGlobalsMachO(
2300 IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
2301 ArrayRef<Constant *> MetadataInitializers) {
2302 assert(ExtendedGlobals.size() == MetadataInitializers.size());
2303
2304 // On recent Mach-O platforms, use a structure which binds the liveness of
2305 // the global variable to the metadata struct. Keep the list of "Liveness" GV
2306 // created to be added to llvm.compiler.used
2307 StructType *LivenessTy = StructType::get(elt1: IntptrTy, elts: IntptrTy);
2308 SmallVector<GlobalValue *, 16> LivenessGlobals(ExtendedGlobals.size());
2309
2310 for (size_t i = 0; i < ExtendedGlobals.size(); i++) {
2311 Constant *Initializer = MetadataInitializers[i];
2312 GlobalVariable *G = ExtendedGlobals[i];
2313 GlobalVariable *Metadata = CreateMetadataGlobal(Initializer, OriginalName: G->getName());
2314
2315 // On recent Mach-O platforms, we emit the global metadata in a way that
2316 // allows the linker to properly strip dead globals.
2317 auto LivenessBinder =
2318 ConstantStruct::get(T: LivenessTy, Vs: Initializer->getAggregateElement(Elt: 0u),
2319 Vs: ConstantExpr::getPointerCast(C: Metadata, Ty: IntptrTy));
2320 GlobalVariable *Liveness = new GlobalVariable(
2321 M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder,
2322 Twine("__asan_binder_") + G->getName());
2323 Liveness->setSection("__DATA,__asan_liveness,regular,live_support");
2324 LivenessGlobals[i] = Liveness;
2325 }
2326
2327 // Update llvm.compiler.used, adding the new liveness globals. This is
2328 // needed so that during LTO these variables stay alive. The alternative
2329 // would be to have the linker handling the LTO symbols, but libLTO
2330 // current API does not expose access to the section for each symbol.
2331 if (!LivenessGlobals.empty())
2332 appendToCompilerUsed(M, Values: LivenessGlobals);
2333
2334 // RegisteredFlag serves two purposes. First, we can pass it to dladdr()
2335 // to look up the loaded image that contains it. Second, we can store in it
2336 // whether registration has already occurred, to prevent duplicate
2337 // registration.
2338 //
2339 // common linkage ensures that there is only one global per shared library.
2340 GlobalVariable *RegisteredFlag = new GlobalVariable(
2341 M, IntptrTy, false, GlobalVariable::CommonLinkage,
2342 ConstantInt::get(Ty: IntptrTy, V: 0), kAsanGlobalsRegisteredFlagName);
2343 RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
2344
2345 if (ConstructorKind == AsanCtorKind::Global)
2346 IRB.CreateCall(Callee: AsanRegisterImageGlobals,
2347 Args: {IRB.CreatePointerCast(V: RegisteredFlag, DestTy: IntptrTy)});
2348
2349 // We also need to unregister globals at the end, e.g., when a shared library
2350 // gets closed.
2351 if (DestructorKind != AsanDtorKind::None) {
2352 IRBuilder<> IrbDtor(CreateAsanModuleDtor());
2353 IrbDtor.CreateCall(Callee: AsanUnregisterImageGlobals,
2354 Args: {IRB.CreatePointerCast(V: RegisteredFlag, DestTy: IntptrTy)});
2355 }
2356}
2357
2358void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
2359 IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
2360 ArrayRef<Constant *> MetadataInitializers) {
2361 assert(ExtendedGlobals.size() == MetadataInitializers.size());
2362 unsigned N = ExtendedGlobals.size();
2363 assert(N > 0);
2364
2365 // On platforms that don't have a custom metadata section, we emit an array
2366 // of global metadata structures.
2367 ArrayType *ArrayOfGlobalStructTy =
2368 ArrayType::get(ElementType: MetadataInitializers[0]->getType(), NumElements: N);
2369 auto AllGlobals = new GlobalVariable(
2370 M, ArrayOfGlobalStructTy, false, GlobalVariable::InternalLinkage,
2371 ConstantArray::get(T: ArrayOfGlobalStructTy, V: MetadataInitializers), "");
2372 if (Mapping.Scale > 3)
2373 AllGlobals->setAlignment(Align::fromLog2(Log2Value: Mapping.Scale));
2374
2375 if (ConstructorKind == AsanCtorKind::Global)
2376 IRB.CreateCall(Callee: AsanRegisterGlobals,
2377 Args: {IRB.CreatePointerCast(V: AllGlobals, DestTy: IntptrTy),
2378 ConstantInt::get(Ty: IntptrTy, V: N)});
2379
2380 // We also need to unregister globals at the end, e.g., when a shared library
2381 // gets closed.
2382 if (DestructorKind != AsanDtorKind::None) {
2383 IRBuilder<> IrbDtor(CreateAsanModuleDtor());
2384 IrbDtor.CreateCall(Callee: AsanUnregisterGlobals,
2385 Args: {IRB.CreatePointerCast(V: AllGlobals, DestTy: IntptrTy),
2386 ConstantInt::get(Ty: IntptrTy, V: N)});
2387 }
2388}
2389
2390// This function replaces all global variables with new variables that have
2391// trailing redzones. It also creates a function that poisons
2392// redzones and inserts this function into llvm.global_ctors.
2393// Sets *CtorComdat to true if the global registration code emitted into the
2394// asan constructor is comdat-compatible.
2395void ModuleAddressSanitizer::instrumentGlobals(IRBuilder<> &IRB,
2396 bool *CtorComdat) {
2397 // Build set of globals that are aliased by some GA, where
2398 // getExcludedAliasedGlobal(GA) returns the relevant GlobalVariable.
2399 SmallPtrSet<const GlobalVariable *, 16> AliasedGlobalExclusions;
2400 if (CompileKernel) {
2401 for (auto &GA : M.aliases()) {
2402 if (const GlobalVariable *GV = getExcludedAliasedGlobal(GA))
2403 AliasedGlobalExclusions.insert(Ptr: GV);
2404 }
2405 }
2406
2407 SmallVector<GlobalVariable *, 16> GlobalsToChange;
2408 for (auto &G : M.globals()) {
2409 if (!AliasedGlobalExclusions.count(Ptr: &G) && shouldInstrumentGlobal(G: &G))
2410 GlobalsToChange.push_back(Elt: &G);
2411 }
2412
2413 size_t n = GlobalsToChange.size();
2414 auto &DL = M.getDataLayout();
2415
2416 // A global is described by a structure
2417 // size_t beg;
2418 // size_t size;
2419 // size_t size_with_redzone;
2420 // const char *name;
2421 // const char *module_name;
2422 // size_t has_dynamic_init;
2423 // size_t padding_for_windows_msvc_incremental_link;
2424 // size_t odr_indicator;
2425 // We initialize an array of such structures and pass it to a run-time call.
2426 StructType *GlobalStructTy =
2427 StructType::get(elt1: IntptrTy, elts: IntptrTy, elts: IntptrTy, elts: IntptrTy, elts: IntptrTy,
2428 elts: IntptrTy, elts: IntptrTy, elts: IntptrTy);
2429 SmallVector<GlobalVariable *, 16> NewGlobals(n);
2430 SmallVector<Constant *, 16> Initializers(n);
2431
2432 for (size_t i = 0; i < n; i++) {
2433 GlobalVariable *G = GlobalsToChange[i];
2434
2435 GlobalValue::SanitizerMetadata MD;
2436 if (G->hasSanitizerMetadata())
2437 MD = G->getSanitizerMetadata();
2438
2439 // The runtime library tries demangling symbol names in the descriptor but
2440 // functionality like __cxa_demangle may be unavailable (e.g.
2441 // -static-libstdc++). So we demangle the symbol names here.
2442 std::string NameForGlobal = G->getName().str();
2443 GlobalVariable *Name =
2444 createPrivateGlobalForString(M, Str: llvm::demangle(MangledName: NameForGlobal),
2445 /*AllowMerging*/ true, NamePrefix: genName(suffix: "global"));
2446
2447 Type *Ty = G->getValueType();
2448 const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty);
2449 const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes);
2450 Type *RightRedZoneTy = ArrayType::get(ElementType: IRB.getInt8Ty(), NumElements: RightRedzoneSize);
2451
2452 StructType *NewTy = StructType::get(elt1: Ty, elts: RightRedZoneTy);
2453 Constant *NewInitializer = ConstantStruct::get(
2454 T: NewTy, Vs: G->getInitializer(), Vs: Constant::getNullValue(Ty: RightRedZoneTy));
2455
2456 // Create a new global variable with enough space for a redzone.
2457 GlobalValue::LinkageTypes Linkage = G->getLinkage();
2458 if (G->isConstant() && Linkage == GlobalValue::PrivateLinkage)
2459 Linkage = GlobalValue::InternalLinkage;
2460 GlobalVariable *NewGlobal = new GlobalVariable(
2461 M, NewTy, G->isConstant(), Linkage, NewInitializer, "", G,
2462 G->getThreadLocalMode(), G->getAddressSpace());
2463 NewGlobal->copyAttributesFrom(Src: G);
2464 NewGlobal->setComdat(G->getComdat());
2465 NewGlobal->setAlignment(Align(getMinRedzoneSizeForGlobal()));
2466 // Don't fold globals with redzones. ODR violation detector and redzone
2467 // poisoning implicitly creates a dependence on the global's address, so it
2468 // is no longer valid for it to be marked unnamed_addr.
2469 NewGlobal->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
2470
2471 // Move null-terminated C strings to "__asan_cstring" section on Darwin.
2472 if (TargetTriple.isOSBinFormatMachO() && !G->hasSection() &&
2473 G->isConstant()) {
2474 auto Seq = dyn_cast<ConstantDataSequential>(Val: G->getInitializer());
2475 if (Seq && Seq->isCString())
2476 NewGlobal->setSection("__TEXT,__asan_cstring,regular");
2477 }
2478
2479 // Transfer the debug info and type metadata. The payload starts at offset
2480 // zero so we can copy the metadata over as is.
2481 NewGlobal->copyMetadata(Src: G, Offset: 0);
2482
2483 G->replaceAllUsesWith(V: NewGlobal);
2484 NewGlobal->takeName(V: G);
2485 G->eraseFromParent();
2486 NewGlobals[i] = NewGlobal;
2487
2488 Constant *ODRIndicator = Constant::getNullValue(Ty: IntptrTy);
2489 GlobalValue *InstrumentedGlobal = NewGlobal;
2490
2491 bool CanUsePrivateAliases =
2492 TargetTriple.isOSBinFormatELF() || TargetTriple.isOSBinFormatMachO() ||
2493 TargetTriple.isOSBinFormatWasm();
2494 if (CanUsePrivateAliases && UsePrivateAlias) {
2495 // Create local alias for NewGlobal to avoid crash on ODR between
2496 // instrumented and non-instrumented libraries.
2497 InstrumentedGlobal =
2498 GlobalAlias::create(Linkage: GlobalValue::PrivateLinkage, Name: "", Aliasee: NewGlobal);
2499 }
2500
2501 // ODR should not happen for local linkage.
2502 if (NewGlobal->hasLocalLinkage()) {
2503 ODRIndicator = ConstantInt::getAllOnesValue(Ty: IntptrTy);
2504 } else if (UseOdrIndicator) {
2505 // With local aliases, we need to provide another externally visible
2506 // symbol __odr_asan_XXX to detect ODR violation.
2507 auto *ODRIndicatorSym =
2508 new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage,
2509 Constant::getNullValue(Ty: IRB.getInt8Ty()),
2510 kODRGenPrefix + NameForGlobal, nullptr,
2511 NewGlobal->getThreadLocalMode());
2512
2513 // Set meaningful attributes for indicator symbol.
2514 ODRIndicatorSym->setVisibility(NewGlobal->getVisibility());
2515 ODRIndicatorSym->setDLLStorageClass(NewGlobal->getDLLStorageClass());
2516 ODRIndicatorSym->setAlignment(Align(1));
2517 ODRIndicator = ConstantExpr::getPtrToInt(C: ODRIndicatorSym, Ty: IntptrTy);
2518 }
2519
2520 Constant *Initializer = ConstantStruct::get(
2521 T: GlobalStructTy,
2522 Vs: ConstantExpr::getPointerCast(C: InstrumentedGlobal, Ty: IntptrTy),
2523 Vs: ConstantInt::get(Ty: IntptrTy, V: SizeInBytes),
2524 Vs: ConstantInt::get(Ty: IntptrTy, V: SizeInBytes + RightRedzoneSize),
2525 Vs: ConstantExpr::getPointerCast(C: Name, Ty: IntptrTy),
2526 Vs: ConstantExpr::getPointerCast(C: getOrCreateModuleName(), Ty: IntptrTy),
2527 Vs: ConstantInt::get(Ty: IntptrTy, V: MD.IsDynInit),
2528 Vs: Constant::getNullValue(Ty: IntptrTy), Vs: ODRIndicator);
2529
2530 LLVM_DEBUG(dbgs() << "NEW GLOBAL: " << *NewGlobal << "\n");
2531
2532 Initializers[i] = Initializer;
2533 }
2534
2535 // Add instrumented globals to llvm.compiler.used list to avoid LTO from
2536 // ConstantMerge'ing them.
2537 SmallVector<GlobalValue *, 16> GlobalsToAddToUsedList;
2538 for (size_t i = 0; i < n; i++) {
2539 GlobalVariable *G = NewGlobals[i];
2540 if (G->getName().empty()) continue;
2541 GlobalsToAddToUsedList.push_back(Elt: G);
2542 }
2543 appendToCompilerUsed(M, Values: ArrayRef<GlobalValue *>(GlobalsToAddToUsedList));
2544
2545 if (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) {
2546 // Use COMDAT and register globals even if n == 0 to ensure that (a) the
2547 // linkage unit will only have one module constructor, and (b) the register
2548 // function will be called. The module destructor is not created when n ==
2549 // 0.
2550 *CtorComdat = true;
2551 instrumentGlobalsELF(IRB, ExtendedGlobals: NewGlobals, MetadataInitializers: Initializers, UniqueModuleId: getUniqueModuleId(M: &M));
2552 } else if (n == 0) {
2553 // When UseGlobalsGC is false, COMDAT can still be used if n == 0, because
2554 // all compile units will have identical module constructor/destructor.
2555 *CtorComdat = TargetTriple.isOSBinFormatELF();
2556 } else {
2557 *CtorComdat = false;
2558 if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) {
2559 InstrumentGlobalsCOFF(IRB, ExtendedGlobals: NewGlobals, MetadataInitializers: Initializers);
2560 } else if (UseGlobalsGC && ShouldUseMachOGlobalsSection()) {
2561 InstrumentGlobalsMachO(IRB, ExtendedGlobals: NewGlobals, MetadataInitializers: Initializers);
2562 } else {
2563 InstrumentGlobalsWithMetadataArray(IRB, ExtendedGlobals: NewGlobals, MetadataInitializers: Initializers);
2564 }
2565 }
2566
2567 // Create calls for poisoning before initializers run and unpoisoning after.
2568 if (Opts.asan_initialization_order)
2569 createInitializerPoisonCalls();
2570
2571 LLVM_DEBUG(dbgs() << M);
2572}
2573
2574uint64_t
2575ModuleAddressSanitizer::getRedzoneSizeForGlobal(uint64_t SizeInBytes) const {
2576 constexpr uint64_t kMaxRZ = 1 << 18;
2577 const uint64_t MinRZ = getMinRedzoneSizeForGlobal();
2578
2579 uint64_t RZ = 0;
2580 if (SizeInBytes <= MinRZ / 2) {
2581 // Reduce redzone size for small size objects, e.g. int, char[1]. MinRZ is
2582 // at least 32 bytes, optimize when SizeInBytes is less than or equal to
2583 // half of MinRZ.
2584 RZ = MinRZ - SizeInBytes;
2585 } else {
2586 // Calculate RZ, where MinRZ <= RZ <= MaxRZ, and RZ ~ 1/4 * SizeInBytes.
2587 RZ = std::clamp(val: (SizeInBytes / MinRZ / 4) * MinRZ, lo: MinRZ, hi: kMaxRZ);
2588
2589 // Round up to multiple of MinRZ.
2590 if (SizeInBytes % MinRZ)
2591 RZ += MinRZ - (SizeInBytes % MinRZ);
2592 }
2593
2594 assert((RZ + SizeInBytes) % MinRZ == 0);
2595
2596 return RZ;
2597}
2598
2599int ModuleAddressSanitizer::GetAsanVersion() const {
2600 int LongSize = M.getDataLayout().getPointerSizeInBits();
2601 bool isAndroid = M.getTargetTriple().isAndroid();
2602 int Version = 8;
2603 // 32-bit Android is one version ahead because of the switch to dynamic
2604 // shadow.
2605 Version += (LongSize == 32 && isAndroid);
2606 return Version;
2607}
2608
2609GlobalVariable *ModuleAddressSanitizer::getOrCreateModuleName() {
2610 if (!ModuleName) {
2611 // We shouldn't merge same module names, as this string serves as unique
2612 // module ID in runtime.
2613 ModuleName =
2614 createPrivateGlobalForString(M, Str: M.getModuleIdentifier(),
2615 /*AllowMerging*/ false, NamePrefix: genName(suffix: "module"));
2616 }
2617 return ModuleName;
2618}
2619
2620bool ModuleAddressSanitizer::instrumentModule() {
2621 initializeCallbacks();
2622
2623 for (Function &F : M)
2624 removeASanIncompatibleFnAttributes(F, /*ReadsArgMem=*/false);
2625
2626 // Create a module constructor. A destructor is created lazily because not all
2627 // platforms, and not all modules need it.
2628 if (ConstructorKind == AsanCtorKind::Global) {
2629 if (CompileKernel) {
2630 // The kernel always builds with its own runtime, and therefore does not
2631 // need the init and version check calls.
2632 AsanCtorFunction = createSanitizerCtor(M, CtorName: kAsanModuleCtorName);
2633 } else {
2634 std::string AsanVersion = std::to_string(val: GetAsanVersion());
2635 std::string VersionCheckName =
2636 InsertVersionCheck ? (kAsanVersionCheckNamePrefix + AsanVersion) : "";
2637 std::tie(args&: AsanCtorFunction, args: std::ignore) =
2638 createSanitizerCtorAndInitFunctions(
2639 M, CtorName: kAsanModuleCtorName, InitName: kAsanInitName, /*InitArgTypes=*/{},
2640 /*InitArgs=*/{}, VersionCheckName);
2641 }
2642 }
2643
2644 bool CtorComdat = true;
2645 if (Opts.asan_globals) {
2646 assert(AsanCtorFunction || ConstructorKind == AsanCtorKind::None);
2647 if (AsanCtorFunction) {
2648 IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2649 instrumentGlobals(IRB, CtorComdat: &CtorComdat);
2650 } else {
2651 IRBuilder<> IRB(M);
2652 instrumentGlobals(IRB, CtorComdat: &CtorComdat);
2653 }
2654 }
2655
2656 const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
2657
2658 // Put the constructor and destructor in comdat if both
2659 // (1) global instrumentation is not TU-specific
2660 // (2) target is ELF.
2661 if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2662 if (AsanCtorFunction) {
2663 AsanCtorFunction->setComdat(M.getOrInsertComdat(Name: kAsanModuleCtorName));
2664 appendToGlobalCtors(M, F: AsanCtorFunction, Priority, Data: AsanCtorFunction);
2665 }
2666 if (AsanDtorFunction) {
2667 AsanDtorFunction->setComdat(M.getOrInsertComdat(Name: kAsanModuleDtorName));
2668 appendToGlobalDtors(M, F: AsanDtorFunction, Priority, Data: AsanDtorFunction);
2669 }
2670 } else {
2671 if (AsanCtorFunction)
2672 appendToGlobalCtors(M, F: AsanCtorFunction, Priority);
2673 if (AsanDtorFunction)
2674 appendToGlobalDtors(M, F: AsanDtorFunction, Priority);
2675 }
2676
2677 return true;
2678}
2679
2680void AddressSanitizer::initializeCallbacks(const TargetLibraryInfo *TLI) {
2681 IRBuilder<> IRB(M);
2682
2683 const std::string EndingStr = Recover ? "_noabort" : "";
2684 AsanAssumeDereferenceableCallback = M.getOrInsertFunction(
2685 Name: "__asan_report_assume_dereferenceable" + EndingStr,
2686 T: FunctionType::get(Result: IRB.getVoidTy(), Params: {IntptrTy, IntptrTy}, isVarArg: false));
2687
2688 // Create __asan_report* callbacks.
2689 // IsWrite, TypeSize and Exp are encoded in the function name.
2690 for (int Exp = 0; Exp < 2; Exp++) {
2691 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
2692 const std::string TypeStr = AccessIsWrite ? "store" : "load";
2693 const std::string ExpStr = Exp ? "exp_" : "";
2694 const std::string EndingStr = Recover ? "_noabort" : "";
2695
2696 SmallVector<Type *, 3> Args2 = {IntptrTy, IntptrTy};
2697 SmallVector<Type *, 2> Args1{1, IntptrTy};
2698 AttributeList AL2;
2699 AttributeList AL1;
2700 if (Exp) {
2701 Type *ExpType = Type::getInt32Ty(C&: *C);
2702 Args2.push_back(Elt: ExpType);
2703 Args1.push_back(Elt: ExpType);
2704 if (auto AK = TLI->getExtAttrForI32Param(Signed: false)) {
2705 AL2 = AL2.addParamAttribute(C&: *C, ArgNo: 2, Kind: AK);
2706 AL1 = AL1.addParamAttribute(C&: *C, ArgNo: 1, Kind: AK);
2707 }
2708 }
2709 AsanErrorCallbackSized[AccessIsWrite][Exp] = Inserter.insertFunction(
2710 Name: kAsanReportErrorTemplate + ExpStr + TypeStr + "_n" + EndingStr,
2711 Args: FunctionType::get(Result: IRB.getVoidTy(), Params: Args2, isVarArg: false), Args&: AL2);
2712
2713 AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] =
2714 Inserter.insertFunction(
2715 Name: (Opts.asan_memory_access_callback_prefix + ExpStr + TypeStr +
2716 "N" + EndingStr)
2717 .str(),
2718 Args: FunctionType::get(Result: IRB.getVoidTy(), Params: Args2, isVarArg: false), Args&: AL2);
2719
2720 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
2721 AccessSizeIndex++) {
2722 const std::string Suffix = TypeStr + itostr(X: 1ULL << AccessSizeIndex);
2723 AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] =
2724 Inserter.insertFunction(
2725 Name: kAsanReportErrorTemplate + ExpStr + Suffix + EndingStr,
2726 Args: FunctionType::get(Result: IRB.getVoidTy(), Params: Args1, isVarArg: false), Args&: AL1);
2727
2728 AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] =
2729 Inserter.insertFunction(
2730 Name: (Opts.asan_memory_access_callback_prefix + ExpStr + Suffix +
2731 EndingStr)
2732 .str(),
2733 Args: FunctionType::get(Result: IRB.getVoidTy(), Params: Args1, isVarArg: false), Args&: AL1);
2734 }
2735 }
2736 }
2737
2738 const std::string MemIntrinCallbackPrefix =
2739 (CompileKernel && !Opts.asan_kernel_mem_intrinsic_prefix)
2740 ? std::string("")
2741 : Opts.asan_memory_access_callback_prefix.str();
2742 AsanMemmove = Inserter.insertFunction(Name: MemIntrinCallbackPrefix + "memmove",
2743 Args&: PtrTy, Args&: PtrTy, Args&: PtrTy, Args&: IntptrTy);
2744 AsanMemcpy = Inserter.insertFunction(Name: MemIntrinCallbackPrefix + "memcpy",
2745 Args&: PtrTy, Args&: PtrTy, Args&: PtrTy, Args&: IntptrTy);
2746 AsanMemset =
2747 Inserter.insertFunction(Name: MemIntrinCallbackPrefix + "memset",
2748 Args: TLI->getAttrList(C, ArgNos: {1},
2749 /*Signed=*/false),
2750 Args&: PtrTy, Args&: PtrTy, Args: IRB.getInt32Ty(), Args&: IntptrTy);
2751
2752 AsanHandleNoReturnFunc =
2753 Inserter.insertFunction(Name: kAsanHandleNoReturnName, Args: IRB.getVoidTy());
2754
2755 AsanPtrCmpFunction =
2756 Inserter.insertFunction(Name: kAsanPtrCmp, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
2757 AsanPtrSubFunction =
2758 Inserter.insertFunction(Name: kAsanPtrSub, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
2759 if (Mapping.InGlobal)
2760 AsanShadowGlobal = M.getOrInsertGlobal(Name: "__asan_shadow",
2761 Ty: ArrayType::get(ElementType: IRB.getInt8Ty(), NumElements: 0));
2762
2763 AMDGPUAddressShared =
2764 Inserter.insertFunction(Name: kAMDGPUAddressSharedName, Args: IRB.getInt1Ty(), Args&: PtrTy);
2765 AMDGPUAddressPrivate = Inserter.insertFunction(Name: kAMDGPUAddressPrivateName,
2766 Args: IRB.getInt1Ty(), Args&: PtrTy);
2767}
2768
2769bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
2770 // For each NSObject descendant having a +load method, this method is invoked
2771 // by the ObjC runtime before any of the static constructors is called.
2772 // Therefore we need to instrument such methods with a call to __asan_init
2773 // at the beginning in order to initialize our runtime before any access to
2774 // the shadow memory.
2775 // We cannot just ignore these methods, because they may call other
2776 // instrumented functions.
2777 if (F.getName().contains(Other: " load]")) {
2778 FunctionCallee AsanInitFunction =
2779 declareSanitizerInitFunction(M&: *F.getParent(), InitName: kAsanInitName, InitArgTypes: {});
2780 IRBuilder<> IRB(F.front().begin());
2781 IRB.CreateCall(Callee: AsanInitFunction, Args: {});
2782 return true;
2783 }
2784 return false;
2785}
2786
2787bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(Function &F) {
2788 // Generate code only when dynamic addressing is needed.
2789 if (Mapping.Offset != kDynamicShadowSentinel)
2790 return false;
2791
2792 IRBuilder<> IRB(&F.front().front());
2793 if (Mapping.InGlobal) {
2794 if (Opts.asan_with_ifunc_suppress_remat) {
2795 // An empty inline asm with input reg == output reg.
2796 // An opaque pointer-to-int cast, basically.
2797 InlineAsm *Asm = InlineAsm::get(
2798 Ty: FunctionType::get(Result: IntptrTy, Params: {AsanShadowGlobal->getType()}, isVarArg: false),
2799 AsmString: StringRef(""), Constraints: StringRef("=r,0"),
2800 /*hasSideEffects=*/false);
2801 LocalDynamicShadow =
2802 IRB.CreateCall(Callee: Asm, Args: {AsanShadowGlobal}, Name: ".asan.shadow");
2803 } else {
2804 LocalDynamicShadow =
2805 IRB.CreatePointerCast(V: AsanShadowGlobal, DestTy: IntptrTy, Name: ".asan.shadow");
2806 }
2807 } else {
2808 Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal(
2809 Name: kAsanShadowMemoryDynamicAddress, Ty: IntptrTy);
2810 LocalDynamicShadow = IRB.CreateLoad(Ty: IntptrTy, Ptr: GlobalDynamicAddress);
2811 }
2812 return true;
2813}
2814
2815void AddressSanitizer::markEscapedLocalAllocas(Function &F) {
2816 // Find the one possible call to llvm.localescape and pre-mark allocas passed
2817 // to it as uninteresting. This assumes we haven't started processing allocas
2818 // yet. This check is done up front because iterating the use list in
2819 // isInterestingAlloca would be algorithmically slower.
2820 assert(ProcessedAllocas.empty() && "must process localescape before allocas");
2821
2822 // Try to get the declaration of llvm.localescape. If it's not in the module,
2823 // we can exit early.
2824 if (!F.getParent()->getFunction(Name: "llvm.localescape")) return;
2825
2826 // Look for a call to llvm.localescape call in the entry block. It can't be in
2827 // any other block.
2828 for (Instruction &I : F.getEntryBlock()) {
2829 IntrinsicInst *II = dyn_cast<IntrinsicInst>(Val: &I);
2830 if (II && II->getIntrinsicID() == Intrinsic::localescape) {
2831 // We found a call. Mark all the allocas passed in as uninteresting.
2832 for (Value *Arg : II->args()) {
2833 AllocaInst *AI = dyn_cast<AllocaInst>(Val: Arg->stripPointerCasts());
2834 assert(AI && AI->isStaticAlloca() &&
2835 "non-static alloca arg to localescape");
2836 ProcessedAllocas[AI] = false;
2837 }
2838 break;
2839 }
2840 }
2841}
2842// Mitigation for https://github.com/google/sanitizers/issues/749
2843// We don't instrument Windows catch-block parameters to avoid
2844// interfering with exception handling assumptions.
2845void AddressSanitizer::markCatchParametersAsUninteresting(Function &F) {
2846 for (BasicBlock &BB : F) {
2847 for (Instruction &I : BB) {
2848 if (auto *CatchPad = dyn_cast<CatchPadInst>(Val: &I)) {
2849 // Mark the parameters to a catch-block as uninteresting to avoid
2850 // instrumenting them.
2851 for (Value *Operand : CatchPad->arg_operands())
2852 if (auto *AI = dyn_cast<AllocaInst>(Val: Operand))
2853 ProcessedAllocas[AI] = false;
2854 }
2855 }
2856 }
2857}
2858
2859bool AddressSanitizer::suppressInstrumentationSiteForDebug(int &Instrumented) {
2860 bool ShouldInstrument = Opts.asan_debug_min < 0 || Opts.asan_debug_max < 0 ||
2861 (Instrumented >= Opts.asan_debug_min &&
2862 Instrumented <= Opts.asan_debug_max);
2863 Instrumented++;
2864 return !ShouldInstrument;
2865}
2866
2867bool AddressSanitizer::instrumentFunction(Function &F,
2868 const TargetLibraryInfo *TLI,
2869 const TargetTransformInfo *TTI) {
2870 bool FunctionModified = false;
2871
2872 // Do not apply any instrumentation for naked functions.
2873 if (F.hasFnAttribute(Kind: Attribute::Naked))
2874 return FunctionModified;
2875
2876 // If needed, insert __asan_init before checking for SanitizeAddress attr.
2877 // This function needs to be called even if the function body is not
2878 // instrumented.
2879 if (maybeInsertAsanInitAtFunctionEntry(F))
2880 FunctionModified = true;
2881
2882 // Leave if the function doesn't need instrumentation.
2883 if (!F.hasFnAttribute(Kind: Attribute::SanitizeAddress)) return FunctionModified;
2884
2885 if (F.hasFnAttribute(Kind: Attribute::DisableSanitizerInstrumentation))
2886 return FunctionModified;
2887
2888 LLVM_DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n");
2889
2890 initializeCallbacks(TLI);
2891
2892 FunctionStateRAII CleanupObj(this);
2893
2894 RuntimeCallInserter RTCI(F);
2895
2896 FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(F);
2897
2898 // We can't instrument allocas used with llvm.localescape. Only static allocas
2899 // can be passed to that intrinsic.
2900 markEscapedLocalAllocas(F);
2901
2902 if (TargetTriple.isOSWindows())
2903 markCatchParametersAsUninteresting(F);
2904
2905 // We want to instrument every address only once per basic block (unless there
2906 // are calls between uses).
2907 SmallPtrSet<Value *, 16> TempsToInstrument;
2908 SmallVector<InterestingMemoryOperand, 16> OperandsToInstrument;
2909 SmallVector<MemIntrinsic *, 16> IntrinToInstrument;
2910 SmallVector<Instruction *, 8> NoReturnCalls;
2911 SmallVector<BasicBlock *, 16> AllBlocks;
2912 SmallVector<Instruction *, 16> PointerComparisonsOrSubtracts;
2913 SmallVector<AssumeInst *, 8> DerefAssumptions;
2914
2915 // Fill the set of memory operations to instrument.
2916 for (auto &BB : F) {
2917 AllBlocks.push_back(Elt: &BB);
2918 TempsToInstrument.clear();
2919 int NumInsnsPerBB = 0;
2920 for (auto &Inst : BB) {
2921 if (LooksLikeCodeInBug11395(I: &Inst)) return false;
2922 // Skip instructions inserted by another instrumentation.
2923 if (Inst.hasMetadata(KindID: LLVMContext::MD_nosanitize))
2924 continue;
2925 SmallVector<InterestingMemoryOperand, 1> InterestingOperands;
2926 getInterestingMemoryOperands(I: &Inst, Interesting&: InterestingOperands, TTI);
2927
2928 AssumeInst *AI;
2929 if (!InterestingOperands.empty()) {
2930 for (auto &Operand : InterestingOperands) {
2931 if (Opts.asan_opt && Opts.asan_opt_same_temp) {
2932 Value *Ptr = Operand.getPtr();
2933 // If we have a mask, skip instrumentation if we've already
2934 // instrumented the full object. But don't add to TempsToInstrument
2935 // because we might get another load/store with a different mask.
2936 if (Operand.MaybeMask) {
2937 if (TempsToInstrument.count(Ptr))
2938 continue; // We've seen this (whole) temp in the current BB.
2939 } else {
2940 if (!TempsToInstrument.insert(Ptr).second)
2941 continue; // We've seen this temp in the current BB.
2942 }
2943 }
2944 OperandsToInstrument.push_back(Elt: Operand);
2945 NumInsnsPerBB++;
2946 }
2947 } else if (((Opts.asan_detect_invalid_pointer_pair ||
2948 Opts.asan_detect_invalid_pointer_cmp) &&
2949 isInterestingPointerComparison(I: &Inst)) ||
2950 ((Opts.asan_detect_invalid_pointer_pair ||
2951 Opts.asan_detect_invalid_pointer_sub) &&
2952 isInterestingPointerSubtraction(I: &Inst))) {
2953 PointerComparisonsOrSubtracts.push_back(Elt: &Inst);
2954 } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(Val: &Inst)) {
2955 // ok, take it.
2956 IntrinToInstrument.push_back(Elt: MI);
2957 NumInsnsPerBB++;
2958 } else if (Opts.asan_instrument_assume_dereferenceable &&
2959 (AI = dyn_cast<AssumeInst>(Val: &Inst))) {
2960 if (AI->getOperandBundle(Name: "dereferenceable")) {
2961 DerefAssumptions.push_back(Elt: AI);
2962 NumInsnsPerBB++;
2963 }
2964 } else {
2965 if (auto *CB = dyn_cast<CallBase>(Val: &Inst)) {
2966 // A call inside BB.
2967 TempsToInstrument.clear();
2968 if (CB->doesNotReturn())
2969 NoReturnCalls.push_back(Elt: CB);
2970 }
2971 if (CallInst *CI = dyn_cast<CallInst>(Val: &Inst))
2972 maybeMarkSanitizerLibraryCallNoBuiltin(CI, TLI);
2973 }
2974 if (NumInsnsPerBB >= Opts.asan_max_ins_per_bb)
2975 break;
2976 }
2977 }
2978
2979 bool UseCalls = (InstrumentationWithCallsThreshold >= 0 &&
2980 OperandsToInstrument.size() + IntrinToInstrument.size() >
2981 (unsigned)InstrumentationWithCallsThreshold);
2982 const DataLayout &DL = F.getDataLayout();
2983 ObjectSizeOffsetVisitor ObjSizeVis(DL, TLI, F.getContext());
2984
2985 // Instrument.
2986 int NumInstrumented = 0;
2987 for (auto &Operand : OperandsToInstrument) {
2988 if (!suppressInstrumentationSiteForDebug(Instrumented&: NumInstrumented))
2989 instrumentMop(ObjSizeVis, O&: Operand, UseCalls,
2990 DL: F.getDataLayout(), RTCI);
2991 FunctionModified = true;
2992 }
2993 for (auto *Inst : IntrinToInstrument) {
2994 if (!suppressInstrumentationSiteForDebug(Instrumented&: NumInstrumented))
2995 instrumentMemIntrinsic(MI: Inst, RTCI);
2996 FunctionModified = true;
2997 }
2998
2999 FunctionStackPoisoner FSP(F, *this, RTCI);
3000 bool ChangedStack = FSP.runOnFunction();
3001
3002 // We must unpoison the stack before NoReturn calls (throw, _exit, etc).
3003 // See e.g. https://github.com/google/sanitizers/issues/37
3004 for (auto *CI : NoReturnCalls) {
3005 IRBuilder<> IRB(CI);
3006 RTCI.createRuntimeCall(IRB, Callee: AsanHandleNoReturnFunc, Args: {});
3007 }
3008
3009 for (auto *Inst : PointerComparisonsOrSubtracts) {
3010 FunctionModified |= instrumentPointerComparisonOrSubtraction(I: Inst, RTCI);
3011 }
3012
3013 for (auto *AI : DerefAssumptions) {
3014 if (auto Bundle = AI->getOperandBundle(Name: "dereferenceable")) {
3015 Value *Ptr = Bundle->Inputs[0];
3016 Value *Size = Bundle->Inputs[1];
3017
3018 // Skip if size is exactly 0 without generating IR.
3019 if (auto *CI = dyn_cast<ConstantInt>(Val: Size)) {
3020 if (CI->getValue().zextOrTrunc(width: IntptrTy->getIntegerBitWidth()).isZero())
3021 continue;
3022 }
3023
3024 IRBuilder<> IRB(AI);
3025 Value *AddrLong = IRB.CreatePointerCast(V: Ptr, DestTy: IntptrTy);
3026 Value *SizeExt = IRB.CreateZExtOrTrunc(V: Size, DestTy: IntptrTy);
3027
3028 RTCI.createRuntimeCall(IRB, Callee: AsanAssumeDereferenceableCallback,
3029 Args: {AddrLong, SizeExt});
3030
3031 FunctionModified = true;
3032 }
3033 }
3034
3035 if (ChangedStack || !NoReturnCalls.empty())
3036 FunctionModified = true;
3037
3038 LLVM_DEBUG(dbgs() << "ASAN done instrumenting: " << FunctionModified << " "
3039 << F << "\n");
3040
3041 return FunctionModified;
3042}
3043
3044// Workaround for bug 11395: we don't want to instrument stack in functions
3045// with large assembly blobs (32-bit only), otherwise reg alloc may crash.
3046// FIXME: remove once the bug 11395 is fixed.
3047bool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) {
3048 if (LongSize != 32) return false;
3049 CallInst *CI = dyn_cast<CallInst>(Val: I);
3050 if (!CI || !CI->isInlineAsm()) return false;
3051 if (CI->arg_size() <= 5)
3052 return false;
3053 // We have inline assembly with quite a few arguments.
3054 return true;
3055}
3056
3057void FunctionStackPoisoner::initializeCallbacks(Module &M) {
3058 IRBuilder<> IRB(M);
3059 if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always ||
3060 ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) {
3061 const char *MallocNameTemplate =
3062 ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always
3063 ? kAsanStackMallocAlwaysNameTemplate
3064 : kAsanStackMallocNameTemplate;
3065 for (int Index = 0; Index <= kMaxAsanStackMallocSizeClass; Index++) {
3066 std::string Suffix = itostr(X: Index);
3067 AsanStackMallocFunc[Index] = ASan.Inserter.insertFunction(
3068 Name: MallocNameTemplate + Suffix, Args&: IntptrTy, Args&: IntptrTy);
3069 AsanStackFreeFunc[Index] =
3070 ASan.Inserter.insertFunction(Name: kAsanStackFreeNameTemplate + Suffix,
3071 Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3072 }
3073 }
3074 if (ASan.UseAfterScope) {
3075 AsanPoisonStackMemoryFunc = ASan.Inserter.insertFunction(
3076 Name: kAsanPoisonStackMemoryName, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3077 AsanUnpoisonStackMemoryFunc = ASan.Inserter.insertFunction(
3078 Name: kAsanUnpoisonStackMemoryName, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3079 }
3080
3081 for (size_t Val : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf1, 0xf2,
3082 0xf3, 0xf5, 0xf8}) {
3083 std::ostringstream Name;
3084 Name << kAsanSetShadowPrefix;
3085 Name << std::setw(2) << std::setfill('0') << std::hex << Val;
3086 AsanSetShadowFunc[Val] = ASan.Inserter.insertFunction(
3087 Name: Name.str(), Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3088 }
3089
3090 AsanAllocaPoisonFunc = ASan.Inserter.insertFunction(
3091 Name: kAsanAllocaPoison, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3092 AsanAllocasUnpoisonFunc = ASan.Inserter.insertFunction(
3093 Name: kAsanAllocasUnpoison, Args: IRB.getVoidTy(), Args&: IntptrTy, Args&: IntptrTy);
3094}
3095
3096void FunctionStackPoisoner::copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
3097 ArrayRef<uint8_t> ShadowBytes,
3098 size_t Begin, size_t End,
3099 IRBuilder<> &IRB,
3100 Value *ShadowBase) {
3101 if (Begin >= End)
3102 return;
3103
3104 const size_t LargestStoreSizeInBytes =
3105 std::min<size_t>(a: sizeof(uint64_t), b: ASan.LongSize / 8);
3106
3107 const bool IsLittleEndian = F.getDataLayout().isLittleEndian();
3108
3109 // Poison given range in shadow using larges store size with out leading and
3110 // trailing zeros in ShadowMask. Zeros never change, so they need neither
3111 // poisoning nor up-poisoning. Still we don't mind if some of them get into a
3112 // middle of a store.
3113 for (size_t i = Begin; i < End;) {
3114 if (!ShadowMask[i]) {
3115 assert(!ShadowBytes[i]);
3116 ++i;
3117 continue;
3118 }
3119
3120 size_t StoreSizeInBytes = LargestStoreSizeInBytes;
3121 // Fit store size into the range.
3122 while (StoreSizeInBytes > End - i)
3123 StoreSizeInBytes /= 2;
3124
3125 // Minimize store size by trimming trailing zeros.
3126 for (size_t j = StoreSizeInBytes - 1; j && !ShadowMask[i + j]; --j) {
3127 while (j <= StoreSizeInBytes / 2)
3128 StoreSizeInBytes /= 2;
3129 }
3130
3131 uint64_t Val = 0;
3132 for (size_t j = 0; j < StoreSizeInBytes; j++) {
3133 if (IsLittleEndian)
3134 Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
3135 else
3136 Val = (Val << 8) | ShadowBytes[i + j];
3137 }
3138
3139 Value *Ptr = IRB.CreateAdd(LHS: ShadowBase, RHS: ConstantInt::get(Ty: IntptrTy, V: i));
3140 Value *Poison = IRB.getIntN(N: StoreSizeInBytes * 8, C: Val);
3141 IRB.CreateAlignedStore(
3142 Val: Poison, Ptr: IRB.CreateIntToPtr(V: Ptr, DestTy: PointerType::getUnqual(C&: Poison->getContext())),
3143 Align: Align(1));
3144
3145 i += StoreSizeInBytes;
3146 }
3147}
3148
3149void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
3150 ArrayRef<uint8_t> ShadowBytes,
3151 IRBuilder<> &IRB, Value *ShadowBase) {
3152 copyToShadow(ShadowMask, ShadowBytes, Begin: 0, End: ShadowMask.size(), IRB, ShadowBase);
3153}
3154
3155void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
3156 ArrayRef<uint8_t> ShadowBytes,
3157 size_t Begin, size_t End,
3158 IRBuilder<> &IRB, Value *ShadowBase) {
3159 assert(ShadowMask.size() == ShadowBytes.size());
3160 size_t Done = Begin;
3161 for (size_t i = Begin, j = Begin + 1; i < End; i = j++) {
3162 if (!ShadowMask[i]) {
3163 assert(!ShadowBytes[i]);
3164 continue;
3165 }
3166 uint8_t Val = ShadowBytes[i];
3167 if (!AsanSetShadowFunc[Val])
3168 continue;
3169
3170 // Skip same values.
3171 for (; j < End && ShadowMask[j] && Val == ShadowBytes[j]; ++j) {
3172 }
3173
3174 if (j - i >= ASan.MaxInlinePoisoningSize) {
3175 copyToShadowInline(ShadowMask, ShadowBytes, Begin: Done, End: i, IRB, ShadowBase);
3176 RTCI.createRuntimeCall(
3177 IRB, Callee: AsanSetShadowFunc[Val],
3178 Args: {IRB.CreateAdd(LHS: ShadowBase, RHS: ConstantInt::get(Ty: IntptrTy, V: i)),
3179 ConstantInt::get(Ty: IntptrTy, V: j - i)});
3180 Done = j;
3181 }
3182 }
3183
3184 copyToShadowInline(ShadowMask, ShadowBytes, Begin: Done, End, IRB, ShadowBase);
3185}
3186
3187// Fake stack allocator (asan_fake_stack.h) has 11 size classes
3188// for every power of 2 from kMinStackMallocSize to kMaxAsanStackMallocSizeClass
3189static int StackMallocSizeClass(uint64_t LocalStackSize) {
3190 assert(LocalStackSize <= kMaxStackMallocSize);
3191 uint64_t MaxSize = kMinStackMallocSize;
3192 for (int i = 0;; i++, MaxSize *= 2)
3193 if (LocalStackSize <= MaxSize) return i;
3194 llvm_unreachable("impossible LocalStackSize");
3195}
3196
3197void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
3198 Instruction *CopyInsertPoint = &F.front().front();
3199 if (CopyInsertPoint == ASan.LocalDynamicShadow) {
3200 // Insert after the dynamic shadow location is determined
3201 CopyInsertPoint = CopyInsertPoint->getNextNode();
3202 assert(CopyInsertPoint);
3203 }
3204 IRBuilder<> IRB(CopyInsertPoint);
3205 const DataLayout &DL = F.getDataLayout();
3206 for (Argument &Arg : F.args()) {
3207 if (Arg.hasByValAttr()) {
3208 Type *Ty = Arg.getParamByValType();
3209 const Align Alignment =
3210 DL.getValueOrABITypeAlignment(Alignment: Arg.getParamAlign(), Ty);
3211
3212 AllocaInst *AI = IRB.CreateAlloca(
3213 Ty, ArraySize: nullptr,
3214 Name: (Arg.hasName() ? Arg.getName() : "Arg" + Twine(Arg.getArgNo())) +
3215 ".byval");
3216 AI->setAlignment(Alignment);
3217 Arg.replaceAllUsesWith(V: AI);
3218
3219 uint64_t AllocSize = DL.getTypeAllocSize(Ty);
3220 IRB.CreateMemCpy(Dst: AI, DstAlign: Alignment, Src: &Arg, SrcAlign: Alignment, Size: AllocSize);
3221 }
3222 }
3223}
3224
3225PHINode *FunctionStackPoisoner::createPHI(IRBuilder<> &IRB, Value *Cond,
3226 Value *ValueIfTrue,
3227 Instruction *ThenTerm,
3228 Value *ValueIfFalse) {
3229 PHINode *PHI = IRB.CreatePHI(Ty: ValueIfTrue->getType(), NumReservedValues: 2);
3230 BasicBlock *CondBlock = cast<Instruction>(Val: Cond)->getParent();
3231 PHI->addIncoming(V: ValueIfFalse, BB: CondBlock);
3232 BasicBlock *ThenBlock = ThenTerm->getParent();
3233 PHI->addIncoming(V: ValueIfTrue, BB: ThenBlock);
3234 return PHI;
3235}
3236
3237Value *FunctionStackPoisoner::createAllocaForLayout(
3238 IRBuilder<> &IRB, const ASanStackFrameLayout &L, bool Dynamic) {
3239 AllocaInst *Alloca;
3240 if (Dynamic) {
3241 Alloca = IRB.CreateAlloca(Ty: IRB.getInt8Ty(),
3242 ArraySize: ConstantInt::get(Ty: IRB.getInt64Ty(), V: L.FrameSize),
3243 Name: "MyAlloca");
3244 } else {
3245 Alloca = IRB.CreateAlloca(Ty: ArrayType::get(ElementType: IRB.getInt8Ty(), NumElements: L.FrameSize),
3246 ArraySize: nullptr, Name: "MyAlloca");
3247 assert(Alloca->isStaticAlloca());
3248 }
3249 assert((Opts.asan_realign_stack & (Opts.asan_realign_stack - 1)) == 0);
3250 uint64_t FrameAlignment =
3251 std::max(a: L.FrameAlignment, b: uint64_t(Opts.asan_realign_stack));
3252 Alloca->setAlignment(Align(FrameAlignment));
3253 return Alloca;
3254}
3255
3256void FunctionStackPoisoner::createDynamicAllocasInitStorage() {
3257 BasicBlock &FirstBB = *F.begin();
3258 IRBuilder<> IRB(dyn_cast<Instruction>(Val: FirstBB.begin()));
3259 DynamicAllocaLayout = IRB.CreateAlloca(Ty: IntptrTy, ArraySize: nullptr);
3260 IRB.CreateStore(Val: Constant::getNullValue(Ty: IntptrTy), Ptr: DynamicAllocaLayout);
3261 DynamicAllocaLayout->setAlignment(Align(32));
3262}
3263
3264void FunctionStackPoisoner::processDynamicAllocas() {
3265 if (!Opts.asan_instrument_dynamic_allocas || DynamicAllocaVec.empty()) {
3266 assert(DynamicAllocaPoisonCallVec.empty());
3267 return;
3268 }
3269
3270 // Insert poison calls for lifetime intrinsics for dynamic allocas.
3271 for (const auto &APC : DynamicAllocaPoisonCallVec) {
3272 assert(APC.InsBefore);
3273 assert(APC.AI);
3274 assert(ASan.isInterestingAlloca(*APC.AI));
3275 assert(!APC.AI->isStaticAlloca());
3276
3277 IRBuilder<> IRB(APC.InsBefore);
3278 poisonAlloca(V: APC.AI, Size: APC.Size, IRB, DoPoison: APC.DoPoison);
3279 // Dynamic allocas will be unpoisoned unconditionally below in
3280 // unpoisonDynamicAllocas.
3281 // Flag that we need unpoison static allocas.
3282 }
3283
3284 // Handle dynamic allocas.
3285 createDynamicAllocasInitStorage();
3286 for (auto &AI : DynamicAllocaVec)
3287 handleDynamicAllocaCall(AI);
3288 unpoisonDynamicAllocas();
3289}
3290
3291/// Collect instructions in the entry block after \p InsBefore which initialize
3292/// permanent storage for a function argument. These instructions must remain in
3293/// the entry block so that uninitialized values do not appear in backtraces. An
3294/// added benefit is that this conserves spill slots. This does not move stores
3295/// before instrumented / "interesting" allocas.
3296static void findStoresToUninstrumentedArgAllocas(
3297 AddressSanitizer &ASan, Instruction &InsBefore,
3298 SmallVectorImpl<Instruction *> &InitInsts) {
3299 Instruction *Start = InsBefore.getNextNode();
3300 for (Instruction *It = Start; It; It = It->getNextNode()) {
3301 // Argument initialization looks like:
3302 // 1) store <Argument>, <Alloca> OR
3303 // 2) <CastArgument> = cast <Argument> to ...
3304 // store <CastArgument> to <Alloca>
3305 // Do not consider any other kind of instruction.
3306 //
3307 // Note: This covers all known cases, but may not be exhaustive. An
3308 // alternative to pattern-matching stores is to DFS over all Argument uses:
3309 // this might be more general, but is probably much more complicated.
3310 if (isa<AllocaInst>(Val: It) || isa<CastInst>(Val: It))
3311 continue;
3312 if (auto *Store = dyn_cast<StoreInst>(Val: It)) {
3313 // The store destination must be an alloca that isn't interesting for
3314 // ASan to instrument. These are moved up before InsBefore, and they're
3315 // not interesting because allocas for arguments can be mem2reg'd.
3316 auto *Alloca = dyn_cast<AllocaInst>(Val: Store->getPointerOperand());
3317 if (!Alloca || ASan.isInterestingAlloca(AI: *Alloca))
3318 continue;
3319
3320 Value *Val = Store->getValueOperand();
3321 bool IsDirectArgInit = isa<Argument>(Val);
3322 bool IsArgInitViaCast =
3323 isa<CastInst>(Val) &&
3324 isa<Argument>(Val: cast<CastInst>(Val)->getOperand(i_nocapture: 0)) &&
3325 // Check that the cast appears directly before the store. Otherwise
3326 // moving the cast before InsBefore may break the IR.
3327 Val == It->getPrevNode();
3328 bool IsArgInit = IsDirectArgInit || IsArgInitViaCast;
3329 if (!IsArgInit)
3330 continue;
3331
3332 if (IsArgInitViaCast)
3333 InitInsts.push_back(Elt: cast<Instruction>(Val));
3334 InitInsts.push_back(Elt: Store);
3335 continue;
3336 }
3337
3338 // Do not reorder past unknown instructions: argument initialization should
3339 // only involve casts and stores.
3340 return;
3341 }
3342}
3343
3344static StringRef getAllocaName(AllocaInst *AI) {
3345 // Alloca could have been renamed for uniqueness. Its true name will have been
3346 // recorded as an annotation.
3347 if (AI->hasMetadata(KindID: LLVMContext::MD_annotation)) {
3348 MDTuple *AllocaAnnotations =
3349 cast<MDTuple>(Val: AI->getMetadata(KindID: LLVMContext::MD_annotation));
3350 for (auto &Annotation : AllocaAnnotations->operands()) {
3351 if (!isa<MDTuple>(Val: Annotation))
3352 continue;
3353 auto AnnotationTuple = cast<MDTuple>(Val: Annotation);
3354 for (unsigned Index = 0; Index < AnnotationTuple->getNumOperands();
3355 Index++) {
3356 // All annotations are strings
3357 auto MetadataString =
3358 cast<MDString>(Val: AnnotationTuple->getOperand(I: Index));
3359 if (MetadataString->getString() == "alloca_name_altered")
3360 return cast<MDString>(Val: AnnotationTuple->getOperand(I: Index + 1))
3361 ->getString();
3362 }
3363 }
3364 }
3365 return AI->getName();
3366}
3367
3368void FunctionStackPoisoner::processStaticAllocas() {
3369 if (AllocaVec.empty()) {
3370 assert(StaticAllocaPoisonCallVec.empty());
3371 return;
3372 }
3373
3374 int StackMallocIdx = -1;
3375 DebugLoc EntryDebugLocation;
3376 if (auto SP = F.getSubprogram())
3377 EntryDebugLocation =
3378 DILocation::get(Context&: SP->getContext(), Line: SP->getScopeLine(), Column: 0, Scope: SP);
3379
3380 Instruction *InsBefore = AllocaVec[0];
3381 IRBuilder<> IRB(InsBefore);
3382
3383 // Make sure non-instrumented allocas stay in the entry block. Otherwise,
3384 // debug info is broken, because only entry-block allocas are treated as
3385 // regular stack slots.
3386 auto InsBeforeB = InsBefore->getParent();
3387 assert(InsBeforeB == &F.getEntryBlock());
3388 for (auto *AI : StaticAllocasToMoveUp)
3389 if (AI->getParent() == InsBeforeB)
3390 AI->moveBefore(InsertPos: InsBefore->getIterator());
3391
3392 // Move stores of arguments into entry-block allocas as well. This prevents
3393 // extra stack slots from being generated (to house the argument values until
3394 // they can be stored into the allocas). This also prevents uninitialized
3395 // values from being shown in backtraces.
3396 SmallVector<Instruction *, 8> ArgInitInsts;
3397 findStoresToUninstrumentedArgAllocas(ASan, InsBefore&: *InsBefore, InitInsts&: ArgInitInsts);
3398 for (Instruction *ArgInitInst : ArgInitInsts)
3399 ArgInitInst->moveBefore(InsertPos: InsBefore->getIterator());
3400
3401 // If we have a call to llvm.localescape, keep it in the entry block.
3402 if (LocalEscapeCall)
3403 LocalEscapeCall->moveBefore(InsertPos: InsBefore->getIterator());
3404
3405 SmallVector<ASanStackVariableDescription, 16> SVD;
3406 SVD.reserve(N: AllocaVec.size());
3407 for (AllocaInst *AI : AllocaVec) {
3408 StringRef Name = getAllocaName(AI);
3409 ASanStackVariableDescription D = {.Name: Name.data(),
3410 .Size: ASan.getAllocaSizeInBytes(AI: *AI),
3411 .LifetimeSize: 0,
3412 .Alignment: AI->getAlign().value(),
3413 .AI: AI,
3414 .Offset: 0,
3415 .Line: 0};
3416 SVD.push_back(Elt: D);
3417 }
3418
3419 // Minimal header size (left redzone) is 4 pointers,
3420 // i.e. 32 bytes on 64-bit platforms and 16 bytes in 32-bit platforms.
3421 uint64_t Granularity = 1ULL << Mapping.Scale;
3422 uint64_t MinHeaderSize = std::max(a: (uint64_t)ASan.LongSize / 2, b: Granularity);
3423 const ASanStackFrameLayout &L =
3424 ComputeASanStackFrameLayout(Vars&: SVD, Granularity, MinHeaderSize);
3425
3426 // Build AllocaToSVDMap for ASanStackVariableDescription lookup.
3427 DenseMap<const AllocaInst *, ASanStackVariableDescription *> AllocaToSVDMap;
3428 for (auto &Desc : SVD)
3429 AllocaToSVDMap[Desc.AI] = &Desc;
3430
3431 // Update SVD with information from lifetime intrinsics.
3432 for (const auto &APC : StaticAllocaPoisonCallVec) {
3433 assert(APC.InsBefore);
3434 assert(APC.AI);
3435 assert(ASan.isInterestingAlloca(*APC.AI));
3436 assert(APC.AI->isStaticAlloca());
3437
3438 ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI];
3439 Desc.LifetimeSize = Desc.Size;
3440 if (const DILocation *FnLoc = EntryDebugLocation.get()) {
3441 if (const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
3442 if (LifetimeLoc->getFile() == FnLoc->getFile())
3443 if (unsigned Line = LifetimeLoc->getLine())
3444 Desc.Line = std::min(a: Desc.Line ? Desc.Line : Line, b: Line);
3445 }
3446 }
3447 }
3448
3449 auto DescriptionString = ComputeASanStackFrameDescription(Vars: SVD);
3450 LLVM_DEBUG(dbgs() << DescriptionString << " --- " << L.FrameSize << "\n");
3451 uint64_t LocalStackSize = L.FrameSize;
3452 bool DoStackMalloc =
3453 ASan.UseAfterReturn != AsanDetectStackUseAfterReturnMode::Never &&
3454 !ASan.CompileKernel && LocalStackSize <= kMaxStackMallocSize;
3455 bool DoDynamicAlloca = Opts.asan_stack_dynamic_alloca;
3456 // Don't do dynamic alloca or stack malloc if:
3457 // 1) There is inline asm: too often it makes assumptions on which registers
3458 // are available.
3459 // 2) There is a returns_twice call (typically setjmp), which is
3460 // optimization-hostile, and doesn't play well with introduced indirect
3461 // register-relative calculation of local variable addresses.
3462 DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall;
3463 DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall;
3464
3465 Type *PtrTy = F.getDataLayout().getAllocaPtrType(Ctx&: F.getContext());
3466 Value *StaticAlloca =
3467 DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L, Dynamic: false);
3468
3469 Value *FakeStackPtr;
3470 Value *FakeStackInt;
3471 Value *LocalStackBase;
3472 Value *LocalStackBaseAlloca;
3473 uint8_t DIExprFlags = DIExpression::ApplyOffset;
3474
3475 if (DoStackMalloc) {
3476 LocalStackBaseAlloca =
3477 IRB.CreateAlloca(Ty: IntptrTy, ArraySize: nullptr, Name: "asan_local_stack_base");
3478 if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) {
3479 // void *FakeStack = __asan_option_detect_stack_use_after_return
3480 // ? __asan_stack_malloc_N(LocalStackSize)
3481 // : nullptr;
3482 // void *LocalStackBase = (FakeStack) ? FakeStack :
3483 // alloca(LocalStackSize);
3484 Constant *OptionDetectUseAfterReturn = F.getParent()->getOrInsertGlobal(
3485 Name: kAsanOptionDetectUseAfterReturn, Ty: IRB.getInt32Ty());
3486 Value *UseAfterReturnIsEnabled = IRB.CreateICmpNE(
3487 LHS: IRB.CreateLoad(Ty: IRB.getInt32Ty(), Ptr: OptionDetectUseAfterReturn),
3488 RHS: Constant::getNullValue(Ty: IRB.getInt32Ty()));
3489 Instruction *Term =
3490 SplitBlockAndInsertIfThen(Cond: UseAfterReturnIsEnabled, SplitBefore: InsBefore, Unreachable: false);
3491 IRBuilder<> IRBIf(Term);
3492 StackMallocIdx = StackMallocSizeClass(LocalStackSize);
3493 assert(StackMallocIdx <= kMaxAsanStackMallocSizeClass);
3494 Value *FakeStackValue =
3495 RTCI.createRuntimeCall(IRB&: IRBIf, Callee: AsanStackMallocFunc[StackMallocIdx],
3496 Args: ConstantInt::get(Ty: IntptrTy, V: LocalStackSize));
3497 IRB.SetInsertPoint(InsBefore);
3498 FakeStackInt = createPHI(IRB, Cond: UseAfterReturnIsEnabled, ValueIfTrue: FakeStackValue,
3499 ThenTerm: Term, ValueIfFalse: ConstantInt::get(Ty: IntptrTy, V: 0));
3500 } else {
3501 // assert(ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode:Always)
3502 // void *FakeStack = __asan_stack_malloc_N(LocalStackSize);
3503 // void *LocalStackBase = (FakeStack) ? FakeStack :
3504 // alloca(LocalStackSize);
3505 StackMallocIdx = StackMallocSizeClass(LocalStackSize);
3506 FakeStackInt =
3507 RTCI.createRuntimeCall(IRB, Callee: AsanStackMallocFunc[StackMallocIdx],
3508 Args: ConstantInt::get(Ty: IntptrTy, V: LocalStackSize));
3509 }
3510 FakeStackPtr = IRB.CreateIntToPtr(V: FakeStackInt, DestTy: PtrTy);
3511 Value *NoFakeStack =
3512 IRB.CreateICmpEQ(LHS: FakeStackInt, RHS: Constant::getNullValue(Ty: IntptrTy));
3513 Instruction *Term =
3514 SplitBlockAndInsertIfThen(Cond: NoFakeStack, SplitBefore: InsBefore, Unreachable: false);
3515 IRBuilder<> IRBIf(Term);
3516 Value *AllocaValue =
3517 DoDynamicAlloca ? createAllocaForLayout(IRB&: IRBIf, L, Dynamic: true) : StaticAlloca;
3518
3519 IRB.SetInsertPoint(InsBefore);
3520 LocalStackBase =
3521 createPHI(IRB, Cond: NoFakeStack, ValueIfTrue: AllocaValue, ThenTerm: Term, ValueIfFalse: FakeStackPtr);
3522 IRB.CreateStore(Val: LocalStackBase, Ptr: LocalStackBaseAlloca);
3523 DIExprFlags |= DIExpression::DerefBefore;
3524 } else {
3525 // void *FakeStack = nullptr;
3526 // void *LocalStackBase = alloca(LocalStackSize);
3527 FakeStackInt = Constant::getNullValue(Ty: IntptrTy);
3528 FakeStackPtr = Constant::getNullValue(Ty: PtrTy);
3529 LocalStackBase =
3530 DoDynamicAlloca ? createAllocaForLayout(IRB, L, Dynamic: true) : StaticAlloca;
3531 LocalStackBaseAlloca = LocalStackBase;
3532 }
3533
3534 // Replace Alloca instructions with base+offset.
3535 SmallVector<Value *> NewAllocaPtrs;
3536 for (const auto &Desc : SVD) {
3537 AllocaInst *AI = Desc.AI;
3538 replaceDbgDeclare(Address: AI, NewAddress: LocalStackBaseAlloca, Builder&: DIB, DIExprFlags, Offset: Desc.Offset);
3539 Value *NewAllocaPtr = IRB.CreatePtrAdd(
3540 Ptr: LocalStackBase, Offset: ConstantInt::get(Ty: IntptrTy, V: Desc.Offset));
3541 if (NewAllocaPtr->getType() != AI->getType())
3542 NewAllocaPtr = IRB.CreateAddrSpaceCast(V: NewAllocaPtr, DestTy: AI->getType());
3543 AI->replaceAllUsesWith(V: NewAllocaPtr);
3544 NewAllocaPtrs.push_back(Elt: NewAllocaPtr);
3545 }
3546
3547 // The left-most redzone has enough space for at least 4 pointers.
3548 // Write the Magic value to redzone[0].
3549 IRB.CreateStore(Val: ConstantInt::get(Ty: IntptrTy, V: kCurrentStackFrameMagic),
3550 Ptr: LocalStackBase);
3551 // Write the frame description constant to redzone[1].
3552 Value *BasePlus1 = IRB.CreatePtrAdd(
3553 Ptr: LocalStackBase, Offset: ConstantInt::get(Ty: IntptrTy, V: ASan.LongSize / 8));
3554 GlobalVariable *StackDescriptionGlobal =
3555 createPrivateGlobalForString(M&: *F.getParent(), Str: DescriptionString,
3556 /*AllowMerging*/ true, NamePrefix: genName(suffix: "stack"));
3557 Value *Description = IRB.CreatePointerCast(V: StackDescriptionGlobal, DestTy: IntptrTy);
3558 IRB.CreateStore(Val: Description, Ptr: BasePlus1);
3559 // Write the PC to redzone[2].
3560 Value *BasePlus2 = IRB.CreatePtrAdd(
3561 Ptr: LocalStackBase, Offset: ConstantInt::get(Ty: IntptrTy, V: 2 * ASan.LongSize / 8));
3562 IRB.CreateStore(Val: IRB.CreatePointerCast(V: &F, DestTy: IntptrTy), Ptr: BasePlus2);
3563
3564 const auto &ShadowAfterScope = GetShadowBytesAfterScope(Vars: SVD, Layout: L);
3565
3566 // Poison the stack red zones at the entry.
3567 Value *ShadowBase =
3568 ASan.memToShadow(Shadow: IRB.CreatePtrToInt(V: LocalStackBase, DestTy: IntptrTy), IRB);
3569 // As mask we must use most poisoned case: red zones and after scope.
3570 // As bytes we can use either the same or just red zones only.
3571 copyToShadow(ShadowMask: ShadowAfterScope, ShadowBytes: ShadowAfterScope, IRB, ShadowBase);
3572
3573 if (!StaticAllocaPoisonCallVec.empty()) {
3574 const auto &ShadowInScope = GetShadowBytes(Vars: SVD, Layout: L);
3575
3576 // Poison static allocas near lifetime intrinsics.
3577 for (const auto &APC : StaticAllocaPoisonCallVec) {
3578 const ASanStackVariableDescription &Desc = *AllocaToSVDMap[APC.AI];
3579 assert(Desc.Offset % L.Granularity == 0);
3580 size_t Begin = Desc.Offset / L.Granularity;
3581 size_t End = Begin + (APC.Size + L.Granularity - 1) / L.Granularity;
3582
3583 IRBuilder<> IRB(APC.InsBefore);
3584 copyToShadow(ShadowMask: ShadowAfterScope,
3585 ShadowBytes: APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin, End,
3586 IRB, ShadowBase);
3587 }
3588 }
3589
3590 // Remove lifetime markers now that these are no longer allocas.
3591 for (Value *NewAllocaPtr : NewAllocaPtrs) {
3592 for (User *U : make_early_inc_range(Range: NewAllocaPtr->users())) {
3593 auto *I = cast<Instruction>(Val: U);
3594 if (I->isLifetimeStartOrEnd())
3595 I->eraseFromParent();
3596 }
3597 }
3598
3599 SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0);
3600 SmallVector<uint8_t, 64> ShadowAfterReturn;
3601
3602 // (Un)poison the stack before all ret instructions.
3603 for (Instruction *Ret : RetVec) {
3604 IRBuilder<> IRBRet(Ret);
3605 // Mark the current frame as retired.
3606 IRBRet.CreateStore(Val: ConstantInt::get(Ty: IntptrTy, V: kRetiredStackFrameMagic),
3607 Ptr: LocalStackBase);
3608 if (DoStackMalloc) {
3609 assert(StackMallocIdx >= 0);
3610 // if FakeStack != 0 // LocalStackBase == FakeStack
3611 // // In use-after-return mode, poison the whole stack frame.
3612 // if StackMallocIdx <= 4
3613 // // For small sizes inline the whole thing:
3614 // memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize);
3615 // **SavedFlagPtr(FakeStack) = 0
3616 // else
3617 // __asan_stack_free_N(FakeStack, LocalStackSize)
3618 // else
3619 // <This is not a fake stack; unpoison the redzones>
3620 Value *Cmp =
3621 IRBRet.CreateICmpNE(LHS: FakeStackInt, RHS: Constant::getNullValue(Ty: IntptrTy));
3622 Instruction *ThenTerm, *ElseTerm;
3623 SplitBlockAndInsertIfThenElse(Cond: Cmp, SplitBefore: Ret, ThenTerm: &ThenTerm, ElseTerm: &ElseTerm);
3624
3625 IRBuilder<> IRBPoison(ThenTerm);
3626 if (ASan.MaxInlinePoisoningSize != 0 && StackMallocIdx <= 4) {
3627 int ClassSize = kMinStackMallocSize << StackMallocIdx;
3628 ShadowAfterReturn.resize(N: ClassSize / L.Granularity,
3629 NV: kAsanStackUseAfterReturnMagic);
3630 copyToShadow(ShadowMask: ShadowAfterReturn, ShadowBytes: ShadowAfterReturn, IRB&: IRBPoison,
3631 ShadowBase);
3632 Value *SavedFlagPtrPtr = IRBPoison.CreatePtrAdd(
3633 Ptr: FakeStackPtr,
3634 Offset: ConstantInt::get(Ty: IntptrTy, V: ClassSize - ASan.LongSize / 8));
3635 Value *SavedFlagPtr = IRBPoison.CreateLoad(Ty: IntptrTy, Ptr: SavedFlagPtrPtr);
3636 IRBPoison.CreateStore(
3637 Val: Constant::getNullValue(Ty: IRBPoison.getInt8Ty()),
3638 Ptr: IRBPoison.CreateIntToPtr(V: SavedFlagPtr, DestTy: IRBPoison.getPtrTy()));
3639 } else {
3640 // For larger frames call __asan_stack_free_*.
3641 RTCI.createRuntimeCall(
3642 IRB&: IRBPoison, Callee: AsanStackFreeFunc[StackMallocIdx],
3643 Args: {FakeStackInt, ConstantInt::get(Ty: IntptrTy, V: LocalStackSize)});
3644 }
3645
3646 IRBuilder<> IRBElse(ElseTerm);
3647 copyToShadow(ShadowMask: ShadowAfterScope, ShadowBytes: ShadowClean, IRB&: IRBElse, ShadowBase);
3648 } else {
3649 copyToShadow(ShadowMask: ShadowAfterScope, ShadowBytes: ShadowClean, IRB&: IRBRet, ShadowBase);
3650 }
3651 }
3652
3653 // We are done. Remove the old unused alloca instructions.
3654 for (auto *AI : AllocaVec)
3655 AI->eraseFromParent();
3656}
3657
3658void FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size,
3659 IRBuilder<> &IRB, bool DoPoison) {
3660 // For now just insert the call to ASan runtime.
3661 Value *AddrArg = IRB.CreatePointerCast(V, DestTy: IntptrTy);
3662 Value *SizeArg = ConstantInt::get(Ty: IntptrTy, V: Size);
3663 RTCI.createRuntimeCall(
3664 IRB, Callee: DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc,
3665 Args: {AddrArg, SizeArg});
3666}
3667
3668// Handling llvm.lifetime intrinsics for a given %alloca:
3669// (1) collect all llvm.lifetime.xxx(%size, %value) describing the alloca.
3670// (2) if %size is constant, poison memory for llvm.lifetime.end (to detect
3671// invalid accesses) and unpoison it for llvm.lifetime.start (the memory
3672// could be poisoned by previous llvm.lifetime.end instruction, as the
3673// variable may go in and out of scope several times, e.g. in loops).
3674// (3) if we poisoned at least one %alloca in a function,
3675// unpoison the whole stack frame at function exit.
3676void FunctionStackPoisoner::handleDynamicAllocaCall(AllocaInst *AI) {
3677 IRBuilder<> IRB(AI);
3678
3679 const Align Alignment = std::max(a: Align(kAllocaRzSize), b: AI->getAlign());
3680 const uint64_t AllocaRedzoneMask = kAllocaRzSize - 1;
3681
3682 Value *Zero = Constant::getNullValue(Ty: IntptrTy);
3683 Value *AllocaRzSize = ConstantInt::get(Ty: IntptrTy, V: kAllocaRzSize);
3684 Value *AllocaRzMask = ConstantInt::get(Ty: IntptrTy, V: AllocaRedzoneMask);
3685
3686 // Since we need to extend alloca with additional memory to locate
3687 // redzones, and OldSize is number of allocated blocks with
3688 // ElementSize size, get allocated memory size in bytes by
3689 // OldSize * ElementSize.
3690 Value *OldSize = IRB.CreateAllocationSize(DestTy: IntptrTy, AI);
3691
3692 // PartialSize = OldSize % 32
3693 Value *PartialSize = IRB.CreateAnd(LHS: OldSize, RHS: AllocaRzMask);
3694
3695 // Misalign = kAllocaRzSize - PartialSize;
3696 Value *Misalign = IRB.CreateSub(LHS: AllocaRzSize, RHS: PartialSize);
3697
3698 // PartialPadding = Misalign != kAllocaRzSize ? Misalign : 0;
3699 Value *Cond = IRB.CreateICmpNE(LHS: Misalign, RHS: AllocaRzSize);
3700 Value *PartialPadding = IRB.CreateSelect(C: Cond, True: Misalign, False: Zero);
3701
3702 // AdditionalChunkSize = Alignment + PartialPadding + kAllocaRzSize
3703 // Alignment is added to locate left redzone, PartialPadding for possible
3704 // partial redzone and kAllocaRzSize for right redzone respectively.
3705 Value *AdditionalChunkSize = IRB.CreateAdd(
3706 LHS: ConstantInt::get(Ty: IntptrTy, V: Alignment.value() + kAllocaRzSize),
3707 RHS: PartialPadding);
3708
3709 Value *NewSize = IRB.CreateAdd(LHS: OldSize, RHS: AdditionalChunkSize);
3710
3711 // Insert new alloca with new NewSize and Alignment params.
3712 AllocaInst *NewAlloca = IRB.CreateAlloca(Ty: IRB.getInt8Ty(), ArraySize: NewSize);
3713 NewAlloca->setAlignment(Alignment);
3714
3715 // NewAddress = Address + Alignment
3716 Value *NewAddress =
3717 IRB.CreateAdd(LHS: IRB.CreatePtrToInt(V: NewAlloca, DestTy: IntptrTy),
3718 RHS: ConstantInt::get(Ty: IntptrTy, V: Alignment.value()));
3719
3720 // Insert __asan_alloca_poison call for new created alloca.
3721 RTCI.createRuntimeCall(IRB, Callee: AsanAllocaPoisonFunc, Args: {NewAddress, OldSize});
3722
3723 // Store the last alloca's address to DynamicAllocaLayout. We'll need this
3724 // for unpoisoning stuff.
3725 IRB.CreateStore(Val: IRB.CreatePtrToInt(V: NewAlloca, DestTy: IntptrTy), Ptr: DynamicAllocaLayout);
3726
3727 Value *NewAddressPtr = IRB.CreateIntToPtr(V: NewAddress, DestTy: AI->getType());
3728
3729 // Remove lifetime markers now that this is no longer an alloca.
3730 for (User *U : make_early_inc_range(Range: AI->users())) {
3731 auto *I = cast<Instruction>(Val: U);
3732 if (I->isLifetimeStartOrEnd())
3733 I->eraseFromParent();
3734 }
3735
3736 // Replace all uses of AddressReturnedByAlloca with NewAddressPtr.
3737 AI->replaceAllUsesWith(V: NewAddressPtr);
3738
3739 // We are done. Erase old alloca from parent.
3740 AI->eraseFromParent();
3741}
3742
3743// isSafeAccess returns true if Addr is always inbounds with respect to its
3744// base object. For example, it is a field access or an array access with
3745// constant inbounds index.
3746bool AddressSanitizer::isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis,
3747 Value *Addr, TypeSize TypeStoreSize) const {
3748 if (TypeStoreSize.isScalable())
3749 // TODO: We can use vscale_range to convert a scalable value to an
3750 // upper bound on the access size.
3751 return false;
3752
3753 SizeOffsetAPInt SizeOffset = ObjSizeVis.compute(V: Addr);
3754 if (!SizeOffset.bothKnown())
3755 return false;
3756
3757 uint64_t Size = SizeOffset.Size.getZExtValue();
3758 int64_t Offset = SizeOffset.Offset.getSExtValue();
3759
3760 // Three checks are required to ensure safety:
3761 // . Offset >= 0 (since the offset is given from the base ptr)
3762 // . Size >= Offset (unsigned)
3763 // . Size - Offset >= NeededSize (unsigned)
3764 return Offset >= 0 && Size >= uint64_t(Offset) &&
3765 Size - uint64_t(Offset) >= TypeStoreSize / 8;
3766}
3767