Index: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10470,9 +10470,9 @@ } bool AArch64TargetLowering::useLoadStackGuardNode() const { - if (!Subtarget->isTargetAndroid()) - return true; - return TargetLowering::useLoadStackGuardNode(); + if (Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia()) + return TargetLowering::useLoadStackGuardNode(); + return true; } unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const { @@ -10610,36 +10610,43 @@ return false; } -Value *AArch64TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { - if (!Subtarget->isTargetAndroid()) - return TargetLowering::getIRStackGuard(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; +static Value *UseTlsOffset(IRBuilder<> &IRB, unsigned Offset) { Module *M = IRB.GetInsertBlock()->getParent()->getParent(); Function *ThreadPointerFunc = Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); return IRB.CreatePointerCast( - IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), TlsOffset), + IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), Offset), Type::getInt8PtrTy(IRB.getContext())->getPointerTo(0)); } -Value *AArch64TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const { - if (!Subtarget->isTargetAndroid()) - return TargetLowering::getSafeStackPointerLocation(IRB); +Value *AArch64TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { + // 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 + if (Subtarget->isTargetAndroid()) + return UseTlsOffset(IRB, 0x28); + // Fuchsia is similar. + // defines MX_TLS_STACK_GUARD_OFFSET with this value. + if (Subtarget->isTargetFuchsia()) + return UseTlsOffset(IRB, -0x10); + + return TargetLowering::getIRStackGuard(IRB); +} + +Value *AArch64TargetLowering::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 - const unsigned TlsOffset = 0x48; - Module *M = IRB.GetInsertBlock()->getParent()->getParent(); - Function *ThreadPointerFunc = - Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); - return IRB.CreatePointerCast( - IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), TlsOffset), - Type::getInt8PtrTy(IRB.getContext())->getPointerTo(0)); + if (Subtarget->isTargetAndroid()) + return UseTlsOffset(IRB, 0x48); + + // Fuchsia is similar. + // defines MX_TLS_UNSAFE_SP_OFFSET with this value. + if (Subtarget->isTargetFuchsia()) + return UseTlsOffset(IRB, -0x8); + + return TargetLowering::getSafeStackPointerLocation(IRB); } bool AArch64TargetLowering::isMaskAndCmp0FoldingBeneficial( Index: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h @@ -236,6 +236,7 @@ bool isTargetLinux() const { return TargetTriple.isOSLinux(); } bool isTargetWindows() const { return TargetTriple.isOSWindows(); } bool isTargetAndroid() const { return TargetTriple.isAndroid(); } + bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } Index: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -719,7 +719,8 @@ // For more information see http://people.redhat.com/drepper/tls.pdf if (ConstantSDNode *C = dyn_cast(Address)) if (C->getSExtValue() == 0 && AM.Segment.getNode() == nullptr && - (Subtarget->isTargetGlibc() || Subtarget->isTargetAndroid())) + (Subtarget->isTargetGlibc() || Subtarget->isTargetAndroid() || + Subtarget->isTargetFuchsia())) switch (N->getPointerInfo().getAddrSpace()) { case 256: AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16); Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -2006,26 +2006,36 @@ } static bool hasStackGuardSlotTLS(const Triple &TargetTriple) { - return TargetTriple.isOSGlibc() || + return TargetTriple.isOSGlibc() || TargetTriple.isOSFuchsia() || (TargetTriple.isAndroid() && !TargetTriple.isAndroidVersionLT(17)); } -Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { - // glibc and bionic have a special slot for the stack guard in tcbhead_t, use - // it instead of the usual global variable (see - // sysdeps/{i386,x86_64}/nptl/tls.h) - if (!hasStackGuardSlotTLS(Subtarget.getTargetTriple())) - return TargetLowering::getIRStackGuard(IRB); - - // %fs:0x28, unless we're using a Kernel code model, in which case it's %gs: - // %gs:0x14 on i386 - unsigned Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14; - unsigned AddressSpace = getAddressSpace(); +static Constant* SegmentOffset(IRBuilder<> &IRB, + unsigned Offset, unsigned AddressSpace) { return ConstantExpr::getIntToPtr( ConstantInt::get(Type::getInt32Ty(IRB.getContext()), Offset), Type::getInt8PtrTy(IRB.getContext())->getPointerTo(AddressSpace)); } +Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { + // glibc, bionic, and Fuchsia have a special slot for the stack guard in + // tcbhead_t; use it instead of the usual global variable (see + // sysdeps/{i386,x86_64}/nptl/tls.h) + if (hasStackGuardSlotTLS(Subtarget.getTargetTriple())) { + if (Subtarget.isTargetFuchsia()) { + // defines MX_TLS_STACK_GUARD_OFFSET with this value. + return SegmentOffset(IRB, 0x10, 257); + } else { + // %fs:0x28, unless we're using a Kernel code model, in which case + // it's %gs:0x28. gs:0x14 on i386. + unsigned Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14; + return SegmentOffset(IRB, Offset, getAddressSpace()); + } + } + + return TargetLowering::getIRStackGuard(IRB); +} + void X86TargetLowering::insertSSPDeclarations(Module &M) const { // MSVC CRT provides functionalities for stack protection. if (Subtarget.getTargetTriple().isOSMSVCRT()) { @@ -2042,7 +2052,7 @@ SecurityCheckCookie->addAttribute(1, Attribute::AttrKind::InReg); return; } - // glibc and bionic have a special slot for the stack guard. + // glibc, bionic, and Fuchsia have a special slot for the stack guard. if (hasStackGuardSlotTLS(Subtarget.getTargetTriple())) return; TargetLowering::insertSSPDeclarations(M); @@ -2066,21 +2076,23 @@ if (Subtarget.getTargetTriple().isOSContiki()) return getDefaultSafeStackPointerLocation(IRB, false); - 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 - unsigned AddressSpace, Offset; + if (Subtarget.isTargetAndroid()) { + // %fs:0x48, unless we're using a Kernel code model, in which case it's %gs: + // %gs:0x24 on i386 + unsigned Offset = (Subtarget.is64Bit()) ? 0x48 : 0x24; + return SegmentOffset(IRB, Offset, getAddressSpace()); + } - // %fs:0x48, unless we're using a Kernel code model, in which case it's %gs: - // %gs:0x24 on i386 - Offset = (Subtarget.is64Bit()) ? 0x48 : 0x24; - AddressSpace = getAddressSpace(); - return ConstantExpr::getIntToPtr( - ConstantInt::get(Type::getInt32Ty(IRB.getContext()), Offset), - Type::getInt8PtrTy(IRB.getContext())->getPointerTo(AddressSpace)); + // Fuchsia is similar. + if (Subtarget.isTargetFuchsia()) { + // defines MX_TLS_UNSAFE_SP_OFFSET with this value. + return SegmentOffset(IRB, 0x18, 257); + } + + return TargetLowering::getSafeStackPointerLocation(IRB); } bool X86TargetLowering::isNoopAddrSpaceCast(unsigned SrcAS, Index: llvm/trunk/lib/Target/X86/X86Subtarget.h =================================================================== --- llvm/trunk/lib/Target/X86/X86Subtarget.h +++ llvm/trunk/lib/Target/X86/X86Subtarget.h @@ -518,6 +518,7 @@ bool isTargetNaCl32() const { return isTargetNaCl() && !is64Bit(); } bool isTargetNaCl64() const { return isTargetNaCl() && is64Bit(); } bool isTargetMCU() const { return TargetTriple.isOSIAMCU(); } + bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } bool isTargetWindowsMSVC() const { return TargetTriple.isWindowsMSVCEnvironment(); Index: llvm/trunk/test/CodeGen/AArch64/stack-protector-target.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/stack-protector-target.ll +++ llvm/trunk/test/CodeGen/AArch64/stack-protector-target.ll @@ -1,5 +1,6 @@ ; Test target-specific stack cookie location. ; RUN: llc -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefix=ANDROID-AARCH64 %s +; RUN: llc -mtriple=aarch64-fuchsia < %s -o - | FileCheck --check-prefix=FUCHSIA-AARCH64 %s define void @_Z1fv() sspreq { entry: @@ -17,3 +18,10 @@ ; ANDROID-AARCH64: ldr [[C:.*]], {{\[}}[[A]], #40] ; ANDROID-AARCH64: ldr [[D:.*]], [sp, ; ANDROID-AARCH64: cmp [[C]], [[D]] + +; FUCHSIA-AARCH64: mrs [[A:.*]], TPIDR_EL0 +; FUCHSIA-AARCH64: ldur [[B:.*]], {{\[}}[[A]], #-16] +; FUCHSIA-AARCH64: str [[B]], [sp, +; FUCHSIA-AARCH64: ldur [[C:.*]], {{\[}}[[A]], #-16] +; FUCHSIA-AARCH64: ldr [[D:.*]], [sp, +; FUCHSIA-AARCH64: cmp [[C]], [[D]] Index: llvm/trunk/test/CodeGen/X86/safestack.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/safestack.ll +++ llvm/trunk/test/CodeGen/X86/safestack.ll @@ -2,6 +2,7 @@ ; 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=ANDROID-I386 %s ; RUN: llc -mtriple=x86_64-linux-android < %s -o - | FileCheck --check-prefix=ANDROID-X64 %s +; RUN: llc -mtriple=x86_64-fuchsia < %s -o - | FileCheck --check-prefix=FUCHSIA-X64 %s define void @_Z1fv() safestack { entry: @@ -30,3 +31,7 @@ ; ANDROID-X64: movq %fs:72, %[[A:.*]] ; ANDROID-X64: leaq -16(%[[A]]), %[[B:.*]] ; ANDROID-X64: movq %[[B]], %fs:72 + +; FUCHSIA-X64: movq %fs:24, %[[A:.*]] +; FUCHSIA-X64: leaq -16(%[[A]]), %[[B:.*]] +; FUCHSIA-X64: movq %[[B]], %fs:24 Index: llvm/trunk/test/CodeGen/X86/safestack_ssp.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/safestack_ssp.ll +++ llvm/trunk/test/CodeGen/X86/safestack_ssp.ll @@ -1,6 +1,7 @@ ; Test codegen pipeline for SafeStack + StackProtector combination. ; 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=x86_64-fuchsia < %s -o - | FileCheck --check-prefix=FUCHSIA-X64 %s define void @_Z1fv() safestack sspreq { entry: @@ -25,3 +26,9 @@ ; LINUX-I386-DAG: leal -16(%[[B]]), %[[C:.*]] ; LINUX-I386-DAG: movl %[[C]], %gs:(%[[A]]) ; LINUX-I386-DAG: movl %[[COOKIE]], -4(%[[B]]) + +; FUCHSIA-X64-DAG: movq %fs:24, %[[B:.*]] +; FUCHSIA-X64-DAG: movq %fs:16, %[[COOKIE:.*]] +; FUCHSIA-X64-DAG: leaq -16(%[[B]]), %[[C:.*]] +; FUCHSIA-X64-DAG: movq %[[C]], %fs:24 +; FUCHSIA-X64-DAG: movq %[[COOKIE]], -8(%[[B]]) Index: llvm/trunk/test/Transforms/SafeStack/AArch64/abi_ssp.ll =================================================================== --- llvm/trunk/test/Transforms/SafeStack/AArch64/abi_ssp.ll +++ llvm/trunk/test/Transforms/SafeStack/AArch64/abi_ssp.ll @@ -1,5 +1,5 @@ -; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefix=TLS %s - +; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefixes=TLS,ANDROID %s +; RUN: opt -safe-stack -S -mtriple=aarch64-unknown-fuchsia < %s -o - | FileCheck --check-prefixes=TLS,FUCHSIA %s define void @foo() nounwind uwtable safestack sspreq { entry: @@ -7,7 +7,8 @@ ; TLS: call i8* @llvm.thread.pointer() ; TLS: %[[TP2:.*]] = call i8* @llvm.thread.pointer() -; TLS: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 40 +; ANDROID: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 40 +; FUCHSIA: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 -16 ; TLS: %[[C:.*]] = bitcast i8* %[[B]] to i8** ; TLS: %[[StackGuard:.*]] = load i8*, i8** %[[C]] ; TLS: store i8* %[[StackGuard]], i8** %[[StackGuardSlot:.*]] Index: llvm/trunk/test/Transforms/SafeStack/X86/abi_ssp.ll =================================================================== --- llvm/trunk/test/Transforms/SafeStack/X86/abi_ssp.ll +++ llvm/trunk/test/Transforms/SafeStack/X86/abi_ssp.ll @@ -6,10 +6,13 @@ ; RUN: opt -safe-stack -S -mtriple=x86_64-linux-android < %s -o - | FileCheck --check-prefixes=COMMON,TLS64 %s +; RUN: opt -safe-stack -S -mtriple=x86_64-unknown-fuchsia < %s -o - | FileCheck --check-prefixes=COMMON,FUCHSIA64 %s + define void @foo() safestack sspreq { entry: ; TLS32: %[[StackGuard:.*]] = load i8*, i8* addrspace(256)* inttoptr (i32 20 to i8* addrspace(256)*) ; TLS64: %[[StackGuard:.*]] = load i8*, i8* addrspace(257)* inttoptr (i32 40 to i8* addrspace(257)*) +; FUCHSIA64: %[[StackGuard:.*]] = load i8*, i8* addrspace(257)* inttoptr (i32 16 to i8* addrspace(257)*) ; GLOBAL32: %[[StackGuard:.*]] = load i8*, i8** @__stack_chk_guard ; COMMON: store i8* %[[StackGuard]], i8** %[[StackGuardSlot:.*]] %a = alloca i8, align 1