Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -629,7 +629,7 @@ } } if (SanArgs.needsSafeStackRt()) { - NonWholeStaticRuntimes.push_back("safestack"); + StaticRuntimes.push_back("safestack"); RequiredSymbols.push_back("__safestack_init"); } if (SanArgs.needsCfiRt()) Index: compiler-rt/lib/safestack/CMakeLists.txt =================================================================== --- compiler-rt/lib/safestack/CMakeLists.txt +++ compiler-rt/lib/safestack/CMakeLists.txt @@ -1,6 +1,6 @@ add_compiler_rt_component(safestack) -set(SAFESTACK_SOURCES safestack.cc) +set(SAFESTACK_SOURCES safestack.cc safestack_customcc.S) include_directories(..) Index: compiler-rt/lib/safestack/safestack.cc =================================================================== --- compiler-rt/lib/safestack/safestack.cc +++ compiler-rt/lib/safestack/safestack.cc @@ -85,9 +85,10 @@ // For now, store it in a thread-local variable. extern "C" { __attribute__((visibility( - "default"))) __thread void *__safestack_unsafe_stack_ptr = nullptr; + "default"))) __attribute__((tls_model("initial-exec"))) __thread void *__safestack_unsafe_stack_ptr = nullptr; } + // Per-thread unsafe stack information. It's not frequently accessed, so there // it can be kept out of the tcb in normal thread-local variables. static __thread void *unsafe_stack_start = nullptr; @@ -253,3 +254,8 @@ __attribute__((visibility("default"))) void *__get_unsafe_stack_ptr() { return __safestack_unsafe_stack_ptr; } + +extern "C" __attribute__((visibility("default"))) void ** +__safestack_pointer_address() { + return &__safestack_unsafe_stack_ptr; +} Index: compiler-rt/lib/safestack/safestack_customcc.S =================================================================== --- /dev/null +++ compiler-rt/lib/safestack/safestack_customcc.S @@ -0,0 +1,10 @@ +#if defined(__x86_64__) + .text + .globl __safestack_pointer_address_customcc + .p2align 4, 0x90 + .type __safestack_pointer_address_customcc,@function +__safestack_pointer_address_customcc: + movq %fs:0, %r14 + addq __safestack_unsafe_stack_ptr@GOTTPOFF(%rip), %r14 + retq +#endif Index: llvm/lib/CodeGen/SafeStack.cpp =================================================================== --- llvm/lib/CodeGen/SafeStack.cpp +++ llvm/lib/CodeGen/SafeStack.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" @@ -61,6 +62,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" #include #include @@ -88,6 +90,14 @@ } // namespace llvm +static cl::opt + SafeStackUsePointerAddressCustomCC("safestack-use-pointer-address-customcc", + cl::init(false), cl::Hidden); + +static cl::opt + SafeStackUsePointerAddressInline("safestack-use-pointer-address-inline", + cl::init(false), cl::Hidden); + namespace { /// Rewrite an SCEV expression for a memory access address to an expression that @@ -191,6 +201,8 @@ bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, uint64_t AllocaSize); + Value *callCustomCC(IRBuilder<> &IRB, StringRef Name); + public: SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL, ScalarEvolution &SE) @@ -695,6 +707,34 @@ } } +Value *SafeStack::callCustomCC(IRBuilder<> &IRB, StringRef Name) { + Triple TargetTriple{F.getParent()->getTargetTriple()}; + Value *Fn = + F.getParent()->getOrInsertFunction(Name, StackPtrTy->getPointerTo(0)); + InlineAsm *Asm; + const char *AsmStr; + const char *ConstraintStr; + if (TargetTriple.getArch() == Triple::aarch64) { + AsmStr = "bl $1"; + ConstraintStr = "={x19},s,~{memory},~{lr}"; + } else if (TargetTriple.isARM() || TargetTriple.isThumb()) { + AsmStr = "bl $1"; + ConstraintStr = "={r4},s,~{memory},~{lr}"; + } else if (TargetTriple.getArch() == Triple::x86_64) { + AsmStr = "callq ${1:c}"; + ConstraintStr = "={r14},s,~{memory}"; + } else if (TargetTriple.getArch() == Triple::x86) { + AsmStr = "call ${1:c}"; + ConstraintStr = "={esi},s,~{memory}"; + } else { + report_fatal_error("Unsupported architecture for safestack-use-pointer-address"); + } + Asm = InlineAsm::get( + FunctionType::get(StackPtrTy->getPointerTo(0), {Fn->getType()}, false), + AsmStr, ConstraintStr, false); + return IRB.CreateCall(Asm, Fn); +} + bool SafeStack::run() { assert(F.hasFnAttribute(Attribute::SafeStack) && "Can't run SafeStack on a function without the attribute"); @@ -731,7 +771,15 @@ ++NumUnsafeStackRestorePointsFunctions; IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); - UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); + if (SafeStackUsePointerAddressCustomCC) { + UnsafeStackPtr = callCustomCC(IRB, "__safestack_pointer_address_customcc"); + } else if (SafeStackUsePointerAddressInline) { + Value *Fn = F.getParent()->getOrInsertFunction( + "__safestack_pointer_address_inline", StackPtrTy->getPointerTo(0)); + UnsafeStackPtr = IRB.CreateCall(Fn); + } else { + UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); + } // Load the current stack pointer (we'll also use it as a base pointer). // FIXME: use a dedicated register for it ? @@ -779,6 +827,15 @@ IRB.CreateStore(BasePointer, UnsafeStackPtr); } + if (SafeStackUsePointerAddressInline) { + CallSite CS(UnsafeStackPtr); + InlineFunctionInfo IFI; + if (!InlineFunction(CS, IFI)) + report_fatal_error( + "SafeStack failed to inline __safestack_pointer_address_inline in " + + F.getName()); + } + DEBUG(dbgs() << "[SafeStack] safestack applied\n"); return true; } Index: llvm/test/CodeGen/X86/safestack.ll =================================================================== --- llvm/test/CodeGen/X86/safestack.ll +++ llvm/test/CodeGen/X86/safestack.ll @@ -4,6 +4,8 @@ ; 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 +; RUN: llc -mtriple=i386-linux -safestack-use-pointer-address < %s -o - | FileCheck --check-prefix=LINUX-I386-PA %s + define void @_Z1fv() safestack { entry: %x = alloca i32, align 4 @@ -35,3 +37,9 @@ ; FUCHSIA-X64: movq %fs:24, %[[A:.*]] ; FUCHSIA-X64: leaq -16(%[[A]]), %[[B:.*]] ; FUCHSIA-X64: movq %[[B]], %fs:24 + +; LINUX-I386-PA: calll __safestack_pointer_address +; LINUX-I386-PA: movl %eax, %[[A:.*]] +; LINUX-I386-PA: movl (%eax), %[[B:.*]] +; LINUX-I386-PA: leal -16(%[[B]]), %[[C:.*]] +; LINUX-I386-PA: movl %[[C]], (%[[A]])