From 34583c1089755406877cde9ebd9f75f73858a9bc Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 13 Nov 2018 15:30:07 -0800 Subject: [PATCH] Move dlerror out of a TLS slot and into a pthread_internal_t member. Bug: N/A Test: boots, tests pass. Change-Id: Idf25d2ee457a5d26d0bdd6281cee72c345c8b755 --- libc/bionic/pthread_internal.h | 1 + libc/private/bionic_tls.h | 7 ++++--- linker/dlfcn.cpp | 5 ++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h index 5a5318d6b..2ebd2b4e5 100644 --- a/libc/bionic/pthread_internal.h +++ b/libc/bionic/pthread_internal.h @@ -139,6 +139,7 @@ class pthread_internal_t { * The dynamic linker implements dlerror(3), which makes it hard for us to implement this * per-thread buffer by simply using malloc(3) and free(3). */ + char* current_dlerror; #define __BIONIC_DLERROR_BUFFER_SIZE 512 char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE]; diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h index 80dc9bce7..36e3d7b5a 100644 --- a/libc/private/bionic_tls.h +++ b/libc/private/bionic_tls.h @@ -64,14 +64,15 @@ enum { TLS_SLOT_OPENGL = 4, TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86. - TLS_SLOT_DLERROR, + + // TLS slot 6 was used for dlerror but is now free. // Fast storage for Thread::Current() in ART. - TLS_SLOT_ART_THREAD_SELF, + TLS_SLOT_ART_THREAD_SELF = 7, // Lets TSAN avoid using pthread_getspecific for finding the current thread // state. - TLS_SLOT_TSAN, + TLS_SLOT_TSAN = 8, BIONIC_TLS_SLOTS // Must come last! }; diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 5ae7b9b19..5a47272c1 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -96,10 +96,9 @@ _Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_ static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; static char* __bionic_set_dlerror(char* new_value) { - char** dlerror_slot = &reinterpret_cast(__get_tls())[TLS_SLOT_DLERROR]; + char* old_value = __get_thread()->current_dlerror; + __get_thread()->current_dlerror = new_value; - char* old_value = *dlerror_slot; - *dlerror_slot = new_value; if (new_value != nullptr) LD_LOG(kLogErrors, "dlerror set to \"%s\"", new_value); return old_value; }