diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/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. diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/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__); } } } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/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 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) { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/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; diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/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; diff --git a/lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp b/lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/Inputs/main.cpp @@ -0,0 +1,3 @@ +#include "signal_file.h" + +int main() { return get_signal_crash(); } diff --git a/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h b/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.h @@ -0,0 +1 @@ +int get_signal_crash(void); diff --git a/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp b/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/Inputs/signal_file.cpp @@ -0,0 +1,7 @@ +#include "signal_file.h" +#include + +int get_signal_crash(void) { + raise(SIGSEGV); + return 0; +} diff --git a/lldb/test/Shell/ObjectFile/ELF/ld_test.test b/lldb/test/Shell/ObjectFile/ELF/ld_test.test new file mode 100644 --- /dev/null +++ b/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() +#