https://github.com/GeorgeHuyubo updated 
https://github.com/llvm/llvm-project/pull/92492

>From a9714b155a116e9b1d18434c0485ea2ad35680f3 Mon Sep 17 00:00:00 2001
From: George Hu <huyubo...@gmail.com>
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH 1/3] Read and store gnu build id from loaded core file

---
 .../Process/elf-core/ProcessElfCore.cpp       | 74 ++++++++++++++++++-
 .../Plugins/Process/elf-core/ProcessElfCore.h | 10 +++
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6d..0e0937b77f4b4 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -250,6 +250,9 @@ Status ProcessElfCore::DoLoadCore() {
     }
   }
 
+  // Try to find gnu build id before we load the executable.
+  UpdateBuildIdForNTFileEntries();
+
   // Core files are useless without the main executable. See if we can locate
   // the main executable using data we found in the core file notes.
   lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
@@ -258,6 +261,7 @@ Status ProcessElfCore::DoLoadCore() {
     if (!m_nt_file_entries.empty()) {
       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,
                                             FileSpec::Style::native);
       if (exe_module_spec.GetFileSpec()) {
@@ -271,6 +275,14 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+    for (NT_FILE_Entry &entry : m_nt_file_entries) {
+      entry.uuid = FindBuidIdInCoreMemory(entry.start);
+    }
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
     m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -573,7 +585,6 @@ llvm::Expected<std::vector<CoreNote>>
 ProcessElfCore::parseSegment(const DataExtractor &segment) {
   lldb::offset_t offset = 0;
   std::vector<CoreNote> result;
-
   while (offset < segment.GetByteSize()) {
     ELFNote note = ELFNote();
     if (!note.Parse(segment, &offset))
@@ -983,6 +994,67 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+UUID ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
+  UUID invalid_uuid;
+  const uint32_t addr_size = GetAddressByteSize();
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+                                                : 
sizeof(llvm::ELF::Elf64_Ehdr);
+
+  // 80 bytes buffer is larger enough for the ELF header or program headers
+  unsigned char buf[80];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size || !elf::ELFHeader::MagicBytesMatch(buf))
+    return invalid_uuid;
+  assert(sizeof(buf) >= elf_header_size);
+  DataExtractor elf_header_data(buf, elf_header_size, GetByteOrder(),
+                                addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(elf_header_data, &offset);
+
+  const lldb::addr_t ph_addr = address + elf_header.e_phoff;
+
+  for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {
+    byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize, buf,
+                           elf_header.e_phentsize, error);
+    if (byte_read != elf_header.e_phentsize)
+      break;
+    assert(sizeof(buf) >= elf_header.e_phentsize);
+    DataExtractor program_header_data(buf, elf_header.e_phentsize,
+                                      GetByteOrder(), addr_size);
+    offset = 0;
+    elf::ELFProgramHeader program_header;
+    program_header.Parse(program_header_data, &offset);
+    if (program_header.p_type != llvm::ELF::PT_NOTE)
+      continue;
+
+    std::vector<uint8_t> note_bytes;
+    note_bytes.resize(program_header.p_memsz);
+
+    byte_read = ReadMemory(program_header.p_vaddr, note_bytes.data(),
+                           program_header.p_memsz, error);
+    if (byte_read != program_header.p_memsz)
+      continue;
+    assert(sizeof(buf) >= program_header.p_memsz);
+    DataExtractor segment_data(note_bytes.data(), note_bytes.size(),
+                               GetByteOrder(), addr_size);
+    auto notes_or_error = parseSegment(segment_data);
+    if (!notes_or_error)
+      return invalid_uuid;
+    for (const CoreNote &note : *notes_or_error) {
+      if (note.info.n_namesz == 4 &&
+          note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID) {
+        if ("GNU" == note.info.n_name)
+          return UUID(llvm::ArrayRef<uint8_t>(
+              note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
+      }
+    }
+  }
+  return invalid_uuid;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
     DoLoadCore();
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 2cec635bbacfe..668a7c4846747 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -117,6 +117,10 @@ 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
@@ -158,6 +162,12 @@ class ProcessElfCore : public 
lldb_private::PostMortemProcess {
   // Returns number of thread contexts stored in the core file
   uint32_t GetNumThreadContexts();
 
+  // Populate gnu uuid for each NT_FILE entry
+  void UpdateBuildIdForNTFileEntries();
+
+  // Returns the value of certain type of note of a given start address
+  lldb_private::UUID FindBuidIdInCoreMemory(lldb::addr_t address);
+
   // Parse a contiguous address range of the process from LOAD segment
   lldb::addr_t
   AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);

>From 112a5bf7a75ade64a4f6cabd9f09d2e8eae7e8f1 Mon Sep 17 00:00:00 2001
From: George Hu <huyubo...@gmail.com>
Date: Fri, 24 May 2024 08:31:09 -0700
Subject: [PATCH 2/3] Address several review comments

---
 .../Process/elf-core/ProcessElfCore.cpp       | 34 +++++++++----------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 0e0937b77f4b4..637570259e91c 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -1000,15 +1000,16 @@ UUID 
ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
   const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
                                                 : 
sizeof(llvm::ELF::Elf64_Ehdr);
 
-  // 80 bytes buffer is larger enough for the ELF header or program headers
-  unsigned char buf[80];
+  std::vector<uint8_t> elf_header_bytes;
+  elf_header_bytes.resize(elf_header_size);
   Status error;
-  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
-  if (byte_read != elf_header_size || !elf::ELFHeader::MagicBytesMatch(buf))
+  size_t byte_read =
+      ReadMemory(address, elf_header_bytes.data(), elf_header_size, error);
+  if (byte_read != elf_header_size ||
+      !elf::ELFHeader::MagicBytesMatch(elf_header_bytes.data()))
     return invalid_uuid;
-  assert(sizeof(buf) >= elf_header_size);
-  DataExtractor elf_header_data(buf, elf_header_size, GetByteOrder(),
-                                addr_size);
+  DataExtractor elf_header_data(elf_header_bytes.data(), elf_header_size,
+                                GetByteOrder(), addr_size);
   lldb::offset_t offset = 0;
 
   elf::ELFHeader elf_header;
@@ -1016,13 +1017,14 @@ UUID 
ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
 
   const lldb::addr_t ph_addr = address + elf_header.e_phoff;
 
+  std::vector<uint8_t> ph_bytes;
+  ph_bytes.resize(elf_header.e_phentsize);
   for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {
-    byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize, buf,
-                           elf_header.e_phentsize, error);
+    byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize,
+                           ph_bytes.data(), elf_header.e_phentsize, error);
     if (byte_read != elf_header.e_phentsize)
       break;
-    assert(sizeof(buf) >= elf_header.e_phentsize);
-    DataExtractor program_header_data(buf, elf_header.e_phentsize,
+    DataExtractor program_header_data(ph_bytes.data(), elf_header.e_phentsize,
                                       GetByteOrder(), addr_size);
     offset = 0;
     elf::ELFProgramHeader program_header;
@@ -1037,7 +1039,6 @@ UUID ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t 
address) {
                            program_header.p_memsz, error);
     if (byte_read != program_header.p_memsz)
       continue;
-    assert(sizeof(buf) >= program_header.p_memsz);
     DataExtractor segment_data(note_bytes.data(), note_bytes.size(),
                                GetByteOrder(), addr_size);
     auto notes_or_error = parseSegment(segment_data);
@@ -1045,11 +1046,10 @@ UUID 
ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {
       return invalid_uuid;
     for (const CoreNote &note : *notes_or_error) {
       if (note.info.n_namesz == 4 &&
-          note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID) {
-        if ("GNU" == note.info.n_name)
-          return UUID(llvm::ArrayRef<uint8_t>(
-              note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
-      }
+          note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID &&
+          "GNU" == note.info.n_name &&
+          note.data.ValidOffsetForDataOfSize(0, note.info.n_descsz))
+        return UUID(note.data.GetData().take_front(note.info.n_descsz));
     }
   }
   return invalid_uuid;

>From 95d455be8a5b2bcf588b835972bb9ed6852521a1 Mon Sep 17 00:00:00 2001
From: George Hu <huyubo...@gmail.com>
Date: Fri, 24 May 2024 10:55:34 -0700
Subject: [PATCH 3/3] Address comment, revert empty line change

---
 lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 637570259e91c..30af9345999c4 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -276,10 +276,8 @@ Status ProcessElfCore::DoLoadCore() {
 }
 
 void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
-  if (!m_nt_file_entries.empty()) {
-    for (NT_FILE_Entry &entry : m_nt_file_entries) {
-      entry.uuid = FindBuidIdInCoreMemory(entry.start);
-    }
+  for (NT_FILE_Entry &entry : m_nt_file_entries) {
+    entry.uuid = FindBuidIdInCoreMemory(entry.start);
   }
 }
 
@@ -585,6 +583,7 @@ llvm::Expected<std::vector<CoreNote>>
 ProcessElfCore::parseSegment(const DataExtractor &segment) {
   lldb::offset_t offset = 0;
   std::vector<CoreNote> result;
+
   while (offset < segment.GetByteSize()) {
     ELFNote note = ELFNote();
     if (!note.Parse(segment, &offset))

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to