Use shared globals so getauxval works earlier

Make getauxval() work in .preinit_array. It still won't be usable for
ifuncs unless we can guarantee that the __loader_shared_globals relocation
is resolved before the ifunc calls [__bionic_]getauxval.

Define __bionic_getauxval for use in replacing calls to
KernelArgumentBlock::getauxval, which doesn't (and sometimes isn't allowed
to) access TLS variables like errno.

Bug: http://b/25751302
Test: bionic unit tests
Change-Id: I461feeaed7f43cfa2a2b6c34147194f0df82b516
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index cef3d7d..e6e0c56 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -30,7 +30,6 @@
 
 #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"
@@ -71,7 +70,7 @@
 // are hazardous, such as accessing non-hidden global variables.
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 void __libc_init_main_thread_early(KernelArgumentBlock& args) {
-  __libc_auxv = args.auxv;
+  __libc_shared_globals()->auxv = args.auxv;
 #if defined(__i386__)
   __libc_init_sysinfo(args);
 #endif
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..fca628b 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -45,7 +45,6 @@
 
 #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"
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 25d462f..2ec1556 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"
@@ -79,7 +78,6 @@
 // protector.
 __attribute__((noinline))
 static void __libc_preinit_impl(KernelArgumentBlock& args) {
-  __libc_auxv = args.auxv;
 #if defined(__i386__)
   __libc_init_sysinfo(args);
 #endif
diff --git a/libc/private/bionic_auxv.h b/libc/private/bionic_auxv.h
index 494fe9c..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
-
-__LIBC_HIDDEN__ 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..9c74d92 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;
 
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";