Merge "Merge pie-platform-release (PPRL.181105.017, history only) into master" am: 998175dc6f am: 9edc5a4591
am: 7a70f79748

Change-Id: I2a11efc04ed374df996e2a1b4690c992d4f6c959
diff --git a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
index 1bb7ab0..849d253 100644
--- a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
+++ b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
@@ -26,14 +26,15 @@
  * SUCH DAMAGE.
  */
 
-#include "private/KernelArgumentBlock.h"
+#include "private/bionic_auxv.h"
 #include "private/bionic_globals.h"
 
 // This file is compiled without stack protection, because it runs before TLS
 // has been set up.
 
-__LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args) {
-  __libc_sysinfo = reinterpret_cast<void*>(args.getauxval(AT_SYSINFO));
+__LIBC_HIDDEN__ void __libc_init_sysinfo() {
+  bool dummy;
+  __libc_sysinfo = reinterpret_cast<void*>(__bionic_getauxval(AT_SYSINFO, dummy));
 }
 
 // TODO: lose this function and just access __libc_sysinfo directly.
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index be9d32e..5abdc07 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -30,12 +30,12 @@
 
 #include "private/KernelArgumentBlock.h"
 #include "private/bionic_arc4random.h"
-#include "private/bionic_auxv.h"
 #include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_ssp.h"
 #include "pthread_internal.h"
 
+extern "C" pid_t __getpid();
 extern "C" int __set_tid_address(int* tid_address);
 
 // Declared in "private/bionic_ssp.h".
@@ -61,23 +61,36 @@
 // -fno-stack-protector because it's responsible for setting up the main
 // thread's TLS (which stack protector relies on).
 
+// Do enough setup to:
+//  - Let the dynamic linker invoke system calls (and access errno)
+//  - Ensure that TLS access functions (__get_{tls,thread}) never return NULL
+//  - Allow the stack protector to work (with a zero cookie)
+// Avoid doing much more because, when this code is called within the dynamic
+// linker, the linker binary hasn't been relocated yet, so certain kinds of code
+// are hazardous, such as accessing non-hidden global variables.
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
-void __libc_init_main_thread(KernelArgumentBlock& args) {
-  __libc_auxv = args.auxv;
+void __libc_init_main_thread_early(KernelArgumentBlock& args) {
+  __libc_shared_globals()->auxv = args.auxv;
 #if defined(__i386__)
-  __libc_init_sysinfo(args);
+  __libc_init_sysinfo();
 #endif
-
-  // The -fstack-protector implementation uses TLS, so make sure that's
-  // set up before we call any function that might get a stack check inserted.
-  // TLS also needs to be set up before errno (and therefore syscalls) can be used.
   __set_tls(main_thread.tls);
-  if (!__init_tls(&main_thread)) async_safe_fatal("failed to initialize TLS: %s", strerror(errno));
+  __init_tls(&main_thread);
+  main_thread.tid = __getpid();
+  main_thread.set_cached_pid(main_thread.tid);
+}
+
+// Finish initializing the main thread.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+void __libc_init_main_thread_late() {
+  main_thread.bionic_tls = __allocate_bionic_tls();
+  if (main_thread.bionic_tls == nullptr) {
+    // Avoid strerror because it might need bionic_tls.
+    async_safe_fatal("failed to allocate bionic_tls: error %d", errno);
+  }
 
   // Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
-  // As a side-effect, this tells us our pid (which is the same as the main thread's tid).
-  main_thread.tid = __set_tid_address(&main_thread.tid);
-  main_thread.set_cached_pid(main_thread.tid);
+  __set_tid_address(&main_thread.tid);
 
   // 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.
@@ -96,8 +109,8 @@
   // The TLS stack guard is set from the global, so ensure that we've initialized the global
   // before we initialize the TLS. Dynamic executables will initialize their copy of the global
   // stack protector from the one in the main thread's TLS.
-  __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard), args);
-  __init_thread_stack_guard(&main_thread);
+  __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
+  __init_tls_stack_guard(&main_thread);
 
   __init_thread(&main_thread);
 
diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp
index fa2617f..74ac43c 100644
--- a/libc/bionic/bionic_arc4random.cpp
+++ b/libc/bionic/bionic_arc4random.cpp
@@ -35,9 +35,7 @@
 
 #include <async_safe/log.h>
 
-#include "private/KernelArgumentBlock.h"
-
-void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args) {
+void __libc_safe_arc4random_buf(void* buf, size_t n) {
   // Only call arc4random_buf once we have `/dev/urandom` because getentropy(3)
   // will fall back to using `/dev/urandom` if getrandom(2) fails, and abort if
   // if can't use `/dev/urandom`.
@@ -53,7 +51,7 @@
                      16 - at_random_bytes_consumed, n);
   }
 
-  memcpy(buf, reinterpret_cast<char*>(args.getauxval(AT_RANDOM)) + at_random_bytes_consumed, n);
+  memcpy(buf, reinterpret_cast<char*>(getauxval(AT_RANDOM)) + at_random_bytes_consumed, n);
   at_random_bytes_consumed += n;
   return;
 }
diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp
index 607e89c..c8f867b 100644
--- a/libc/bionic/getauxval.cpp
+++ b/libc/bionic/getauxval.cpp
@@ -30,17 +30,27 @@
 #include <sys/cdefs.h>
 #include <sys/auxv.h>
 #include <private/bionic_auxv.h>
+#include <private/bionic_globals.h>
 #include <elf.h>
 #include <errno.h>
 
-__LIBC_HIDDEN__ ElfW(auxv_t)* __libc_auxv = nullptr;
-
-extern "C" unsigned long int getauxval(unsigned long int type) {
-  for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
+// This function needs to be safe to call before TLS is set up, so it can't
+// access errno or the stack protector.
+__attribute__((no_stack_protector))
+__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists) {
+  for (ElfW(auxv_t)* v = __libc_shared_globals()->auxv; v->a_type != AT_NULL; ++v) {
     if (v->a_type == type) {
+      exists = true;
       return v->a_un.a_val;
     }
   }
-  errno = ENOENT;
+  exists = false;
   return 0;
 }
+
+extern "C" unsigned long getauxval(unsigned long type) {
+  bool exists;
+  unsigned long result = __bionic_getauxval(type, exists);
+  if (!exists) errno = ENOENT;
+  return result;
+}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 4702e1c..f1fbfa9 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -43,9 +43,7 @@
 
 #include <async_safe/log.h>
 
-#include "private/KernelArgumentBlock.h"
 #include "private/WriteProtected.h"
-#include "private/bionic_auxv.h"
 #include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
@@ -59,14 +57,14 @@
 // Not public, but well-known in the BSDs.
 const char* __progname;
 
-void __libc_init_globals(KernelArgumentBlock& args) {
+void __libc_init_globals() {
   // Initialize libc globals that are needed in both the linker and in libc.
   // In dynamic binaries, this is run at least twice for different copies of the
   // globals, once for the linker's copy and once for the one in libc.so.
   __libc_globals.initialize();
-  __libc_globals.mutate([&args](libc_globals* globals) {
-    __libc_init_vdso(globals, args);
-    __libc_init_setjmp_cookie(globals, args);
+  __libc_globals.mutate([](libc_globals* globals) {
+    __libc_init_vdso(globals);
+    __libc_init_setjmp_cookie(globals);
   });
 }
 
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 84b59ca..73f5817 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -50,9 +50,7 @@
 
 #if defined(__cplusplus)
 
-class KernelArgumentBlock;
-
-__LIBC_HIDDEN__ void __libc_init_globals(KernelArgumentBlock& args);
+__LIBC_HIDDEN__ void __libc_init_globals();
 
 __LIBC_HIDDEN__ void __libc_init_common();
 
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 25d462f..af1b847 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -51,7 +51,6 @@
 #include <elf.h>
 #include "libc_init_common.h"
 
-#include "private/bionic_auxv.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_macros.h"
 #include "private/bionic_ssp.h"
@@ -78,13 +77,12 @@
 // after __stack_chk_guard is initialized and therefore can safely have a stack
 // protector.
 __attribute__((noinline))
-static void __libc_preinit_impl(KernelArgumentBlock& args) {
-  __libc_auxv = args.auxv;
+static void __libc_preinit_impl() {
 #if defined(__i386__)
-  __libc_init_sysinfo(args);
+  __libc_init_sysinfo();
 #endif
 
-  __libc_init_globals(args);
+  __libc_init_globals();
   __libc_init_common();
 
   // Hooks for various libraries to let them know that we're starting up.
@@ -100,17 +98,11 @@
 // 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, then clear the slot so no
-  // other initializer sees its value.
-  void** tls = __get_tls();
-  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.
-  __stack_chk_guard = reinterpret_cast<uintptr_t>(tls[TLS_SLOT_STACK_GUARD]);
+  __stack_chk_guard = reinterpret_cast<uintptr_t>(__get_tls()[TLS_SLOT_STACK_GUARD]);
 
-  __libc_preinit_impl(*args);
+  __libc_preinit_impl();
 }
 
 // This function is called from the executable's _start entry point
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 51fbe07..289b4a3 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -95,14 +95,12 @@
                                         structors_array_t const * const structors) {
   BIONIC_STOP_UNWIND;
 
+  // Initialize TLS early so system calls and errno work.
   KernelArgumentBlock args(raw_args);
+  __libc_init_main_thread_early(args);
+  __libc_init_main_thread_late();
+  __libc_init_globals();
   __libc_shared_globals()->init_progname = args.argv[0];
-
-  // Initializing the globals requires TLS to be available for errno.
-  __libc_init_main_thread(args);
-
-  __libc_init_globals(args);
-
   __libc_init_AT_SECURE(args.envp);
   __libc_init_common();
 
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 6f632e8..8e8d180 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -53,39 +53,43 @@
 #endif
 
 // This code is used both by each new pthread and the code that initializes the main thread.
-bool __init_tls(pthread_internal_t* thread) {
+__attribute__((no_stack_protector))
+void __init_tls(pthread_internal_t* thread) {
   // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
   thread->tls[TLS_SLOT_SELF] = thread->tls;
   thread->tls[TLS_SLOT_THREAD_ID] = thread;
+}
 
+__attribute__((no_stack_protector))
+void __init_tls_stack_guard(pthread_internal_t* thread) {
+  // GCC looks in the TLS for the stack guard on x86, so copy it there from our global.
+  thread->tls[TLS_SLOT_STACK_GUARD] = reinterpret_cast<void*>(__stack_chk_guard);
+}
+
+bionic_tls* __allocate_bionic_tls() {
   // Add a guard before and after.
   size_t allocation_size = BIONIC_TLS_SIZE + (2 * PTHREAD_GUARD_SIZE);
   void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (allocation == MAP_FAILED) {
     async_safe_format_log(ANDROID_LOG_WARN, "libc",
                           "pthread_create failed: couldn't allocate TLS: %s", strerror(errno));
-    return false;
+    return nullptr;
   }
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard");
 
   // Carve out the writable TLS section.
-  thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) +
+  bionic_tls* result = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) +
                                                      PTHREAD_GUARD_SIZE);
-  if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
+  if (mprotect(result, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
     async_safe_format_log(ANDROID_LOG_WARN, "libc",
                           "pthread_create failed: couldn't mprotect TLS: %s", strerror(errno));
     munmap(allocation, allocation_size);
-    return false;
+    return nullptr;
   }
 
-  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
-  return true;
-}
-
-void __init_thread_stack_guard(pthread_internal_t* thread) {
-  // GCC looks in the TLS for the stack guard on x86, so copy it there from our global.
-  thread->tls[TLS_SLOT_STACK_GUARD] = reinterpret_cast<void*>(__stack_chk_guard);
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, result, BIONIC_TLS_SIZE, "bionic TLS");
+  return result;
 }
 
 static void __init_alternate_signal_stack(pthread_internal_t* thread) {
@@ -255,11 +259,15 @@
 
   thread->mmap_size = mmap_size;
   thread->attr = *attr;
-  if (!__init_tls(thread)) {
+
+  thread->bionic_tls = __allocate_bionic_tls();
+  if (thread->bionic_tls == nullptr) {
     if (thread->mmap_size != 0) munmap(thread->attr.stack_base, thread->mmap_size);
     return EAGAIN;
   }
-  __init_thread_stack_guard(thread);
+
+  __init_tls(thread);
+  __init_tls_stack_guard(thread);
 
   *threadp = thread;
   *child_stack = stack_top;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 81b885a..5a5318d 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -152,10 +152,11 @@
   pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
 };
 
-__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
-__LIBC_HIDDEN__ bool __init_tls(pthread_internal_t* thread);
-__LIBC_HIDDEN__ void __init_thread_stack_guard(pthread_internal_t* thread);
+__LIBC_HIDDEN__ void __init_tls(pthread_internal_t* thread);
+__LIBC_HIDDEN__ void __init_tls_stack_guard(pthread_internal_t* thread);
+__LIBC_HIDDEN__ bionic_tls* __allocate_bionic_tls();
 __LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
+__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
 
 __LIBC_HIDDEN__ pthread_t           __pthread_internal_add(pthread_internal_t* thread);
 __LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id);
diff --git a/libc/bionic/setjmp_cookie.cpp b/libc/bionic/setjmp_cookie.cpp
index 41a439f..e2a3fc0 100644
--- a/libc/bionic/setjmp_cookie.cpp
+++ b/libc/bionic/setjmp_cookie.cpp
@@ -38,11 +38,10 @@
 
 #include "private/bionic_arc4random.h"
 #include "private/bionic_globals.h"
-#include "private/KernelArgumentBlock.h"
 
-void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args) {
+void __libc_init_setjmp_cookie(libc_globals* globals) {
   long value;
-  __libc_safe_arc4random_buf(&value, sizeof(value), args);
+  __libc_safe_arc4random_buf(&value, sizeof(value));
 
   // Mask off the last bit to store the signal flag.
   globals->setjmp_cookie = value & ~1;
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
index c926a58..dbca9c0 100644
--- a/libc/bionic/vdso.cpp
+++ b/libc/bionic/vdso.cpp
@@ -20,11 +20,11 @@
 #include <limits.h>
 #include <link.h>
 #include <string.h>
+#include <sys/auxv.h>
 #include <sys/cdefs.h>
 #include <sys/time.h>
 #include <time.h>
 #include <unistd.h>
-#include "private/KernelArgumentBlock.h"
 
 static inline int vdso_return(int result) {
   if (__predict_true(result == 0)) return 0;
@@ -73,7 +73,7 @@
   return tv.tv_sec;
 }
 
-void __libc_init_vdso(libc_globals* globals, KernelArgumentBlock& args) {
+void __libc_init_vdso(libc_globals* globals) {
   auto&& vdso = globals->vdso;
   vdso[VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, nullptr };
   vdso[VDSO_CLOCK_GETRES] = { VDSO_CLOCK_GETRES_SYMBOL, nullptr };
@@ -81,7 +81,7 @@
   vdso[VDSO_TIME] = { VDSO_TIME_SYMBOL, nullptr };
 
   // Do we have a vdso?
-  uintptr_t vdso_ehdr_addr = args.getauxval(AT_SYSINFO_EHDR);
+  uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
   ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
   if (vdso_ehdr == nullptr) {
     return;
diff --git a/libc/private/bionic_arc4random.h b/libc/private/bionic_arc4random.h
index 0e9376e..cdc9b6d 100644
--- a/libc/private/bionic_arc4random.h
+++ b/libc/private/bionic_arc4random.h
@@ -31,13 +31,11 @@
 
 #include <stddef.h>
 
-#include "private/KernelArgumentBlock.h"
-
 // arc4random(3) aborts if it's unable to fetch entropy, which is always
 // the case for init on devices. GCE kernels have a workaround to ensure
 // sufficient entropy during early boot, but no device kernels do. This
 // wrapper falls back to AT_RANDOM if the kernel doesn't have enough
 // entropy for getrandom(2) or /dev/urandom.
-void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args);
+void __libc_safe_arc4random_buf(void* buf, size_t n);
 
 #endif
diff --git a/libc/private/bionic_auxv.h b/libc/private/bionic_auxv.h
index 53fcc49..8e33c1c 100644
--- a/libc/private/bionic_auxv.h
+++ b/libc/private/bionic_auxv.h
@@ -25,17 +25,9 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _PRIVATE_BIONIC_AUXV_H_
-#define _PRIVATE_BIONIC_AUXV_H_
 
-#include <elf.h>
-#include <link.h>
+#pragma once
+
 #include <sys/cdefs.h>
 
-__BEGIN_DECLS
-
-extern ElfW(auxv_t)* __libc_auxv;
-
-__END_DECLS
-
-#endif /* _PRIVATE_BIONIC_AUXV_H_ */
+__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists);
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 906d569..ba510b1 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 <link.h>
 #include <pthread.h>
 
 #include "private/bionic_fdsan.h"
@@ -56,6 +57,8 @@
   // the program it's loading. Typically 0, sometimes 1.
   int initial_linker_arg_count;
 
+  ElfW(auxv_t)* auxv;
+
   pthread_mutex_t abort_msg_lock;
   abort_msg_t* abort_msg;
 
@@ -67,14 +70,13 @@
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
 __LIBC_HIDDEN__ void __libc_init_fdsan();
 
-class KernelArgumentBlock;
 __LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals);
-__LIBC_HIDDEN__ void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args);
-__LIBC_HIDDEN__ void __libc_init_vdso(libc_globals* globals, KernelArgumentBlock& args);
+__LIBC_HIDDEN__ void __libc_init_setjmp_cookie(libc_globals* globals);
+__LIBC_HIDDEN__ void __libc_init_vdso(libc_globals* globals);
 
 #if defined(__i386__)
 __LIBC_HIDDEN__ extern void* __libc_sysinfo;
-__LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args);
+__LIBC_HIDDEN__ void __libc_init_sysinfo();
 #endif
 
 #endif
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index de086f2..80dc9bc 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -63,12 +63,6 @@
   TLS_SLOT_OPENGL_API = 3,
   TLS_SLOT_OPENGL = 4,
 
-  // This slot is only used to pass information from the dynamic linker to
-  // libc.so when the C library is loaded in to memory. The C runtime init
-  // function will then clear it. Since its use is extremely temporary,
-  // we reuse an existing location that isn't needed during libc startup.
-  TLS_SLOT_BIONIC_PREINIT = TLS_SLOT_OPENGL_API,
-
   TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
   TLS_SLOT_DLERROR,
 
@@ -132,7 +126,8 @@
 
 #if defined(__cplusplus)
 class KernelArgumentBlock;
-extern void __libc_init_main_thread(KernelArgumentBlock&);
+extern void __libc_init_main_thread_early(KernelArgumentBlock& args);
+extern void __libc_init_main_thread_late();
 #endif
 
 #endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index aa12b6e..3318c2c 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -148,8 +148,8 @@
 // An empty list of soinfos
 static soinfo_list_t g_empty_list;
 
-static void add_vdso(KernelArgumentBlock& args) {
-  ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(args.getauxval(AT_SYSINFO_EHDR));
+static void add_vdso() {
+  ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(getauxval(AT_SYSINFO_EHDR));
   if (ehdr_vdso == nullptr) {
     return;
   }
@@ -191,7 +191,7 @@
   ElfW(Addr) entry_point;
 };
 
-static ExecutableInfo get_executable_info(KernelArgumentBlock& args) {
+static ExecutableInfo get_executable_info() {
   ExecutableInfo result = {};
 
   if (is_first_stage_init()) {
@@ -222,9 +222,9 @@
     result.path = std::string(path, path_len);
   }
 
-  result.phdr = reinterpret_cast<const ElfW(Phdr)*>(args.getauxval(AT_PHDR));
-  result.phdr_count = args.getauxval(AT_PHNUM);
-  result.entry_point = args.getauxval(AT_ENTRY);
+  result.phdr = reinterpret_cast<const ElfW(Phdr)*>(getauxval(AT_PHDR));
+  result.phdr_count = getauxval(AT_PHNUM);
+  result.entry_point = getauxval(AT_ENTRY);
   return result;
 }
 
@@ -344,7 +344,7 @@
   }
 
   const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
-                                                get_executable_info(args);
+                                                get_executable_info();
 
   // Assign to a static variable for the sake of the debug map, which needs
   // a C-style string to last until the program exits.
@@ -375,7 +375,7 @@
   insert_link_map_into_debug_map(&si->link_map_head);
   insert_link_map_into_debug_map(&solinker->link_map_head);
 
-  add_vdso(args);
+  add_vdso();
 
   ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
 
@@ -452,10 +452,6 @@
 
   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();
   si->call_constructors();
 
@@ -559,22 +555,20 @@
  * function, or other GOT reference will generate a segfault.
  */
 extern "C" ElfW(Addr) __linker_init(void* raw_args) {
+  // Initialize TLS early so system calls and errno work.
   KernelArgumentBlock args(raw_args);
-
-#if defined(__i386__)
-  __libc_init_sysinfo(args);
-#endif
+  __libc_init_main_thread_early(args);
 
   // When the linker is run by itself (rather than as an interpreter for
   // another program), AT_BASE is 0.
-  ElfW(Addr) linker_addr = args.getauxval(AT_BASE);
+  ElfW(Addr) linker_addr = getauxval(AT_BASE);
   if (linker_addr == 0) {
     // Detect an attempt to run the linker on itself (e.g.
     // `linker64 /system/bin/linker64`). If the kernel loaded this instance of
     // the linker, then AT_ENTRY will refer to &_start. If it doesn't, then
     // something else must have loaded this instance of the linker. It's
     // simpler if we only allow one copy of the linker to be loaded at a time.
-    if (args.getauxval(AT_ENTRY) != reinterpret_cast<uintptr_t>(&_start)) {
+    if (getauxval(AT_ENTRY) != reinterpret_cast<uintptr_t>(&_start)) {
       // The first linker already relocated this one and set up TLS, so we don't
       // need further libc initialization.
       __linker_error("error: linker cannot load itself\n");
@@ -583,7 +577,7 @@
     // instance, so use the phdr to find the linker's base address.
     ElfW(Addr) load_bias;
     get_elf_base_from_phdr(
-      reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR)), args.getauxval(AT_PHNUM),
+      reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
       &linker_addr, &load_bias);
   }
 
@@ -622,15 +616,15 @@
  */
 static ElfW(Addr) __attribute__((noinline))
 __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so) {
-  // Initialize the main thread (including TLS, so system calls really work).
-  __libc_init_main_thread(args);
+  // Finish initializing the main thread.
+  __libc_init_main_thread_late();
 
   // We didn't protect the linker's RELRO pages in link_image because we
   // couldn't make system calls on x86 at that point, but we can now...
   if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
 
   // Initialize the linker's static libc's globals
-  __libc_init_globals(args);
+  __libc_init_globals();
 
   // Initialize the linker's own global variables
   tmp_linker_so.call_constructors();
@@ -640,7 +634,7 @@
   // as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the
   // linker's _start.
   const char* exe_to_load = nullptr;
-  if (args.getauxval(AT_ENTRY) == reinterpret_cast<uintptr_t>(&_start)) {
+  if (getauxval(AT_ENTRY) == reinterpret_cast<uintptr_t>(&_start)) {
     if (args.argc <= 1 || !strcmp(args.argv[1], "--help")) {
       async_safe_format_fd(STDOUT_FILENO,
          "Usage: %s program [arguments...]\n"
diff --git a/tests/Android.bp b/tests/Android.bp
index 899fc66..cbe4067 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -38,6 +38,12 @@
         // For glibc.
         "-D__STDC_LIMIT_MACROS",
     ],
+    // Make the bionic tests implicitly test bionic's shadow call stack support.
+    arch: {
+        arm64: {
+           cflags: ["-fsanitize=shadow-call-stack"],
+        },
+    },
     stl: "libc++",
     sanitize: {
         never: true,
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 57d04e9..aea92b4 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -148,7 +148,7 @@
 #endif
 }
 
-TEST(dl, xfail_preinit_getauxval) {
+TEST(dl, preinit_getauxval) {
 #if defined(__BIONIC__)
   std::string helper = GetTestlibRoot() +
       "/preinit_getauxval_test_helper/preinit_getauxval_test_helper";