Expose libc_shared_globals to libc.so with symbol
Previously, the address of the global variable was communicated from the
dynamic linker to libc.so using a field of KernelArgumentBlock, which is
communicated using the TLS_SLOT_BIONIC_PREINIT slot.
As long as this function isn't called during relocations (i.e. while
executing an ifunc), it always return a non-NULL value. If it's called
before its PLT entry is relocated, I expect a crash.
I removed the __libc_init_shared_globals function. It's currently empty,
and I don't think there's one point in libc's initialization where
shared globals should be initialized.
Bug: http://b/25751302
Test: bionic unit tests
Change-Id: I614d25e7ef5e0d2ccc40d5c821dee10f1ec61c2e
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..bd20775 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -56,7 +56,6 @@
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 +71,6 @@
});
}
-void __libc_init_shared_globals(libc_shared_globals*) {
-}
-
#if !defined(__LP64__)
static void __check_max_thread_id() {
if (gettid() > 65535) {
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 08d3df4..24f40ba 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -84,7 +84,6 @@
__libc_init_sysinfo(args);
#endif
- __libc_shared_globals = args.shared_globals;
__libc_init_globals(args);
__libc_init_common(args);
@@ -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..10fc151 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -100,10 +100,6 @@
// 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);
@@ -155,3 +151,8 @@
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;
+ return &globals;
+}
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index 886dd32..1e053a1 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -24,7 +24,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,
@@ -67,7 +66,6 @@
// 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..44ec2e3 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -54,8 +54,7 @@
int initial_linker_arg_count;
};
-__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 66766fe..963e82c 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -622,12 +622,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);
@@ -655,12 +649,12 @@
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;
// Initialize static variables. Note that in order to