Merge changes I376d7695,Ied443375,I614d25e7

* changes:
  Use shared globals to init __progname + environ
  Move the abort message to libc_shared_globals
  Expose libc_shared_globals to libc.so with symbol
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp
index 58f24cf..56e6771 100644
--- a/libc/bionic/android_set_abort_message.cpp
+++ b/libc/bionic/android_set_abort_message.cpp
@@ -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 @@
               "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 @@
 
 __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 @@
   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;
 }
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 9a9fee2..6440ae0 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -132,17 +132,13 @@
       nullptr);
 }
 
-static FdTable* GetFdTable() {
-  if (!__libc_shared_globals) {
-    return nullptr;
-  }
-
-  return &__libc_shared_globals->fd_table;
+static FdTable& GetFdTable() {
+  return __libc_shared_globals()->fd_table;
 }
 
 // Exposed to the platform to allow crash_dump to print out the fd table.
 extern "C" void* android_fdsan_get_fd_table() {
-  return GetFdTable();
+  return &GetFdTable();
 }
 
 static FdEntry* GetFdEntry(int fd) {
@@ -150,21 +146,13 @@
     return nullptr;
   }
 
-  auto* fd_table = GetFdTable();
-  if (!fd_table) {
-    return nullptr;
-  }
-
-  return fd_table->at(fd);
+  return GetFdTable().at(fd);
 }
 
 __printflike(1, 0) static void fdsan_error(const char* fmt, ...) {
-  auto* fd_table = GetFdTable();
-  if (!fd_table) {
-    return;
-  }
+  auto& fd_table = GetFdTable();
 
-  auto error_level = atomic_load(&fd_table->error_level);
+  auto error_level = atomic_load(&fd_table.error_level);
   if (error_level == ANDROID_FDSAN_ERROR_LEVEL_DISABLED) {
     return;
   }
@@ -198,7 +186,7 @@
 
   switch (error_level) {
     case ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE:
-      atomic_compare_exchange_strong(&fd_table->error_level, &error_level,
+      atomic_compare_exchange_strong(&fd_table.error_level, &error_level,
                                      ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
       __BIONIC_FALLTHROUGH;
     case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS:
@@ -360,21 +348,11 @@
 }
 
 android_fdsan_error_level android_fdsan_get_error_level() {
-  auto* fd_table = GetFdTable();
-  if (!fd_table) {
-    async_safe_fatal("attempted to get fdsan error level before libc initialization?");
-  }
-
-  return fd_table->error_level;
+  return GetFdTable().error_level;
 }
 
 android_fdsan_error_level android_fdsan_set_error_level(android_fdsan_error_level new_level) {
-  auto* fd_table = GetFdTable();
-  if (!fd_table) {
-    async_safe_fatal("attempted to get fdsan error level before libc initialization?");
-  }
-
-  return atomic_exchange(&fd_table->error_level, new_level);
+  return atomic_exchange(&GetFdTable().error_level, new_level);
 }
 
 int close(int fd) {
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index a860b98..4702e1c 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -52,11 +52,9 @@
 #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;
-__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals;
 
 // Not public, but well-known in the BSDs.
 const char* __progname;
@@ -72,9 +70,6 @@
   });
 }
 
-void __libc_init_shared_globals(libc_shared_globals*) {
-}
-
 #if !defined(__LP64__)
 static void __check_max_thread_id() {
   if (gettid() > 65535) {
@@ -96,12 +91,11 @@
   __pthread_internal_add(main_thread);
 }
 
-void __libc_init_common(KernelArgumentBlock& args) {
+void __libc_init_common() {
   // Initialize various globals.
-  environ = args.envp;
+  environ = __libc_shared_globals()->init_environ;
   errno = 0;
-  __progname = args.argv[0] ? args.argv[0] : "<unknown>";
-  __abort_message_ptr = args.abort_message_ptr;
+  __progname = __libc_shared_globals()->init_progname ?: "<unknown>";
 
 #if !defined(__LP64__)
   __check_max_thread_id();
@@ -300,9 +294,7 @@
 #endif
 }
 
-void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
-  __abort_message_ptr = args.abort_message_ptr;
-
+void __libc_init_AT_SECURE(char** env) {
   // Check that the kernel provided a value for AT_SECURE.
   errno = 0;
   unsigned long is_AT_SECURE = getauxval(AT_SECURE);
@@ -313,11 +305,11 @@
     // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
     __nullify_closed_stdio();
 
-    __sanitize_environment_variables(args.envp);
+    __sanitize_environment_variables(env);
   }
 
   // Now the environment has been sanitized, make it available.
-  environ = args.envp;
+  environ = __libc_shared_globals()->init_environ = env;
 
   __initialize_personality();
 }
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 6ce4d10..84b59ca 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -54,8 +54,8 @@
 
 __LIBC_HIDDEN__ void __libc_init_globals(KernelArgumentBlock& args);
 
-__LIBC_HIDDEN__ void __libc_init_common(KernelArgumentBlock& args);
+__LIBC_HIDDEN__ void __libc_init_common();
 
-__LIBC_HIDDEN__ void __libc_init_AT_SECURE(KernelArgumentBlock& args);
+__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
 
 #endif
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 08d3df4..25d462f 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -84,9 +84,8 @@
   __libc_init_sysinfo(args);
 #endif
 
-  __libc_shared_globals = args.shared_globals;
   __libc_init_globals(args);
-  __libc_init_common(args);
+  __libc_init_common();
 
   // Hooks for various libraries to let them know that we're starting up.
   __libc_globals.mutate(__libc_init_malloc);
@@ -138,7 +137,13 @@
     __cxa_atexit(__libc_fini,structors->fini_array,nullptr);
   }
 
-  exit(slingshot(args.argc - __libc_shared_globals->initial_linker_arg_count,
-                 args.argv + __libc_shared_globals->initial_linker_arg_count,
+  exit(slingshot(args.argc - __libc_shared_globals()->initial_linker_arg_count,
+                 args.argv + __libc_shared_globals()->initial_linker_arg_count,
                  args.envp));
 }
+
+extern "C" libc_shared_globals* __loader_shared_globals();
+
+__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() {
+  return __loader_shared_globals();
+}
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index ef1c393..51fbe07 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -96,18 +96,15 @@
   BIONIC_STOP_UNWIND;
 
   KernelArgumentBlock args(raw_args);
+  __libc_shared_globals()->init_progname = args.argv[0];
 
   // Initializing the globals requires TLS to be available for errno.
   __libc_init_main_thread(args);
 
-  static libc_shared_globals shared_globals;
-  __libc_shared_globals = &shared_globals;
-  __libc_init_shared_globals(&shared_globals);
-
   __libc_init_globals(args);
 
-  __libc_init_AT_SECURE(args);
-  __libc_init_common(args);
+  __libc_init_AT_SECURE(args.envp);
+  __libc_init_common();
 
   apply_gnu_relro();
 
@@ -155,3 +152,10 @@
 extern "C" void android_set_application_target_sdk_version(int target) {
   g_target_sdk_version = target;
 }
+
+__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() {
+  static libc_shared_globals globals = {
+    .abort_msg_lock = PTHREAD_MUTEX_INITIALIZER,
+  };
+  return &globals;
+}
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index 886dd32..c8ce841 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -23,9 +23,6 @@
 
 #include "private/bionic_macros.h"
 
-struct abort_msg_t;
-struct libc_shared_globals;
-
 // 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
@@ -65,10 +62,6 @@
   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;
-  libc_shared_globals* shared_globals;
-
  private:
   BIONIC_DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
 };
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 8c00551..906d569 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 <pthread.h>
 
 #include "private/bionic_fdsan.h"
 #include "private/bionic_malloc_dispatch.h"
@@ -44,6 +45,8 @@
 
 __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,10 +55,16 @@
   // 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;
+
+  // Values passed from the linker to libc.so.
+  const char* init_progname;
+  char** init_environ;
 };
 
-__LIBC_HIDDEN__ extern libc_shared_globals* __libc_shared_globals;
-__LIBC_HIDDEN__ void __libc_init_shared_globals(libc_shared_globals*);
+__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
 __LIBC_HIDDEN__ void __libc_init_fdsan();
 
 class KernelArgumentBlock;
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 45ae6ed..5ae7b9b 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -38,6 +38,7 @@
 #include <android/api-level.h>
 
 #include <bionic/pthread_internal.h>
+#include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
@@ -86,6 +87,7 @@
                       const void* caller_addr) __LINKER_PUBLIC__;
 void __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
 void __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
+libc_shared_globals* __loader_shared_globals() __LINKER_PUBLIC__;
 #if defined(__arm__)
 _Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__;
 #endif
@@ -299,6 +301,10 @@
   decrement_dso_handle_reference_counter(dso_handle);
 }
 
+libc_shared_globals* __loader_shared_globals() {
+  return __libc_shared_globals();
+}
+
 static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
 static soinfo* __libdl_info = nullptr;
 
diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp
index 0528cd8..152c2e2 100644
--- a/linker/ld_android.cpp
+++ b/linker/ld_android.cpp
@@ -53,6 +53,7 @@
 __strong_alias(__loader_dlvsym, __internal_linker_error);
 __strong_alias(__loader_add_thread_local_dtor, __internal_linker_error);
 __strong_alias(__loader_remove_thread_local_dtor, __internal_linker_error);
+__strong_alias(__loader_shared_globals, __internal_linker_error);
 #if defined(__arm__)
 __strong_alias(__loader_dl_unwind_find_exidx, __internal_linker_error);
 #endif
diff --git a/linker/linker.arm.map b/linker/linker.arm.map
index a58e7c8..be438ca 100644
--- a/linker/linker.arm.map
+++ b/linker/linker.arm.map
@@ -22,6 +22,7 @@
     __loader_dl_unwind_find_exidx;
     __loader_add_thread_local_dtor;
     __loader_remove_thread_local_dtor;
+    __loader_shared_globals;
     rtld_db_dlactivity;
   local:
     *;
diff --git a/linker/linker.generic.map b/linker/linker.generic.map
index 45bb0b5..f3c01c0 100644
--- a/linker/linker.generic.map
+++ b/linker/linker.generic.map
@@ -21,6 +21,7 @@
     __loader_android_get_exported_namespace;
     __loader_add_thread_local_dtor;
     __loader_remove_thread_local_dtor;
+    __loader_shared_globals;
     rtld_db_dlactivity;
   local:
     *;
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 82b10b7..aa12b6e 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -116,7 +116,6 @@
 }
 
 int g_ld_debug_verbosity;
-abort_msg_t* g_abort_message = nullptr; // For debuggerd.
 
 static std::vector<std::string> g_ld_preload_names;
 
@@ -299,7 +298,7 @@
 #endif
 
   // Sanitize the environment.
-  __libc_init_AT_SECURE(args);
+  __libc_init_AT_SECURE(args.envp);
 
   // Initialize system properties
   __system_properties_init(); // may use 'environ'
@@ -308,7 +307,7 @@
 #ifdef __ANDROID__
   debuggerd_callbacks_t callbacks = {
     .get_abort_message = []() {
-      return g_abort_message;
+      return __libc_shared_globals()->abort_msg;
     },
     .post_dump = &notify_gdb_of_libraries,
   };
@@ -630,12 +629,6 @@
   // 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/libc.so shared global inside the linker.
-  static libc_shared_globals shared_globals;
-  __libc_shared_globals = &shared_globals;
-  __libc_init_shared_globals(&shared_globals);
-  args.shared_globals = __libc_shared_globals;
-
   // Initialize the linker's static libc's globals
   __libc_init_globals(args);
 
@@ -663,13 +656,14 @@
       exit(0);
     }
     exe_to_load = args.argv[1];
-    __libc_shared_globals->initial_linker_arg_count = 1;
+    __libc_shared_globals()->initial_linker_arg_count = 1;
   }
 
   // store argc/argv/envp to use them for calling constructors
-  g_argc = args.argc - __libc_shared_globals->initial_linker_arg_count;
-  g_argv = args.argv + __libc_shared_globals->initial_linker_arg_count;
+  g_argc = args.argc - __libc_shared_globals()->initial_linker_arg_count;
+  g_argv = args.argv + __libc_shared_globals()->initial_linker_arg_count;
   g_envp = args.envp;
+  __libc_shared_globals()->init_progname = g_argv[0];
 
   // Initialize static variables. Note that in order to
   // get correct libdl_info we need to call constructors
@@ -678,7 +672,6 @@
   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));
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 18ba011..57d04e9 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -104,6 +104,7 @@
   std::string expected_output =
       "ctor: argc=1 argv[0]=" + helper + "\n" +
       "main: argc=1 argv[0]=" + helper + "\n" +
+      "__progname=" + helper + "\n" +
       "helper_func called\n";
   ExecTestHelper eth;
   eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr });
@@ -118,6 +119,7 @@
   std::string expected_output =
       "ctor: argc=1 argv[0]=" + helper + "\n" +
       "main: argc=1 argv[0]=" + helper + "\n" +
+      "__progname=" + helper + "\n" +
       "helper_func called\n";
   ExecTestHelper eth;
   eth.SetArgs({ kPathToLinker, helper.c_str(), nullptr });
diff --git a/tests/libs/exec_linker_helper.cpp b/tests/libs/exec_linker_helper.cpp
index 01a61e0..56b1eaf 100644
--- a/tests/libs/exec_linker_helper.cpp
+++ b/tests/libs/exec_linker_helper.cpp
@@ -28,7 +28,8 @@
 
 #include <stdio.h>
 
-extern "C" void _start();
+extern "C" const char* __progname;
+
 const char* helper_func();
 
 __attribute__((constructor))
@@ -38,6 +39,7 @@
 
 int main(int argc, char* argv[]) {
   printf("main: argc=%d argv[0]=%s\n", argc, argv[0]);
+  printf("__progname=%s\n", __progname);
   printf("%s\n", helper_func());
   return 0;
 }