Skip to content

Commit

Permalink
Improve dynamic loader support in DynamicLoaderPOSIXDYLD when using c…
Browse files Browse the repository at this point in the history
…ore 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
  • Loading branch information
clayborg committed Oct 14, 2022
1 parent aaecabe commit c338516
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
Expand Up @@ -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:
Expand Down Expand Up @@ -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();
}
2 changes: 2 additions & 0 deletions lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
Expand Up @@ -267,6 +267,8 @@ class DYLDRendezvous {

bool FindMetadata(const char *name, PThreadField field, uint32_t &value);

bool IsCoreFile() const;

enum RendezvousAction {
eNoAction,
eTakeSnapshot,
Expand Down
Expand Up @@ -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(
Expand Down Expand Up @@ -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}"
Expand Down Expand Up @@ -829,3 +838,7 @@ bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(

return module_sp->GetFileSpec().GetPath() == "[vdso]";
}

bool DynamicLoaderPOSIXDYLD::IsCoreFile() const {
return !m_process->IsLiveDebugSession();
}
Expand Up @@ -91,6 +91,9 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader {
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>>
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();
Expand Down

0 comments on commit c338516

Please sign in to comment.