ldd: skip relocation processing, TLS modules, CFI
This avoids a diagnostic on arm32/arm64 when running ldd on a shared
library with a PT_TLS segment:
executable's TLS segment is underaligned: alignment is 8, needs to be at least 64 for ARM64 Bionic
Bug: http://b/328822319
Test: ldd /system/lib64/libc.so
Change-Id: Idb061b980333ba3b5b3f44b52becf041d76ea0b7
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index d6592af..cf26f39 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -493,6 +493,12 @@
}
si->increment_ref_count();
}
+
+ // Exit early for ldd. We don't want to run the code that was loaded, so skip
+ // the constructor calls. Skip CFI setup because it would call __cfi_init in
+ // libdl.so.
+ if (g_is_ldd) _exit(EXIT_SUCCESS);
+
#if defined(__aarch64__)
// This has to happen after the find_libraries, which will have collected any possible
// libraries that request memtag_stack in the dynamic section.
@@ -826,8 +832,6 @@
ElfW(Addr) start_address = linker_main(args, exe_to_load);
- if (g_is_ldd) _exit(EXIT_SUCCESS);
-
INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
// Return the address that the calling assembly stub should jump to.
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 15d87ba..65b20f5 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -587,6 +587,11 @@
}
bool soinfo::relocate(const SymbolLookupList& lookup_list) {
+ // For ldd, don't apply relocations because TLS segments are not registered.
+ // We don't care whether ldd diagnoses unresolved symbols.
+ if (g_is_ldd) {
+ return true;
+ }
VersionTracker version_tracker;
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 3e7506c..802c06a 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -503,15 +503,13 @@
}
void soinfo::call_pre_init_constructors() {
- if (g_is_ldd) return;
-
// DT_PREINIT_ARRAY functions are called before any other constructors for executables,
// but ignored in a shared library.
call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false, get_realpath());
}
void soinfo::call_constructors() {
- if (constructors_called || g_is_ldd) {
+ if (constructors_called) {
return;
}
diff --git a/linker/linker_tls.cpp b/linker/linker_tls.cpp
index 97892f4..e90b8cb 100644
--- a/linker/linker_tls.cpp
+++ b/linker/linker_tls.cpp
@@ -31,14 +31,15 @@
#include <vector>
#include "async_safe/CHECK.h"
+#include "linker_globals.h"
+#include "linker_main.h"
+#include "linker_soinfo.h"
#include "private/ScopedRWLock.h"
#include "private/ScopedSignalBlocker.h"
#include "private/bionic_defs.h"
#include "private/bionic_elf_tls.h"
#include "private/bionic_globals.h"
#include "private/linker_native_bridge.h"
-#include "linker_main.h"
-#include "linker_soinfo.h"
static bool g_static_tls_finished;
static std::vector<TlsModule> g_tls_modules;
@@ -109,7 +110,11 @@
void linker_setup_exe_static_tls(const char* progname) {
soinfo* somain = solist_get_somain();
StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
- if (somain->get_tls() == nullptr) {
+
+ // For ldd, don't add the executable's TLS segment to the static TLS layout.
+ // It is likely to trigger the underaligned TLS segment error on arm32/arm64
+ // when the ldd argument is actually a shared object.
+ if (somain->get_tls() == nullptr || g_is_ldd) {
layout.reserve_exe_segment_and_tcb(nullptr, progname);
} else {
register_tls_module(somain, layout.reserve_exe_segment_and_tcb(&somain->get_tls()->segment, progname));
@@ -133,6 +138,11 @@
}
void register_soinfo_tls(soinfo* si) {
+ // ldd skips registration of the executable's TLS segment above to avoid the
+ // arm32/arm64 underalignment error. For consistency, also skip registration
+ // of TLS segments here, for shared objects.
+ if (g_is_ldd) return;
+
soinfo_tls* si_tls = si->get_tls();
if (si_tls == nullptr || si_tls->module_id != kTlsUninitializedModuleId) {
return;