Faster stack-protector for Android/AArch64.

Bionic has a defined thread-local location for the stack protector
cookie. Emit a direct load instead of going through __stack_chk_guard.

llvm-svn: 265481
This commit is contained in:
Evgeniy Stepanov 2016-04-05 22:41:50 +00:00
parent d8f96bea63
commit c80f414fe8
8 changed files with 89 additions and 32 deletions

View File

@ -1011,12 +1011,10 @@ public:
return PrefLoopAlignment;
}
/// Return true if the target stores stack protector cookies at a fixed offset
/// in some non-standard address space, and populates the address space and
/// offset as appropriate.
virtual bool getStackCookieLocation(unsigned &/*AddressSpace*/,
unsigned &/*Offset*/) const {
return false;
/// If the target has a standard location for the stack protector cookie,
/// returns the address of that location. Otherwise, returns nullptr.
virtual Value *getStackCookieLocation(IRBuilder<> &IRB) const {
return nullptr;
}
/// If the target has a standard location for the unsafe stack pointer,

View File

@ -333,24 +333,20 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI,
AllocaInst *&AI, Value *&StackGuardVar) {
bool SupportsSelectionDAGSP = false;
PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext());
unsigned AddressSpace, Offset;
if (TLI->getStackCookieLocation(AddressSpace, Offset)) {
Constant *OffsetVal =
ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset);
IRBuilder<> B(&F->getEntryBlock().front());
StackGuardVar =
ConstantExpr::getIntToPtr(OffsetVal, PointerType::get(PtrTy,
AddressSpace));
} else if (TT.isOSOpenBSD()) {
StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy);
cast<GlobalValue>(StackGuardVar)
->setVisibility(GlobalValue::HiddenVisibility);
} else {
SupportsSelectionDAGSP = true;
StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy);
StackGuardVar = TLI->getStackCookieLocation(B);
if (!StackGuardVar) {
if (TT.isOSOpenBSD()) {
StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy);
cast<GlobalValue>(StackGuardVar)
->setVisibility(GlobalValue::HiddenVisibility);
} else {
SupportsSelectionDAGSP = true;
StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy);
}
}
IRBuilder<> B(&F->getEntryBlock().front());
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
LoadInst *LI = B.CreateLoad(StackGuardVar, "StackGuard");
B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),

View File

@ -10212,6 +10212,22 @@ bool AArch64TargetLowering::shouldNormalizeToSelectSequence(LLVMContext &,
return false;
}
Value *AArch64TargetLowering::getStackCookieLocation(IRBuilder<> &IRB) const {
if (!Subtarget->isTargetAndroid())
return TargetLowering::getStackCookieLocation(IRB);
// Android provides a fixed TLS slot for the stack cookie. See the definition
// of TLS_SLOT_STACK_GUARD in
// https://android.googlesource.com/platform/bionic/+/master/libc/private/bionic_tls.h
const unsigned TlsOffset = 0x28;
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
Function *ThreadPointerFunc =
Intrinsic::getDeclaration(M, Intrinsic::aarch64_thread_pointer);
return IRB.CreatePointerCast(
IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), TlsOffset),
Type::getInt8PtrTy(IRB.getContext())->getPointerTo(0));
}
Value *AArch64TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const {
if (!Subtarget->isTargetAndroid())
return TargetLowering::getSafeStackPointerLocation(IRB);

View File

@ -358,6 +358,10 @@ public:
TargetLoweringBase::LegalizeTypeAction
getPreferredVectorAction(EVT VT) const override;
/// If the target has a standard location for the stack protector cookie,
/// returns the address of that location. Otherwise, returns nullptr.
Value *getStackCookieLocation(IRBuilder<> &IRB) const override;
/// If the target has a standard location for the unsafe stack pointer,
/// returns the address of that location. Otherwise, returns nullptr.
Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const override;

View File

@ -2193,16 +2193,17 @@ unsigned X86TargetLowering::getAddressSpace() const {
return 256;
}
bool X86TargetLowering::getStackCookieLocation(unsigned &AddressSpace,
unsigned &Offset) const {
Value *X86TargetLowering::getStackCookieLocation(IRBuilder<> &IRB) const {
if (!Subtarget.isTargetLinux())
return false;
return TargetLowering::getStackCookieLocation(IRB);
// %fs:0x28, unless we're using a Kernel code model, in which case it's %gs:
// %gs:0x14 on i386
Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14;
AddressSpace = getAddressSpace();
return true;
unsigned Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14;
unsigned AddressSpace = getAddressSpace();
return ConstantExpr::getIntToPtr(
ConstantInt::get(Type::getInt32Ty(IRB.getContext()), Offset),
Type::getInt8PtrTy(IRB.getContext())->getPointerTo(AddressSpace));
}
Value *X86TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const {

View File

@ -960,11 +960,9 @@ namespace llvm {
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo) const override;
/// Return true if the target stores stack protector cookies at a fixed
/// offset in some non-standard address space, and populates the address
/// space and offset as appropriate.
bool getStackCookieLocation(unsigned &AddressSpace,
unsigned &Offset) const override;
/// If the target has a standard location for the stack protector cookie,
/// returns the address of that location. Otherwise, returns nullptr.
Value *getStackCookieLocation(IRBuilder<> &IRB) const override;
/// Return true if the target stores SafeStack pointer at a fixed offset in
/// some non-standard address space, and populates the address space and

View File

@ -0,0 +1,19 @@
; Test target-specific stack cookie location.
; RUN: llc -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefix=ANDROID-AARCH64 %s
define void @_Z1fv() sspreq {
entry:
%x = alloca i32, align 4
%0 = bitcast i32* %x to i8*
call void @_Z7CapturePi(i32* nonnull %x)
ret void
}
declare void @_Z7CapturePi(i32*)
; ANDROID-AARCH64: mrs [[A:.*]], TPIDR_EL0
; ANDROID-AARCH64: ldr [[B:.*]], {{\[}}[[A]], #40]
; ANDROID-AARCH64: str [[B]], [sp,
; ANDROID-AARCH64: ldr [[C:.*]], {{\[}}[[A]], #40]
; ANDROID-AARCH64: ldr [[D:.*]], [sp,
; ANDROID-AARCH64: cmp [[C]], [[D]]

View File

@ -0,0 +1,25 @@
; Test target-specific stack cookie location.
; RUN: llc -mtriple=i386-linux < %s -o - | FileCheck --check-prefix=LINUX-I386 %s
; RUN: llc -mtriple=x86_64-linux < %s -o - | FileCheck --check-prefix=LINUX-X64 %s
; RUN: llc -mtriple=i386-linux-android < %s -o - | FileCheck --check-prefix=LINUX-I386 %s
; RUN: llc -mtriple=x86_64-linux-android < %s -o - | FileCheck --check-prefix=LINUX-X64 %s
define void @_Z1fv() sspreq {
entry:
%x = alloca i32, align 4
%0 = bitcast i32* %x to i8*
call void @_Z7CapturePi(i32* nonnull %x)
ret void
}
declare void @_Z7CapturePi(i32*)
; LINUX-X64: movq %fs:40, %[[B:.*]]
; LINUX-X64: movq %[[B]], 16(%rsp)
; LINUX-X64: movq %fs:40, %[[C:.*]]
; LINUX-X64: cmpq 16(%rsp), %[[C]]
; LINUX-I386: movl %gs:20, %[[B:.*]]
; LINUX-I386: movl %[[B]], 8(%esp)
; LINUX-I386: movl %gs:20, %[[C:.*]]
; LINUX-I386: cmpl 8(%esp), %[[C]]