From 844145720c0895226ab7cc4124af8ea19da57a5b Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 15 Oct 2015 21:26:49 +0000 Subject: [PATCH] Revert "[safestack] Fast access to the unsafe stack pointer on AArch64/Android." Breaks the hexagon buildbot. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250461 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 10 ++-- lib/CodeGen/TargetLoweringBase.cpp | 34 ------------ lib/Target/AArch64/AArch64ISelLowering.cpp | 16 ------ lib/Target/AArch64/AArch64ISelLowering.h | 4 -- lib/Target/X86/X86ISelLowering.cpp | 17 +++--- lib/Target/X86/X86ISelLowering.h | 3 +- lib/Transforms/Instrumentation/SafeStack.cpp | 57 +++++++++++++++++++- test/Transforms/SafeStack/AArch64/abi.ll | 4 +- 8 files changed, 73 insertions(+), 72 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 310091ca2b6..10194e37fef 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -995,9 +995,13 @@ public: return false; } - /// If the target has a standard location for the unsafe stack pointer, - /// returns the address of that location. Otherwise, returns nullptr. - virtual Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const; + /// Return true if the target stores SafeStack pointer at a fixed offset in + /// some non-standard address space, and populates the address space and + /// offset as appropriate. + virtual bool getSafeStackPointerLocation(unsigned & /*AddressSpace*/, + unsigned & /*Offset*/) const { + return false; + } /// Returns true if a cast between SrcAS and DestAS is a noop. virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp index 6de59b93331..7250fdc9385 100644 --- a/lib/CodeGen/TargetLoweringBase.cpp +++ b/lib/CodeGen/TargetLoweringBase.cpp @@ -1662,40 +1662,6 @@ TargetLoweringBase::getTypeLegalizationCost(const DataLayout &DL, } } -Value *TargetLoweringBase::getSafeStackPointerLocation(IRBuilder<> &IRB) const { - Module *M = IRB.GetInsertBlock()->getParent()->getParent(); - Type *StackPtrTy = Type::getInt8PtrTy(M->getContext()); - if (TM.getTargetTriple().getEnvironment() == llvm::Triple::Android) { - // Android provides a libc function to retrieve the address of the current - // thread's unsafe stack pointer. - Value *Fn = M->getOrInsertFunction("__safestack_pointer_address", - StackPtrTy->getPointerTo(0), nullptr); - return IRB.CreateCall(Fn); - } else { - // Otherwise, assume the target links with compiler-rt, which provides a - // thread-local variable with a magic name. - const char *UnsafeStackPtrVar = "__safestack_unsafe_stack_ptr"; - auto UnsafeStackPtr = - dyn_cast_or_null(M->getNamedValue(UnsafeStackPtrVar)); - - if (!UnsafeStackPtr) { - // The global variable is not defined yet, define it ourselves. - // We use the initial-exec TLS model because we do not support the - // variable living anywhere other than in the main executable. - UnsafeStackPtr = new GlobalVariable( - *M, StackPtrTy, false, GlobalValue::ExternalLinkage, 0, - UnsafeStackPtrVar, nullptr, GlobalValue::InitialExecTLSModel); - } else { - // The variable exists, check its type and attributes. - if (UnsafeStackPtr->getValueType() != StackPtrTy) - report_fatal_error(Twine(UnsafeStackPtrVar) + " must have void* type"); - if (!UnsafeStackPtr->isThreadLocal()) - report_fatal_error(Twine(UnsafeStackPtrVar) + " must be thread-local"); - } - return UnsafeStackPtr; - } -} - //===----------------------------------------------------------------------===// // Loop Strength Reduction hooks //===----------------------------------------------------------------------===// diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 93cb5ecdc6e..b8e30921e8a 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9921,19 +9921,3 @@ bool AArch64TargetLowering::shouldNormalizeToSelectSequence(LLVMContext &, EVT) const { return false; } - -Value *AArch64TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const { - if (!Subtarget->isTargetAndroid()) - return TargetLowering::getSafeStackPointerLocation(IRB); - - // Android provides a fixed TLS slot for the SafeStack pointer. See the - // definition of TLS_SLOT_SAFESTACK in - // https://android.googlesource.com/platform/bionic/+/master/libc/private/bionic_tls.h - const unsigned TlsOffset = 0x48; - 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)); -} diff --git a/lib/Target/AArch64/AArch64ISelLowering.h b/lib/Target/AArch64/AArch64ISelLowering.h index 64a2934d1d5..b815f55da6b 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.h +++ b/lib/Target/AArch64/AArch64ISelLowering.h @@ -362,10 +362,6 @@ public: TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(EVT VT) 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; - private: bool isExtFreeImpl(const Instruction *Ext) const override; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9df41ec9e6d..618290a257a 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2086,14 +2086,14 @@ bool X86TargetLowering::getStackCookieLocation(unsigned &AddressSpace, return true; } -Value *X86TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const { +/// Android provides a fixed TLS slot for the SafeStack pointer. +/// See the definition of TLS_SLOT_SAFESTACK in +/// https://android.googlesource.com/platform/bionic/+/master/libc/private/bionic_tls.h +bool X86TargetLowering::getSafeStackPointerLocation(unsigned &AddressSpace, + unsigned &Offset) const { if (!Subtarget->isTargetAndroid()) - return TargetLowering::getSafeStackPointerLocation(IRB); + return false; - // Android provides a fixed TLS slot for the SafeStack pointer. See the - // definition of TLS_SLOT_SAFESTACK in - // https://android.googlesource.com/platform/bionic/+/master/libc/private/bionic_tls.h - unsigned AddressSpace, Offset; if (Subtarget->is64Bit()) { // %fs:0x48, unless we're using a Kernel code model, in which case it's %gs: Offset = 0x48; @@ -2106,10 +2106,7 @@ Value *X86TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const { Offset = 0x24; AddressSpace = 256; } - - return ConstantExpr::getIntToPtr( - ConstantInt::get(Type::getInt32Ty(IRB.getContext()), Offset), - Type::getInt8PtrTy(IRB.getContext())->getPointerTo(AddressSpace)); + return true; } bool X86TargetLowering::isNoopAddrSpaceCast(unsigned SrcAS, diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 713a4d66ad7..0028eb0c82c 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -901,7 +901,8 @@ namespace llvm { /// Return true if the target stores SafeStack pointer at a fixed offset in /// some non-standard address space, and populates the address space and /// offset as appropriate. - Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const override; + bool getSafeStackPointerLocation(unsigned &AddressSpace, + unsigned &Offset) const override; SDValue BuildFILD(SDValue Op, EVT SrcVT, SDValue Chain, SDValue StackSlot, SelectionDAG &DAG) const; diff --git a/lib/Transforms/Instrumentation/SafeStack.cpp b/lib/Transforms/Instrumentation/SafeStack.cpp index ea5b1ee11d7..96ef639138a 100644 --- a/lib/Transforms/Instrumentation/SafeStack.cpp +++ b/lib/Transforms/Instrumentation/SafeStack.cpp @@ -46,6 +46,9 @@ using namespace llvm; #define DEBUG_TYPE "safestack" +static const char *const kUnsafeStackPtrVar = "__safestack_unsafe_stack_ptr"; +static const char *const kUnsafeStackPtrAddrFn = "__safestack_pointer_address"; + namespace llvm { STATISTIC(NumFunctions, "Total number of functions"); @@ -179,6 +182,10 @@ class SafeStack : public FunctionPass { /// might expect to appear on the stack on most common targets. enum { StackAlignment = 16 }; + /// \brief Build a constant representing a pointer to the unsafe stack + /// pointer. + Value *getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F); + /// \brief Find all static allocas, dynamic allocas, return instructions and /// stack restore points (exception unwind blocks and setjmp calls) in the /// given function and append them to the respective vectors. @@ -240,6 +247,54 @@ public: bool runOnFunction(Function &F) override; }; // class SafeStack +Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) { + Module &M = *F.getParent(); + Triple TargetTriple(M.getTargetTriple()); + + unsigned Offset; + unsigned AddressSpace; + // Check if the target keeps the unsafe stack pointer at a fixed offset. + if (TLI && TLI->getSafeStackPointerLocation(AddressSpace, Offset)) { + Constant *OffsetVal = + ConstantInt::get(Type::getInt32Ty(F.getContext()), Offset); + return ConstantExpr::getIntToPtr(OffsetVal, + StackPtrTy->getPointerTo(AddressSpace)); + } + + // Android provides a libc function that returns the stack pointer address. + if (TargetTriple.isAndroid()) { + Value *Fn = M.getOrInsertFunction(kUnsafeStackPtrAddrFn, + StackPtrTy->getPointerTo(0), nullptr); + return IRB.CreateCall(Fn); + } else { + // Otherwise, declare a thread-local variable with a magic name. + auto UnsafeStackPtr = + dyn_cast_or_null(M.getNamedValue(kUnsafeStackPtrVar)); + + if (!UnsafeStackPtr) { + // The global variable is not defined yet, define it ourselves. + // We use the initial-exec TLS model because we do not support the + // variable living anywhere other than in the main executable. + UnsafeStackPtr = new GlobalVariable( + /*Module=*/M, /*Type=*/StackPtrTy, + /*isConstant=*/false, /*Linkage=*/GlobalValue::ExternalLinkage, + /*Initializer=*/nullptr, /*Name=*/kUnsafeStackPtrVar, + /*InsertBefore=*/nullptr, + /*ThreadLocalMode=*/GlobalValue::InitialExecTLSModel); + } else { + // The variable exists, check its type and attributes. + if (UnsafeStackPtr->getValueType() != StackPtrTy) { + report_fatal_error(Twine(kUnsafeStackPtrVar) + " must have void* type"); + } + + if (!UnsafeStackPtr->isThreadLocal()) { + report_fatal_error(Twine(kUnsafeStackPtrVar) + " must be thread-local"); + } + } + return UnsafeStackPtr; + } +} + void SafeStack::findInsts(Function &F, SmallVectorImpl &StaticAllocas, SmallVectorImpl &DynamicAllocas, @@ -542,7 +597,7 @@ bool SafeStack::runOnFunction(Function &F) { ++NumUnsafeStackRestorePointsFunctions; IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); - UnsafeStackPtr = TLI->getSafeStackPointerLocation(IRB); + UnsafeStackPtr = getOrCreateUnsafeStackPtr(IRB, F); // The top of the unsafe stack after all unsafe static allocas are allocated. Value *StaticTop = moveStaticAllocasToUnsafeStack(IRB, F, StaticAllocas, Returns); diff --git a/test/Transforms/SafeStack/AArch64/abi.ll b/test/Transforms/SafeStack/AArch64/abi.ll index cdec923eb74..942658a89d2 100644 --- a/test/Transforms/SafeStack/AArch64/abi.ll +++ b/test/Transforms/SafeStack/AArch64/abi.ll @@ -3,9 +3,7 @@ define void @foo() nounwind uwtable safestack { entry: -; CHECK: %[[TP:.*]] = call i8* @llvm.aarch64.thread.pointer() -; CHECK: %[[SPA0:.*]] = getelementptr i8, i8* %[[TP]], i32 72 -; CHECK: %[[SPA:.*]] = bitcast i8* %[[SPA0]] to i8** +; CHECK: %[[SPA:.*]] = call i8** @__safestack_pointer_address() ; CHECK: %[[USP:.*]] = load i8*, i8** %[[SPA]] ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 ; CHECK: store i8* %[[USST]], i8** %[[SPA]] -- 2.34.1