Merge changes Idb061b98,I93c17ca6 into main
* changes:
ldd: skip relocation processing, TLS modules, CFI
Guard against linker[64] having a PT_TLS segment
diff --git a/linker/linker.cpp b/linker/linker.cpp
index e54a524..81869b3 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2866,11 +2866,12 @@
TlsSegment tls_segment;
if (__bionic_get_tls_segment(phdr, phnum, load_bias, &tls_segment)) {
+ // The loader does not (currently) support ELF TLS, so it shouldn't have
+ // a TLS segment.
+ CHECK(!relocating_linker && "TLS not supported in loader");
if (!__bionic_check_tls_alignment(&tls_segment.alignment)) {
- if (!relocating_linker) {
- DL_ERR("TLS segment alignment in \"%s\" is not a power of 2: %zu",
- get_realpath(), tls_segment.alignment);
- }
+ DL_ERR("TLS segment alignment in \"%s\" is not a power of 2: %zu", get_realpath(),
+ tls_segment.alignment);
return false;
}
tls_ = std::make_unique<soinfo_tls>();
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 1860ccc..c9dcfa3 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -496,6 +496,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.
@@ -829,8 +835,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 5b58895..080570d 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -421,6 +421,7 @@
} else {
CHECK(found_in->get_tls() != nullptr); // We rejected a missing TLS segment above.
module_id = found_in->get_tls()->module_id;
+ CHECK(module_id != kTlsUninitializedModuleId);
}
trace_reloc("RELO TLS_DTPMOD %16p <- %zu %s",
rel_target, module_id, sym_name);
@@ -588,6 +589,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;