[Lldb-commits] [lldb] [LLDB] Add FreeBSD kernel coredump matching check. (PR #80785)

via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 6 06:39:31 PST 2024


https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/80785

>From 5f9eac19a45cd4b71afe48643fc0cf8b4b4ab6be Mon Sep 17 00:00:00 2001
From: aokblast <aokblast at FreeBSD.org>
Date: Tue, 6 Feb 2024 10:18:34 +0800
Subject: [PATCH 1/2] [LLDB] Fetch UUID from note section in coredump

---
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 29 +++++++++++++++++++
 .../Plugins/ObjectFile/ELF/ObjectFileELF.h    |  3 ++
 2 files changed, 32 insertions(+)

diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 0d95a1c12bde3..3b047e3d5c759 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -795,6 +795,32 @@ bool ObjectFileELF::ParseHeader() {
   return m_header.Parse(m_data, &offset);
 }
 
+UUID ObjectFileELF::GetUUIDByNoteSection() {
+  if (!ParseProgramHeaders())
+    return UUID();
+  for (const ELFProgramHeader &H : m_program_headers) {
+    if (H.p_type == llvm::ELF::PT_NOTE) {
+      const elf_off ph_offset = H.p_offset;
+      const size_t ph_size = H.p_filesz;
+
+      DataExtractor segment_data;
+      if (segment_data.SetData(m_data, ph_offset, ph_size) != ph_size) {
+        // The ELF program header contained incorrect data, probably corefile
+        // is incomplete or corrupted.
+        break;
+      }
+
+      UUID uuid;
+      ArchSpec arch;
+
+      if (RefineModuleDetailsFromNote(segment_data, arch, uuid).Success())
+        return uuid;
+    }
+  }
+
+  return UUID();
+}
+
 UUID ObjectFileELF::GetUUID() {
   // Need to parse the section list to get the UUIDs, so make sure that's been
   // done.
@@ -809,6 +835,9 @@ UUID ObjectFileELF::GetUUID() {
       if (!ParseProgramHeaders())
         return UUID();
 
+      if ((m_uuid = GetUUIDByNoteSection()).IsValid())
+        return m_uuid;
+
       core_notes_crc =
           CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
 
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index bc8e34981a9d8..6954bd96b753a 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -272,6 +272,9 @@ class ObjectFileELF : public lldb_private::ObjectFile {
                                      uint32_t &gnu_debuglink_crc,
                                      lldb_private::ArchSpec &arch_spec);
 
+  // Use Note Section to get uuid.
+  lldb_private::UUID GetUUIDByNoteSection();
+
   /// Scans the dynamic section and locates all dependent modules (shared
   /// libraries) populating m_filespec_up.  This method will compute the
   /// dependent module list only once.  Returns the number of dependent

>From 9df99033e10650d2afc68d5438f658bfbcdc0a29 Mon Sep 17 00:00:00 2001
From: aokblast <aokblast at FreeBSD.org>
Date: Tue, 6 Feb 2024 22:38:57 +0800
Subject: [PATCH 2/2] Add match check between binary and coredump of FreeBSD
 kernel

---
 .../DynamicLoaderFreeBSDKernel.cpp            | 41 +++++++++++++++----
 .../DynamicLoaderFreeBSDKernel.h              |  3 +-
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
index e504e6cbf6921..c134f1d46c275 100644
--- a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
@@ -153,9 +153,10 @@ addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress(
 }
 
 // Read ELF header from memry and return
+template <typename Elf_Ehdr>
 bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process,
                                                lldb::addr_t addr,
-                                               llvm::ELF::Elf32_Ehdr &header,
+                                               Elf_Ehdr &header,
                                                bool *read_error) {
   Status error;
   if (read_error)
@@ -200,8 +201,23 @@ lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
   if (header.e_type != llvm::ELF::ET_EXEC)
     return UUID();
 
-  ModuleSP memory_module_sp =
-      process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);
+  ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine));
+
+  // If the memory module is 64bit, we should use the Elf64_Ehdr or the e_shoff
+  // would be wrong
+  ModuleSP memory_module_sp;
+  if (header.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64) {
+    llvm::ELF::Elf64_Ehdr elf64_header;
+    if (!ReadELFHeader(process, addr, elf64_header)) {
+      *read_error = true;
+      return UUID();
+    }
+    memory_module_sp = process->ReadModuleFromMemory(
+        FileSpec("temp_freebsd_kernel"), addr, elf64_header.e_shoff);
+  } else {
+    memory_module_sp = process->ReadModuleFromMemory(
+        FileSpec("temp_freebsd_kernel"), addr, header.e_shoff);
+  }
 
   if (!memory_module_sp.get()) {
     *read_error = true;
@@ -218,10 +234,21 @@ lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
     return UUID();
   }
 
-  // In here, I should check is_kernel for memory_module_sp
-  // However, the ReadModuleFromMemory reads wrong section so that this check
-  // will failed
-  ArchSpec kernel_arch(llvm::ELF::convertEMachineToArchName(header.e_machine));
+  // Because the memory module is read from memory and in the memory, the type
+  // is eTypeExecutable so we have to assign the type manually
+  memory_module_sp->GetObjectFile()->SetType(ObjectFile::eTypeCoreFile);
+  UUID memory_module_uuid = memory_module_sp->GetUUID();
+
+  // FreeBSD did not always include the .note.gnu.build-id section in core
+  // dumps, only check if present.
+  if (memory_module_uuid.IsValid() &&
+      (memory_module_uuid !=
+       process->GetTarget().GetExecutableModule()->GetUUID())) {
+    LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress "
+                   ".note.gnu.build-id mismatched. Maybe you are using "
+                   "coredump with incompatible kernel binary?");
+    return UUID();
+  }
 
   if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
     process->GetTarget().SetArchitecture(kernel_arch);
diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h
index d8656e9c49dfe..bce0837aa4df4 100644
--- a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h
@@ -148,8 +148,9 @@ class DynamicLoaderFreeBSDKernel : public lldb_private::DynamicLoader {
 
   static lldb::addr_t FindKernelAtLoadAddress(lldb_private::Process *process);
 
+  template <typename Elf_Ehdr>
   static bool ReadELFHeader(lldb_private::Process *process,
-                            lldb::addr_t address, llvm::ELF::Elf32_Ehdr &header,
+                            lldb::addr_t address, Elf_Ehdr &header,
                             bool *read_error = nullptr);
 
   lldb_private::Process *m_process;



More information about the lldb-commits mailing list