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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits