[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread via lldb-commits

https://github.com/GeorgeHuyubo closed 
https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread via lldb-commits

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 
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  : 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>
 ProcessElfCore::parseSegment(const DataExtractor ) {
   lldb::offset_t offset = 0;
   std::vector result;
-
   while (offset < segment.GetByteSize()) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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  : *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(
+  note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
+  }
+}
+  }
+  return invalid_uuid;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
 DoLoadCore();
diff --git 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread via lldb-commits

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 
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  : 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>
 ProcessElfCore::parseSegment(const DataExtractor ) {
   lldb::offset_t offset = 0;
   std::vector result;
-
   while (offset < segment.GetByteSize()) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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  : *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(
+  note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
+  }
+}
+  }
+  return invalid_uuid;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
 DoLoadCore();
diff --git 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits

labath wrote:

Thanks for your patience.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits


@@ -271,6 +275,14 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {

labath wrote:

No need to explicitly check for emptyness. The loop will naturally do nothing 
if the array is empty.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits


@@ -573,7 +585,6 @@ llvm::Expected>
 ProcessElfCore::parseSegment(const DataExtractor ) {
   lldb::offset_t offset = 0;
   std::vector result;
-

labath wrote:

I know why this came to be, but it'd be nice to revert it so the final patch 
does not contain a spurious newline edit.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits

https://github.com/labath approved this pull request.


https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits

https://github.com/labath edited https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread via lldb-commits

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 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH 1/2] 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  : 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>
 ProcessElfCore::parseSegment(const DataExtractor ) {
   lldb::offset_t offset = 0;
   std::vector result;
-
   while (offset < segment.GetByteSize()) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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  : *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(
+  note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
+  }
+}
+  }
+  return invalid_uuid;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
 DoLoadCore();
diff --git 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits


@@ -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, );
+
+  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);

labath wrote:

This could be a static_assert, but it might even be better to do declare the 
array as something like `char buf[sizeof(Elf64_Ehdr)] and avoid any doubt about 
it being large enough (then you also wouldn't need the comment above the array 
declaration).

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits

https://github.com/labath commented:

Very close. Just a couple of details.

BTW, I believe the recommended workflow for working with pull requests is to 
put your new changes as additional commits on top and then squash them all 
together after merging. The GitHub UI just works better that way.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits


@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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  : *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(
+  note.data.GetDataStart(), note.info.n_descsz /*byte size*/));

labath wrote:

In case of a corrupted core file, `note.data` can contain less than `n_descsz` 
bytes, and this will create a invalid ArrayRef (and possibly crash lldb). 
Writing this like `return UUID(note.data.GetData())` will ensure that does not 
happen, although it could return a truncated UUID in that case. If you want to 
check that case explicitly, then I'd recommend something like:
```
if(note.data.ValidOffsetForDataOfSize(0, note.info.n_descsz))
  return UUID(note.data.GetData().take_front(note.info.n_descsz);
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits

https://github.com/labath edited https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-24 Thread Pavel Labath via lldb-commits


@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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);

labath wrote:

This looks like an obsolete assertion as the program headers are read into a 
dynamically sized vector now.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread via lldb-commits

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 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] 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  : 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>
 ProcessElfCore::parseSegment(const DataExtractor ) {
   lldb::offset_t offset = 0;
   std::vector result;
-
   while (offset < segment.GetByteSize()) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
@@ -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, );
+
+  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, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+std::vector 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  : *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(
+  note.data.GetDataStart(), note.info.n_descsz /*byte size*/));
+  }
+}
+  }
+  return invalid_uuid;
+}
+
 uint32_t ProcessElfCore::GetNumThreadContexts() {
   if (!m_thread_data_valid)
 DoLoadCore();
diff --git 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread Pavel Labath via lldb-commits

https://github.com/labath edited https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread Pavel Labath via lldb-commits


@@ -271,6 +282,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {

labath wrote:

Makes sense. I though something like this might be the case.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread Pavel Labath via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {

labath wrote:

I don't think this `type` argument is useful, as this function already a UUID, 
and so it can't be used to parse any other kind of a note. I'd recommend 
inlining NT_GNU_BUILD_ID into the function (and renaming it to something like 
FindBuidIdInCoreMemory).

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread Pavel Labath via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;

labath wrote:

I think you can just delete this and put the magic bytes check at on line 
~1024, after you read the full header. Reading 4 bytes is not going to be 
appreciably faster than reading 64 (sizeof(Elf64_Ehdr)), and this will make the 
code look more like the one on lines 60--70 (which essentially does the same 
thing).

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-23 Thread Pavel Labath via lldb-commits


@@ -271,6 +276,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+for (NT_FILE_Entry  : m_nt_file_entries) {
+  std::optional uuid =

labath wrote:

Since UUID already has an IsValid() method I don't think wrapping it in an 
optional is not going to help (in fact, it will add ambiguity: Does returning 
an invalid UUID mean something different than std::nullopt?) Up to you, but I'd 
remove the optional here...

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -570,11 +586,13 @@ static void ParseOpenBSDProcInfo(ThreadData _data,
 }
 
 llvm::Expected>
-ProcessElfCore::parseSegment(const DataExtractor ) {
+ProcessElfCore::parseSegment(const DataExtractor ,
+ unsigned long segment_size) {
   lldb::offset_t offset = 0;
   std::vector result;
-
-  while (offset < segment.GetByteSize()) {
+  unsigned long note_size =
+  segment_size == 0 ? segment.GetByteSize() : segment_size;
+  while (offset < note_size) {

clayborg wrote:

revert this, we will trim the size of the data down before passing it in.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );
+
+  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;
+offset = 0;
+elf::ELFProgramHeader program_header;
+program_header.Parse(data, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+byte_read =
+ReadMemory(program_header.p_vaddr, buf, program_header.p_memsz, error);
+if (byte_read != program_header.p_memsz)
+  continue;
+
+auto notes_or_error = parseSegment(data, program_header.p_memsz);

clayborg wrote:

Create a DataBuffer for only the note data, and then we won't need to pass the 
`program_header.p_memsz` to `parseSegment(...)`:
```
DataExtractor note_data(note_bytes.data(), note_bytes.size(), GetByteOrder(), 
addr_size);
auto notes_or_error = parseSegment(note_data);
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );

clayborg wrote:

Use `header_data` to only allow access to the bytes we read.
```
elf_header.Parse(header_data, );
```



https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );
+
+  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;
+offset = 0;
+elf::ELFProgramHeader program_header;
+program_header.Parse(data, );

clayborg wrote:

Create a `DataExtractor` that contains only a program header worth of data:
```
assert(sizeof(buf) >= elf_header.e_phentsize);
DataExtractor phdr_data(buf, elf_header.e_phentsize, GetByteOrder(), addr_size);
program_header.Parse(phdr_data, );
```


https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );
+
+  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;
+offset = 0;
+elf::ELFProgramHeader program_header;
+program_header.Parse(data, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+byte_read =
+ReadMemory(program_header.p_vaddr, buf, program_header.p_memsz, error);

clayborg wrote:

Make a dynamic memory buffer to make sure we have enough bytes to store the 
note data as it could exceed 4096 bytes, and then read into this buffer:
```
std::vector note_bytes;
note_bytes.resize(program_header.p_memsz);
byte_read =
ReadMemory(note_bytes.data(), note_bytes.size(), 
program_header.p_memsz, error);
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -117,6 +117,7 @@ class ProcessElfCore : public 
lldb_private::PostMortemProcess {
 lldb::addr_t end;
 lldb::addr_t file_ofs;
 std::string path;
+lldb_private::UUID uuid; //.note.gnu.build-id

clayborg wrote:

Add a comment letting the user know the UUID isn't actually in the 
NT_FILE_Entry:
```
// 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.
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits

https://github.com/clayborg requested changes to this pull request.


https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -570,11 +586,13 @@ static void ParseOpenBSDProcInfo(ThreadData _data,
 }
 
 llvm::Expected>
-ProcessElfCore::parseSegment(const DataExtractor ) {
+ProcessElfCore::parseSegment(const DataExtractor ,
+ unsigned long segment_size) {

clayborg wrote:

Remove thuis change, we can easily trim down the size of the DataExtractor 
before passing it in. See inline comments below.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits

https://github.com/clayborg edited 
https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);

clayborg wrote:

It is ok to have a large buffer, but we should make sure the data extractor 
points to just the data we have read for each place that we use it by 
contructing new DataExtractor objects:
```
assert(sizeof(buf) >= elf_header_size);
DataExtractor header_data(buf, elf_header_size, GetByteOrder(), addr_size);
```


https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread Greg Clayton via lldb-commits


@@ -167,7 +178,8 @@ class ProcessElfCore : public 
lldb_private::PostMortemProcess {
   AddAddressRangeFromMemoryTagSegment(const elf::ELFProgramHeader );
 
   llvm::Expected>
-  parseSegment(const lldb_private::DataExtractor );
+  parseSegment(const lldb_private::DataExtractor ,
+   unsigned long segment_size = 0);

clayborg wrote:

revert

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread via lldb-commits

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

>From 11dda0b456880005695b6d1f195060788ad0edb7 Mon Sep 17 00:00:00 2001
From: George Hu 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] Read and store gnu build id from loaded core file

---
 .../Process/elf-core/ProcessElfCore.cpp   | 84 ++-
 .../Plugins/Process/elf-core/ProcessElfCore.h | 14 +++-
 2 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6d..cc82d1c2b5132 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -11,6 +11,7 @@
 #include 
 #include 
 
+#include "Plugins/ObjectFile/ELF/ELFHeader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
@@ -250,6 +251,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 +262,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 +276,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+for (NT_FILE_Entry  : m_nt_file_entries) {
+  std::optional uuid =
+  FindNoteInCoreMemory(entry.start, llvm::ELF::NT_GNU_BUILD_ID);
+  if (uuid)
+entry.uuid = uuid.value();
+}
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
 m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -570,11 +586,13 @@ static void ParseOpenBSDProcInfo(ThreadData _data,
 }
 
 llvm::Expected>
-ProcessElfCore::parseSegment(const DataExtractor ) {
+ProcessElfCore::parseSegment(const DataExtractor ,
+ unsigned long segment_size) {
   lldb::offset_t offset = 0;
   std::vector result;
-
-  while (offset < segment.GetByteSize()) {
+  unsigned long note_size =
+  segment_size == 0 ? segment.GetByteSize() : segment_size;
+  while (offset < note_size) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
   return llvm::make_error(
@@ -983,6 +1001,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );
+
+  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;
+offset = 0;
+elf::ELFProgramHeader program_header;
+program_header.Parse(data, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+byte_read =
+ReadMemory(program_header.p_vaddr, buf, program_header.p_memsz, error);
+if (byte_read != program_header.p_memsz)
+  continue;
+
+auto notes_or_error = parseSegment(data, program_header.p_memsz);
+if (!notes_or_error)
+  return std::nullopt;
+for (const CoreNote  : *notes_or_error) {
+  if (note.info.n_namesz == 4 && note.info.n_type == type) {
+if ("GNU" == note.info.n_name)
+  return UUID(llvm::ArrayRef(
+  note.data.GetDataStart(), 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread via lldb-commits

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

>From 4e4ca8edc4116cba0925cca8229bd5b1cb002b21 Mon Sep 17 00:00:00 2001
From: George Hu 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] Read and store gnu build id from loaded core file

---
 .../Process/elf-core/ProcessElfCore.cpp   | 87 ++-
 .../Plugins/Process/elf-core/ProcessElfCore.h | 14 ++-
 2 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6d..3a126220fabf0 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,11 +6,14 @@
 //
 
//===--===//
 
+#include 
 #include 
 
 #include 
 #include 
+#include 
 
+#include "Plugins/ObjectFile/ELF/ELFHeader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
@@ -33,6 +36,7 @@
 #include "Plugins/Process/elf-core/RegisterUtilities.h"
 #include "ProcessElfCore.h"
 #include "ThreadElfCore.h"
+#include "lldb/lldb-types.h"
 
 using namespace lldb_private;
 namespace ELF = llvm::ELF;
@@ -250,6 +254,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 +265,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 +279,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+for (NT_FILE_Entry  : m_nt_file_entries) {
+  std::optional uuid =
+  FindNoteInCoreMemory(entry.start, llvm::ELF::NT_GNU_BUILD_ID);
+  if (uuid)
+entry.uuid = uuid.value();
+}
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
 m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -570,11 +589,13 @@ static void ParseOpenBSDProcInfo(ThreadData _data,
 }
 
 llvm::Expected>
-ProcessElfCore::parseSegment(const DataExtractor ) {
+ProcessElfCore::parseSegment(const DataExtractor ,
+ unsigned long segment_size) {
   lldb::offset_t offset = 0;
   std::vector result;
-
-  while (offset < segment.GetByteSize()) {
+  unsigned long note_size =
+  segment_size == 0 ? segment.GetByteSize() : segment_size;
+  while (offset < note_size) {
 ELFNote note = ELFNote();
 if (!note.Parse(segment, ))
   return llvm::make_error(
@@ -983,6 +1004,66 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNoteInCoreMemory(lldb::addr_t address,
+ uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  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);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  if (byte_read != elf_header_size)
+return std::nullopt;
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = 0;
+
+  elf::ELFHeader elf_header;
+  elf_header.Parse(data, );
+
+  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;
+offset = 0;
+elf::ELFProgramHeader program_header;
+program_header.Parse(data, );
+if (program_header.p_type != llvm::ELF::PT_NOTE)
+  continue;
+
+byte_read =
+ReadMemory(program_header.p_vaddr, buf, program_header.p_memsz, error);
+if (byte_read != program_header.p_memsz)
+  continue;
+
+auto 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread via lldb-commits

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

>From fc7ae3cd19a999375504733be6c942978d80d5d7 Mon Sep 17 00:00:00 2001
From: George Hu 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] Read and store gnu build id from loaded core file

---
 .../Plugins/ObjectFile/ELF/ELFHeader.cpp  | 13 +++
 .../source/Plugins/ObjectFile/ELF/ELFHeader.h | 25 ++
 .../Process/elf-core/ProcessElfCore.cpp   | 87 +++
 .../Plugins/Process/elf-core/ProcessElfCore.h | 15 
 4 files changed, 140 insertions(+)

diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp 
b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index a6e385f70709b..fcb677ed28a92 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -252,6 +252,19 @@ bool ELFSectionHeader::Parse(const 
lldb_private::DataExtractor ,
   return true;
 }
 
+// SectionNote
+
+SectionNote::SectionNote() { memset(this, 0, sizeof(SectionNote)); }
+
+bool SectionNote::Parse(const lldb_private::DataExtractor ,
+lldb::offset_t *offset) {
+  // Read sn_namesz and sn_descsz, sn_type.
+  if (data.GetU32(offset, _namesz, 3) == nullptr)
+return false;
+
+  return true;
+}
+
 // ELFSymbol
 
 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h 
b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
index 963cc850736ff..da6dfc7343bcf 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -271,6 +271,31 @@ struct ELFSymbol {
 const lldb_private::SectionList *section_list);
 };
 
+/// \class SectionNote
+/// Represents an entry of PT_NOTE in program header
+struct SectionNote {
+  elf_word sn_namesz;
+  elf_word sn_descsz;
+  elf_word sn_type;
+
+  SectionNote();
+
+  /// Parse an SectionNote entry from the given DataExtractor starting at
+  /// position \p offset.
+  ///
+  /// \param[in] data
+  ///The DataExtractor to read from.
+  ///
+  /// \param[in,out] offset
+  ///Pointer to an offset in the data.  On return the offset will be
+  ///advanced by the number of bytes read.
+  ///
+  /// \return
+  ///True if the SectionNote was successfully read and false
+  ///otherwise.
+  bool Parse(const lldb_private::DataExtractor , lldb::offset_t *offset);
+};
+
 /// \class ELFDynamic
 /// Represents an entry in an ELF dynamic table.
 struct ELFDynamic {
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6d..4e5e70ceae438 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,11 +6,14 @@
 //
 
//===--===//
 
+#include 
 #include 
 
 #include 
 #include 
+#include 
 
+#include "Plugins/ObjectFile/ELF/ELFHeader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
@@ -33,6 +36,7 @@
 #include "Plugins/Process/elf-core/RegisterUtilities.h"
 #include "ProcessElfCore.h"
 #include "ThreadElfCore.h"
+#include "lldb/lldb-types.h"
 
 using namespace lldb_private;
 namespace ELF = llvm::ELF;
@@ -250,6 +254,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 +265,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 +279,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+for (NT_FILE_Entry  : m_nt_file_entries) {
+  std::optional uuid =
+  FindNoteInCoreMemory(entry.start, llvm::ELF::NT_GNU_BUILD_ID);
+  if (uuid)
+entry.uuid = uuid.value();
+}
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
 m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -983,6 +1002,74 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread via lldb-commits


@@ -271,6 +282,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {

GeorgeHuyubo wrote:

@labath 
There are two reasons,
1. We need to do this after we load PT_LOAD segment, so that we have address 
map which is essential to ReadMemory. PT_LOAD is usually after PT_NOTE afaik.
2. We need to do this after the core architecture is set, so 
GetAddressByteSize() will return non zero value.

@kevinfrei 
During the pass, it's parsing the elf header of the core file, during which we 
don't have the gnu build id in there yet. We need to let the pass finish so 
that we have the core file loaded into memory, and then we will need to read 
from certain memory region which represent a loaded module and parse the elf 
header there to get the gnu build id. 

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-22 Thread via lldb-commits

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

>From 304528acdd3590bf4d8d1a03e31fd0970ed2eaa2 Mon Sep 17 00:00:00 2001
From: George Hu 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] Read and store gnu build id from loaded core file

---
 .../Plugins/ObjectFile/ELF/ELFHeader.cpp  | 13 +++
 .../source/Plugins/ObjectFile/ELF/ELFHeader.h | 27 ++
 .../Process/elf-core/ProcessElfCore.cpp   | 87 +++
 .../Plugins/Process/elf-core/ProcessElfCore.h | 15 
 4 files changed, 142 insertions(+)

diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp 
b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index a6e385f70709b..fcb677ed28a92 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -252,6 +252,19 @@ bool ELFSectionHeader::Parse(const 
lldb_private::DataExtractor ,
   return true;
 }
 
+// SectionNote
+
+SectionNote::SectionNote() { memset(this, 0, sizeof(SectionNote)); }
+
+bool SectionNote::Parse(const lldb_private::DataExtractor ,
+lldb::offset_t *offset) {
+  // Read sn_namesz and sn_descsz, sn_type.
+  if (data.GetU32(offset, _namesz, 3) == nullptr)
+return false;
+
+  return true;
+}
+
 // ELFSymbol
 
 ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h 
b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
index 963cc850736ff..baf35d4a78c18 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -271,6 +271,33 @@ struct ELFSymbol {
 const lldb_private::SectionList *section_list);
 };
 
+/// \class SectionNote
+/// Represents an entry of PT_NOTE in program header
+struct SectionNote {
+  elf_word sn_namesz;
+  elf_word sn_descsz;
+  elf_word sn_type;
+
+  SectionNote();
+
+  /// Parse an SectionNote entry from the given DataExtractor starting at
+  /// position \p offset.  The address size of the DataExtractor determines if
+  /// a 32 or 64 bit object is to be parsed.
+  ///
+  /// \param[in] data
+  ///The DataExtractor to read from.  The address size of the extractor
+  ///determines if a 32 or 64 bit object should be read.
+  ///
+  /// \param[in,out] offset
+  ///Pointer to an offset in the data.  On return the offset will be
+  ///advanced by the number of bytes read.
+  ///
+  /// \return
+  ///True if the SectionNote was successfully read and false
+  ///otherwise.
+  bool Parse(const lldb_private::DataExtractor , lldb::offset_t *offset);
+};
+
 /// \class ELFDynamic
 /// Represents an entry in an ELF dynamic table.
 struct ELFDynamic {
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp 
b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 36812c27a5b6d..4e5e70ceae438 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,11 +6,14 @@
 //
 
//===--===//
 
+#include 
 #include 
 
 #include 
 #include 
+#include 
 
+#include "Plugins/ObjectFile/ELF/ELFHeader.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
@@ -33,6 +36,7 @@
 #include "Plugins/Process/elf-core/RegisterUtilities.h"
 #include "ProcessElfCore.h"
 #include "ThreadElfCore.h"
+#include "lldb/lldb-types.h"
 
 using namespace lldb_private;
 namespace ELF = llvm::ELF;
@@ -250,6 +254,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 +265,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 +279,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {
+for (NT_FILE_Entry  : m_nt_file_entries) {
+  std::optional uuid =
+  FindNoteInCoreMemory(entry.start, llvm::ELF::NT_GNU_BUILD_ID);
+  if (uuid)
+entry.uuid = uuid.value();
+}
+  }
+}
+
 lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
 m_dyld_up.reset(DynamicLoader::FindPlugin(
@@ -983,6 +1002,74 @@ llvm::Error 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,
+ const uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  const uint32_t addr_size = GetAddressByteSize();
+  const lldb::offset_t ehdr_phoff_offset = ELFOFFSETOF(Ehdr, e_phoff);
+  const lldb::offset_t ehdr_phentsize_offset = ELFOFFSETOF(Ehdr, e_phentsize);
+  const lldb::offset_t ehdr_phnum_offset = ELFOFFSETOF(Ehdr, e_phnum);
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+: 
sizeof(llvm::ELF::Elf64_Ehdr);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = ehdr_phoff_offset;
+  lldb::offset_t phoff = data.GetAddress();
+
+  offset = ehdr_phentsize_offset;
+  lldb::offset_t phentsize = data.GetU16();
+  offset = ehdr_phnum_offset;
+  lldb::offset_t phnum = data.GetU16();

clayborg wrote:

header for the `ELFHeader` class is in: 
```
lldb/source/Plugins/ObjectFile/ELF/ELFHeader.h
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,
+ const uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  const uint32_t addr_size = GetAddressByteSize();
+  const lldb::offset_t ehdr_phoff_offset = ELFOFFSETOF(Ehdr, e_phoff);
+  const lldb::offset_t ehdr_phentsize_offset = ELFOFFSETOF(Ehdr, e_phentsize);
+  const lldb::offset_t ehdr_phnum_offset = ELFOFFSETOF(Ehdr, e_phnum);

clayborg wrote:

pass `addr_size` to the macro

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -1649,6 +1679,26 @@ class Process : public 
std::enable_shared_from_this,
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status );
 
+  /// Find a string within a memory region.
+  ///
+  /// This function searches for the string represented by the provided buffer
+  /// within the memory range specified by the low and high addresses. It uses
+  /// a bad character heuristic to optimize the search process.
+  ///
+  /// \param[in] low The starting address of the memory region to be searched.
+  ///
+  /// \param[in] high The ending address of the memory region to be searched.
+  ///
+  /// \param[in] buffer A pointer to the buffer containing the string to be
+  /// searched.

clayborg wrote:

```
  /// \param[in] buffer A pointer to the buffer containing the bytes to be
  /// searched.
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -33,12 +35,17 @@
 #include "Plugins/Process/elf-core/RegisterUtilities.h"
 #include "ProcessElfCore.h"
 #include "ThreadElfCore.h"
+#include "lldb/lldb-types.h"
 
 using namespace lldb_private;
 namespace ELF = llvm::ELF;
 
 LLDB_PLUGIN_DEFINE(ProcessElfCore)
 
+#define ELFOFFSETOF(T, M)  
\
+  addr_size == 4 ? offsetof(llvm::ELF::Elf32_##T, M)   
\
+ : offsetof(llvm::ELF::Elf64_##T, M)

clayborg wrote:

We should pass in `addr_size` here:
```
#define ELFOFFSETOF(type_name, member, addr_size) ...
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -117,6 +117,13 @@ class ProcessElfCore : public 
lldb_private::PostMortemProcess {
 lldb::addr_t end;
 lldb::addr_t file_ofs;
 std::string path;
+lldb_private::UUID uuid; //.note.gnu.build-id
+  };
+
+  struct Section_Note {
+uint32_t namesz;
+uint32_t descsz;
+uint32_t type;

clayborg wrote:

or move it into ELFHeader.h and then add a parse method. We are using a ton of 
stuff already from ELFHeader.h, so we should follow that path

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,

clayborg wrote:

Maybe the name of `FindNoteInCoreMemory`?

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -1649,6 +1679,26 @@ class Process : public 
std::enable_shared_from_this,
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status );
 
+  /// Find a string within a memory region.

clayborg wrote:

Change to:
```
/// Find bytes within a memory range.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Greg Clayton via lldb-commits


@@ -1649,6 +1679,26 @@ class Process : public 
std::enable_shared_from_this,
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status );
 
+  /// Find a string within a memory region.
+  ///
+  /// This function searches for the string represented by the provided buffer

clayborg wrote:

change to:
```
  /// This function searches for the bytes represented by the provided buffer
```

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Kevin Frei via lldb-commits


@@ -117,6 +117,13 @@ class ProcessElfCore : public 
lldb_private::PostMortemProcess {
 lldb::addr_t end;
 lldb::addr_t file_ofs;
 std::string path;
+lldb_private::UUID uuid; //.note.gnu.build-id
+  };
+
+  struct Section_Note {
+uint32_t namesz;
+uint32_t descsz;
+uint32_t type;

kevinfrei wrote:

Move this to the ThreadElfCore.h header and add a 'parse' method to it, so the 
UUID is populated much like the PRPSINFO data and other useful info from the 
coredump.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Kevin Frei via lldb-commits

https://github.com/kevinfrei edited 
https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Kevin Frei via lldb-commits

https://github.com/kevinfrei requested changes to this pull request.


https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Kevin Frei via lldb-commits


@@ -271,6 +282,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {

kevinfrei wrote:

I'd suggest adding it to that pass as well, though it will be a little bit 
messier, as NT_PRPSINFO and NT_GNU_BUILD_ID have the same values, so they 
depend on the Name field (CORE and GNU, respectively...). Do a check for the 
GNU name at the very top (line 902ish?) and handle NT_GNU_BUILD_ID's before the 
rest of that loop body, or dealing with PRPSINFO logic will get much messier...

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Kevin Frei via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,

kevinfrei wrote:

I'd suggest instead, implement support for the Note section in the same fashion 
as the other ELF components, with a "parse" method and the like (check out 
ThreadElfCore.h) and integrated it into the top level loop, same as the other 
Program Header structures.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,
+ const uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  const uint32_t addr_size = GetAddressByteSize();
+  const lldb::offset_t ehdr_phoff_offset = ELFOFFSETOF(Ehdr, e_phoff);
+  const lldb::offset_t ehdr_phentsize_offset = ELFOFFSETOF(Ehdr, e_phentsize);
+  const lldb::offset_t ehdr_phnum_offset = ELFOFFSETOF(Ehdr, e_phnum);
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+: 
sizeof(llvm::ELF::Elf64_Ehdr);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = ehdr_phoff_offset;
+  lldb::offset_t phoff = data.GetAddress();
+
+  offset = ehdr_phentsize_offset;
+  lldb::offset_t phentsize = data.GetU16();
+  offset = ehdr_phnum_offset;
+  lldb::offset_t phnum = data.GetU16();

labath wrote:

Reuse the existing `ELFHeader` class for this. I.e., read the necessary amount 
of bytes (you can just always read `sizeof(Elf64_Ehdr)` as that's larger) into 
a DataExtractor and call `header.Parse(extractor, 0)`.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -271,6 +282,17 @@ Status ProcessElfCore::DoLoadCore() {
   return error;
 }
 
+void ProcessElfCore::UpdateBuildIdForNTFileEntries() {
+  if (!m_nt_file_entries.empty()) {

labath wrote:

Any specific reason doing this as a separate pass (and not from inside parsing 
loop on line 936)?

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,
+ const uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  const uint32_t addr_size = GetAddressByteSize();
+  const lldb::offset_t ehdr_phoff_offset = ELFOFFSETOF(Ehdr, e_phoff);
+  const lldb::offset_t ehdr_phentsize_offset = ELFOFFSETOF(Ehdr, e_phentsize);
+  const lldb::offset_t ehdr_phnum_offset = ELFOFFSETOF(Ehdr, e_phnum);
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+: 
sizeof(llvm::ELF::Elf64_Ehdr);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = ehdr_phoff_offset;
+  lldb::offset_t phoff = data.GetAddress();
+
+  offset = ehdr_phentsize_offset;
+  lldb::offset_t phentsize = data.GetU16();
+  offset = ehdr_phnum_offset;
+  lldb::offset_t phnum = data.GetU16();
+
+  Section_Note note;
+  const lldb::addr_t ph_addr = address + phoff;
+
+  for (unsigned int i = 0; i < phnum; ++i) {
+byte_read = ReadMemory(ph_addr + i * phentsize, buf, phentsize, error);
+if (byte_read != phentsize)
+  break;
+offset = 0;
+uint32_t p_type = data.GetU32();
+if (p_type != llvm::ELF::PT_NOTE)
+  continue;
+offset = ELFOFFSETOF(Phdr, p_vaddr);
+lldb::addr_t p_vaddr = data.GetAddress();
+offset = ELFOFFSETOF(Phdr, p_memsz);
+lldb::addr_t p_memsz = data.GetAddress();
+
+byte_read = ReadMemory(p_vaddr, buf, p_memsz, error);
+if (byte_read != p_memsz)
+  continue;
+offset = 0;
+while (
+offset < p_memsz &&
+data.GetU32(, , sizeof(Section_Note) / sizeof(uint32_t))) {
+  if (note.namesz == 4 && note.type == type) {
+const char *name = data.GetCStr();
+if (name && strcmp("GNU", name) == 0)
+  return UUID(
+  llvm::ArrayRef(buf + offset, note.descsz /*byte 
size*/));
+  }
+  offset += note.namesz + note.descsz;
+}

labath wrote:

And `parseSegment` for this (despite the generic name, this is really for 
parsing note segments, maybe you could rename it while you're in here).

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -158,6 +165,16 @@ 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
+  std::optional FindNote(const lldb::addr_t address,

labath wrote:

`const` on a value parameter (pointer and reference parameters are of course 
different) declaration don't actually do anything, and I don't believe we 
usually use them.

If you really want to you can still make them `const` in [the function 
definition](https://godbolt.org/z/PxM739P84) even if they're not const in the 
header (though we usually don't do that either).

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,

labath wrote:

Please give this a more specific name (to say what kind of note its searching 
for and where). An uninformed reader would think this is searching for a note 
in the core file itself.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -406,6 +406,36 @@ class Process : public 
std::enable_shared_from_this,
   lldb::StateType state);
   } Notifications;
 
+  class ProcessMemoryIterator {

labath wrote:

AFAICT, this isn't necessary anymore. If you think it's useful, you can make it 
a separate patch.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits

https://github.com/labath commented:

This looks much better, though, after looking at this closer, I don't think 
it's necessary to reimplement the elf parsing code. We already have all the 
necessary data structures for parsing notes in the core file itself, and it 
looks like it would be fairly easy to reuse them for this purpose as well.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits


@@ -983,6 +1005,73 @@ llvm::Error 
ProcessElfCore::ParseThreadContextsFromNoteSegment(
   }
 }
 
+bool ProcessElfCore::IsElf(const lldb::addr_t address) {
+  uint8_t buf[4];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, 4, error);
+  if (byte_read != 4)
+return false;
+  return elf::ELFHeader::MagicBytesMatch(buf);
+}
+
+std::optional ProcessElfCore::FindNote(const lldb::addr_t address,
+ const uint32_t type) {
+  if (!IsElf(address))
+return std::nullopt;
+  const uint32_t addr_size = GetAddressByteSize();
+  const lldb::offset_t ehdr_phoff_offset = ELFOFFSETOF(Ehdr, e_phoff);
+  const lldb::offset_t ehdr_phentsize_offset = ELFOFFSETOF(Ehdr, e_phentsize);
+  const lldb::offset_t ehdr_phnum_offset = ELFOFFSETOF(Ehdr, e_phnum);
+  const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)
+: 
sizeof(llvm::ELF::Elf64_Ehdr);
+
+  unsigned char buf[4096];
+  Status error;
+  size_t byte_read = ReadMemory(address, buf, elf_header_size, error);
+  DataExtractor data(buf, 4096, GetByteOrder(), addr_size);
+  lldb::offset_t offset = ehdr_phoff_offset;
+  lldb::offset_t phoff = data.GetAddress();
+
+  offset = ehdr_phentsize_offset;
+  lldb::offset_t phentsize = data.GetU16();
+  offset = ehdr_phnum_offset;
+  lldb::offset_t phnum = data.GetU16();
+
+  Section_Note note;
+  const lldb::addr_t ph_addr = address + phoff;
+
+  for (unsigned int i = 0; i < phnum; ++i) {
+byte_read = ReadMemory(ph_addr + i * phentsize, buf, phentsize, error);
+if (byte_read != phentsize)
+  break;
+offset = 0;
+uint32_t p_type = data.GetU32();
+if (p_type != llvm::ELF::PT_NOTE)
+  continue;
+offset = ELFOFFSETOF(Phdr, p_vaddr);
+lldb::addr_t p_vaddr = data.GetAddress();
+offset = ELFOFFSETOF(Phdr, p_memsz);
+lldb::addr_t p_memsz = data.GetAddress();

labath wrote:

Similarly, you can use `ELFProgramHeader::Parse` for this bit.

https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-17 Thread Pavel Labath via lldb-commits

https://github.com/labath edited https://github.com/llvm/llvm-project/pull/92492
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-16 Thread via lldb-commits

llvmbot wrote:




@llvm/pr-subscribers-lldb

Author: None (GeorgeHuyubo)


Changes

As we have debuginfod as symbol locator available in lldb now, we want to make 
full use of it.
In case of post mortem debugging, we don't always have the main executable 
available.
However, the .note.gnu.build-id of the main executable(some other modules too), 
should be available in the core file, as those binaries are loaded in memory 
and dumped in the core file.

We try to iterate through the NT_FILE entries, read and store the gnu build id 
if possible. This will be very useful as this id is the unique key which is 
needed for querying the debuginfod server.

Test:
Build and run lldb. Breakpoint set to 
https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp#L147
Verified after this commit, module_uuid is the correct gnu build id of the main 
executable which caused the crash(first in the NT_FILE entry)

Previous PR: https://github.com/llvm/llvm-project/pull/92078 was mistakenly 
merged. This PR is re-opening the commit.

---
Full diff: https://github.com/llvm/llvm-project/pull/92492.diff


5 Files Affected:

- (modified) lldb/include/lldb/Target/Process.h (+50) 
- (modified) lldb/source/Commands/CommandObjectMemory.cpp (+2-59) 
- (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp (+89) 
- (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.h (+17) 
- (modified) lldb/source/Target/Process.cpp (+27) 


``diff
diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index aac0cf51680a9..c8a49edc5c78d 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -406,6 +406,36 @@ class Process : public 
std::enable_shared_from_this,
   lldb::StateType state);
   } Notifications;
 
+  class ProcessMemoryIterator {
+  public:
+ProcessMemoryIterator(lldb::ProcessSP process_sp, lldb::addr_t base)
+: m_process_sp(process_sp), m_base_addr(base) {
+  lldbassert(process_sp.get() != nullptr);
+}
+
+bool IsValid() { return m_is_valid; }
+
+uint8_t operator[](lldb::addr_t offset) {
+  if (!IsValid())
+return 0;
+
+  uint8_t retval = 0;
+  Status error;
+  if (0 ==
+  m_process_sp->ReadMemory(m_base_addr + offset, , 1, error)) {
+m_is_valid = false;
+return 0;
+  }
+
+  return retval;
+}
+
+  private:
+lldb::ProcessSP m_process_sp;
+lldb::addr_t m_base_addr;
+bool m_is_valid = true;
+  };
+
   class ProcessEventData : public EventData {
 friend class Process;
 
@@ -1649,6 +1679,26 @@ class Process : public 
std::enable_shared_from_this,
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status );
 
+  /// Find a string within a memory region.
+  ///
+  /// This function searches for the string represented by the provided buffer
+  /// within the memory range specified by the low and high addresses. It uses
+  /// a bad character heuristic to optimize the search process.
+  ///
+  /// \param[in] low The starting address of the memory region to be searched.
+  ///
+  /// \param[in] high The ending address of the memory region to be searched.
+  ///
+  /// \param[in] buffer A pointer to the buffer containing the string to be
+  /// searched.
+  ///
+  /// \param[in] buffer_size The size of the buffer in bytes.
+  ///
+  /// \return The address where the string was found or LLDB_INVALID_ADDRESS if
+  /// not found.
+  lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
+uint8_t *buffer, size_t buffer_size);
+
   bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value,
 Status );
 
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp 
b/lldb/source/Commands/CommandObjectMemory.cpp
index b78a0492cca55..1c13484dede64 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -977,35 +977,6 @@ class CommandObjectMemoryFind : public CommandObjectParsed 
{
   Options *GetOptions() override { return _option_group; }
 
 protected:
-  class ProcessMemoryIterator {
-  public:
-ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base)
-: m_process_sp(process_sp), m_base_addr(base) {
-  lldbassert(process_sp.get() != nullptr);
-}
-
-bool IsValid() { return m_is_valid; }
-
-uint8_t operator[](lldb::addr_t offset) {
-  if (!IsValid())
-return 0;
-
-  uint8_t retval = 0;
-  Status error;
-  if (0 ==
-  m_process_sp->ReadMemory(m_base_addr + offset, , 1, error)) {
-m_is_valid = false;
-return 0;
-  }
-
-  return retval;
-}
-
-  private:
-ProcessSP m_process_sp;
-lldb::addr_t m_base_addr;
-bool m_is_valid = true;
-  };
   void DoExecute(Args , CommandReturnObject ) override {
 // No need to check "process" 

[Lldb-commits] [lldb] Read and store gnu build id from loaded core file (PR #92492)

2024-05-16 Thread via lldb-commits

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

As we have debuginfod as symbol locator available in lldb now, we want to make 
full use of it.
In case of post mortem debugging, we don't always have the main executable 
available.
However, the .note.gnu.build-id of the main executable(some other modules too), 
should be available in the core file, as those binaries are loaded in memory 
and dumped in the core file.

We try to iterate through the NT_FILE entries, read and store the gnu build id 
if possible. This will be very useful as this id is the unique key which is 
needed for querying the debuginfod server.

Test:
Build and run lldb. Breakpoint set to 
https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp#L147
Verified after this commit, module_uuid is the correct gnu build id of the main 
executable which caused the crash(first in the NT_FILE entry)

Previous PR: https://github.com/llvm/llvm-project/pull/92078 was mistakenly 
merged. This PR is re-opening the commit.

>From d375cfe76369413c248e59481b4f299fceba6e62 Mon Sep 17 00:00:00 2001
From: George Hu 
Date: Tue, 14 May 2024 16:18:20 -0700
Subject: [PATCH] Read and store gnu build id from loaded core file

---
 lldb/include/lldb/Target/Process.h| 50 +++
 lldb/source/Commands/CommandObjectMemory.cpp  | 61 +
 .../Process/elf-core/ProcessElfCore.cpp   | 89 +++
 .../Plugins/Process/elf-core/ProcessElfCore.h | 17 
 lldb/source/Target/Process.cpp| 27 ++
 5 files changed, 185 insertions(+), 59 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index aac0cf51680a9..c8a49edc5c78d 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -406,6 +406,36 @@ class Process : public 
std::enable_shared_from_this,
   lldb::StateType state);
   } Notifications;
 
+  class ProcessMemoryIterator {
+  public:
+ProcessMemoryIterator(lldb::ProcessSP process_sp, lldb::addr_t base)
+: m_process_sp(process_sp), m_base_addr(base) {
+  lldbassert(process_sp.get() != nullptr);
+}
+
+bool IsValid() { return m_is_valid; }
+
+uint8_t operator[](lldb::addr_t offset) {
+  if (!IsValid())
+return 0;
+
+  uint8_t retval = 0;
+  Status error;
+  if (0 ==
+  m_process_sp->ReadMemory(m_base_addr + offset, , 1, error)) {
+m_is_valid = false;
+return 0;
+  }
+
+  return retval;
+}
+
+  private:
+lldb::ProcessSP m_process_sp;
+lldb::addr_t m_base_addr;
+bool m_is_valid = true;
+  };
+
   class ProcessEventData : public EventData {
 friend class Process;
 
@@ -1649,6 +1679,26 @@ class Process : public 
std::enable_shared_from_this,
 
   lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status );
 
+  /// Find a string within a memory region.
+  ///
+  /// This function searches for the string represented by the provided buffer
+  /// within the memory range specified by the low and high addresses. It uses
+  /// a bad character heuristic to optimize the search process.
+  ///
+  /// \param[in] low The starting address of the memory region to be searched.
+  ///
+  /// \param[in] high The ending address of the memory region to be searched.
+  ///
+  /// \param[in] buffer A pointer to the buffer containing the string to be
+  /// searched.
+  ///
+  /// \param[in] buffer_size The size of the buffer in bytes.
+  ///
+  /// \return The address where the string was found or LLDB_INVALID_ADDRESS if
+  /// not found.
+  lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
+uint8_t *buffer, size_t buffer_size);
+
   bool WritePointerToMemory(lldb::addr_t vm_addr, lldb::addr_t ptr_value,
 Status );
 
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp 
b/lldb/source/Commands/CommandObjectMemory.cpp
index b78a0492cca55..1c13484dede64 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -977,35 +977,6 @@ class CommandObjectMemoryFind : public CommandObjectParsed 
{
   Options *GetOptions() override { return _option_group; }
 
 protected:
-  class ProcessMemoryIterator {
-  public:
-ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base)
-: m_process_sp(process_sp), m_base_addr(base) {
-  lldbassert(process_sp.get() != nullptr);
-}
-
-bool IsValid() { return m_is_valid; }
-
-uint8_t operator[](lldb::addr_t offset) {
-  if (!IsValid())
-return 0;
-
-  uint8_t retval = 0;
-  Status error;
-  if (0 ==
-  m_process_sp->ReadMemory(m_base_addr + offset, , 1, error)) {
-m_is_valid = false;
-return 0;
-  }
-
-  return retval;
-}
-
-  private:
-ProcessSP m_process_sp;
-