1 //===- HWAddressSanitizer.cpp - detector of uninitialized reads -------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// This file is a part of HWAddressSanitizer, an address sanity checker 12 /// based on tagged addressing. 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/IR/Attributes.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/Constant.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/IRBuilder.h" 27 #include "llvm/IR/InlineAsm.h" 28 #include "llvm/IR/InstVisitor.h" 29 #include "llvm/IR/Instruction.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/IntrinsicInst.h" 32 #include "llvm/IR/Intrinsics.h" 33 #include "llvm/IR/LLVMContext.h" 34 #include "llvm/IR/MDBuilder.h" 35 #include "llvm/IR/Module.h" 36 #include "llvm/IR/Type.h" 37 #include "llvm/IR/Value.h" 38 #include "llvm/Pass.h" 39 #include "llvm/Support/Casting.h" 40 #include "llvm/Support/CommandLine.h" 41 #include "llvm/Support/Debug.h" 42 #include "llvm/Support/raw_ostream.h" 43 #include "llvm/Transforms/Instrumentation.h" 44 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 45 #include "llvm/Transforms/Utils/ModuleUtils.h" 46 #include "llvm/Transforms/Utils/PromoteMemToReg.h" 47 #include <sstream> 48 49 using namespace llvm; 50 51 #define DEBUG_TYPE "hwasan" 52 53 static const char *const kHwasanModuleCtorName = "hwasan.module_ctor"; 54 static const char *const kHwasanInitName = "__hwasan_init"; 55 56 static const char *const kHwasanShadowMemoryDynamicAddress = 57 "__hwasan_shadow_memory_dynamic_address"; 58 59 // Accesses sizes are powers of two: 1, 2, 4, 8, 16. 60 static const size_t kNumberOfAccessSizes = 5; 61 62 static const size_t kDefaultShadowScale = 4; 63 static const uint64_t kDynamicShadowSentinel = 64 std::numeric_limits<uint64_t>::max(); 65 static const unsigned kPointerTagShift = 56; 66 67 static const unsigned kShadowBaseAlignment = 32; 68 69 static cl::opt<std::string> ClMemoryAccessCallbackPrefix( 70 "hwasan-memory-access-callback-prefix", 71 cl::desc("Prefix for memory access callbacks"), cl::Hidden, 72 cl::init("__hwasan_")); 73 74 static cl::opt<bool> 75 ClInstrumentWithCalls("hwasan-instrument-with-calls", 76 cl::desc("instrument reads and writes with callbacks"), 77 cl::Hidden, cl::init(false)); 78 79 static cl::opt<bool> ClInstrumentReads("hwasan-instrument-reads", 80 cl::desc("instrument read instructions"), 81 cl::Hidden, cl::init(true)); 82 83 static cl::opt<bool> ClInstrumentWrites( 84 "hwasan-instrument-writes", cl::desc("instrument write instructions"), 85 cl::Hidden, cl::init(true)); 86 87 static cl::opt<bool> ClInstrumentAtomics( 88 "hwasan-instrument-atomics", 89 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, 90 cl::init(true)); 91 92 static cl::opt<bool> ClRecover( 93 "hwasan-recover", 94 cl::desc("Enable recovery mode (continue-after-error)."), 95 cl::Hidden, cl::init(false)); 96 97 static cl::opt<bool> ClInstrumentStack("hwasan-instrument-stack", 98 cl::desc("instrument stack (allocas)"), 99 cl::Hidden, cl::init(true)); 100 101 static cl::opt<bool> ClUARRetagToZero( 102 "hwasan-uar-retag-to-zero", 103 cl::desc("Clear alloca tags before returning from the function to allow " 104 "non-instrumented and instrumented function calls mix. When set " 105 "to false, allocas are retagged before returning from the " 106 "function to detect use after return."), 107 cl::Hidden, cl::init(true)); 108 109 static cl::opt<bool> ClGenerateTagsWithCalls( 110 "hwasan-generate-tags-with-calls", 111 cl::desc("generate new tags with runtime library calls"), cl::Hidden, 112 cl::init(false)); 113 114 static cl::opt<int> ClMatchAllTag( 115 "hwasan-match-all-tag", 116 cl::desc("don't report bad accesses via pointers with this tag"), 117 cl::Hidden, cl::init(-1)); 118 119 static cl::opt<bool> ClEnableKhwasan( 120 "hwasan-kernel", 121 cl::desc("Enable KernelHWAddressSanitizer instrumentation"), 122 cl::Hidden, cl::init(false)); 123 124 // These flags allow to change the shadow mapping and control how shadow memory 125 // is accessed. The shadow mapping looks like: 126 // Shadow = (Mem >> scale) + offset 127 128 static cl::opt<unsigned long long> ClMappingOffset( 129 "hwasan-mapping-offset", 130 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden, 131 cl::init(0)); 132 133 static cl::opt<bool> 134 ClWithIfunc("hwasan-with-ifunc", 135 cl::desc("Access dynamic shadow through an ifunc global on " 136 "platforms that support this"), 137 cl::Hidden, cl::init(false)); 138 139 static cl::opt<bool> ClWithTls( 140 "hwasan-with-tls", 141 cl::desc("Access dynamic shadow through an thread-local pointer on " 142 "platforms that support this"), 143 cl::Hidden, cl::init(true)); 144 145 static cl::opt<bool> 146 ClRecordStackHistory("hwasan-record-stack-history", 147 cl::desc("Record stack frames with tagged allocations " 148 "in a thread-local ring buffer"), 149 cl::Hidden, cl::init(true)); 150 static cl::opt<bool> 151 ClCreateFrameDescriptions("hwasan-create-frame-descriptions", 152 cl::desc("create static frame descriptions"), 153 cl::Hidden, cl::init(true)); 154 155 static cl::opt<bool> 156 ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", 157 cl::desc("instrument memory intrinsics"), 158 cl::Hidden, cl::init(true)); 159 namespace { 160 161 /// An instrumentation pass implementing detection of addressability bugs 162 /// using tagged pointers. 163 class HWAddressSanitizer : public FunctionPass { 164 public: 165 // Pass identification, replacement for typeid. 166 static char ID; 167 168 explicit HWAddressSanitizer(bool CompileKernel = false, bool Recover = false) 169 : FunctionPass(ID) { 170 this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; 171 this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 ? 172 ClEnableKhwasan : CompileKernel; 173 } 174 175 StringRef getPassName() const override { return "HWAddressSanitizer"; } 176 177 bool runOnFunction(Function &F) override; 178 bool doInitialization(Module &M) override; 179 180 void initializeCallbacks(Module &M); 181 182 Value *getDynamicShadowNonTls(IRBuilder<> &IRB); 183 184 void untagPointerOperand(Instruction *I, Value *Addr); 185 Value *memToShadow(Value *Shadow, Type *Ty, IRBuilder<> &IRB); 186 void instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 187 unsigned AccessSizeIndex, 188 Instruction *InsertBefore); 189 void instrumentMemIntrinsic(MemIntrinsic *MI); 190 bool instrumentMemAccess(Instruction *I); 191 Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, 192 uint64_t *TypeSize, unsigned *Alignment, 193 Value **MaybeMask); 194 195 bool isInterestingAlloca(const AllocaInst &AI); 196 bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag); 197 Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag); 198 Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong); 199 bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas, 200 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag); 201 Value *getNextTagWithCall(IRBuilder<> &IRB); 202 Value *getStackBaseTag(IRBuilder<> &IRB); 203 Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, AllocaInst *AI, 204 unsigned AllocaNo); 205 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag); 206 207 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty); 208 Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord); 209 210 private: 211 LLVMContext *C; 212 std::string CurModuleUniqueId; 213 Triple TargetTriple; 214 Function *HWAsanMemmove, *HWAsanMemcpy, *HWAsanMemset; 215 216 // Frame description is a way to pass names/sizes of local variables 217 // to the run-time w/o adding extra executable code in every function. 218 // We do this by creating a separate section with {PC,Descr} pairs and passing 219 // the section beg/end to __hwasan_init_frames() at module init time. 220 std::string createFrameString(ArrayRef<AllocaInst*> Allocas); 221 void createFrameGlobal(Function &F, const std::string &FrameString); 222 // Get the section name for frame descriptions. Currently ELF-only. 223 const char *getFrameSection() { return "__hwasan_frames"; } 224 const char *getFrameSectionBeg() { return "__start___hwasan_frames"; } 225 const char *getFrameSectionEnd() { return "__stop___hwasan_frames"; } 226 GlobalVariable *createFrameSectionBound(Module &M, Type *Ty, 227 const char *Name) { 228 auto GV = new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, 229 nullptr, Name); 230 GV->setVisibility(GlobalValue::HiddenVisibility); 231 return GV; 232 } 233 234 /// This struct defines the shadow mapping using the rule: 235 /// shadow = (mem >> Scale) + Offset. 236 /// If InGlobal is true, then 237 /// extern char __hwasan_shadow[]; 238 /// shadow = (mem >> Scale) + &__hwasan_shadow 239 /// If InTls is true, then 240 /// extern char *__hwasan_tls; 241 /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment) 242 struct ShadowMapping { 243 int Scale; 244 uint64_t Offset; 245 bool InGlobal; 246 bool InTls; 247 248 void init(Triple &TargetTriple); 249 unsigned getAllocaAlignment() const { return 1U << Scale; } 250 }; 251 ShadowMapping Mapping; 252 253 Type *IntptrTy; 254 Type *Int8PtrTy; 255 Type *Int8Ty; 256 257 bool CompileKernel; 258 bool Recover; 259 260 Function *HwasanCtorFunction; 261 262 Function *HwasanMemoryAccessCallback[2][kNumberOfAccessSizes]; 263 Function *HwasanMemoryAccessCallbackSized[2]; 264 265 Function *HwasanTagMemoryFunc; 266 Function *HwasanGenerateTagFunc; 267 Function *HwasanThreadEnterFunc; 268 269 Constant *ShadowGlobal; 270 271 Value *LocalDynamicShadow = nullptr; 272 GlobalValue *ThreadPtrGlobal = nullptr; 273 }; 274 275 } // end anonymous namespace 276 277 char HWAddressSanitizer::ID = 0; 278 279 INITIALIZE_PASS_BEGIN( 280 HWAddressSanitizer, "hwasan", 281 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, 282 false) 283 INITIALIZE_PASS_END( 284 HWAddressSanitizer, "hwasan", 285 "HWAddressSanitizer: detect memory bugs using tagged addressing.", false, 286 false) 287 288 FunctionPass *llvm::createHWAddressSanitizerPass(bool CompileKernel, 289 bool Recover) { 290 assert(!CompileKernel || Recover); 291 return new HWAddressSanitizer(CompileKernel, Recover); 292 } 293 294 /// Module-level initialization. 295 /// 296 /// inserts a call to __hwasan_init to the module's constructor list. 297 bool HWAddressSanitizer::doInitialization(Module &M) { 298 LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n"); 299 auto &DL = M.getDataLayout(); 300 301 TargetTriple = Triple(M.getTargetTriple()); 302 303 Mapping.init(TargetTriple); 304 305 C = &(M.getContext()); 306 CurModuleUniqueId = getUniqueModuleId(&M); 307 IRBuilder<> IRB(*C); 308 IntptrTy = IRB.getIntPtrTy(DL); 309 Int8PtrTy = IRB.getInt8PtrTy(); 310 Int8Ty = IRB.getInt8Ty(); 311 312 HwasanCtorFunction = nullptr; 313 if (!CompileKernel) { 314 std::tie(HwasanCtorFunction, std::ignore) = 315 createSanitizerCtorAndInitFunctions(M, kHwasanModuleCtorName, 316 kHwasanInitName, 317 /*InitArgTypes=*/{}, 318 /*InitArgs=*/{}); 319 Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName); 320 HwasanCtorFunction->setComdat(CtorComdat); 321 appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction); 322 323 // Create a zero-length global in __hwasan_frame so that the linker will 324 // always create start and stop symbols. 325 // 326 // N.B. If we ever start creating associated metadata in this pass this 327 // global will need to be associated with the ctor. 328 Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0); 329 auto GV = 330 new GlobalVariable(M, Int8Arr0Ty, /*isConstantGlobal*/ true, 331 GlobalVariable::PrivateLinkage, 332 Constant::getNullValue(Int8Arr0Ty), "__hwasan"); 333 GV->setSection(getFrameSection()); 334 GV->setComdat(CtorComdat); 335 appendToCompilerUsed(M, GV); 336 337 IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator()); 338 IRBCtor.CreateCall( 339 declareSanitizerInitFunction(M, "__hwasan_init_frames", 340 {Int8PtrTy, Int8PtrTy}), 341 {createFrameSectionBound(M, Int8Ty, getFrameSectionBeg()), 342 createFrameSectionBound(M, Int8Ty, getFrameSectionEnd())}); 343 } 344 345 if (!TargetTriple.isAndroid()) 346 appendToCompilerUsed( 347 M, ThreadPtrGlobal = new GlobalVariable( 348 M, IntptrTy, false, GlobalVariable::ExternalLinkage, nullptr, 349 "__hwasan_tls", nullptr, GlobalVariable::InitialExecTLSModel)); 350 351 return true; 352 } 353 354 void HWAddressSanitizer::initializeCallbacks(Module &M) { 355 IRBuilder<> IRB(*C); 356 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) { 357 const std::string TypeStr = AccessIsWrite ? "store" : "load"; 358 const std::string EndingStr = Recover ? "_noabort" : ""; 359 360 HwasanMemoryAccessCallbackSized[AccessIsWrite] = 361 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 362 ClMemoryAccessCallbackPrefix + TypeStr + "N" + EndingStr, 363 FunctionType::get(IRB.getVoidTy(), {IntptrTy, IntptrTy}, false))); 364 365 for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; 366 AccessSizeIndex++) { 367 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] = 368 checkSanitizerInterfaceFunction(M.getOrInsertFunction( 369 ClMemoryAccessCallbackPrefix + TypeStr + 370 itostr(1ULL << AccessSizeIndex) + EndingStr, 371 FunctionType::get(IRB.getVoidTy(), {IntptrTy}, false))); 372 } 373 } 374 375 HwasanTagMemoryFunc = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 376 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy)); 377 HwasanGenerateTagFunc = checkSanitizerInterfaceFunction( 378 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty)); 379 380 if (Mapping.InGlobal) 381 ShadowGlobal = M.getOrInsertGlobal("__hwasan_shadow", 382 ArrayType::get(IRB.getInt8Ty(), 0)); 383 384 const std::string MemIntrinCallbackPrefix = 385 CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix; 386 HWAsanMemmove = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 387 MemIntrinCallbackPrefix + "memmove", IRB.getInt8PtrTy(), 388 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy)); 389 HWAsanMemcpy = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 390 MemIntrinCallbackPrefix + "memcpy", IRB.getInt8PtrTy(), 391 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy)); 392 HWAsanMemset = checkSanitizerInterfaceFunction(M.getOrInsertFunction( 393 MemIntrinCallbackPrefix + "memset", IRB.getInt8PtrTy(), 394 IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy)); 395 396 HwasanThreadEnterFunc = checkSanitizerInterfaceFunction( 397 M.getOrInsertFunction("__hwasan_thread_enter", IRB.getVoidTy())); 398 } 399 400 Value *HWAddressSanitizer::getDynamicShadowNonTls(IRBuilder<> &IRB) { 401 // Generate code only when dynamic addressing is needed. 402 if (Mapping.Offset != kDynamicShadowSentinel) 403 return nullptr; 404 405 if (Mapping.InGlobal) { 406 // An empty inline asm with input reg == output reg. 407 // An opaque pointer-to-int cast, basically. 408 InlineAsm *Asm = InlineAsm::get( 409 FunctionType::get(IntptrTy, {ShadowGlobal->getType()}, false), 410 StringRef(""), StringRef("=r,0"), 411 /*hasSideEffects=*/false); 412 return IRB.CreateCall(Asm, {ShadowGlobal}, ".hwasan.shadow"); 413 } else { 414 Value *GlobalDynamicAddress = 415 IRB.GetInsertBlock()->getParent()->getParent()->getOrInsertGlobal( 416 kHwasanShadowMemoryDynamicAddress, IntptrTy); 417 return IRB.CreateLoad(GlobalDynamicAddress); 418 } 419 } 420 421 Value *HWAddressSanitizer::isInterestingMemoryAccess(Instruction *I, 422 bool *IsWrite, 423 uint64_t *TypeSize, 424 unsigned *Alignment, 425 Value **MaybeMask) { 426 // Skip memory accesses inserted by another instrumentation. 427 if (I->getMetadata("nosanitize")) return nullptr; 428 429 // Do not instrument the load fetching the dynamic shadow address. 430 if (LocalDynamicShadow == I) 431 return nullptr; 432 433 Value *PtrOperand = nullptr; 434 const DataLayout &DL = I->getModule()->getDataLayout(); 435 if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 436 if (!ClInstrumentReads) return nullptr; 437 *IsWrite = false; 438 *TypeSize = DL.getTypeStoreSizeInBits(LI->getType()); 439 *Alignment = LI->getAlignment(); 440 PtrOperand = LI->getPointerOperand(); 441 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 442 if (!ClInstrumentWrites) return nullptr; 443 *IsWrite = true; 444 *TypeSize = DL.getTypeStoreSizeInBits(SI->getValueOperand()->getType()); 445 *Alignment = SI->getAlignment(); 446 PtrOperand = SI->getPointerOperand(); 447 } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { 448 if (!ClInstrumentAtomics) return nullptr; 449 *IsWrite = true; 450 *TypeSize = DL.getTypeStoreSizeInBits(RMW->getValOperand()->getType()); 451 *Alignment = 0; 452 PtrOperand = RMW->getPointerOperand(); 453 } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { 454 if (!ClInstrumentAtomics) return nullptr; 455 *IsWrite = true; 456 *TypeSize = DL.getTypeStoreSizeInBits(XCHG->getCompareOperand()->getType()); 457 *Alignment = 0; 458 PtrOperand = XCHG->getPointerOperand(); 459 } 460 461 if (PtrOperand) { 462 // Do not instrument accesses from different address spaces; we cannot deal 463 // with them. 464 Type *PtrTy = cast<PointerType>(PtrOperand->getType()->getScalarType()); 465 if (PtrTy->getPointerAddressSpace() != 0) 466 return nullptr; 467 468 // Ignore swifterror addresses. 469 // swifterror memory addresses are mem2reg promoted by instruction 470 // selection. As such they cannot have regular uses like an instrumentation 471 // function and it makes no sense to track them as memory. 472 if (PtrOperand->isSwiftError()) 473 return nullptr; 474 } 475 476 return PtrOperand; 477 } 478 479 static unsigned getPointerOperandIndex(Instruction *I) { 480 if (LoadInst *LI = dyn_cast<LoadInst>(I)) 481 return LI->getPointerOperandIndex(); 482 if (StoreInst *SI = dyn_cast<StoreInst>(I)) 483 return SI->getPointerOperandIndex(); 484 if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) 485 return RMW->getPointerOperandIndex(); 486 if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) 487 return XCHG->getPointerOperandIndex(); 488 report_fatal_error("Unexpected instruction"); 489 return -1; 490 } 491 492 static size_t TypeSizeToSizeIndex(uint32_t TypeSize) { 493 size_t Res = countTrailingZeros(TypeSize / 8); 494 assert(Res < kNumberOfAccessSizes); 495 return Res; 496 } 497 498 void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) { 499 if (TargetTriple.isAArch64()) 500 return; 501 502 IRBuilder<> IRB(I); 503 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 504 Value *UntaggedPtr = 505 IRB.CreateIntToPtr(untagPointer(IRB, AddrLong), Addr->getType()); 506 I->setOperand(getPointerOperandIndex(I), UntaggedPtr); 507 } 508 509 Value *HWAddressSanitizer::memToShadow(Value *Mem, Type *Ty, IRBuilder<> &IRB) { 510 // Mem >> Scale 511 Value *Shadow = IRB.CreateLShr(Mem, Mapping.Scale); 512 if (Mapping.Offset == 0) 513 return Shadow; 514 // (Mem >> Scale) + Offset 515 Value *ShadowBase; 516 if (LocalDynamicShadow) 517 ShadowBase = LocalDynamicShadow; 518 else 519 ShadowBase = ConstantInt::get(Ty, Mapping.Offset); 520 return IRB.CreateAdd(Shadow, ShadowBase); 521 } 522 523 void HWAddressSanitizer::instrumentMemAccessInline(Value *PtrLong, bool IsWrite, 524 unsigned AccessSizeIndex, 525 Instruction *InsertBefore) { 526 IRBuilder<> IRB(InsertBefore); 527 Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift), 528 IRB.getInt8Ty()); 529 Value *AddrLong = untagPointer(IRB, PtrLong); 530 Value *ShadowLong = memToShadow(AddrLong, PtrLong->getType(), IRB); 531 Value *MemTag = IRB.CreateLoad(IRB.CreateIntToPtr(ShadowLong, Int8PtrTy)); 532 Value *TagMismatch = IRB.CreateICmpNE(PtrTag, MemTag); 533 534 int matchAllTag = ClMatchAllTag.getNumOccurrences() > 0 ? 535 ClMatchAllTag : (CompileKernel ? 0xFF : -1); 536 if (matchAllTag != -1) { 537 Value *TagNotIgnored = IRB.CreateICmpNE(PtrTag, 538 ConstantInt::get(PtrTag->getType(), matchAllTag)); 539 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored); 540 } 541 542 Instruction *CheckTerm = 543 SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, !Recover, 544 MDBuilder(*C).createBranchWeights(1, 100000)); 545 546 IRB.SetInsertPoint(CheckTerm); 547 const int64_t AccessInfo = Recover * 0x20 + IsWrite * 0x10 + AccessSizeIndex; 548 InlineAsm *Asm; 549 switch (TargetTriple.getArch()) { 550 case Triple::x86_64: 551 // The signal handler will find the data address in rdi. 552 Asm = InlineAsm::get( 553 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 554 "int3\nnopl " + itostr(0x40 + AccessInfo) + "(%rax)", 555 "{rdi}", 556 /*hasSideEffects=*/true); 557 break; 558 case Triple::aarch64: 559 case Triple::aarch64_be: 560 // The signal handler will find the data address in x0. 561 Asm = InlineAsm::get( 562 FunctionType::get(IRB.getVoidTy(), {PtrLong->getType()}, false), 563 "brk #" + itostr(0x900 + AccessInfo), 564 "{x0}", 565 /*hasSideEffects=*/true); 566 break; 567 default: 568 report_fatal_error("unsupported architecture"); 569 } 570 IRB.CreateCall(Asm, PtrLong); 571 } 572 573 void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { 574 IRBuilder<> IRB(MI); 575 if (isa<MemTransferInst>(MI)) { 576 IRB.CreateCall( 577 isa<MemMoveInst>(MI) ? HWAsanMemmove : HWAsanMemcpy, 578 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), 579 IRB.CreatePointerCast(MI->getOperand(1), IRB.getInt8PtrTy()), 580 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); 581 } else if (isa<MemSetInst>(MI)) { 582 IRB.CreateCall( 583 HWAsanMemset, 584 {IRB.CreatePointerCast(MI->getOperand(0), IRB.getInt8PtrTy()), 585 IRB.CreateIntCast(MI->getOperand(1), IRB.getInt32Ty(), false), 586 IRB.CreateIntCast(MI->getOperand(2), IntptrTy, false)}); 587 } 588 MI->eraseFromParent(); 589 } 590 591 bool HWAddressSanitizer::instrumentMemAccess(Instruction *I) { 592 LLVM_DEBUG(dbgs() << "Instrumenting: " << *I << "\n"); 593 bool IsWrite = false; 594 unsigned Alignment = 0; 595 uint64_t TypeSize = 0; 596 Value *MaybeMask = nullptr; 597 598 if (ClInstrumentMemIntrinsics && isa<MemIntrinsic>(I)) { 599 instrumentMemIntrinsic(cast<MemIntrinsic>(I)); 600 return true; 601 } 602 603 Value *Addr = 604 isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment, &MaybeMask); 605 606 if (!Addr) 607 return false; 608 609 if (MaybeMask) 610 return false; //FIXME 611 612 IRBuilder<> IRB(I); 613 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy); 614 if (isPowerOf2_64(TypeSize) && 615 (TypeSize / 8 <= (1UL << (kNumberOfAccessSizes - 1))) && 616 (Alignment >= (1UL << Mapping.Scale) || Alignment == 0 || 617 Alignment >= TypeSize / 8)) { 618 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); 619 if (ClInstrumentWithCalls) { 620 IRB.CreateCall(HwasanMemoryAccessCallback[IsWrite][AccessSizeIndex], 621 AddrLong); 622 } else { 623 instrumentMemAccessInline(AddrLong, IsWrite, AccessSizeIndex, I); 624 } 625 } else { 626 IRB.CreateCall(HwasanMemoryAccessCallbackSized[IsWrite], 627 {AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8)}); 628 } 629 untagPointerOperand(I, Addr); 630 631 return true; 632 } 633 634 static uint64_t getAllocaSizeInBytes(const AllocaInst &AI) { 635 uint64_t ArraySize = 1; 636 if (AI.isArrayAllocation()) { 637 const ConstantInt *CI = dyn_cast<ConstantInt>(AI.getArraySize()); 638 assert(CI && "non-constant array size"); 639 ArraySize = CI->getZExtValue(); 640 } 641 Type *Ty = AI.getAllocatedType(); 642 uint64_t SizeInBytes = AI.getModule()->getDataLayout().getTypeAllocSize(Ty); 643 return SizeInBytes * ArraySize; 644 } 645 646 bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, 647 Value *Tag) { 648 size_t Size = (getAllocaSizeInBytes(*AI) + Mapping.getAllocaAlignment() - 1) & 649 ~(Mapping.getAllocaAlignment() - 1); 650 651 Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); 652 if (ClInstrumentWithCalls) { 653 IRB.CreateCall(HwasanTagMemoryFunc, 654 {IRB.CreatePointerCast(AI, Int8PtrTy), JustTag, 655 ConstantInt::get(IntptrTy, Size)}); 656 } else { 657 size_t ShadowSize = Size >> Mapping.Scale; 658 Value *ShadowPtr = IRB.CreateIntToPtr( 659 memToShadow(IRB.CreatePointerCast(AI, IntptrTy), AI->getType(), IRB), 660 Int8PtrTy); 661 // If this memset is not inlined, it will be intercepted in the hwasan 662 // runtime library. That's OK, because the interceptor skips the checks if 663 // the address is in the shadow region. 664 // FIXME: the interceptor is not as fast as real memset. Consider lowering 665 // llvm.memset right here into either a sequence of stores, or a call to 666 // hwasan_tag_memory. 667 IRB.CreateMemSet(ShadowPtr, JustTag, ShadowSize, /*Align=*/1); 668 } 669 return true; 670 } 671 672 static unsigned RetagMask(unsigned AllocaNo) { 673 // A list of 8-bit numbers that have at most one run of non-zero bits. 674 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these 675 // masks. 676 // The list does not include the value 255, which is used for UAR. 677 static unsigned FastMasks[] = { 678 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24, 679 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120, 680 124, 126, 127, 128, 192, 224, 240, 248, 252, 254}; 681 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))]; 682 } 683 684 Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) { 685 return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy); 686 } 687 688 Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { 689 if (ClGenerateTagsWithCalls) 690 return getNextTagWithCall(IRB); 691 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend 692 // first). 693 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 694 auto GetStackPointerFn = 695 Intrinsic::getDeclaration(M, Intrinsic::frameaddress); 696 Value *StackPointer = IRB.CreateCall( 697 GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())}); 698 699 // Extract some entropy from the stack pointer for the tags. 700 // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ 701 // between functions). 702 Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy); 703 Value *StackTag = 704 IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20), 705 "hwasan.stack.base.tag"); 706 return StackTag; 707 } 708 709 Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag, 710 AllocaInst *AI, unsigned AllocaNo) { 711 if (ClGenerateTagsWithCalls) 712 return getNextTagWithCall(IRB); 713 return IRB.CreateXor(StackTag, 714 ConstantInt::get(IntptrTy, RetagMask(AllocaNo))); 715 } 716 717 Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) { 718 if (ClUARRetagToZero) 719 return ConstantInt::get(IntptrTy, 0); 720 if (ClGenerateTagsWithCalls) 721 return getNextTagWithCall(IRB); 722 return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU)); 723 } 724 725 // Add a tag to an address. 726 Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty, 727 Value *PtrLong, Value *Tag) { 728 Value *TaggedPtrLong; 729 if (CompileKernel) { 730 // Kernel addresses have 0xFF in the most significant byte. 731 Value *ShiftedTag = IRB.CreateOr( 732 IRB.CreateShl(Tag, kPointerTagShift), 733 ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1)); 734 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag); 735 } else { 736 // Userspace can simply do OR (tag << 56); 737 Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift); 738 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag); 739 } 740 return IRB.CreateIntToPtr(TaggedPtrLong, Ty); 741 } 742 743 // Remove tag from an address. 744 Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) { 745 Value *UntaggedPtrLong; 746 if (CompileKernel) { 747 // Kernel addresses have 0xFF in the most significant byte. 748 UntaggedPtrLong = IRB.CreateOr(PtrLong, 749 ConstantInt::get(PtrLong->getType(), 0xFFULL << kPointerTagShift)); 750 } else { 751 // Userspace addresses have 0x00. 752 UntaggedPtrLong = IRB.CreateAnd(PtrLong, 753 ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift))); 754 } 755 return UntaggedPtrLong; 756 } 757 758 Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) { 759 Module *M = IRB.GetInsertBlock()->getParent()->getParent(); 760 if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) { 761 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER 762 // in Bionic's libc/private/bionic_tls.h. 763 Function *ThreadPointerFunc = 764 Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); 765 Value *SlotPtr = IRB.CreatePointerCast( 766 IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), 0x30), 767 Ty->getPointerTo(0)); 768 return SlotPtr; 769 } 770 if (ThreadPtrGlobal) 771 return ThreadPtrGlobal; 772 773 774 return nullptr; 775 } 776 777 // Creates a string with a description of the stack frame (set of Allocas). 778 // The string is intended to be human readable. 779 // The current form is: Size1 Name1; Size2 Name2; ... 780 std::string 781 HWAddressSanitizer::createFrameString(ArrayRef<AllocaInst *> Allocas) { 782 std::ostringstream Descr; 783 for (auto AI : Allocas) 784 Descr << getAllocaSizeInBytes(*AI) << " " << AI->getName().str() << "; "; 785 return Descr.str(); 786 } 787 788 // Creates a global in the frame section which consists of two pointers: 789 // the function PC and the frame string constant. 790 void HWAddressSanitizer::createFrameGlobal(Function &F, 791 const std::string &FrameString) { 792 Module &M = *F.getParent(); 793 auto DescrGV = createPrivateGlobalForString(M, FrameString, true); 794 auto PtrPairTy = StructType::get(F.getType(), DescrGV->getType()); 795 auto GV = new GlobalVariable( 796 M, PtrPairTy, /*isConstantGlobal*/ true, GlobalVariable::PrivateLinkage, 797 ConstantStruct::get(PtrPairTy, (Constant *)&F, (Constant *)DescrGV), 798 "__hwasan"); 799 GV->setSection(getFrameSection()); 800 appendToCompilerUsed(M, GV); 801 // Put GV into the F's Comadat so that if F is deleted GV can be deleted too. 802 if (auto Comdat = 803 GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) 804 GV->setComdat(Comdat); 805 } 806 807 Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, 808 bool WithFrameRecord) { 809 if (!Mapping.InTls) 810 return getDynamicShadowNonTls(IRB); 811 812 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); 813 assert(SlotPtr); 814 815 Instruction *ThreadLong = IRB.CreateLoad(SlotPtr); 816 817 Function *F = IRB.GetInsertBlock()->getParent(); 818 if (F->getFnAttribute("hwasan-abi").getValueAsString() == "interceptor") { 819 Value *ThreadLongEqZero = 820 IRB.CreateICmpEQ(ThreadLong, ConstantInt::get(IntptrTy, 0)); 821 auto *Br = cast<BranchInst>(SplitBlockAndInsertIfThen( 822 ThreadLongEqZero, cast<Instruction>(ThreadLongEqZero)->getNextNode(), 823 false, MDBuilder(*C).createBranchWeights(1, 100000))); 824 825 IRB.SetInsertPoint(Br); 826 // FIXME: This should call a new runtime function with a custom calling 827 // convention to avoid needing to spill all arguments here. 828 IRB.CreateCall(HwasanThreadEnterFunc); 829 LoadInst *ReloadThreadLong = IRB.CreateLoad(SlotPtr); 830 831 IRB.SetInsertPoint(&*Br->getSuccessor(0)->begin()); 832 PHINode *ThreadLongPhi = IRB.CreatePHI(IntptrTy, 2); 833 ThreadLongPhi->addIncoming(ThreadLong, ThreadLong->getParent()); 834 ThreadLongPhi->addIncoming(ReloadThreadLong, ReloadThreadLong->getParent()); 835 ThreadLong = ThreadLongPhi; 836 } 837 838 // Extract the address field from ThreadLong. Unnecessary on AArch64 with TBI. 839 Value *ThreadLongMaybeUntagged = 840 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong); 841 842 if (WithFrameRecord) { 843 // Prepare ring buffer data. 844 auto PC = IRB.CreatePtrToInt(F, IntptrTy); 845 auto GetStackPointerFn = 846 Intrinsic::getDeclaration(F->getParent(), Intrinsic::frameaddress); 847 Value *SP = IRB.CreatePtrToInt( 848 IRB.CreateCall(GetStackPointerFn, 849 {Constant::getNullValue(IRB.getInt32Ty())}), 850 IntptrTy); 851 // Mix SP and PC. TODO: also add the tag to the mix. 852 // Assumptions: 853 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero) 854 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero) 855 // We only really need ~20 lower non-zero bits (SSSS), so we mix like this: 856 // 0xSSSSPPPPPPPPPPPP 857 SP = IRB.CreateShl(SP, 44); 858 859 // Store data to ring buffer. 860 Value *RecordPtr = 861 IRB.CreateIntToPtr(ThreadLongMaybeUntagged, IntptrTy->getPointerTo(0)); 862 IRB.CreateStore(IRB.CreateOr(PC, SP), RecordPtr); 863 864 // Update the ring buffer. Top byte of ThreadLong defines the size of the 865 // buffer in pages, it must be a power of two, and the start of the buffer 866 // must be aligned by twice that much. Therefore wrap around of the ring 867 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12). 868 // The use of AShr instead of LShr is due to 869 // https://bugs.llvm.org/show_bug.cgi?id=39030 870 // Runtime library makes sure not to use the highest bit. 871 Value *WrapMask = IRB.CreateXor( 872 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true), 873 ConstantInt::get(IntptrTy, (uint64_t)-1)); 874 Value *ThreadLongNew = IRB.CreateAnd( 875 IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask); 876 IRB.CreateStore(ThreadLongNew, SlotPtr); 877 } 878 879 // Get shadow base address by aligning RecordPtr up. 880 // Note: this is not correct if the pointer is already aligned. 881 // Runtime library will make sure this never happens. 882 Value *ShadowBase = IRB.CreateAdd( 883 IRB.CreateOr( 884 ThreadLongMaybeUntagged, 885 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)), 886 ConstantInt::get(IntptrTy, 1), "hwasan.shadow"); 887 return ShadowBase; 888 } 889 890 bool HWAddressSanitizer::instrumentStack( 891 SmallVectorImpl<AllocaInst *> &Allocas, 892 SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) { 893 // Ideally, we want to calculate tagged stack base pointer, and rewrite all 894 // alloca addresses using that. Unfortunately, offsets are not known yet 895 // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a 896 // temp, shift-OR it into each alloca address and xor with the retag mask. 897 // This generates one extra instruction per alloca use. 898 for (unsigned N = 0; N < Allocas.size(); ++N) { 899 auto *AI = Allocas[N]; 900 IRBuilder<> IRB(AI->getNextNode()); 901 902 // Replace uses of the alloca with tagged address. 903 Value *Tag = getAllocaTag(IRB, StackTag, AI, N); 904 Value *AILong = IRB.CreatePointerCast(AI, IntptrTy); 905 Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag); 906 std::string Name = 907 AI->hasName() ? AI->getName().str() : "alloca." + itostr(N); 908 Replacement->setName(Name + ".hwasan"); 909 910 for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) { 911 Use &U = *UI++; 912 if (U.getUser() != AILong) 913 U.set(Replacement); 914 } 915 916 tagAlloca(IRB, AI, Tag); 917 918 for (auto RI : RetVec) { 919 IRB.SetInsertPoint(RI); 920 921 // Re-tag alloca memory with the special UAR tag. 922 Value *Tag = getUARTag(IRB, StackTag); 923 tagAlloca(IRB, AI, Tag); 924 } 925 } 926 927 return true; 928 } 929 930 bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) { 931 return (AI.getAllocatedType()->isSized() && 932 // FIXME: instrument dynamic allocas, too 933 AI.isStaticAlloca() && 934 // alloca() may be called with 0 size, ignore it. 935 getAllocaSizeInBytes(AI) > 0 && 936 // We are only interested in allocas not promotable to registers. 937 // Promotable allocas are common under -O0. 938 !isAllocaPromotable(&AI) && 939 // inalloca allocas are not treated as static, and we don't want 940 // dynamic alloca instrumentation for them as well. 941 !AI.isUsedWithInAlloca() && 942 // swifterror allocas are register promoted by ISel 943 !AI.isSwiftError()); 944 } 945 946 bool HWAddressSanitizer::runOnFunction(Function &F) { 947 if (&F == HwasanCtorFunction) 948 return false; 949 950 if (!F.hasFnAttribute(Attribute::SanitizeHWAddress)) 951 return false; 952 953 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n"); 954 955 SmallVector<Instruction*, 16> ToInstrument; 956 SmallVector<AllocaInst*, 8> AllocasToInstrument; 957 SmallVector<Instruction*, 8> RetVec; 958 for (auto &BB : F) { 959 for (auto &Inst : BB) { 960 if (ClInstrumentStack) 961 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { 962 // Realign all allocas. We don't want small uninteresting allocas to 963 // hide in instrumented alloca's padding. 964 if (AI->getAlignment() < Mapping.getAllocaAlignment()) 965 AI->setAlignment(Mapping.getAllocaAlignment()); 966 // Instrument some of them. 967 if (isInterestingAlloca(*AI)) 968 AllocasToInstrument.push_back(AI); 969 continue; 970 } 971 972 if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) || 973 isa<CleanupReturnInst>(Inst)) 974 RetVec.push_back(&Inst); 975 976 Value *MaybeMask = nullptr; 977 bool IsWrite; 978 unsigned Alignment; 979 uint64_t TypeSize; 980 Value *Addr = isInterestingMemoryAccess(&Inst, &IsWrite, &TypeSize, 981 &Alignment, &MaybeMask); 982 if (Addr || isa<MemIntrinsic>(Inst)) 983 ToInstrument.push_back(&Inst); 984 } 985 } 986 987 if (AllocasToInstrument.empty() && ToInstrument.empty()) 988 return false; 989 990 if (ClCreateFrameDescriptions && !AllocasToInstrument.empty()) 991 createFrameGlobal(F, createFrameString(AllocasToInstrument)); 992 993 initializeCallbacks(*F.getParent()); 994 995 assert(!LocalDynamicShadow); 996 997 Instruction *InsertPt = &*F.getEntryBlock().begin(); 998 IRBuilder<> EntryIRB(InsertPt); 999 LocalDynamicShadow = emitPrologue(EntryIRB, 1000 /*WithFrameRecord*/ ClRecordStackHistory && 1001 !AllocasToInstrument.empty()); 1002 1003 bool Changed = false; 1004 if (!AllocasToInstrument.empty()) { 1005 Value *StackTag = 1006 ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB); 1007 Changed |= instrumentStack(AllocasToInstrument, RetVec, StackTag); 1008 } 1009 1010 for (auto Inst : ToInstrument) 1011 Changed |= instrumentMemAccess(Inst); 1012 1013 LocalDynamicShadow = nullptr; 1014 1015 return Changed; 1016 } 1017 1018 void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple) { 1019 Scale = kDefaultShadowScale; 1020 if (ClMappingOffset.getNumOccurrences() > 0) { 1021 InGlobal = false; 1022 InTls = false; 1023 Offset = ClMappingOffset; 1024 } else if (ClEnableKhwasan || ClInstrumentWithCalls) { 1025 InGlobal = false; 1026 InTls = false; 1027 Offset = 0; 1028 } else if (ClWithIfunc) { 1029 InGlobal = true; 1030 InTls = false; 1031 Offset = kDynamicShadowSentinel; 1032 } else if (ClWithTls) { 1033 InGlobal = false; 1034 InTls = true; 1035 Offset = kDynamicShadowSentinel; 1036 } else { 1037 InGlobal = false; 1038 InTls = false; 1039 Offset = kDynamicShadowSentinel; 1040 } 1041 } 1042