rdhindsa created this revision.
rdhindsa added reviewers: labath, clayborg.
Herald added a subscriber: emaste.
rdhindsa requested review of this revision.
Herald added a subscriber: MaskRay.
Herald added a project: LLDB.

Add support for shared library load when executable called through ld.

Currently, when an executable is called like: ld-linux --library-path <path> 
executable, lldb is not able to load the shared libraries needed by the 
executable provided by library-path. lldb is not able to set Rendezvous 
breakpoint in this case.

This patch adds the support to enable setting rendezvous breakpoint when called 
using ld-*.so. It enables it to hit the breakpoint and extract the address of 
the rendezvous structure, which is how lldb is now able to load the shared 
libraries.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D108061

Files:
  lldb/include/lldb/Symbol/ObjectFile.h
  lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
  lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
  lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp
  lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp
  lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h
  lldb/test/Shell/ObjectFile/ELF/ld_test.test

Index: lldb/test/Shell/ObjectFile/ELF/ld_test.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/ld_test.test
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# REQUIRES: system-linux
+#
+# RUN: %clang -target x86_64-pc-linux -o %t1.o -c %S/Inputs/signal_file.cpp
+# RUN: %clang -target x86_64-pc-linux -o %t2.o -c %S/Inputs/main.cpp
+# RUN: %clang -target x86_64-pc-linux -shared %t1.o -o %t3.so
+# RUN: %clang -o %tmain %t2.o %t3.so -L. -Wl,-rpath,%t
+#
+# RUN: echo '-n' > %t.in
+# RUN: echo 'run' >> %t.in
+# RUN: echo 'bt' >> %t.in
+#
+# RUN: %lldb -b -s %t.in -- %tmain 2>&1 | FileCheck %s
+#
+# RUN: %lldb -b -s %t.in -- /lib64/ld-linux-x86-64.so.2 --library-path %t  %tmain 2>&1 | FileCheck %s 
+#
+# bt
+# CHECK: (lldb) bt
+# CHECK: ld_test.test.tmp3.so`get_signal_crash()
+#
Index: lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h
@@ -0,0 +1 @@
+int get_signal_crash(void);
Index: lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp
@@ -0,0 +1,7 @@
+#include "signal_file.h"
+#include <signal.h>
+
+int get_signal_crash(void) {
+  raise(SIGSEGV);
+  return 0;
+}
Index: lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp
@@ -0,0 +1,3 @@
+#include "signal_file.h"
+
+int main() { return get_signal_crash(); }
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -131,6 +131,9 @@
   lldb_private::Address
   GetImageInfoAddress(lldb_private::Target *target) override;
 
+  lldb_private::Address
+  GetRendezvousStructureAddress(lldb_private::Target *target) override;
+
   lldb_private::Address GetEntryPointAddress() override;
 
   lldb_private::Address GetBaseAddress() override;
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -882,6 +882,21 @@
   return Address();
 }
 
+Address ObjectFileELF::GetRendezvousStructureAddress(Target *target) {
+  ModuleSP module_sp(GetModule());
+  if (module_sp) {
+    SymbolContextList contexts;
+    SymbolContext context;
+    module_sp->FindSymbolsWithNameAndType(ConstString("_r_debug"),
+                                          eSymbolTypeAny, contexts);
+    if (contexts.GetSize()) {
+      if (contexts.GetContextAtIndex(0, context))
+        return context.symbol->GetAddress();
+    }
+  }
+  return Address();
+}
+
 lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
   if (m_entry_point_address.IsValid())
     return m_entry_point_address;
Index: lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -333,28 +333,48 @@
     LLDB_LOG(log, "Rendezvous structure is not set up yet. "
                   "Trying to locate rendezvous breakpoint in the interpreter "
                   "by symbol name.");
-    ModuleSP interpreter = LoadInterpreterModule();
-    if (!interpreter) {
-      LLDB_LOG(log, "Can't find interpreter, rendezvous breakpoint isn't set.");
-      return false;
-    }
-
-    // Function names from different dynamic loaders that are known to be used
-    // as rendezvous between the loader and debuggers.
+    // Function names from different dynamic loaders that are known to be
+    // used as rendezvous between the loader and debuggers.
     static std::vector<std::string> DebugStateCandidates{
         "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
         "r_debug_state",   "_r_debug_state",     "_rtld_debug_state",
     };
 
-    FileSpecList containingModules;
-    containingModules.Append(interpreter->GetFileSpec());
-    dyld_break = target.CreateBreakpoint(
-        &containingModules, nullptr /* containingSourceFiles */,
-        DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
-        0,           /* offset */
-        eLazyBoolNo, /* skip_prologue */
-        true,        /* internal */
-        false /* request_hardware */);
+    ModuleSP interpreter = LoadInterpreterModule();
+    if (!interpreter) {
+      if (NameMatches(m_process->GetTarget()
+                          .GetExecutableModulePointer()
+                          ->GetFileSpec()
+                          .GetFilename()
+                          .GetCString(),
+                      NameMatch::StartsWith, "ld-")) {
+        FileSpecList containingModules;
+        containingModules.Append(
+            m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec());
+
+        dyld_break = target.CreateBreakpoint(
+            &containingModules, nullptr /* containingSourceFiles */,
+            DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+            0,           /* offset */
+            eLazyBoolNo, /* skip_prologue */
+            true,        /* internal */
+            false /* request_hardware */);
+      } else {
+        LLDB_LOG(log,
+                 "Can't find interpreter, rendezvous breakpoint isn't set.");
+        return false;
+      }
+    } else {
+      FileSpecList containingModules;
+      containingModules.Append(interpreter->GetFileSpec());
+      dyld_break = target.CreateBreakpoint(
+          &containingModules, nullptr /* containingSourceFiles */,
+          DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+          0,           /* offset */
+          eLazyBoolNo, /* skip_prologue */
+          true,        /* internal */
+          false /* request_hardware */);
+    }
   }
 
   if (dyld_break->GetNumResolvedLocations() != 1) {
Index: lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -56,10 +56,15 @@
                   "%s resolved via direct object file approach to 0x%" PRIx64,
                   __FUNCTION__, info_location);
       } else {
-        LLDB_LOGF(log,
-                  "%s FAILED - direct object file approach did not yield a "
-                  "valid address",
-                  __FUNCTION__);
+        Address rendezvous_addr =
+            obj_file->GetRendezvousStructureAddress(target);
+        if (rendezvous_addr.IsValid())
+          return rendezvous_addr.GetLoadAddress(target);
+        else
+          LLDB_LOGF(log,
+                    "%s FAILED - direct object file approach did not yield a "
+                    "valid address",
+                    __FUNCTION__);
       }
     }
   }
Index: lldb/include/lldb/Symbol/ObjectFile.h
===================================================================
--- lldb/include/lldb/Symbol/ObjectFile.h
+++ lldb/include/lldb/Symbol/ObjectFile.h
@@ -462,6 +462,21 @@
     return Address();
   }
 
+  /// Extracts the rendezvous structure address from r_debug.
+  ///
+  /// Especially in the case of running a program through the interpreter, the
+  /// GetImageInfoAddress is not able to extract the address. However, the
+  /// rendezvous address in that case can be extracted from the load address of
+  /// _r_debug symbol. This method returns the address of such a structure if
+  /// the information can be resolved via entries in the object file.
+  ///
+  /// \return
+  ///     The address of redezvous structure, or an invalid address if this
+  ///     object file format does not support or contain such information.
+  virtual lldb_private::Address GetRendezvousStructureAddress(Target *target) {
+    return Address();
+  }
+
   /// Returns the address of the Entry Point in this object file - if the
   /// object file doesn't have an entry point (because it is not an executable
   /// file) then an invalid address is returned.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to