From c338516463ff9bb7183c8322847f2eddf6febec9 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Wed, 28 Sep 2022 16:50:38 -0700 Subject: [PATCH] Improve dynamic loader support in DynamicLoaderPOSIXDYLD when using core files. Prior to this fix, no shared libraries would be loaded for a core file, even if they exist on the current machine. The issue was the DYLDRendezvous would read a DYLDRendezvous::Rendezvous from memory of the process in DYLDRendezvous::Resolve() which would read some ld.so structures as they existed in the middle of a process' lifetime. In core files we see, the DYLDRendezvous::Rendezvous::state would be set to eAdd for running processes. When ProcessELFCore.cpp would load the core file, it would call DynamicLoaderPOSIXDYLD::DidAttach(), which would call the above Rendezvous functions. The issue came when during the DidAttach function it call DYLDRendezvous::GetAction() which would return eNoAction if the DYLDRendezvous::m_current.state was read from memory as eAdd. This caused no shared libraries to be loaded for any ELF core files. We now detect if we have a core file and after reading the DYLDRendezvous::m_current.state from memory we set it to eConsistent, which causes DYLDRendezvous::GetAction() to return the correct action of eTakeSnapshot and shared libraries get loaded. We also improve the DynamicLoaderPOSIXDYLD class to not try and set any breakpoints to catch shared library loads/unloads when we have a core file, which saves a bit of time. Differential Revision: https://reviews.llvm.org/D134842 --- .../Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp | 12 ++++++++++++ .../Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h | 2 ++ .../DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 13 +++++++++++++ .../DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 3 +++ 4 files changed, 30 insertions(+) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 9e7baae8..f20167b 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -190,6 +190,14 @@ bool DYLDRendezvous::IsValid() { } DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { + // If we have a core file, we will read the current rendezvous state + // from the core file's memory into m_current which can be in an inconsistent + // state, so we can't rely on its state to determine what we should do. We + // always need it to load all of the shared libraries one time when we attach + // to a core file. + if (IsCoreFile()) + return eTakeSnapshot; + switch (m_current.state) { case eConsistent: @@ -664,3 +672,7 @@ void DYLDRendezvous::DumpToLog(Log *log) const { LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } + +bool DYLDRendezvous::IsCoreFile() const { + return !m_process->IsLiveDebugSession(); +} diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 04d3e66..fc1dd69 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -267,6 +267,8 @@ protected: bool FindMetadata(const char *name, PThreadField field, uint32_t &value); + bool IsCoreFile() const; + enum RendezvousAction { eNoAction, eTakeSnapshot, diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index ee03775..27d2044 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -213,6 +213,10 @@ void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { void DynamicLoaderPOSIXDYLD::ProbeEntry() { Log *log = GetLog(LLDBLog::DynamicLoader); + // If we have a core file, we don't need any breakpoints. + if (IsCoreFile()) + return; + const addr_t entry = GetEntryPoint(); if (entry == LLDB_INVALID_ADDRESS) { LLDB_LOGF( @@ -297,6 +301,11 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { Log *log = GetLog(LLDBLog::DynamicLoader); + + // If we have a core file, we don't need any breakpoints. + if (IsCoreFile()) + return false; + if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { LLDB_LOG(log, "Rendezvous breakpoint breakpoint id {0} for pid {1}" @@ -829,3 +838,7 @@ bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo( return module_sp->GetFileSpec().GetPath() == "[vdso]"; } + +bool DynamicLoaderPOSIXDYLD::IsCoreFile() const { + return !m_process->IsLiveDebugSession(); +} diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 8d3e4cd..4c92335 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -91,6 +91,9 @@ protected: std::map> m_loaded_modules; + /// Returns true if the process is for a core file. + bool IsCoreFile() const; + /// If possible sets a breakpoint on a function called by the runtime /// linker each time a module is loaded or unloaded. bool SetRendezvousBreakpoint(); -- 2.7.4