Disable stack protector for __libc_preinit

__libc_preinit sets up the stack protector global cookie value, and thus
cannot intialize a stack protector cookie for itself in the function
prologue. LTO compilation can inline functions requiring a stack
protector into __libc_preinit. This patch disables stack protection for
__libc_preinit and forces all potentially inlined functions into a
helper that can have a stack protector.

Test: run bionic-unit-tests

Change-Id: I45911611190f216c91eb6feff722967214c5f99f
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 43bca30..7c73950 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -61,6 +61,21 @@
   extern int __cxa_atexit(void (*)(void *), void *, void *);
 };
 
+// We need a helper function for __libc_preinit because compiling with LTO may
+// inline functions requiring a stack protector check, but __stack_chk_guard is
+// not initialized at the start of __libc_preinit. __libc_preinit_impl will run
+// after __stack_chk_guard is initialized and therefore can safely have a stack
+// protector.
+__attribute__((noinline))
+static void __libc_preinit_impl(KernelArgumentBlock& args) {
+  __libc_init_globals(args);
+  __libc_init_common(args);
+
+  // Hooks for various libraries to let them know that we're starting up.
+  __libc_globals.mutate(__libc_init_malloc);
+  netdClientInit();
+}
+
 // We flag the __libc_preinit function as a constructor to ensure
 // that its address is listed in libc.so's .init_array section.
 // This ensures that the function is called by the dynamic linker
@@ -79,12 +94,7 @@
   // 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]);
 
-  __libc_init_globals(*args);
-  __libc_init_common(*args);
-
-  // Hooks for various libraries to let them know that we're starting up.
-  __libc_globals.mutate(__libc_init_malloc);
-  netdClientInit();
+  __libc_preinit_impl(*args);
 }
 
 // This function is called from the executable's _start entry point