[Lldb-commits] [lldb] [lldb][ElfCore] Improve main executable detection in core files (PR #157170)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 10 14:57:07 PDT 2025
https://github.com/GeorgeHuyubo updated https://github.com/llvm/llvm-project/pull/157170
>From ce400ed7fc2ac60e76fb807d70744d1e42618b4c Mon Sep 17 00:00:00 2001
From: George Hu <hyubo at meta.com>
Date: Fri, 5 Sep 2025 13:23:48 -0700
Subject: [PATCH] [lldb][ElfCore] Improve main executable detection in core
files
---
.../Process/elf-core/ProcessElfCore.cpp | 46 +++++++++++++------
.../Plugins/Process/elf-core/ProcessElfCore.h | 14 ++++--
2 files changed, 42 insertions(+), 18 deletions(-)
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<CoreNote> 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 <list>
+#include <unordered_map>
#include <vector>
#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<NT_FILE_Entry> m_nt_file_entries;
+ // Map from file path to UUID for quick lookup
+ std::unordered_map<std::string, lldb_private::UUID> 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);
More information about the lldb-commits
mailing list