diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -264,11 +264,15 @@ /// If InTls is true, then /// extern char *__hwasan_tls; /// shadow = (mem>>Scale) + align_up(__hwasan_shadow, kShadowBaseAlignment) + /// + /// If WithFrameRecord is true, then __hwasan_tls will be used to access the + /// ring buffer for storing stack allocations on targets that support it. struct ShadowMapping { int Scale; uint64_t Offset; bool InGlobal; bool InTls; + bool WithFrameRecord; void init(Triple &TargetTriple, bool InstrumentWithCalls); unsigned getObjectAlignment() const { return 1U << Scale; } @@ -1042,15 +1046,13 @@ } void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { - if (!Mapping.InTls) { + if (!Mapping.InTls) ShadowBase = getShadowNonTls(IRB); - return; - } - - if (!WithFrameRecord && TargetTriple.isAndroid()) { + else if (!WithFrameRecord && TargetTriple.isAndroid()) ShadowBase = getDynamicShadowIfunc(IRB); + + if (!WithFrameRecord && ShadowBase) return; - } Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); assert(SlotPtr); @@ -1106,15 +1108,17 @@ IRB.CreateStore(ThreadLongNew, SlotPtr); } - // Get shadow base address by aligning RecordPtr up. - // Note: this is not correct if the pointer is already aligned. - // Runtime library will make sure this never happens. - ShadowBase = IRB.CreateAdd( - IRB.CreateOr( - ThreadLongMaybeUntagged, - ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)), - ConstantInt::get(IntptrTy, 1), "hwasan.shadow"); - ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy); + if (!ShadowBase) { + // Get shadow base address by aligning RecordPtr up. + // Note: this is not correct if the pointer is already aligned. + // Runtime library will make sure this never happens. + ShadowBase = IRB.CreateAdd( + IRB.CreateOr( + ThreadLongMaybeUntagged, + ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)), + ConstantInt::get(IntptrTy, 1), "hwasan.shadow"); + ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy); + } } Value *HWAddressSanitizer::readRegister(IRBuilder<> &IRB, StringRef Name) { @@ -1273,7 +1277,7 @@ IRBuilder<> EntryIRB(InsertPt); emitPrologue(EntryIRB, /*WithFrameRecord*/ ClRecordStackHistory && - !AllocasToInstrument.empty()); + Mapping.WithFrameRecord && !AllocasToInstrument.empty()); if (!AllocasToInstrument.empty()) { Value *StackTag = @@ -1540,25 +1544,31 @@ InGlobal = false; InTls = false; Offset = 0; + WithFrameRecord = true; } else if (ClMappingOffset.getNumOccurrences() > 0) { InGlobal = false; InTls = false; Offset = ClMappingOffset; + WithFrameRecord = false; } else if (ClEnableKhwasan || InstrumentWithCalls) { InGlobal = false; InTls = false; Offset = 0; + WithFrameRecord = false; } else if (ClWithIfunc) { InGlobal = true; InTls = false; Offset = kDynamicShadowSentinel; + WithFrameRecord = false; } else if (ClWithTls) { InGlobal = false; InTls = true; Offset = kDynamicShadowSentinel; + WithFrameRecord = true; } else { InGlobal = false; InTls = false; Offset = kDynamicShadowSentinel; + WithFrameRecord = false; } } diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll @@ -1,9 +1,9 @@ ; Test -hwasan-with-ifunc flag. ; ; RUN: opt -hwasan -S < %s | \ -; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOGLOBAL,CHECK-TLS,CHECK-HISTORY +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOGLOBAL,CHECK-TLS-SLOT,CHECK-HISTORY ; RUN: opt -hwasan -S -hwasan-with-ifunc=0 -hwasan-with-tls=1 -hwasan-record-stack-history=1 < %s | \ -; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOGLOBAL,CHECK-TLS,CHECK-HISTORY +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOGLOBAL,CHECK-TLS-SLOT,CHECK-HISTORY ; RUN: opt -hwasan -S -hwasan-with-ifunc=0 -hwasan-with-tls=1 -hwasan-record-stack-history=0 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOGLOBAL,CHECK-IFUNC,CHECK-NOHISTORY ; RUN: opt -hwasan -S -hwasan-with-ifunc=0 -hwasan-with-tls=0 < %s | \ @@ -25,6 +25,8 @@ ; CHECK-NOGLOBAL: %[[A:[^ ]*]] = call i8* asm "", "=r,0"([0 x i8]* @__hwasan_shadow) ; CHECK-NOGLOBAL: @llvm.hwasan.check.memaccess(i8* %[[A]] +; CHECK-ZERO-OFFSET: %[[A:[^ ]*]] = call i8* asm "", "=r,0"(i8* null) +; CHECK-SHORT-GRANULES: @llvm.hwasan.check.memaccess.shortgranules(i8* %[[A]] ; CHECK-GLOBAL: load i8*, i8** @__hwasan_shadow_memory_dynamic_address @@ -52,11 +54,13 @@ ; CHECK-GLOBAL: load i8*, i8** @__hwasan_shadow_memory_dynamic_address -; CHECK-TLS: %[[A:[^ ]*]] = call i8* @llvm.thread.pointer() -; CHECK-TLS: %[[B:[^ ]*]] = getelementptr i8, i8* %[[A]], i32 48 -; CHECK-TLS: %[[C:[^ ]*]] = bitcast i8* %[[B]] to i64* -; CHECK-TLS: %[[D:[^ ]*]] = load i64, i64* %[[C]] -; CHECK-TLS: %[[E:[^ ]*]] = ashr i64 %[[D]], 3 +; CHECK-TLS-SLOT: %[[A:[^ ]*]] = call i8* @llvm.thread.pointer() +; CHECK-TLS-SLOT: %[[B:[^ ]*]] = getelementptr i8, i8* %[[A]], i32 48 +; CHECK-TLS-SLOT: %[[C:[^ ]*]] = bitcast i8* %[[B]] to i64* +; CHECK-TLS-SLOT: %[[D:[^ ]*]] = load i64, i64* %[[C]] +; CHECK-TLS-SLOT: %[[E:[^ ]*]] = ashr i64 %[[D]], 3 +; CHECK-HWASAN-TLS: $[[D:[^ ]*]] = load i64, i64* @__hwasan_tls, align 8 +; CHECK-HWASAN-TLS: %[[E:[^ ]*]] = ashr i64 %[[D]], 3 ; CHECK-NOHISTORY-NOT: store i64