From 776f33aede0eeb72764d19ff1c9b3c65e42c6efa Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 22 Dec 2015 00:13:11 +0000 Subject: [PATCH] [safestack] Add option for non-TLS unsafe stack pointer. This patch adds an option, -safe-stack-no-tls, for using normal storage instead of thread-local storage for the unsafe stack pointer. This can be useful when SafeStack is applied to an operating system kernel. http://reviews.llvm.org/D15673 Patch by Michael LeMay. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256221 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Instrumentation/SafeStack.cpp | 23 +++++++++++++++++--- test/Transforms/SafeStack/array.ll | 5 +++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/Instrumentation/SafeStack.cpp b/lib/Transforms/Instrumentation/SafeStack.cpp index 4441663fc6d..abed465f102 100644 --- a/lib/Transforms/Instrumentation/SafeStack.cpp +++ b/lib/Transforms/Instrumentation/SafeStack.cpp @@ -47,6 +47,17 @@ using namespace llvm; #define DEBUG_TYPE "safestack" +enum UnsafeStackPtrStorageVal { ThreadLocalUSP, SingleThreadUSP }; + +static cl::opt 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"), + clEnumValEnd)); + namespace llvm { STATISTIC(NumFunctions, "Total number of functions"); @@ -344,19 +355,25 @@ Value *SafeStack::getOrCreateUnsafeStackPtr(IRBuilder<> &IRB, Function &F) { auto UnsafeStackPtr = dyn_cast_or_null(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, GlobalValue::InitialExecTLSModel); + 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 (!UnsafeStackPtr->isThreadLocal()) - report_fatal_error(Twine(UnsafeStackPtrVar) + " must be thread-local"); + if (UseTLS != UnsafeStackPtr->isThreadLocal()) + report_fatal_error(Twine(UnsafeStackPtrVar) + " must " + + (UseTLS ? "" : "not ") + "be thread-local"); } return UnsafeStackPtr; } diff --git a/test/Transforms/SafeStack/array.ll b/test/Transforms/SafeStack/array.ll index b2454dc2bb9..564213e6d58 100644 --- a/test/Transforms/SafeStack/array.ll +++ b/test/Transforms/SafeStack/array.ll @@ -1,9 +1,14 @@ ; 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=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. +; CHECK: @__safestack_unsafe_stack_ptr = external thread_local(initialexec) global i8* +; SINGLE-THREAD: @__safestack_unsafe_stack_ptr = external global i8* + define void @foo(i8* %a) nounwind uwtable safestack { entry: ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr -- 2.34.1