diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:05:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:05:08 +0000 |
commit | 0646903fc1f75f6e605754621119473ee083f4a4 (patch) | |
tree | 57bce79a7423a054cccec23bdf6cd96e2d271b4a /lib/safestack | |
parent | 005b7ed8f76756d94ef6266ded755ab7863cb936 (diff) | |
download | src-0646903fc1f75f6e605754621119473ee083f4a4.tar.gz src-0646903fc1f75f6e605754621119473ee083f4a4.zip |
Vendor import of compiler-rt trunk r351319 (just before the release_80vendor/compiler-rt/compiler-rt-trunk-r351319vendor/compiler-rt/compiler-rt-release_80-r351543
branch point):
https://llvm.org/svn/llvm-project/compiler-rt/trunk@351319
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=343175
svn path=/vendor/compiler-rt/compiler-rt-release_80-r351543/; revision=343195; tag=vendor/compiler-rt/compiler-rt-release_80-r351543
Diffstat (limited to 'lib/safestack')
-rw-r--r-- | lib/safestack/CMakeLists.txt | 27 | ||||
-rw-r--r-- | lib/safestack/safestack.cc | 83 |
2 files changed, 68 insertions, 42 deletions
diff --git a/lib/safestack/CMakeLists.txt b/lib/safestack/CMakeLists.txt index 5a1bac2912b7..cc874a3fe8f1 100644 --- a/lib/safestack/CMakeLists.txt +++ b/lib/safestack/CMakeLists.txt @@ -6,29 +6,14 @@ include_directories(..) set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -if(APPLE) - # Build universal binary on APPLE. +foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) add_compiler_rt_runtime(clang_rt.safestack STATIC - OS osx - ARCHS ${SAFESTACK_SUPPORTED_ARCH} + ARCHS ${arch} SOURCES ${SAFESTACK_SOURCES} - $<TARGET_OBJECTS:RTInterception.osx> - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - $<TARGET_OBJECTS:RTSanitizerCommonNoLibc.osx> + $<TARGET_OBJECTS:RTInterception.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> + $<TARGET_OBJECTS:RTSanitizerCommonNoLibc.${arch}> CFLAGS ${SAFESTACK_CFLAGS} PARENT_TARGET safestack) -else() - # Otherwise, build separate libraries for each target. - foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.safestack - STATIC - ARCHS ${arch} - SOURCES ${SAFESTACK_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonNoLibc.${arch}> - CFLAGS ${SAFESTACK_CFLAGS} - PARENT_TARGET safestack) - endforeach() -endif() +endforeach() diff --git a/lib/safestack/safestack.cc b/lib/safestack/safestack.cc index 8af93624b991..e68208015fb9 100644 --- a/lib/safestack/safestack.cc +++ b/lib/safestack/safestack.cc @@ -14,11 +14,13 @@ // //===----------------------------------------------------------------------===// +#include <errno.h> #include <limits.h> #include <pthread.h> #include <stddef.h> #include <stdint.h> #include <unistd.h> +#include <stdlib.h> #include <sys/resource.h> #include <sys/types.h> #if !defined(__NetBSD__) @@ -115,14 +117,6 @@ static inline void unsafe_stack_setup(void *start, size_t size, size_t guard) { unsafe_stack_guard = guard; } -static void unsafe_stack_free() { - if (unsafe_stack_start) { - UnmapOrDie((char *)unsafe_stack_start - unsafe_stack_guard, - unsafe_stack_size + unsafe_stack_guard); - } - unsafe_stack_start = nullptr; -} - /// Thread data for the cleanup handler static pthread_key_t thread_cleanup_key; @@ -149,26 +143,73 @@ static void *thread_start(void *arg) { 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 - // intercepting the pthread_setspecific function itself pthread_setspecific(thread_cleanup_key, (void *)1); return start_routine(start_routine_arg); } -/// Thread-specific data destructor +/// Linked list used to store exiting threads stack/thread information. +struct thread_stack_ll { + struct thread_stack_ll *next; + void *stack_base; + size_t size; + pid_t pid; + tid_t tid; +}; + +/// Linked list of unsafe stacks for threads that are exiting. We delay +/// unmapping them until the thread exits. +static thread_stack_ll *thread_stacks = nullptr; +static pthread_mutex_t thread_stacks_mutex = PTHREAD_MUTEX_INITIALIZER; + +/// Thread-specific data destructor. We want to free the unsafe stack only after +/// this thread is terminated. libc can call functions in safestack-instrumented +/// code (like free) after thread-specific data destructors have run. static 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. - // User destructors that might run more then PTHREAD_DESTRUCTOR_ITERATIONS-1 - // times might still end up executing after the unsafe stack is deallocated. - size_t iter = (size_t)_iter; - if (iter < PTHREAD_DESTRUCTOR_ITERATIONS) { - pthread_setspecific(thread_cleanup_key, (void *)(iter + 1)); - } else { - // This is the last iteration - unsafe_stack_free(); + CHECK_NE(unsafe_stack_start, nullptr); + pthread_setspecific(thread_cleanup_key, NULL); + + pthread_mutex_lock(&thread_stacks_mutex); + // Temporary list to hold the previous threads stacks so we don't hold the + // thread_stacks_mutex for long. + thread_stack_ll *temp_stacks = thread_stacks; + thread_stacks = nullptr; + pthread_mutex_unlock(&thread_stacks_mutex); + + pid_t pid = getpid(); + tid_t tid = GetTid(); + + // Free stacks for dead threads + thread_stack_ll **stackp = &temp_stacks; + while (*stackp) { + thread_stack_ll *stack = *stackp; + int error; + if (stack->pid != pid || + (internal_iserror(TgKill(stack->pid, stack->tid, 0), &error) && + error == ESRCH)) { + UnmapOrDie(stack->stack_base, stack->size); + *stackp = stack->next; + free(stack); + } else + stackp = &stack->next; } + + thread_stack_ll *cur_stack = + (thread_stack_ll *)malloc(sizeof(thread_stack_ll)); + cur_stack->stack_base = (char *)unsafe_stack_start - unsafe_stack_guard; + cur_stack->size = unsafe_stack_size + unsafe_stack_guard; + cur_stack->pid = pid; + cur_stack->tid = tid; + + pthread_mutex_lock(&thread_stacks_mutex); + // Merge thread_stacks with the current thread's stack and any remaining + // temp_stacks + *stackp = thread_stacks; + cur_stack->next = temp_stacks; + thread_stacks = cur_stack; + pthread_mutex_unlock(&thread_stacks_mutex); + + unsafe_stack_start = nullptr; } static void EnsureInterceptorsInitialized(); |