[Lldb-commits] [lldb] [lldb][FreeBSD] Add dynamic loader handle class for FreeBSD Kernel (PR #67106)

via lldb-commits lldb-commits at lists.llvm.org
Fri Sep 22 03:15:36 PDT 2023


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

>From f8ed3ed64be0a451542a4ec71f254dc9038b2d19 Mon Sep 17 00:00:00 2001
From: aokblast <i19670219111 at kimo.com>
Date: Fri, 22 Sep 2023 18:11:07 +0800
Subject: [PATCH 1/2] feat: add DynamicLoaderFreeBSDKernel

---
 .../Plugins/DynamicLoader/CMakeLists.txt      |   1 +
 .../FreeBSD-Kernel/CMakeLists.txt             |  13 +
 .../DynamicLoaderFreeBSDKernel.cpp            | 770 ++++++++++++++++++
 .../DynamicLoaderFreeBSDKernel.h              | 165 ++++
 .../FreeBSDKernel/ProcessFreeBSDKernel.cpp    |   4 +-
 5 files changed, 951 insertions(+), 2 deletions(-)
 create mode 100644 lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
 create mode 100644 lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h

diff --git a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
index f357fea02efbe68..30607159acdc088 100644
--- a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
+++ b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(Darwin-Kernel)
+add_subdirectory(FreeBSD-Kernel)
 add_subdirectory(MacOSX-DYLD)
 add_subdirectory(POSIX-DYLD)
 add_subdirectory(Static)
diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/CMakeLists.txt
new file mode 100644
index 000000000000000..76daf0a327cf97b
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_lldb_library(lldbPluginDynamicLoaderFreeBSDKernel PLUGIN
+  DynamicLoaderFreeBSDKernel.cpp
+
+  LINK_LIBS
+    lldbBreakpoint
+    lldbCore
+    lldbHost
+    lldbInterpreter
+    lldbSymbol
+    lldbTarget
+    lldbUtility
+    lldbPluginObjectFileELF
+  )
diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
new file mode 100644
index 000000000000000..d5eb891f0060bea
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
@@ -0,0 +1,770 @@
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/OperatingSystem.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
+
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+
+#include "DynamicLoaderFreeBSDKernel.h"
+#include <memory>
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(DynamicLoaderFreeBSDKernel)
+
+void DynamicLoaderFreeBSDKernel::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                DebuggerInit);
+}
+
+void DynamicLoaderFreeBSDKernel::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef DynamicLoaderFreeBSDKernel::GetPluginDescriptionStatic() {
+  return "The Dynamic Loader Plugin For FreeBSD Kernel";
+}
+
+static bool is_kernel(Module *module) {
+  if (!module)
+    return false;
+
+  ObjectFile *objfile = module->GetObjectFile();
+  if (!objfile)
+    return false;
+  if (objfile->GetType() != ObjectFile::eTypeExecutable)
+    return false;
+  if (objfile->GetStrata() != ObjectFile::eStrataUnknown &&
+      objfile->GetStrata() != ObjectFile::eStrataUser)
+    return false;
+
+  return true;
+}
+
+static bool is_kmod(Module *module) {
+  if (!module)
+    return false;
+  if (!module->GetObjectFile())
+    return false;
+  ObjectFile *objfile = module->GetObjectFile();
+  if (objfile->GetType() != ObjectFile::eTypeObjectFile &&
+      objfile->GetType() != ObjectFile::eTypeSharedLibrary)
+    return false;
+
+  return true;
+}
+
+static bool is_reloc(Module *module) {
+  if (!module)
+    return false;
+  if (!module->GetObjectFile())
+    return false;
+  ObjectFile *objfile = module->GetObjectFile();
+  if (objfile->GetType() != ObjectFile::eTypeObjectFile)
+    return false;
+
+  return true;
+}
+
+// Instantiate Function of the FreeBSD Kernel Dynamic Loader Plugin called when
+// Register the Plugin
+DynamicLoader *
+DynamicLoaderFreeBSDKernel::CreateInstance(lldb_private::Process *process,
+                                           bool force) {
+  // Check the environment when the plugin is not force loaded
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+  LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::CreateInstance: "
+                 "Try to create instance");
+  if (!force) {
+    Module *exec = process->GetTarget().GetExecutableModulePointer();
+    // Check if the target is kernel
+    if (exec && !is_kernel(exec)) {
+      return nullptr;
+    }
+
+    const llvm::Triple &triple_ref =
+        process->GetTarget().GetArchitecture().GetTriple();
+    if (!triple_ref.isOSFreeBSD()) {
+      return nullptr;
+    }
+  }
+
+  // At this point we have checked the target is a FreeBSD kernel and all we
+  // have to do is to find the kernel address
+  const addr_t kernel_address = FindFreeBSDKernel(process);
+
+  if (CheckForKernelImageAtAddress(process, kernel_address).IsValid())
+    return new DynamicLoaderFreeBSDKernel(process, kernel_address);
+
+  return nullptr;
+}
+
+addr_t
+DynamicLoaderFreeBSDKernel::FindFreeBSDKernel(lldb_private::Process *process) {
+  addr_t kernel_addr = process->GetImageInfoAddress();
+  if (kernel_addr == LLDB_INVALID_ADDRESS)
+    kernel_addr = FindKernelAtLoadAddress(process);
+  return kernel_addr;
+}
+
+// Get the kernel address if the kernel is not loaded with a slide
+addr_t DynamicLoaderFreeBSDKernel::FindKernelAtLoadAddress(
+    lldb_private::Process *process) {
+  Module *exe_module = process->GetTarget().GetExecutableModulePointer();
+
+  if (!is_kernel(exe_module))
+    return LLDB_INVALID_ADDRESS;
+
+  ObjectFile *exe_objfile = exe_module->GetObjectFile();
+
+  if (!exe_objfile->GetBaseAddress().IsValid())
+    return LLDB_INVALID_ADDRESS;
+
+  if (CheckForKernelImageAtAddress(
+          process, exe_objfile->GetBaseAddress().GetFileAddress())
+          .IsValid())
+    return exe_objfile->GetBaseAddress().GetFileAddress();
+
+  return LLDB_INVALID_ADDRESS;
+}
+
+// Read ELF header from memry and return
+bool DynamicLoaderFreeBSDKernel::ReadELFHeader(Process *process,
+                                               lldb::addr_t addr,
+                                               llvm::ELF::Elf32_Ehdr &header,
+                                               bool *read_error) {
+  Status error;
+  if (read_error)
+    *read_error = false;
+
+  if (process->ReadMemory(addr, &header, sizeof(header), error) !=
+      sizeof(header)) {
+    if (read_error)
+      *read_error = true;
+    return false;
+  }
+
+  if (!header.checkMagic())
+    return false;
+
+  return true;
+}
+
+// Check the correctness of Kernel and return UUID
+lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
+    Process *process, lldb::addr_t addr, bool *read_error) {
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+
+  if (addr == LLDB_INVALID_ADDRESS) {
+    if (read_error)
+      *read_error = true;
+    return UUID();
+  }
+
+  LLDB_LOGF(log,
+            "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
+            "looking for kernel binary at 0x%" PRIx64,
+            addr);
+
+  llvm::ELF::Elf32_Ehdr header;
+  if (!ReadELFHeader(process, addr, header))
+    return UUID();
+
+  // Check header type
+  if (header.e_type != llvm::ELF::ET_EXEC)
+    return UUID();
+
+  ModuleSP memory_module_sp =
+      process->ReadModuleFromMemory(FileSpec("temp_freebsd_kernel"), addr);
+  if (!memory_module_sp.get())
+    return UUID();
+
+  ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
+  if (exe_objfile == nullptr) {
+    LLDB_LOGF(log,
+              "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress "
+              "found a binary at 0x%" PRIx64
+              " but could not create an object file from memory",
+              addr);
+    return UUID();
+  }
+
+  if (is_kernel(memory_module_sp.get())) {
+    ArchSpec kernel_arch(
+        llvm::ELF::convertEMachineToArchName(header.e_machine));
+
+    if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
+      process->GetTarget().SetArchitecture(kernel_arch);
+
+    if (log) {
+      std::string uuid_str;
+      if (memory_module_sp->GetUUID().IsValid()) {
+        uuid_str = "with UUID ";
+        uuid_str += memory_module_sp->GetUUID().GetAsString();
+      } else {
+        uuid_str = "and no LC_UUID found in load commands ";
+      }
+      LLDB_LOGF(log,
+                "DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
+                "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
+                addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
+    }
+
+    return memory_module_sp->GetUUID();
+  }
+
+  return UUID();
+}
+
+void DynamicLoaderFreeBSDKernel::DebuggerInit(
+    lldb_private::Debugger &debugger) {}
+
+DynamicLoaderFreeBSDKernel::DynamicLoaderFreeBSDKernel(Process *process,
+                                                       addr_t kernel_address)
+    : DynamicLoader(process), m_process(process),
+      m_linker_file_list_struct_addr(LLDB_INVALID_ADDRESS),
+      m_linker_file_head_addr(LLDB_INVALID_ADDRESS),
+      m_kernel_load_address(kernel_address), m_mutex() {
+  process->SetCanRunCode(false);
+}
+
+DynamicLoaderFreeBSDKernel::~DynamicLoaderFreeBSDKernel() { Clear(true); }
+
+void DynamicLoaderFreeBSDKernel::Update() {
+  LoadKernelModules();
+  SetNotificationBreakPoint();
+}
+
+// Create in memory Module at the load address
+bool DynamicLoaderFreeBSDKernel::KModImageInfo::ReadMemoryModule(
+    lldb_private::Process *process) {
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+  if (m_memory_module_sp)
+    return true;
+  if (m_load_address == LLDB_INVALID_ADDRESS)
+    return false;
+
+  FileSpec file_spec(m_name.c_str());
+
+  ModuleSP memory_module_sp;
+
+  llvm::ELF::Elf32_Ehdr elf_eheader;
+  size_t size_to_read = 512;
+
+  if (ReadELFHeader(process, m_load_address, elf_eheader)) {
+    if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) {
+      size_to_read = sizeof(llvm::ELF::Elf32_Ehdr) +
+                     elf_eheader.e_phnum * elf_eheader.e_phentsize;
+    } else if (elf_eheader.e_ident[llvm::ELF::EI_CLASS] ==
+               llvm::ELF::ELFCLASS64) {
+      llvm::ELF::Elf64_Ehdr elf_eheader;
+      Status error;
+      if (process->ReadMemory(m_load_address, &elf_eheader, sizeof(elf_eheader),
+                              error) == sizeof(elf_eheader))
+        size_to_read = sizeof(llvm::ELF::Elf64_Ehdr) +
+                       elf_eheader.e_phnum * elf_eheader.e_phentsize;
+    }
+  }
+
+  memory_module_sp =
+      process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);
+
+  if (!memory_module_sp)
+    return false;
+
+  bool this_is_kernel = is_kernel(memory_module_sp.get());
+
+  if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
+    m_uuid = memory_module_sp->GetUUID();
+
+  m_memory_module_sp = memory_module_sp;
+  m_is_kernel = this_is_kernel;
+
+  // The kernel binary is from memory
+  if (this_is_kernel) {
+    if (log)
+      LLDB_LOGF(log,
+                "KextImageInfo::ReadMemoryModule read the kernel binary out "
+                "of memory");
+
+    if (memory_module_sp->GetArchitecture().IsValid())
+      process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
+  }
+
+  return true;
+}
+
+bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
+    lldb_private::Process *process) {
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+
+  if (IsLoaded())
+    return true;
+
+  Target &target = process->GetTarget();
+
+  if (IsKernel() && m_uuid.IsValid()) {
+    Stream &s = target.GetDebugger().GetOutputStream();
+    s.Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
+    s.Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
+  }
+
+  // Test if the module is loaded into the taget,
+  // maybe the module is loaded manually by user by doing target module add
+  // So that we have to create the module manually
+  if (!m_module_sp) {
+    const ModuleList &target_images = target.GetImages();
+    m_module_sp = target_images.FindModule(m_uuid);
+
+    // Search in the file system
+    if (!m_module_sp) {
+      ModuleSpec module_spec(FileSpec(GetPath()), target.GetArchitecture());
+      if (IsKernel()) {
+        Status error;
+        if (Symbols::DownloadObjectAndSymbolFile(module_spec, error, true)) {
+          if (FileSystem::Instance().Exists(module_spec.GetFileSpec()))
+            m_module_sp = std::make_shared<Module>(module_spec.GetFileSpec(),
+                                                   target.GetArchitecture());
+        }
+      }
+
+      if (!m_module_sp)
+        m_module_sp = target.GetOrCreateModule(module_spec, true);
+      if (IsKernel() && !m_module_sp) {
+        Stream &s = target.GetDebugger().GetOutputStream();
+        s.Printf("WARNING: Unable to locate kernel binary on the debugger "
+                 "system.\n");
+      }
+    }
+
+    if (m_module_sp) {
+      // If the file is not kernel or kmod, the target should be loaded once and
+      // don't reload again
+      if (!IsKernel() && !is_kmod(m_module_sp.get())) {
+        ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid);
+        if (existing_module_sp &&
+            existing_module_sp->IsLoadedInTarget(&target)) {
+          LLDB_LOGF(log,
+                    "'%s' with UUID %s is not a kmod or kernel, and is "
+                    "already registered in target, not loading.",
+                    m_name.c_str(), m_uuid.GetAsString().c_str());
+          return true;
+        }
+      }
+      m_uuid = m_module_sp->GetUUID();
+
+      // or append to the images
+      target.GetImages().AppendIfNeeded(m_module_sp, false);
+    }
+  }
+
+  // If this file is relocatable kernel module(x86_64), adjust it's
+  // section(PT_LOAD segment) and return Because the kernel module's load
+  // address is the text section. lldb cannot create full memory module upon
+  // relocatable file So what we do is to set the load address only.
+  if (is_kmod(m_module_sp.get()) && is_reloc(m_module_sp.get())) {
+    m_stop_id = process->GetStopID();
+    bool changed;
+    m_module_sp->SetLoadAddress(target, m_load_address, true, changed);
+    return true;
+  }
+
+  if (m_module_sp)
+    ReadMemoryModule(process);
+
+  // Calculate the slides of in memory module
+  if (!m_memory_module_sp || !m_module_sp) {
+    m_module_sp.reset();
+    return false;
+  }
+
+  ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
+  ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
+
+  if (!ondisk_object_file || !memory_object_file)
+    m_module_sp.reset();
+
+  // Find the slide address
+  addr_t fixed_slide = LLDB_INVALID_ADDRESS;
+  if (ObjectFileELF *memory_objfile_elf =
+          llvm::dyn_cast<ObjectFileELF>(memory_object_file)) {
+    addr_t load_address = memory_object_file->GetBaseAddress().GetFileAddress();
+
+    if (load_address != LLDB_INVALID_ADDRESS &&
+        m_load_address != load_address) {
+      fixed_slide = m_load_address - load_address;
+      LLDB_LOGF(log,
+                "kmod %s in-memory LOAD vmaddr is not correct, using a "
+                "fixed slide of 0x%" PRIx64,
+                m_name.c_str(), fixed_slide);
+    }
+  }
+
+  SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
+  SectionList *memory_section_list = memory_object_file->GetSectionList();
+
+  if (memory_section_list && ondisk_object_file) {
+    const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
+    uint32_t num_load_sections = 0;
+
+    for (uint32_t section_idx = 0; section_idx < num_ondisk_sections;
+         ++section_idx) {
+      SectionSP on_disk_section_sp =
+          ondisk_section_list->GetSectionAtIndex(section_idx);
+
+      if (!on_disk_section_sp)
+        continue;
+      if (fixed_slide != LLDB_INVALID_ADDRESS) {
+        target.SetSectionLoadAddress(on_disk_section_sp,
+                                     on_disk_section_sp->GetFileAddress() +
+                                         fixed_slide);
+
+      } else {
+        const Section *memory_section =
+            memory_section_list
+                ->FindSectionByName(on_disk_section_sp->GetName())
+                .get();
+        if (memory_section) {
+          target.SetSectionLoadAddress(on_disk_section_sp,
+                                       memory_section->GetFileAddress());
+          ++num_load_sections;
+        }
+      }
+    }
+
+    if (num_load_sections)
+      m_stop_id = process->GetStopID();
+    else
+      m_module_sp.reset();
+  } else {
+    m_module_sp.reset();
+  }
+
+  if (IsLoaded() && m_module_sp && IsKernel()) {
+    Stream &s = target.GetDebugger().GetOutputStream();
+    ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
+    if (kernel_object_file) {
+      addr_t file_address =
+          kernel_object_file->GetBaseAddress().GetFileAddress();
+      if (m_load_address != LLDB_INVALID_ADDRESS &&
+          file_address != LLDB_INVALID_ADDRESS) {
+        s.Printf("Kernel slide 0x%" PRIx64 " in memory.\n",
+                 m_load_address - file_address);
+        s.Printf("Loaded kernel file %s\n",
+                 m_module_sp->GetFileSpec().GetPath().c_str());
+      }
+    }
+    s.Flush();
+  }
+
+  return IsLoaded();
+}
+
+// This function is work for kernel file, others it wil reset load address and
+// return false
+bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingFileAddress(
+    lldb_private::Process *process) {
+  if (IsLoaded())
+    return true;
+
+  if (m_module_sp) {
+    bool changed = false;
+    if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed))
+      m_stop_id = process->GetStopID();
+  }
+
+  return false;
+}
+
+// Get the head of found_list
+bool DynamicLoaderFreeBSDKernel::ReadKmodsListHeader() {
+  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
+
+  if (m_linker_file_list_struct_addr.IsValid()) {
+    // Get tqh_first struct element from linker_files
+    Status error;
+    addr_t address = m_process->ReadPointerFromMemory(
+        m_linker_file_list_struct_addr.GetLoadAddress(&m_process->GetTarget()),
+        error);
+    if (address != LLDB_INVALID_ADDRESS && error.Success()) {
+      m_linker_file_head_addr = Address(address);
+    } else {
+      m_linker_file_list_struct_addr.Clear();
+      return false;
+    }
+
+    if (!m_linker_file_head_addr.IsValid() ||
+        m_linker_file_head_addr.GetFileAddress() == 0) {
+      m_linker_file_list_struct_addr.Clear();
+      return false;
+    }
+  }
+  return true;
+}
+
+// Parse Kmod info in found_list
+bool DynamicLoaderFreeBSDKernel::ParseKmods(Address linker_files_head_addr) {
+  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
+  KModImageInfo::collection_type linker_files_list;
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+
+  if (!ReadAllKmods(linker_files_head_addr, linker_files_list))
+    return false;
+  LLDB_LOGF(
+      log,
+      "Kmod-changed breakpoint hit, there are %lu kernel modules currently.\n",
+      linker_files_list.size());
+
+  ModuleList &modules = m_process->GetTarget().GetImages();
+  ModuleList remove_modules;
+  ModuleList add_modules;
+
+  for (ModuleSP module : modules.Modules()) {
+    if (is_kernel(module.get()))
+      continue;
+    if (is_kmod(module.get()))
+      remove_modules.AppendIfNeeded(module);
+  }
+
+  m_process->GetTarget().ModulesDidUnload(remove_modules, false);
+
+  for (KModImageInfo &image_info : linker_files_list) {
+    if (m_kld_name_to_uuid.find(image_info.GetName()) !=
+        m_kld_name_to_uuid.end())
+      image_info.SetUUID(m_kld_name_to_uuid[image_info.GetName()]);
+    bool failed_to_load = false;
+    if (!image_info.LoadImageUsingMemoryModule(m_process)) {
+      image_info.LoadImageUsingFileAddress(m_process);
+      failed_to_load = true;
+    } else {
+      m_linker_files_list.push_back(image_info);
+      m_kld_name_to_uuid[image_info.GetName()] = image_info.GetUUID();
+    }
+
+    if (!failed_to_load)
+      add_modules.AppendIfNeeded(image_info.GetModule());
+  }
+  m_process->GetTarget().ModulesDidLoad(add_modules);
+  return true;
+}
+
+// Read all kmod from a given arrays of list
+bool DynamicLoaderFreeBSDKernel::ReadAllKmods(
+    Address linker_files_head_addr,
+    KModImageInfo::collection_type &kmods_list) {
+
+  // Get offset of next member and load address symbol
+  static ConstString kld_off_address_symbol_name("kld_off_address");
+  static ConstString kld_off_next_symbol_name("kld_off_next");
+  static ConstString kld_off_filename_symbol_name("kld_off_filename");
+  static ConstString kld_off_pathname_symbol_name("kld_off_pathname");
+  const Symbol *kld_off_address_symbol =
+      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
+          kld_off_address_symbol_name, eSymbolTypeData);
+  const Symbol *kld_off_next_symbol =
+      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
+          kld_off_next_symbol_name, eSymbolTypeData);
+  const Symbol *kld_off_filename_symbol =
+      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
+          kld_off_filename_symbol_name, eSymbolTypeData);
+  const Symbol *kld_off_pathname_symbol =
+      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
+          kld_off_pathname_symbol_name, eSymbolTypeData);
+
+  if (!kld_off_address_symbol || !kld_off_next_symbol ||
+      !kld_off_filename_symbol || !kld_off_pathname_symbol)
+    return false;
+  Status error;
+  const int32_t kld_off_address = m_process->ReadSignedIntegerFromMemory(
+      kld_off_address_symbol->GetAddress().GetLoadAddress(
+          &m_process->GetTarget()),
+      4, 0, error);
+  if (error.Fail())
+    return false;
+  const int32_t kld_off_next = m_process->ReadSignedIntegerFromMemory(
+      kld_off_next_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget()),
+      4, 0, error);
+  if (error.Fail())
+    return false;
+  const int32_t kld_off_filename = m_process->ReadSignedIntegerFromMemory(
+      kld_off_filename_symbol->GetAddress().GetLoadAddress(
+          &m_process->GetTarget()),
+      4, 0, error);
+  if (error.Fail())
+    return false;
+
+  const int32_t kld_off_pathname = m_process->ReadSignedIntegerFromMemory(
+      kld_off_pathname_symbol->GetAddress().GetLoadAddress(
+          &m_process->GetTarget()),
+      4, 0, error);
+  if (error.Fail())
+    return false;
+
+  // Parse KMods
+  addr_t kld_load_addr(LLDB_INVALID_ADDRESS);
+  char kld_filename[255];
+  char kld_pathname[255];
+  addr_t current_kld =
+      linker_files_head_addr.GetLoadAddress(&m_process->GetTarget());
+
+  while (current_kld != 0) {
+    m_process->ReadCStringFromMemory(
+        m_process->ReadPointerFromMemory(current_kld + kld_off_filename, error),
+        kld_filename, sizeof(kld_filename), error);
+    m_process->ReadCStringFromMemory(
+        m_process->ReadPointerFromMemory(current_kld + kld_off_pathname, error),
+        kld_pathname, sizeof(kld_pathname), error);
+    kld_load_addr =
+        m_process->ReadPointerFromMemory(current_kld + kld_off_address, error);
+
+    kmods_list.emplace_back();
+    KModImageInfo &kmod_info = kmods_list.back();
+    kmod_info.SetName(kld_filename);
+    kmod_info.SetLoadAddress(kld_load_addr);
+    kmod_info.SetPath(kld_pathname);
+    current_kld =
+        m_process->ReadPointerFromMemory(current_kld + kld_off_next, error);
+    if (kmod_info.GetName() == "kernel")
+      kmods_list.pop_back();
+    if (error.Fail())
+      return false;
+  }
+
+  return true;
+}
+
+// Read all kmods
+bool DynamicLoaderFreeBSDKernel::ReadAllKmods() {
+  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
+
+  if (ReadKmodsListHeader()) {
+
+    if (m_linker_file_head_addr.IsValid()) {
+      if (!ParseKmods(m_linker_file_head_addr))
+        m_linker_files_list.clear();
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Load all Kernel Modules
+void DynamicLoaderFreeBSDKernel::LoadKernelModules() {
+  Log *log = GetLog(LLDBLog::DynamicLoader);
+  LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
+                 "Start loading Kernel Module");
+
+  // Initialize Kernel Image Information at the first time
+  if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
+    ModuleSP module_sp = m_process->GetTarget().GetExecutableModule();
+    if (is_kernel(module_sp.get())) {
+      m_kernel_image_info.SetModule(module_sp);
+      m_kernel_image_info.SetIsKernel(true);
+    }
+
+    // Set name for kernel
+    ConstString kernel_name("freebsd_kernel");
+    module_sp = m_kernel_image_info.GetModule();
+    if (module_sp.get() && module_sp->GetObjectFile() &&
+        !module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
+      kernel_name = module_sp->GetObjectFile()->GetFileSpec().GetFilename();
+    m_kernel_image_info.SetName(kernel_name.AsCString());
+
+    if (m_kernel_image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS) {
+      m_kernel_image_info.SetLoadAddress(m_kernel_load_address);
+    }
+
+    // Build In memory Module
+    if (m_kernel_image_info.GetLoadAddress() != LLDB_INVALID_ADDRESS) {
+      // If the kernel is not loaded in the memory, use file to load
+      if (!m_kernel_image_info.LoadImageUsingMemoryModule(m_process))
+        m_kernel_image_info.LoadImageUsingFileAddress(m_process);
+    }
+  }
+
+  LoadOperatingSystemPlugin(false);
+
+  if (!m_kernel_image_info.IsLoaded() || !m_kernel_image_info.GetModule()) {
+    m_kernel_image_info.Clear();
+    return;
+  }
+
+  static ConstString modlist_symbol_name("linker_files");
+
+  const Symbol *symbol =
+      m_kernel_image_info.GetModule()->FindFirstSymbolWithNameAndType(
+          modlist_symbol_name, lldb::eSymbolTypeData);
+
+  if (symbol) {
+    m_linker_file_list_struct_addr = symbol->GetAddress();
+    ReadAllKmods();
+  } else {
+    LLDB_LOGF(log, "DynamicLoaderFreeBSDKernel::LoadKernelModules "
+                   "cannot file modlist symbol");
+  }
+}
+
+// Update symbol when use kldload by setting callback function on kldload
+void DynamicLoaderFreeBSDKernel::SetNotificationBreakPoint() {}
+
+// Hook called when attach to a process
+void DynamicLoaderFreeBSDKernel::DidAttach() {
+  PrivateInitialize(m_process);
+  Update();
+}
+
+// Hook called after attach to a process
+void DynamicLoaderFreeBSDKernel::DidLaunch() {
+  PrivateInitialize(m_process);
+  Update();
+}
+
+// Clear all member except kernel address
+void DynamicLoaderFreeBSDKernel::Clear(bool clear_process) {
+  std::lock_guard<decltype(m_mutex)> guard(m_mutex);
+  if (clear_process)
+    m_process = nullptr;
+  m_linker_file_head_addr.Clear();
+  m_linker_file_list_struct_addr.Clear();
+  m_kernel_image_info.Clear();
+  m_linker_files_list.clear();
+}
+
+// Reinitialize class
+void DynamicLoaderFreeBSDKernel::PrivateInitialize(Process *process) {
+  Clear(true);
+  m_process = process;
+}
+
+ThreadPlanSP DynamicLoaderFreeBSDKernel::GetStepThroughTrampolinePlan(
+    lldb_private::Thread &thread, bool stop_others) {
+  Log *log = GetLog(LLDBLog::Step);
+  LLDB_LOGF(log, "Could not find symbol for step through.");
+  return {};
+}
+
+Status DynamicLoaderFreeBSDKernel::CanLoadImage() {
+  Status error("shared object cannot be loaded into kernel");
+  return error;
+}
diff --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h
new file mode 100644
index 000000000000000..d8d32f91c6229bf
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h
@@ -0,0 +1,165 @@
+#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H
+#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_FREEBSD_KERNEL_DYNAMICLOADERFREEBSDKERNEL_H
+
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/UUID.h"
+#include "llvm/BinaryFormat/ELF.h"
+
+class DynamicLoaderFreeBSDKernel : public lldb_private::DynamicLoader {
+public:
+  DynamicLoaderFreeBSDKernel(lldb_private::Process *process,
+                             lldb::addr_t kernel_addr);
+
+  ~DynamicLoaderFreeBSDKernel() override;
+
+  // Static Functions
+
+  static void Initialize();
+
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() {
+    return "DynamicLoaderFreeBSDKernel";
+  }
+
+  static llvm::StringRef GetPluginDescriptionStatic();
+
+  static lldb_private::DynamicLoader *
+  CreateInstance(lldb_private::Process *process, bool force);
+
+  static void DebuggerInit(lldb_private::Debugger &debugger);
+
+  static lldb::addr_t FindFreeBSDKernel(lldb_private::Process *process);
+
+  // Hooks for time point that after attach to some proccess
+  void DidAttach() override;
+
+  void DidLaunch() override;
+
+  lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+                                                  bool stop_others) override;
+
+  lldb_private::Status CanLoadImage() override;
+
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+protected:
+  class KModImageInfo {
+  public:
+    KModImageInfo()
+        : m_module_sp(), m_memory_module_sp(), m_uuid(), m_name(), m_path() {}
+
+    void Clear() {
+      m_load_address = LLDB_INVALID_ADDRESS;
+      m_name.clear();
+      m_uuid.Clear();
+      m_module_sp.reset();
+      m_memory_module_sp.reset();
+      m_stop_id = UINT32_MAX;
+      m_path.clear();
+    }
+
+    void SetLoadAddress(lldb::addr_t load_address) {
+      m_load_address = load_address;
+    }
+
+    lldb::addr_t GetLoadAddress() const { return m_load_address; }
+
+    void SetUUID(const lldb_private::UUID uuid) { m_uuid = uuid; }
+
+    lldb_private::UUID GetUUID() const { return m_uuid; }
+
+    void SetName(const char *name) { m_name = name; }
+
+    std::string GetName() const { return m_name; }
+
+    void SetPath(const char *path) { m_path = path; }
+
+    std::string GetPath() const { return m_path; }
+
+    void SetModule(lldb::ModuleSP module) { m_module_sp = module; }
+
+    lldb::ModuleSP GetModule() { return m_module_sp; }
+
+    void SetIsKernel(bool is_kernel) { m_is_kernel = is_kernel; }
+
+    bool IsKernel() const { return m_is_kernel; };
+
+    void SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }
+
+    uint32_t GetStopID() { return m_stop_id; }
+
+    bool IsLoaded() const { return m_stop_id != UINT32_MAX; };
+
+    bool ReadMemoryModule(lldb_private::Process *process);
+
+    bool LoadImageUsingMemoryModule(lldb_private::Process *process);
+
+    bool LoadImageUsingFileAddress(lldb_private::Process *process);
+
+    using collection_type = std::vector<KModImageInfo>;
+
+  private:
+    lldb::ModuleSP m_module_sp;
+    lldb::ModuleSP m_memory_module_sp;
+    lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS;
+    lldb_private::UUID m_uuid;
+    bool m_is_kernel = false;
+    std::string m_name;
+    std::string m_path;
+    uint32_t m_stop_id = UINT32_MAX;
+  };
+
+  void PrivateInitialize(lldb_private::Process *process);
+
+  void Clear(bool clear_process);
+
+  void Update();
+
+  void LoadKernelModules();
+
+  bool ReadAllKmods();
+
+  bool ReadAllKmods(lldb_private::Address linker_files_head_address,
+                    KModImageInfo::collection_type &kmods_list);
+
+  bool ReadKmodsListHeader();
+
+  bool ParseKmods(lldb_private::Address linker_files_head_address);
+
+  void SetNotificationBreakPoint();
+
+  static lldb_private::UUID
+  CheckForKernelImageAtAddress(lldb_private::Process *process,
+                               lldb::addr_t address,
+                               bool *read_error = nullptr);
+
+  static lldb::addr_t FindKernelAtLoadAddress(lldb_private::Process *process);
+
+  static bool ReadELFHeader(lldb_private::Process *process,
+                            lldb::addr_t address, llvm::ELF::Elf32_Ehdr &header,
+                            bool *read_error = nullptr);
+
+  lldb_private::Process *m_process;
+  lldb_private::Address m_linker_file_list_struct_addr;
+  lldb_private::Address m_linker_file_head_addr;
+  lldb::addr_t m_kernel_load_address;
+  KModImageInfo m_kernel_image_info;
+  KModImageInfo::collection_type m_linker_files_list;
+  std::recursive_mutex m_mutex;
+  std::unordered_map<std::string, lldb_private::UUID> m_kld_name_to_uuid;
+
+private:
+  DynamicLoaderFreeBSDKernel(const DynamicLoaderFreeBSDKernel &) = delete;
+
+  const DynamicLoaderFreeBSDKernel &
+  operator=(const DynamicLoaderFreeBSDKernel &) = delete;
+};
+
+#endif
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
index e3707365a9c3f19..601f5df43dbba4e 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
@@ -10,7 +10,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Target/DynamicLoader.h"
 
-#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
+#include "Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h"
 #include "ProcessFreeBSDKernel.h"
 #include "ThreadFreeBSDKernel.h"
 
@@ -262,7 +262,7 @@ Status ProcessFreeBSDKernel::DoLoadCore() {
 DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() {
   if (m_dyld_up.get() == nullptr)
     m_dyld_up.reset(DynamicLoader::FindPlugin(
-        this, DynamicLoaderStatic::GetPluginNameStatic()));
+        this, DynamicLoaderFreeBSDKernel::GetPluginNameStatic()));
   return m_dyld_up.get();
 }
 

>From b252695aaa6b04db72527acb2d887dca9693653f Mon Sep 17 00:00:00 2001
From: aokblast <i19670219111 at kimo.com>
Date: Fri, 22 Sep 2023 18:14:17 +0800
Subject: [PATCH 2/2] feat: Support Relocatable file kernel module that will
 adjust section address correctly

---
 .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp  | 111 +++++++++++-------
 1 file changed, 67 insertions(+), 44 deletions(-)

diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 2da971dff895b4a..57a4e434a74f8fb 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -206,16 +206,14 @@ elf_sxword ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
     return rel.reloc.get<ELFRela *>()->r_addend;
 }
 
-elf_sxword  ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
+elf_sxword ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
   if (rel.reloc.is<ELFRel *>())
     return 0;
   else
     return rel.reloc.get<ELFRela *>()->r_addend;
 }
 
-static user_id_t SegmentID(size_t PHdrIndex) {
-  return ~user_id_t(PHdrIndex);
-}
+static user_id_t SegmentID(size_t PHdrIndex) { return ~user_id_t(PHdrIndex); }
 
 bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   // Read all fields.
@@ -248,7 +246,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
   return true;
 }
 
-static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
+static uint32_t mipsVariantFromElfFlags(const elf::ELFHeader &header) {
   const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH;
   uint32_t endian = header.e_ident[EI_DATA];
   uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
@@ -256,7 +254,8 @@ static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
 
   // If there aren't any elf flags available (e.g core elf file) then return
   // default
-  // 32 or 64 bit arch (without any architecture revision) based on object file's class.
+  // 32 or 64 bit arch (without any architecture revision) based on object
+  // file's class.
   if (header.e_type == ET_CORE) {
     switch (fileclass) {
     case llvm::ELF::ELFCLASS32:
@@ -935,6 +934,16 @@ lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
 }
 
 Address ObjectFileELF::GetBaseAddress() {
+  if (GetType() == ObjectFile::eTypeObjectFile) {
+    for (SectionHeaderCollIter I = std::next(m_section_headers.begin());
+         I != m_section_headers.end(); ++I) {
+      const ELFSectionHeaderInfo &header = *I;
+      if (header.sh_flags & SHF_ALLOC)
+        return Address(GetSectionList()->FindSectionByID(SectionIndex(I)), 0);
+    }
+    return LLDB_INVALID_ADDRESS;
+  }
+
   for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
     const ELFProgramHeader &H = EnumPHdr.value();
     if (H.p_type != PT_LOAD)
@@ -1201,7 +1210,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // Set the elf OS version to NetBSD.  Also clear the vendor.
       arch_spec.GetTriple().setOSName(
           llvm::formatv("netbsd{0}.{1}.{2}", version_major, version_minor,
-                        version_patch).str());
+                        version_patch)
+              .str());
       arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
     }
     // Process NetBSD ELF core(5) notes
@@ -1231,17 +1241,23 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
       // count     = 0x000000000000000a (10)
       // page_size = 0x0000000000001000 (4096)
       // Index start              end                file_ofs           path
-      // ===== ------------------ ------------------ ------------------ -------------------------------------
-      // [  0] 0x0000000000401000 0x0000000000000000                    /tmp/a.out
-      // [  1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
-      // [  2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
-      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
-      // [  7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
-      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
-      // [  9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
+      // ===== ------------------ ------------------ ------------------
+      // ------------------------------------- [  0] 0x0000000000401000
+      // 0x0000000000000000                    /tmp/a.out [  1]
+      // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
+      // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  4] 0x00007fa79cba8000
+      // 0x00007fa79cda7000 0x00000000000001bb
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  5] 0x00007fa79cda7000
+      // 0x00007fa79cdab000 0x00000000000001ba
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  6] 0x00007fa79cdab000
+      // 0x00007fa79cdad000 0x00000000000001be
+      // /lib/x86_64-linux-gnu/libc-2.19.so [  7] 0x00007fa79cdb2000
+      // 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
+      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
+      // /lib/x86_64-linux-gnu/ld-2.19.so [  9] 0x00007fa79cfd5000
+      // 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
       //
       // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
       // uint32_t.
@@ -1263,7 +1279,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
             return error;
           }
           llvm::StringRef path(cstr);
-          if (path.contains("/lib/x86_64-linux-gnu") || path.contains("/lib/i386-linux-gnu")) {
+          if (path.contains("/lib/x86_64-linux-gnu") ||
+              path.contains("/lib/i386-linux-gnu")) {
             arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
             break;
           }
@@ -1550,7 +1567,8 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
           DataExtractor data;
 
           if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
-              data.SetData(object_data, sheader.sh_offset, section_size) == section_size)
+              data.SetData(object_data, sheader.sh_offset, section_size) ==
+                  section_size)
             ParseARMAttributes(data, section_size, arch_spec);
         }
 
@@ -1750,7 +1768,7 @@ struct SectionAddressInfo {
 // different sections to not overlap. This class handles that logic.
 class VMAddressProvider {
   using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
-                                       llvm::IntervalMapHalfOpenInfo<addr_t>>;
+                                  llvm::IntervalMapHalfOpenInfo<addr_t>>;
 
   ObjectFile::Type ObjectType;
   addr_t NextVMAddress = 0;
@@ -1764,7 +1782,11 @@ class VMAddressProvider {
   VMRange GetVMRange(const ELFSectionHeader &H) {
     addr_t Address = H.sh_addr;
     addr_t Size = H.sh_flags & SHF_ALLOC ? H.sh_size : 0;
-    if (ObjectType == ObjectFile::Type::eTypeObjectFile && Segments.empty() && (H.sh_flags & SHF_ALLOC)) {
+
+    // When this is a debug file for relocatable file, the address is all zero
+    if ((ObjectType == ObjectFile::Type::eTypeObjectFile ||
+         (ObjectType == ObjectFile::Type::eTypeDebugInfo && H.sh_addr == 0)) &&
+        Segments.empty() && (H.sh_flags & SHF_ALLOC)) {
       NextVMAddress =
           llvm::alignTo(NextVMAddress, std::max<addr_t>(H.sh_addralign, 1));
       Address = NextVMAddress;
@@ -1837,7 +1859,7 @@ class VMAddressProvider {
                     std::move(Sect));
   }
 };
-}
+} // namespace
 
 void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
   if (m_sections_up)
@@ -2009,7 +2031,7 @@ static char FindArmAarch64MappingSymbol(const char *symbol_name) {
 
 #define STO_MIPS_ISA (3 << 6)
 #define STO_MICROMIPS (2 << 6)
-#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
 
 // private
 unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
@@ -2232,13 +2254,15 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
        * flag to check whether the symbol is microMIPS and then set the address
        * class
        * accordingly.
-      */
+       */
       if (arch.IsMIPS()) {
         if (IS_MICROMIPS(symbol.st_other))
-          m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+          m_address_class_map[symbol.st_value] =
+              AddressClass::eCodeAlternateISA;
         else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
           symbol.st_value = symbol.st_value & (~1ull);
-          m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+          m_address_class_map[symbol.st_value] =
+              AddressClass::eCodeAlternateISA;
         } else {
           if (symbol_type == eSymbolTypeCode)
             m_address_class_map[symbol.st_value] = AddressClass::eCode;
@@ -2739,8 +2763,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         case R_386_32:
           symbol = symtab->FindSymbolByID(reloc_symbol(rel));
           if (symbol) {
-            addr_t f_offset =
-                rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
+            addr_t f_offset = rel_section->GetFileOffset() +
+                              ELFRelocation::RelocOffset32(rel);
             DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
             // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
             WritableDataBuffer *data_buffer =
@@ -2757,8 +2781,8 @@ unsigned ObjectFileELF::ApplyRelocations(
             *dst = value;
           } else {
             GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
-                                    rel_section->GetName().AsCString(), i,
-                                    reloc_symbol(rel));
+                                     rel_section->GetName().AsCString(), i,
+                                     reloc_symbol(rel));
           }
           break;
         case R_386_NONE:
@@ -2774,7 +2798,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}", hdr->e_machine);
+        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}",
+                                 hdr->e_machine);
         break;
       }
     } else {
@@ -2821,7 +2846,8 @@ unsigned ObjectFileELF::ApplyRelocations(
         }
         break;
       default:
-        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}", hdr->e_machine);
+        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}",
+                                 hdr->e_machine);
         break;
       }
     }
@@ -2882,9 +2908,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
   if (!module_sp)
     return;
 
-  Progress progress(
-      llvm::formatv("Parsing symbol table for {0}",
-                    m_file.GetFilename().AsCString("<Unknown>")));
+  Progress progress(llvm::formatv("Parsing symbol table for {0}",
+                                  m_file.GetFilename().AsCString("<Unknown>")));
   ElapsedTime elapsed(module_sp->GetSymtabParseTime());
 
   // We always want to use the main object file so we (hopefully) only have one
@@ -2966,8 +2991,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
     bool is_valid_entry_point =
         entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
     addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
-    if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress(
-                                    entry_point_file_addr)) {
+    if (is_valid_entry_point &&
+        !lldb_symtab.FindSymbolContainingFileAddress(entry_point_file_addr)) {
       uint64_t symbol_id = lldb_symtab.GetNumSymbols();
       // Don't set the name for any synthetic symbols, the Symbol
       // object will generate one if needed when the name is accessed
@@ -3004,8 +3029,7 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
   }
 }
 
-void ObjectFileELF::RelocateSection(lldb_private::Section *section)
-{
+void ObjectFileELF::RelocateSection(lldb_private::Section *section) {
   static const char *debug_prefix = ".debug";
 
   // Set relocated bit so we stop getting called, regardless of whether we
@@ -3397,8 +3421,7 @@ ArchSpec ObjectFileELF::GetArchitecture() {
     ParseSectionHeaders();
   }
 
-  if (CalculateType() == eTypeCoreFile &&
-      !m_arch_spec.TripleOSWasSpecified()) {
+  if (CalculateType() == eTypeCoreFile && !m_arch_spec.TripleOSWasSpecified()) {
     // Core files don't have section headers yet they have PT_NOTE program
     // headers that might shed more light on the architecture
     for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
@@ -3480,8 +3503,8 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
 }
 
 size_t ObjectFileELF::ReadSectionData(Section *section,
-                       lldb::offset_t section_offset, void *dst,
-                       size_t dst_len) {
+                                      lldb::offset_t section_offset, void *dst,
+                                      size_t dst_len) {
   // If some other objectfile owns this data, pass this to them.
   if (section->GetObjectFile() != this)
     return section->GetObjectFile()->ReadSectionData(section, section_offset,



More information about the lldb-commits mailing list