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