Hi theraven,

This patch adds runtime support for the Safe Stack protection to compiler-rt 
(see http://reviews.llvm.org/D6094 for the detailed description of the Safe 
Stack).

This patch is our implementation of the safe stack on top of the current SVN 
HEAD of compiler-rt (r220991). The patch adds basic runtime support for the 
safe stack to compiler-rt that manages unsafe stack allocation/deallocation for 
each thread.

http://reviews.llvm.org/D6096

Files:
  CMakeLists.txt
  cmake/config-ix.cmake
  include/CMakeLists.txt
  include/safestack_interface.h
  lib/CMakeLists.txt
  lib/Makefile.mk
  lib/safestack/CMakeLists.txt
  lib/safestack/Makefile.mk
  lib/safestack/safestack.cc
  make/platform/clang_darwin.mk
  make/platform/clang_linux.mk
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -239,6 +239,7 @@
 append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
+append_list_if(COMPILER_RT_HAS_FNO_SAFE_STACK_FLAG -fno-safe-stack SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS)
 
Index: cmake/config-ix.cmake
===================================================================
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -10,6 +10,7 @@
 check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)
 check_cxx_compiler_flag(-funwind-tables      COMPILER_RT_HAS_FUNWIND_TABLES_FLAG)
 check_cxx_compiler_flag(-fno-stack-protector COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG)
+check_cxx_compiler_flag(-fno-safe-stack      COMPILER_RT_HAS_FNO_SAFE_STACK_FLAG)
 check_cxx_compiler_flag(-fvisibility=hidden  COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
 check_cxx_compiler_flag(-fno-rtti            COMPILER_RT_HAS_FNO_RTTI_FLAG)
 check_cxx_compiler_flag(-ffreestanding       COMPILER_RT_HAS_FFREESTANDING_FLAG)
@@ -182,6 +183,7 @@
 filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64 mipsel mips64el aarch64)
 filter_available_targets(TSAN_SUPPORTED_ARCH x86_64)
 filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips mipsel)
+filter_available_targets(SAFESTACK_SUPPORTED_ARCH x86_64 i386 i686)
 
 if(ANDROID)
   set(OS_NAME "Android")
Index: include/CMakeLists.txt
===================================================================
--- include/CMakeLists.txt
+++ include/CMakeLists.txt
@@ -6,7 +6,8 @@
   sanitizer/linux_syscall_hooks.h
   sanitizer/lsan_interface.h
   sanitizer/msan_interface.h
-  sanitizer/tsan_interface_atomic.h)
+  sanitizer/tsan_interface_atomic.h
+  safestack_interface.h)
 
 set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)
 
Index: include/safestack_interface.h
===================================================================
--- /dev/null
+++ include/safestack_interface.h
@@ -0,0 +1,20 @@
+#ifndef SAFESTACK_INTERFACE_H
+#define SAFESTACK_INTERFACE_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *__safestack_get_unsafe_stack_start();
+void *__safestack_get_unsafe_stack_ptr();
+size_t __safestack_get_unsafe_stack_size();
+
+void *__safestack_get_safe_stack_ptr();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SAFESTACK_INTERFACE_H
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt
+++ lib/CMakeLists.txt
@@ -41,3 +41,4 @@
   add_subdirectory(ubsan)
 endif()
 
+add_subdirectory(safestack)
Index: lib/Makefile.mk
===================================================================
--- lib/Makefile.mk
+++ lib/Makefile.mk
@@ -20,3 +20,4 @@
 SubDirs += sanitizer_common
 SubDirs += tsan
 SubDirs += ubsan
+SubDirs += safestack
Index: lib/safestack/CMakeLists.txt
===================================================================
--- /dev/null
+++ lib/safestack/CMakeLists.txt
@@ -0,0 +1,26 @@
+add_custom_target(safestack)
+
+set(SAFESTACK_SOURCES safestack.cc)
+
+include_directories(..)
+
+set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+
+if(APPLE)
+  # Build universal binary on APPLE.
+  add_compiler_rt_osx_static_runtime(clang_rt.safestack_osx
+    ARCH ${SAFESTACK_SUPPORTED_ARCH}
+    SOURCES ${SAFESTACK_SOURCES}
+            $<TARGET_OBJECTS:RTInterception.osx>
+    CFLAGS ${SAFESTACK_CFLAGS})
+  add_dependencies(safestack clang_rt.safestack_osx)
+else()
+  # Otherwise, build separate libraries for each target.
+  foreach(arch ${SAFESTACK_SUPPORTED_ARCH})
+      add_compiler_rt_runtime(clang_rt.safestack-${arch} ${arch} STATIC
+      SOURCES ${SAFESTACK_SOURCES}
+              $<TARGET_OBJECTS:RTInterception.${arch}>
+      CFLAGS ${SAFESTACK_CFLAGS})
+      add_dependencies(safestack clang_rt.safestack-${arch})
+  endforeach()
+endif()
Index: lib/safestack/Makefile.mk
===================================================================
--- /dev/null
+++ lib/safestack/Makefile.mk
@@ -0,0 +1,23 @@
+#===- lib/safestack/Makefile.mk ------------------------------*- Makefile -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+ModuleName := safestack
+SubDirs :=
+
+Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file)))
+ObjNames := $(Sources:%.cc=%.o)
+
+Implementation := Generic
+
+# FIXME: use automatic dependencies?
+Dependencies := $(wildcard $(Dir)/*.h)
+Dependencies += $(wildcard $(Dir)/../interception/*.h)
+
+# Define a convenience variable for all the safestack functions.
+SafeStackFunctions := $(Sources:%.cc=%)
Index: lib/safestack/safestack.cc
===================================================================
--- /dev/null
+++ lib/safestack/safestack.cc
@@ -0,0 +1,347 @@
+//===-- safestack.cc --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the runtime support for the safe stack protection
+// mechanism. The runtime manages allocation/deallocation of the unsafe stack
+// for the main thread, as well as all pthreads threads that are
+// created/destroyed during program execution.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <limits.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <pthread.h>
+
+#if defined(__linux__)
+#include <unistd.h>
+#include <sys/syscall.h>
+#endif
+
+// FIXME: is this in some header?
+#define STACK_ALIGN 16
+
+// Should we make the following configurable?
+#define __SAFESTACK_DEFAULT_STACK_SIZE 0x2800000
+
+#include "interception/interception.h"
+
+namespace __llvm__safestack {
+
+// We don't know whether pthread is linked in or not, so we resolve
+// all symbols from pthread that we use dynamically
+#define __DECLARE_WRAPPER(fn) __typeof__(fn)* __d_ ## fn = NULL;
+
+__DECLARE_WRAPPER(pthread_attr_init)
+__DECLARE_WRAPPER(pthread_attr_destroy)
+__DECLARE_WRAPPER(pthread_attr_getstacksize)
+__DECLARE_WRAPPER(pthread_attr_getguardsize)
+__DECLARE_WRAPPER(pthread_key_create)
+__DECLARE_WRAPPER(pthread_setspecific)
+
+// The unsafe stack pointer is stored in the TCB structure on these platforms
+#if defined(__i386__)
+# define MOVPTR "movl"
+# ifdef __pic__
+#  define IMM_MODE "nr"
+# else
+#  define IMM_MODE "ir"
+# endif
+#elif defined(__x86_64__)
+# define MOVPTR "movq"
+# define IMM_MODE "nr"
+#endif
+
+#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
+
+# define __THREAD_GETMEM_L(offset)                        \
+  __extension__ ({ unsigned long  __v;                    \
+      asm volatile (MOVPTR " %%fs:%P1,%q0"                \
+                    : "=r" (__v) : "i" (offset)); __v; })
+
+# define __THREAD_SETMEM_L(offset, value)                           \
+  asm volatile (MOVPTR " %q0,%%fs:%P1" :                            \
+                : IMM_MODE ((unsigned long) (value)), "i" (offset))
+
+// The following locations are platform-specific
+# define __GET_UNSAFE_STACK_PTR()         (void*) __THREAD_GETMEM_L(0x280)
+# define __SET_UNSAFE_STACK_PTR(value)    __THREAD_SETMEM_L(0x280, value)
+
+# define __GET_UNSAFE_STACK_START()       (void*) __THREAD_GETMEM_L(0x288)
+# define __SET_UNSAFE_STACK_START(value)  __THREAD_SETMEM_L(0x288, value)
+
+# define __GET_UNSAFE_STACK_SIZE()        (size_t) __THREAD_GETMEM_L(0x290)
+# define __SET_UNSAFE_STACK_SIZE(value)   __THREAD_SETMEM_L(0x290, value)
+
+# define __GET_UNSAFE_STACK_GUARD()       (size_t) __THREAD_GETMEM_L(0x298)
+# define __SET_UNSAFE_STACK_GUARD(value)  __THREAD_SETMEM_L(0x298, value)
+
+#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
+
+// OSX uses %gs to directly index thread-specific slots
+# define __THREAD_GETMEM_L(slot)                            \
+  __extension__ ({ unsigned long  __v;                      \
+      asm volatile (MOVPTR " %%gs:%P1,%q0" : "=r" (__v)     \
+                    : "i" ((slot) * sizeof(void*))); __v; })
+
+# define __THREAD_SETMEM_L(slot, value)               \
+  asm volatile (MOVPTR " %q0,%%gs:%P1" :              \
+                : IMM_MODE ((unsigned long) (value)), \
+                  "i" ((slot) * sizeof(void*)))
+
+// Thread-specific slots 0-256 are reserved for the systems on OSX.
+// Slots 192 - 195 seems unused at the moment, so we claim them.
+
+// The following locations are platform-specific
+# define __GET_UNSAFE_STACK_PTR()         (void*) __THREAD_GETMEM_L(192)
+# define __SET_UNSAFE_STACK_PTR(value)    __THREAD_SETMEM_L(192, value)
+
+# define __GET_UNSAFE_STACK_START()       (void*) __THREAD_GETMEM_L(193)
+# define __SET_UNSAFE_STACK_START(value)  __THREAD_SETMEM_L(193, value)
+
+# define __GET_UNSAFE_STACK_SIZE()        (size_t) __THREAD_GETMEM_L(194)
+# define __SET_UNSAFE_STACK_SIZE(value)   __THREAD_SETMEM_L(194, value)
+
+# define __GET_UNSAFE_STACK_GUARD()       (size_t) __THREAD_GETMEM_L(195)
+# define __SET_UNSAFE_STACK_GUARD(value)  __THREAD_SETMEM_L(195, value)
+
+#else
+// The unsafe stack is stored in a thread-local variable on these platforms
+extern "C" {
+  __attribute__((visibility ("default")))
+  __thread void  *__llvm__unsafe_stack_ptr = 0;
+}
+
+__thread void  *unsafe_stack_start = 0;
+__thread size_t unsafe_stack_size = 0;
+__thread size_t unsafe_stack_guard = 0;
+
+# define __GET_UNSAFE_STACK_PTR()         __llvm__unsafe_stack_ptr
+# define __SET_UNSAFE_STACK_PTR(value)    __llvm__unsafe_stack_ptr = (value)
+
+# define __GET_UNSAFE_STACK_START()       unsafe_stack_start
+# define __SET_UNSAFE_STACK_START(value)  unsafe_stack_start = (value)
+
+# define __GET_UNSAFE_STACK_SIZE()        unsafe_stack_size
+# define __SET_UNSAFE_STACK_SIZE(value)   unsafe_stack_size = (value)
+
+# define __GET_UNSAFE_STACK_GUARD()       unsafe_stack_guard
+# define __SET_UNSAFE_STACK_GUARD(value)  unsafe_stack_guard = (value)
+
+#endif
+
+static inline void *unsafe_stack_alloc(size_t size, size_t guard) {
+  void *addr =
+#if defined(__linux__)
+    (void*) syscall(SYS_mmap,
+#else
+    mmap(
+#endif
+              NULL, size + guard, PROT_WRITE  | PROT_READ,
+              MAP_PRIVATE | MAP_ANON
+#if defined(__linux__)
+              | MAP_STACK | MAP_GROWSDOWN
+#endif
+              , -1, 0);
+  mprotect(addr, guard, PROT_NONE);
+  return (char*) addr + guard;
+}
+
+static inline void unsafe_stack_setup(void *start, size_t size, size_t guard) {
+  void* stack_ptr = (char*) start + size;
+  assert((((size_t)stack_ptr) & (STACK_ALIGN-1)) == 0);
+
+  __SET_UNSAFE_STACK_PTR(stack_ptr);
+  __SET_UNSAFE_STACK_START(start);
+  __SET_UNSAFE_STACK_SIZE(size);
+  __SET_UNSAFE_STACK_GUARD(guard);
+}
+
+static void unsafe_stack_free() {
+  if (__GET_UNSAFE_STACK_START()) {
+#if defined(__linux__)
+    syscall(SYS_munmap,
+#else
+    munmap(
+#endif
+      (char*) __GET_UNSAFE_STACK_START() - __GET_UNSAFE_STACK_GUARD(),
+      __GET_UNSAFE_STACK_SIZE() + __GET_UNSAFE_STACK_GUARD());
+  }
+  __SET_UNSAFE_STACK_START(0);
+}
+
+/// Thread data for the cleanup handler
+pthread_key_t thread_cleanup_key;
+
+/// Safe stack per-thread information passed to the thread_start function
+struct tinfo {
+  void *(*start_routine)(void*);
+  void *start_routine_arg;
+
+  void *unsafe_stack_start;
+  size_t unsafe_stack_size;
+  size_t unsafe_stack_guard;
+};
+
+/// Wrap the thread function in order to deallocate the unsafe stack when the
+/// thread terminates by returning from its main function.
+static void* thread_start(void *arg) {
+  struct tinfo *tinfo = (struct tinfo*) arg;
+
+  void *(*start_routine)(void*) = tinfo->start_routine;
+  void *start_routine_arg = tinfo->start_routine_arg;
+
+  // Setup the unsafe stack; this will destroy tinfo content
+  unsafe_stack_setup(tinfo->unsafe_stack_start,
+                     tinfo->unsafe_stack_size,
+                     tinfo->unsafe_stack_guard);
+
+  // Make sure out thread-specific destructor will be called
+  // FIXME: we can do this only any other specific key is set by
+  // intersepting the pthread_setspecific function itself
+  __d_pthread_setspecific(thread_cleanup_key, (void*) 1);
+
+  // Start the original thread rutine
+  return start_routine(start_routine_arg);
+}
+
+/// Intercept thread creation operation to allocate and setup the unsafe stack
+INTERCEPTOR(int, pthread_create, pthread_t *thread,
+            const pthread_attr_t *attr,
+            void *(*start_routine)(void*), void *arg) {
+
+  size_t size = 0;
+  size_t guard = 0;
+
+  if (attr != NULL) {
+    __d_pthread_attr_getstacksize(attr, &size);
+    __d_pthread_attr_getguardsize(attr, &guard);
+  } else {
+    // get pthread default stack size
+    pthread_attr_t tmpattr;
+    __d_pthread_attr_init(&tmpattr);
+    __d_pthread_attr_getstacksize(&tmpattr, &size);
+    __d_pthread_attr_getguardsize(&tmpattr, &guard);
+    __d_pthread_attr_destroy(&tmpattr);
+  }
+
+  assert(size != 0);
+  assert((size & (STACK_ALIGN-1)) == 0);
+  assert((guard & (PAGE_SIZE-1)) == 0);
+
+  void *addr = unsafe_stack_alloc(size, guard);
+  struct tinfo *tinfo = (struct tinfo*) (
+        ((char*)addr) + size - sizeof(struct tinfo));
+  tinfo->start_routine = start_routine;
+  tinfo->start_routine_arg = arg;
+  tinfo->unsafe_stack_start = addr;
+  tinfo->unsafe_stack_size = size;
+  tinfo->unsafe_stack_guard = guard;
+
+  return REAL(pthread_create)(thread, attr, thread_start, tinfo);
+}
+
+/// Thread-specific data destructor
+void thread_cleanup_handler(void* _iter) {
+  // We want to free the unsafe stack only after all other destructors
+  // have already run. We force this function to be called multiple times.
+  size_t iter = (size_t) _iter;
+  if (iter < PTHREAD_DESTRUCTOR_ITERATIONS) {
+    __d_pthread_setspecific(thread_cleanup_key, (void*) (iter + 1));
+  } else {
+    // This is the last iteration
+    unsafe_stack_free();
+  }
+}
+
+int inited = 0;
+
+extern "C"
+__attribute__((visibility ("default")))
+#ifndef __linux__
+__attribute__((constructor(0)))
+#endif
+void __llvm__safestack_init() {
+  if (inited)
+    return;
+
+  inited = 1;
+
+  // Allocate unsafe stack for main thread
+  size_t size = __SAFESTACK_DEFAULT_STACK_SIZE;
+  size_t guard = 4096;
+  void *addr = unsafe_stack_alloc(size, guard);
+  unsafe_stack_setup(addr, size, guard);
+
+  // Initialize pthread interceptors for thread allocation
+  INTERCEPT_FUNCTION(pthread_create);
+
+  #define __FIND_FUNCTION(fn) \
+    __d_ ## fn = __extension__ (__typeof__(__d_ ## fn)) dlsym(RTLD_DEFAULT, #fn);
+
+  // Find pthread functions that we need
+  __FIND_FUNCTION(pthread_attr_init)
+  __FIND_FUNCTION(pthread_attr_destroy)
+  __FIND_FUNCTION(pthread_attr_getstacksize)
+  __FIND_FUNCTION(pthread_attr_getguardsize)
+  __FIND_FUNCTION(pthread_key_create)
+  __FIND_FUNCTION(pthread_setspecific)
+
+  if (__d_pthread_key_create != NULL) {
+    // We're using pthreads, setup the cleanup handler
+    __d_pthread_key_create(&thread_cleanup_key, thread_cleanup_handler);
+  }
+}
+
+#ifndef NDEBUG
+extern "C"
+__attribute__((visibility ("default")))
+void __llvm__safestack_dump() {
+  fprintf(stderr,
+          "Unsafe stack addr = %p, ptr = %p, size = 0x%lx, guard = 0x%lx\n",
+          __GET_UNSAFE_STACK_START(), __GET_UNSAFE_STACK_PTR(),
+          __GET_UNSAFE_STACK_SIZE(), __GET_UNSAFE_STACK_GUARD());
+}
+
+#endif
+
+extern "C"
+__attribute__((visibility ("default")))
+__attribute__((noinline))
+void *__safestack_get_unsafe_stack_start() {
+  return __GET_UNSAFE_STACK_START();
+}
+
+extern "C"
+__attribute__((visibility ("default")))
+__attribute__((noinline))
+void *__safestack_get_unsafe_stack_ptr() {
+  return __GET_UNSAFE_STACK_PTR();
+}
+
+extern "C"
+__attribute__((visibility ("default")))
+__attribute__((noinline))
+void *__safestack_get_safe_stack_ptr() {
+  return (char*) __builtin_frame_address(0) + 2*sizeof(void*);
+}
+
+#ifdef __linux__
+// Run safestack initialization before any other constructors
+// FIXME: can we do something similar on Mac or FreeBSD?
+extern "C" {
+__attribute__((section(".preinit_array"), used))
+void (*__llvm__safestack_preinit)(void) = __llvm__safestack_init;
+}
+#endif
+
+} // namespace __llvm__safestack
Index: make/platform/clang_darwin.mk
===================================================================
--- make/platform/clang_darwin.mk
+++ make/platform/clang_darwin.mk
@@ -106,6 +106,10 @@
 Configs += ubsan_osx
 UniversalArchs.ubsan_osx := $(call CheckArches,i386 x86_64 x86_64h,ubsan_osx)
 
+# Configurations which define the safestack support functions.
+Configs += safestack_osx
+UniversalArchs.safestack_osx = $(call CheckArches,i386 x86_64 x86_64h,safestack_osx)
+
 # Darwin 10.6 has a bug in cctools that makes it unable to use ranlib on our ARM
 # object files. If we are on that platform, strip out all ARM archs. We still
 # build the libraries themselves so that Clang can find them where it expects
@@ -170,6 +174,10 @@
 
 CFLAGS.ubsan_osx := $(CFLAGS) -mmacosx-version-min=10.6 -fno-builtin
 
+CFLAGS.safestack_osx := \
+	$(CFLAGS) -fno-rtti -fno-exceptions -fno-builtin \
+	-fno-stack-protector -fno-safe-stack
+
 CFLAGS.ios.i386		:= $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS)
 CFLAGS.ios.x86_64	:= $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS)
 CFLAGS.ios.x86_64h	:= $(CFLAGS) $(IOSSIM_DEPLOYMENT_ARGS)
@@ -244,6 +252,8 @@
 FUNCTIONS.ubsan_osx := $(UbsanFunctions) $(UbsanCXXFunctions) \
                        $(SanitizerCommonFunctions)
 
+FUNCTIONS.safestack_osx := $(SafeStackFunctions) $(InterceptionFunctions)
+
 CCKEXT_COMMON_FUNCTIONS := \
 	absvdi2 \
 	absvsi2 \
Index: make/platform/clang_linux.mk
===================================================================
--- make/platform/clang_linux.mk
+++ make/platform/clang_linux.mk
@@ -50,21 +50,22 @@
 # Build runtime libraries for i386.
 ifeq ($(call contains,$(SupportedArches),i386),true)
 Configs += builtins-i386 profile-i386 san-i386 asan-i386 asan_cxx-i386 \
-	   ubsan-i386 ubsan_cxx-i386
+	   ubsan-i386 ubsan_cxx-i386 safestack-i386
 Arch.builtins-i386 := i386
 Arch.profile-i386 := i386
 Arch.san-i386 := i386
 Arch.asan-i386 := i386
 Arch.asan_cxx-i386 := i386
 Arch.ubsan-i386 := i386
 Arch.ubsan_cxx-i386 := i386
+Arch.safestack-i386 := i386
 endif
 
 # Build runtime libraries for x86_64.
 ifeq ($(call contains,$(SupportedArches),x86_64),true)
 Configs += builtins-x86_64 profile-x86_64 san-x86_64 asan-x86_64 asan_cxx-x86_64 \
 	   tsan-x86_64 msan-x86_64 ubsan-x86_64 ubsan_cxx-x86_64 dfsan-x86_64 \
-	   lsan-x86_64
+	   lsan-x86_64 safestack-x86_64
 Arch.builtins-x86_64 := x86_64
 Arch.profile-x86_64 := x86_64
 Arch.san-x86_64 := x86_64
@@ -76,6 +77,7 @@
 Arch.ubsan_cxx-x86_64 := x86_64
 Arch.dfsan-x86_64 := x86_64
 Arch.lsan-x86_64 := x86_64
+Arch.safestack-x86_64 := x86_64
 endif
 
 endif
@@ -110,6 +112,10 @@
 CFLAGS.ubsan_cxx-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS)
 CFLAGS.dfsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.lsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
+CFLAGS.safestack-i386 := $(CFLAGS) -m32 -fPIE -fno-builtin -fno-exceptions \
+				-fno-rtti -fno-stack-protector -fno-safe-stack
+CFLAGS.safestack-x86_64 := $(CFLAGS) -m64 -fPIE -fno-builtin -fno-exceptions \
+				-fno-rtti -fno-stack-protector -fno-safe-stack
 
 SHARED_LIBRARY.asan-arm-android := 1
 ANDROID_COMMON_FLAGS := -target arm-linux-androideabi \
@@ -156,6 +162,8 @@
                                             $(SanitizerCommonFunctions)
 FUNCTIONS.lsan-x86_64 := $(LsanFunctions) $(InterceptionFunctions) \
                                           $(SanitizerCommonFunctions)
+FUNCTIONS.safestack-i386 := $(SafeStackFunctions) $(InterceptionFunctions)
+FUNCTIONS.safestack-x86_64 := $(SafeStackFunctions) $(InterceptionFunctions)
 
 # Always use optimized variants.
 OPTIMIZED := 1
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to