diff options
author | Ryan Prichard <rprichard@google.com> | 2018-11-22 02:41:04 -0800 |
---|---|---|
committer | Ryan Prichard <rprichard@google.com> | 2018-11-28 14:26:14 -0800 |
commit | 7752bcb234a9960d2e9e89766d143b7ac0c5f332 (patch) | |
tree | e7bcae45f66a0682f07d242f18b33681fc9e4cfa | |
parent | abf736a7803f4acc8b70a2dab0d43b931aa9c5c0 (diff) |
Move the abort message to libc_shared_globals
__libc_shared_globals() is available in dynamic modules as soon as
relocation has finished (i.e. after ifuncs run). Before ifuncs have run,
the android_set_abort_message() function already doesn't work because it
calls public APIs via the PLT. (If this matters, we can use a static
bool variable to enable android_set_abort_message after libc
initialization).
__libc_shared_globals() is hidden, so it's available in the linker
immediately (i.e. before relocation). TLS memory (e.g. errno) currently
isn't accessible until after relocation, but a later patch fixes that.
Bug: none
Test: bionic unit tests
Change-Id: Ied4433758ed2da9ee404c6158e319cf502d05a53
-rw-r--r-- | libc/bionic/android_set_abort_message.cpp | 16 | ||||
-rw-r--r-- | libc/bionic/libc_init_common.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 4 | ||||
-rw-r--r-- | libc/private/KernelArgumentBlock.h | 5 | ||||
-rw-r--r-- | libc/private/bionic_globals.h | 6 | ||||
-rw-r--r-- | linker/linker_main.cpp | 4 |
6 files changed, 14 insertions, 25 deletions
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp index 58f24cfa8..56e67710a 100644 --- a/libc/bionic/android_set_abort_message.cpp +++ b/libc/bionic/android_set_abort_message.cpp @@ -35,10 +35,9 @@ #include <sys/mman.h> #include "private/bionic_defs.h" +#include "private/bionic_globals.h" #include "private/ScopedPthreadMutexLocker.h" -static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER; - struct abort_msg_t { size_t size; char msg[0]; @@ -56,8 +55,6 @@ static_assert(offsetof(magic_abort_msg_t, msg) == 2 * sizeof(uint64_t), "The in-memory layout of magic_abort_msg_t is not consistent with what automated " "tools expect."); -abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. - [[clang::optnone]] static void fill_abort_message_magic(magic_abort_msg_t* new_magic_abort_message) { // 128-bit magic for the abort message. Chosen by fair dice roll. @@ -71,14 +68,9 @@ static void fill_abort_message_magic(magic_abort_msg_t* new_magic_abort_message) __BIONIC_WEAK_FOR_NATIVE_BRIDGE void android_set_abort_message(const char* msg) { - ScopedPthreadMutexLocker locker(&g_abort_msg_lock); - - if (__abort_message_ptr == nullptr) { - // We must have crashed _very_ early. - return; - } + ScopedPthreadMutexLocker locker(&__libc_shared_globals()->abort_msg_lock); - if (*__abort_message_ptr != nullptr) { + if (__libc_shared_globals()->abort_msg != nullptr) { // We already have an abort message. // Assume that the first crash is the one most worth reporting. return; @@ -94,5 +86,5 @@ void android_set_abort_message(const char* msg) { fill_abort_message_magic(new_magic_abort_message); new_magic_abort_message->msg.size = size; strcpy(new_magic_abort_message->msg.msg, msg); - *__abort_message_ptr = &new_magic_abort_message->msg; + __libc_shared_globals()->abort_msg = &new_magic_abort_message->msg; } diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp index bd2077574..f78a11ab6 100644 --- a/libc/bionic/libc_init_common.cpp +++ b/libc/bionic/libc_init_common.cpp @@ -52,7 +52,6 @@ #include "private/thread_private.h" #include "pthread_internal.h" -extern "C" abort_msg_t** __abort_message_ptr; extern "C" int __system_properties_init(void); __LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals; @@ -97,7 +96,6 @@ void __libc_init_common(KernelArgumentBlock& args) { environ = args.envp; errno = 0; __progname = args.argv[0] ? args.argv[0] : "<unknown>"; - __abort_message_ptr = args.abort_message_ptr; #if !defined(__LP64__) __check_max_thread_id(); @@ -297,8 +295,6 @@ static void __initialize_personality() { } void __libc_init_AT_SECURE(KernelArgumentBlock& args) { - __abort_message_ptr = args.abort_message_ptr; - // Check that the kernel provided a value for AT_SECURE. errno = 0; unsigned long is_AT_SECURE = getauxval(AT_SECURE); diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index 10fc15171..f2168b89e 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -153,6 +153,8 @@ extern "C" void android_set_application_target_sdk_version(int target) { } __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() { - static libc_shared_globals globals; + static libc_shared_globals globals = { + .abort_msg_lock = PTHREAD_MUTEX_INITIALIZER, + }; return &globals; } diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h index 1e053a195..c8ce8411f 100644 --- a/libc/private/KernelArgumentBlock.h +++ b/libc/private/KernelArgumentBlock.h @@ -23,8 +23,6 @@ #include "private/bionic_macros.h" -struct abort_msg_t; - // When the kernel starts the dynamic linker, it passes a pointer to a block // of memory containing argc, the argv array, the environment variable array, // and the array of ELF aux vectors. This class breaks that block up into its @@ -64,9 +62,6 @@ class KernelArgumentBlock { char** envp; ElfW(auxv_t)* auxv; - // Other data that we want to pass from the dynamic linker to libc.so. - abort_msg_t** abort_message_ptr; - private: BIONIC_DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock); }; diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h index 44ec2e3b7..e9eaee096 100644 --- a/libc/private/bionic_globals.h +++ b/libc/private/bionic_globals.h @@ -30,6 +30,7 @@ #define _PRIVATE_BIONIC_GLOBALS_H #include <sys/cdefs.h> +#include <pthread.h> #include "private/bionic_fdsan.h" #include "private/bionic_malloc_dispatch.h" @@ -44,6 +45,8 @@ struct libc_globals { __LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals; +struct abort_msg_t; + // Globals shared between the dynamic linker and libc.so. struct libc_shared_globals { FdTable fd_table; @@ -52,6 +55,9 @@ struct libc_shared_globals { // record the number of arguments passed to the linker itself rather than to // the program it's loading. Typically 0, sometimes 1. int initial_linker_arg_count; + + pthread_mutex_t abort_msg_lock; + abort_msg_t* abort_msg; }; __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals(); diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 963e82c86..442ecd909 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -116,7 +116,6 @@ soinfo* solist_get_vdso() { } int g_ld_debug_verbosity; -abort_msg_t* g_abort_message = nullptr; // For debuggerd. static std::vector<std::string> g_ld_preload_names; @@ -300,7 +299,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load #ifdef __ANDROID__ debuggerd_callbacks_t callbacks = { .get_abort_message = []() { - return g_abort_message; + return __libc_shared_globals()->abort_msg; }, .post_dump = ¬ify_gdb_of_libraries, }; @@ -664,7 +663,6 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) g_default_namespace.add_soinfo(solinker); init_link_map_head(*solinker, kLinkerPath); - args.abort_message_ptr = &g_abort_message; ElfW(Addr) start_address = linker_main(args, exe_to_load); INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address)); |