Clean up TLS_SLOT_BIONIC_PREINIT usage a bit

- It is only needed for dynamic executables, so move the initialization
   out of __libc_init_main_thread and just before the solib constructor
   calls. For static executables, the slot was initialized, then never
   used or cleared. Instead, leave it clear.

 - For static executables, __libc_init_main_thread already initialized the
   stack guard, so remove the redundant __init_thread_stack_guard call.

 - Simplify the slot access/clearing a bit in __libc_preinit.

 - Remove the "__libc_init_common() will change the TLS area so the old one
   won't be accessible anyway." comment. AFAICT, it's incorrect -- the
   main thread's TLS area in a dynamic executable is initialized to a
   static pthread_internal_t object in the linker, then reused by libc.so.

Test: adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
Test: adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static
Change-Id: Ie2da6f5be3ad563fa65b38eaadf8ba6ecc6a64b6
This commit is contained in:
Ryan Prichard 2018-04-30 18:29:32 -07:00
parent aa922bbaf3
commit 6631f9b03d
4 changed files with 12 additions and 18 deletions

View File

@ -81,8 +81,7 @@ void __libc_init_main_thread(KernelArgumentBlock& args) {
// We don't want to free the main thread's stack even when the main thread exits
// because things like environment variables with global scope live on it.
// We also can't free the pthread_internal_t itself, since that lives on the main
// thread's stack rather than on the heap.
// We also can't free the pthread_internal_t itself, since it is a static variable.
// The main thread has no mmap allocated space for stack or pthread_internal_t.
main_thread.mmap_size = 0;
@ -102,9 +101,5 @@ void __libc_init_main_thread(KernelArgumentBlock& args) {
__init_thread(&main_thread);
// Store a pointer to the kernel argument block in a TLS slot to be
// picked up by the libc constructor.
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
__init_alternate_signal_stack(&main_thread);
}

View File

@ -85,14 +85,11 @@ static void __libc_preinit_impl(KernelArgumentBlock& args) {
// to run before any others (such as the jemalloc constructor), and lower
// is better (http://b/68046352).
__attribute__((constructor(1))) static void __libc_preinit() {
// Read the kernel argument block pointer from TLS.
// Read the kernel argument block pointer from TLS, then clear the slot so no
// other initializer sees its value.
void** tls = __get_tls();
KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT];
KernelArgumentBlock* args = *args_slot;
// Clear the slot so no other initializer sees its value.
// __libc_init_common() will change the TLS area so the old one won't be accessible anyway.
*args_slot = NULL;
KernelArgumentBlock* args = static_cast<KernelArgumentBlock*>(tls[TLS_SLOT_BIONIC_PREINIT]);
tls[TLS_SLOT_BIONIC_PREINIT] = nullptr;
// The linker has initialized its copy of the global stack_chk_guard, and filled in the main
// thread's TLS slot with that value. Initialize the local global stack guard with its value.
@ -102,9 +99,8 @@ __attribute__((constructor(1))) static void __libc_preinit() {
}
// This function is called from the executable's _start entry point
// (see arch-$ARCH/bionic/crtbegin_dynamic.S), which is itself
// called by the dynamic linker after it has loaded all shared
// libraries the executable depends on.
// (see arch-$ARCH/bionic/crtbegin.c), which is itself called by the dynamic
// linker after it has loaded all shared libraries the executable depends on.
//
// Note that the dynamic linker has also run all constructors in the
// executable at this point.

View File

@ -86,10 +86,9 @@ __noreturn void __libc_init(void* raw_args,
BIONIC_STOP_UNWIND;
KernelArgumentBlock args(raw_args);
__libc_init_main_thread(args);
// Initializing the globals requires TLS to be available for errno.
__init_thread_stack_guard(__get_thread());
__libc_init_main_thread(args);
__libc_init_globals(args);
__libc_init_AT_SECURE(args);

View File

@ -414,6 +414,10 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) {
if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]);
// Store a pointer to the kernel argument block in a TLS slot to be
// picked up by the libc constructor.
__get_tls()[TLS_SLOT_BIONIC_PREINIT] = &args;
si->call_pre_init_constructors();
/* After the prelink_image, the si->load_bias is initialized.