Skip to content

Commit

Permalink
[safestack] Use non-thread-local unsafe stack pointer for Contiki OS
Browse files Browse the repository at this point in the history
Patch by Michael LeMay

Differential revision: http://reviews.llvm.org/D19852

llvm-svn: 284254
  • Loading branch information
David L Kreitzer committed Oct 14, 2016
1 parent 1deab38 commit d5c6755
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 54 deletions.
8 changes: 6 additions & 2 deletions llvm/include/llvm/Target/TargetLowering.h
Expand Up @@ -1114,8 +1114,12 @@ class TargetLoweringBase {
/// Should be used only when getIRStackGuard returns nullptr.
virtual Value *getSSPStackGuardCheck(const Module &M) const;

/// If the target has a standard location for the unsafe stack pointer,
/// returns the address of that location. Otherwise, returns nullptr.
protected:
Value *getDefaultSafeStackPointerLocation(IRBuilder<> &IRB,
bool UseTLS) const;

public:
/// Returns the target-specific address of the unsafe stack pointer.
virtual Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const;

/// Returns true if a cast between SrcAS and DestAS is a noop.
Expand Down
50 changes: 1 addition & 49 deletions llvm/lib/CodeGen/SafeStack.cpp
Expand Up @@ -52,16 +52,6 @@ using namespace llvm::safestack;

#define DEBUG_TYPE "safestack"

enum UnsafeStackPtrStorageVal { ThreadLocalUSP, SingleThreadUSP };

static cl::opt<UnsafeStackPtrStorageVal> USPStorage("safe-stack-usp-storage",
cl::Hidden, cl::init(ThreadLocalUSP),
cl::desc("Type of storage for the unsafe stack pointer"),
cl::values(clEnumValN(ThreadLocalUSP, "thread-local",
"Thread-local storage"),
clEnumValN(SingleThreadUSP, "single-thread",
"Non-thread-local storage")));

namespace llvm {

STATISTIC(NumFunctions, "Total number of functions");
Expand Down Expand Up @@ -123,9 +113,6 @@ class SafeStack : public FunctionPass {
/// might expect to appear on the stack on most common targets.
enum { StackAlignment = 16 };

/// \brief Build a value representing a pointer to the unsafe stack pointer.
Value *getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F);

/// \brief Return the value of the stack canary.
Value *getStackGuard(IRBuilder<> &IRB, Function &F);

Expand Down Expand Up @@ -355,41 +342,6 @@ bool SafeStack::IsSafeStackAlloca(const Value *AllocaPtr, uint64_t AllocaSize) {
return true;
}

Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) {
// Check if there is a target-specific location for the unsafe stack pointer.
if (Value *V = TL->getSafeStackPointerLocation(IRB))
return V;

// Otherwise, assume the target links with compiler-rt, which provides a
// thread-local variable with a magic name.
Module &M = *F.getParent();
const char *UnsafeStackPtrVar = "__safestack_unsafe_stack_ptr";
auto UnsafeStackPtr =
dyn_cast_or_null<GlobalVariable>(M.getNamedValue(UnsafeStackPtrVar));

bool UseTLS = USPStorage == ThreadLocalUSP;

if (!UnsafeStackPtr) {
auto TLSModel = UseTLS ?
GlobalValue::InitialExecTLSModel :
GlobalValue::NotThreadLocal;
// 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, nullptr,
UnsafeStackPtrVar, nullptr, TLSModel);
} else {
// The variable exists, check its type and attributes.
if (UnsafeStackPtr->getValueType() != StackPtrTy)
report_fatal_error(Twine(UnsafeStackPtrVar) + " must have void* type");
if (UseTLS != UnsafeStackPtr->isThreadLocal())
report_fatal_error(Twine(UnsafeStackPtrVar) + " must " +
(UseTLS ? "" : "not ") + "be thread-local");
}
return UnsafeStackPtr;
}

Value *SafeStack::getStackGuard(IRBuilder<> &IRB, Function &F) {
Value *StackGuardVar = TL->getIRStackGuard(IRB);
if (!StackGuardVar)
Expand Down Expand Up @@ -784,7 +736,7 @@ bool SafeStack::runOnFunction(Function &F) {
++NumUnsafeStackRestorePointsFunctions;

IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt());
UnsafeStackPtr = getOrCreateUnsafeStackPtr(IRB, F);
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
34 changes: 33 additions & 1 deletion llvm/lib/CodeGen/TargetLoweringBase.cpp
Expand Up @@ -1767,9 +1767,41 @@ TargetLoweringBase::getTypeLegalizationCost(const DataLayout &DL,
}
}

Value *TargetLoweringBase::getDefaultSafeStackPointerLocation(IRBuilder<> &IRB,
bool UseTLS) const {
// compiler-rt provides a variable with a magic name. Targets that do not
// link with compiler-rt may also provide such a variable.
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
const char *UnsafeStackPtrVar = "__safestack_unsafe_stack_ptr";
auto UnsafeStackPtr =
dyn_cast_or_null<GlobalVariable>(M->getNamedValue(UnsafeStackPtrVar));

Type *StackPtrTy = Type::getInt8PtrTy(M->getContext());

if (!UnsafeStackPtr) {
auto TLSModel = UseTLS ?
GlobalValue::InitialExecTLSModel :
GlobalValue::NotThreadLocal;
// 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, nullptr,
UnsafeStackPtrVar, nullptr, TLSModel);
} else {
// The variable exists, check its type and attributes.
if (UnsafeStackPtr->getValueType() != StackPtrTy)
report_fatal_error(Twine(UnsafeStackPtrVar) + " must have void* type");
if (UseTLS != UnsafeStackPtr->isThreadLocal())
report_fatal_error(Twine(UnsafeStackPtrVar) + " must " +
(UseTLS ? "" : "not ") + "be thread-local");
}
return UnsafeStackPtr;
}

Value *TargetLoweringBase::getSafeStackPointerLocation(IRBuilder<> &IRB) const {
if (!TM.getTargetTriple().isAndroid())
return nullptr;
return getDefaultSafeStackPointerLocation(IRB, true);

// Android provides a libc function to retrieve the address of the current
// thread's unsafe stack pointer.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -2045,6 +2045,9 @@ Value *X86TargetLowering::getSSPStackGuardCheck(const Module &M) const {
}

Value *X86TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const {
if (Subtarget.getTargetTriple().isOSContiki())
return getDefaultSafeStackPointerLocation(IRB, false);

if (!Subtarget.isTargetAndroid())
return TargetLowering::getSafeStackPointerLocation(IRB);

Expand Down
3 changes: 1 addition & 2 deletions llvm/test/Transforms/SafeStack/X86/array.ll
@@ -1,7 +1,6 @@
; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
; RUN: opt -safe-stack -safe-stack-usp-storage=single-thread -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s
; RUN: opt -safe-stack -S -mtriple=i386-pc-contiki-unknown < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s
; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
; RUN: opt -safe-stack -safe-stack-usp-storage=single-thread -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s

; array [4 x i8]
; Requires protector.
Expand Down

0 comments on commit d5c6755

Please sign in to comment.