Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -1011,12 +1011,10 @@ 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, Index: lib/CodeGen/StackProtector.cpp =================================================================== --- lib/CodeGen/StackProtector.cpp +++ lib/CodeGen/StackProtector.cpp @@ -333,24 +333,20 @@ 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); - - StackGuardVar = - ConstantExpr::getIntToPtr(OffsetVal, PointerType::get(PtrTy, - AddressSpace)); - } else if (TT.isOSOpenBSD()) { - StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy); - cast(StackGuardVar) - ->setVisibility(GlobalValue::HiddenVisibility); - } else { - SupportsSelectionDAGSP = true; - StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + IRBuilder<> B(&F->getEntryBlock().front()); + + StackGuardVar = TLI->getStackCookieLocation(B); + if (!StackGuardVar) { + if (TT.isOSOpenBSD()) { + StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy); + cast(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), Index: lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.h +++ lib/Target/AArch64/AArch64ISelLowering.h @@ -358,6 +358,10 @@ 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; Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10212,6 +10212,22 @@ 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); Index: lib/Target/X86/X86ISelLowering.h =================================================================== --- lib/Target/X86/X86ISelLowering.h +++ lib/Target/X86/X86ISelLowering.h @@ -960,11 +960,9 @@ 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 Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -2193,16 +2193,17 @@ 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 { Index: test/CodeGen/AArch64/stack-protector-target.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/stack-protector-target.ll @@ -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]] Index: test/CodeGen/X86/stack-protector-target.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/stack-protector-target.ll @@ -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]]