diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 88eeddf178788..8f5f1242116f5 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -99,7 +99,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) - : PostMortemProcess(target_sp, listener_sp, core_file) {} + : PostMortemProcess(target_sp, listener_sp, core_file), m_uuids() {} // Destructor ProcessElfCore::~ProcessElfCore() { @@ -257,12 +257,12 @@ Status ProcessElfCore::DoLoadCore() { // the main executable using data we found in the core file notes. lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); if (!exe_module_sp) { - // The first entry in the NT_FILE might be our executable if (!m_nt_file_entries.empty()) { + llvm::StringRef executable_path = GetMainExecutablePath(); ModuleSpec exe_module_spec; exe_module_spec.GetArchitecture() = arch; - exe_module_spec.GetUUID() = m_nt_file_entries[0].uuid; - exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path, + exe_module_spec.GetUUID() = FindModuleUUID(executable_path); + exe_module_spec.GetFileSpec().SetFile(executable_path, FileSpec::Style::native); if (exe_module_spec.GetFileSpec()) { exe_module_sp = @@ -277,21 +277,38 @@ Status ProcessElfCore::DoLoadCore() { void ProcessElfCore::UpdateBuildIdForNTFileEntries() { Log *log = GetLog(LLDBLog::Process); + m_uuids.clear(); for (NT_FILE_Entry &entry : m_nt_file_entries) { - entry.uuid = FindBuidIdInCoreMemory(entry.start); - if (log && entry.uuid.IsValid()) - LLDB_LOGF(log, "%s found UUID @ %16.16" PRIx64 ": %s \"%s\"", - __FUNCTION__, entry.start, entry.uuid.GetAsString().c_str(), - entry.path.c_str()); + UUID uuid = FindBuidIdInCoreMemory(entry.start); + if (uuid.IsValid()) { + // Assert that either the path is not in the map or the UUID matches + assert(m_uuids.count(entry.path) == 0 || m_uuids[entry.path] == uuid); + m_uuids[entry.path] = uuid; + if (log) + LLDB_LOGF(log, "%s found UUID @ %16.16" PRIx64 ": %s \"%s\"", + __FUNCTION__, entry.start, uuid.GetAsString().c_str(), + entry.path.c_str()); + } } } +llvm::StringRef ProcessElfCore::GetMainExecutablePath() { + if (m_nt_file_entries.empty()) + return ""; + + // The first entry in the NT_FILE might be our executable + llvm::StringRef executable_path = m_nt_file_entries[0].path; + // Prefer the NT_FILE entry matching m_executable_name as main executable. + for (const NT_FILE_Entry &file_entry : m_nt_file_entries) + if (llvm::StringRef(file_entry.path).ends_with("/" + m_executable_name)) { + executable_path = file_entry.path; + break; + } + return executable_path; +} + UUID ProcessElfCore::FindModuleUUID(const llvm::StringRef path) { - // Returns the gnu uuid from matched NT_FILE entry - for (NT_FILE_Entry &entry : m_nt_file_entries) - if (path == entry.path && entry.uuid.IsValid()) - return entry.uuid; - return UUID(); + return m_uuids[std::string(path)]; } lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() { @@ -935,6 +952,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef notes) { return status.ToError(); thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname))); SetID(prpsinfo.pr_pid); + m_executable_name = prpsinfo.pr_fname; break; } case ELF::NT_SIGINFO: { diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h index a91c04a277f60..576c6858477a6 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -17,6 +17,7 @@ #define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H #include +#include #include #include "lldb/Target/PostMortemProcess.h" @@ -115,10 +116,6 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { lldb::addr_t end; lldb::addr_t file_ofs; std::string path; - // Add a UUID member for convenient access. The UUID value is not in the - // NT_FILE entries, we will find it in core memory and store it here for - // easy access. - lldb_private::UUID uuid; }; // For ProcessElfCore only @@ -152,6 +149,12 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { // NT_FILE entries found from the NOTE segment std::vector m_nt_file_entries; + // Map from file path to UUID for quick lookup + std::unordered_map m_uuids; + + // Executable name found from the ELF PRPSINFO + std::string m_executable_name; + // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment llvm::Error ParseThreadContextsFromNoteSegment( const elf::ELFProgramHeader &segment_header, @@ -165,6 +168,9 @@ class ProcessElfCore : public lldb_private::PostMortemProcess { lldb_private::UUID FindModuleUUID(const llvm::StringRef path) override; + // Returns the main executable path + llvm::StringRef GetMainExecutablePath(); + // Returns the value of certain type of note of a given start address lldb_private::UUID FindBuidIdInCoreMemory(lldb::addr_t address);