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