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;