Skip to content

Commit

Permalink
[safestack] Inline safestack pointer access when possible.
Browse files Browse the repository at this point in the history
Summary:
This adds an -mllvm flag that forces the use of a runtime function call to
get the unsafe stack pointer, the same that is currently used on non-x86, non-aarch64 android.
The call may be inlined.

Reviewers: pcc

Subscribers: aemerson, kristof.beyls, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D37405

llvm-svn: 323259
  • Loading branch information
eugenis committed Jan 23, 2018
1 parent c1e2290 commit d5a6fdb
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
51 changes: 50 additions & 1 deletion llvm/lib/CodeGen/SafeStack.cpp
Expand Up @@ -24,6 +24,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Expand Down Expand Up @@ -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 <algorithm>
#include <cassert>
Expand Down Expand Up @@ -88,6 +90,13 @@ STATISTIC(NumUnsafeStackRestorePoints, "Number of setjmps and landingpads");

} // namespace llvm

/// Use __safestack_pointer_address even if the platform has a faster way of
/// access safe stack pointer.
static cl::opt<bool>
SafeStackUsePointerAddress("safestack-use-pointer-address",
cl::init(false), cl::Hidden);


namespace {

/// Rewrite an SCEV expression for a memory access address to an expression that
Expand Down Expand Up @@ -191,6 +200,9 @@ class SafeStack {
bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr,
uint64_t AllocaSize);

bool ShouldInlinePointerAddress(CallSite &CS);
void TryInlinePointerAddress();

public:
SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL,
ScalarEvolution &SE)
Expand Down Expand Up @@ -695,6 +707,35 @@ void SafeStack::moveDynamicAllocasToUnsafeStack(
}
}

bool SafeStack::ShouldInlinePointerAddress(CallSite &CS) {
Function *Callee = CS.getCalledFunction();
if (CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee))
return true;
if (Callee->isInterposable() || Callee->hasFnAttribute(Attribute::NoInline) ||
CS.isNoInline())
return false;
return true;
}

void SafeStack::TryInlinePointerAddress() {
if (!isa<CallInst>(UnsafeStackPtr))
return;

if(F.hasFnAttribute(Attribute::OptimizeNone))
return;

CallSite CS(UnsafeStackPtr);
Function *Callee = CS.getCalledFunction();
if (!Callee || Callee->isDeclaration())
return;

if (!ShouldInlinePointerAddress(CS))
return;

InlineFunctionInfo IFI;
InlineFunction(CS, IFI);
}

bool SafeStack::run() {
assert(F.hasFnAttribute(Attribute::SafeStack) &&
"Can't run SafeStack on a function without the attribute");
Expand Down Expand Up @@ -731,7 +772,13 @@ bool SafeStack::run() {
++NumUnsafeStackRestorePointsFunctions;

IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt());
UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB);
if (SafeStackUsePointerAddress) {
Value *Fn = F.getParent()->getOrInsertFunction(
"__safestack_pointer_address", 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 ?
Expand Down Expand Up @@ -779,6 +826,8 @@ bool SafeStack::run() {
IRB.CreateStore(BasePointer, UnsafeStackPtr);
}

TryInlinePointerAddress();

DEBUG(dbgs() << "[SafeStack] safestack applied\n");
return true;
}
Expand Down
8 changes: 8 additions & 0 deletions llvm/test/CodeGen/X86/safestack.ll
Expand Up @@ -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
Expand Down Expand Up @@ -35,3 +37,9 @@ declare void @_Z7CapturePi(i32*)
; 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 (%[[A]]), %[[B:.*]]
; LINUX-I386-PA: leal -16(%[[B]]), %[[C:.*]]
; LINUX-I386-PA: movl %[[C]], (%[[A]])
30 changes: 30 additions & 0 deletions llvm/test/CodeGen/X86/safestack_inline.ll
@@ -0,0 +1,30 @@
; RUN: sed -e "s/ATTR//" %s | llc -mtriple=x86_64-linux -safestack-use-pointer-address | FileCheck --check-prefix=INLINE %s
; RUN: sed -e "s/ATTR/noinline/" %s | llc -mtriple=x86_64-linux -safestack-use-pointer-address | FileCheck --check-prefix=CALL %s

@p = external thread_local global i8*, align 8

define nonnull i8** @__safestack_pointer_address() local_unnamed_addr ATTR {
entry:
ret i8** @p
}

define void @_Z1fv() safestack {
entry:
%x = alloca i32, align 4
%0 = bitcast i32* %x to i8*
call void @_Z7CapturePi(i32* nonnull %x)
ret void
}

declare void @_Z7CapturePi(i32*)

; INLINE: movq p@GOTTPOFF(%rip), %[[A:.*]]
; INLINE: movq %fs:(%[[A]]), %[[B:.*]]
; INLINE: leaq -16(%[[B]]), %[[C:.*]]
; INLINE: movq %[[C]], %fs:(%[[A]])

; CALL: callq __safestack_pointer_address
; CALL: movq %rax, %[[A:.*]]
; CALL: movq (%[[A]]), %[[B:.*]]
; CALL: leaq -16(%[[B]]), %[[C:.*]]
; CALL: movq %[[C]], (%[[A]])

0 comments on commit d5a6fdb

Please sign in to comment.