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
This commit is contained in:
parent
abf736a780
commit
7752bcb234
|
@ -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);
|
||||
ScopedPthreadMutexLocker locker(&__libc_shared_globals()->abort_msg_lock);
|
||||
|
||||
if (__abort_message_ptr == nullptr) {
|
||||
// We must have crashed _very_ early.
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue