1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 13:11:39 +01:00

[compiler-rt][hwasan] Decouple use of the TLS global for getting the shadow base and using the frame record feature

This allows for using the frame record feature (which uses __hwasan_tls)
independently from however the user wants to access the shadow base, which
prior was only usable if shadow wasn't accessed through the TLS variable or ifuncs.

Frame recording can be explicitly set according to ShadowMapping::WithFrameRecord
in ShadowMapping::init. Currently, it is only enabled on Fuchsia and if TLS is
used, so this should mimic the old behavior.

Added an extra case to prologue.ll that covers this new case.

Differential Revision: https://reviews.llvm.org/D103841
This commit is contained in:
Leonard Chan 2021-06-07 14:27:07 -07:00
parent c35099a5e4
commit fca9191cc7
2 changed files with 41 additions and 24 deletions

View File

@ -264,11 +264,15 @@ private:
/// 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 @@ Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) {
}
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 @@ void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
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 @@ bool HWAddressSanitizer::sanitizeFunction(Function &F) {
IRBuilder<> EntryIRB(InsertPt);
emitPrologue(EntryIRB,
/*WithFrameRecord*/ ClRecordStackHistory &&
!AllocasToInstrument.empty());
Mapping.WithFrameRecord && !AllocasToInstrument.empty());
if (!AllocasToInstrument.empty()) {
Value *StackTag =
@ -1540,25 +1544,31 @@ void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple,
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;
}
}

View File

@ -1,15 +1,17 @@
; 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,CHECK-HISTORY-TLS-SLOT
; 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,CHECK-HISTORY-TLS-SLOT
; 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 | \
; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-GLOBAL,CHECK-NOHISTORY
; RUN: opt -hwasan -S -hwasan-with-ifunc=1 -hwasan-with-tls=0 < %s | \
; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC,CHECK-NOHISTORY
; RUN: opt -hwasan -S -mtriple=aarch64-fuchsia < %s | \
; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-ZERO-OFFSET,CHECK-SHORT-GRANULES,CHECK-HISTORY,CHECK-HWASAN-TLS,CHECK-HISTORY-HWASAN-TLS
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-android22"
@ -25,6 +27,8 @@ define i32 @test_load(i32* %a) sanitize_hwaddress {
; 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 +56,13 @@ define void @test_alloca() sanitize_hwaddress {
; 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
@ -68,7 +74,8 @@ define void @test_alloca() sanitize_hwaddress {
; CHECK-HISTORY: %[[D3:[^ ]*]] = xor i64 %[[D2]], -1
; CHECK-HISTORY: %[[D4:[^ ]*]] = add i64 %[[D]], 8
; CHECK-HISTORY: %[[D5:[^ ]*]] = and i64 %[[D4]], %[[D3]]
; CHECK-HISTORY: store i64 %[[D5]], i64* %[[C]]
; CHECK-HISTORY-TLS-SLOT: store i64 %[[D5]], i64* %[[C]]
; CHECK-HISTORY-HWASAN-TLS: store i64 %[[D5]], i64* @__hwasan_tls
; CHECK-TLS: %[[F:[^ ]*]] = or i64 %[[D]], 4294967295
; CHECK-TLS: = add i64 %[[F]], 1