[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