[Lldb-commits] [lldb] 2590e4e - [lldb][FreeBSDKernel] Find .debug files using pseudo sysroot (#224845)

via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 2 17:46:28 PDT 2026


Author: Minsoo Choo
Date: 2026-10-02T20:46:17-04:00
New Revision: 2590e4e2d10606000821336f3a163a0ac6b4d77d

URL: https://github.com/llvm/llvm-project/commit/2590e4e2d10606000821336f3a163a0ac6b4d77d
DIFF: https://github.com/llvm/llvm-project/commit/2590e4e2d10606000821336f3a163a0ac6b4d77d.diff

LOG: [lldb][FreeBSDKernel] Find .debug files using pseudo sysroot (#224845)

Unlike userspace processes, it is common to obtain kernel dump from a
machine (e.g. QEMU) which different from the machine debugging the dump.
In this case users need to run `target symbols add foo.debug` for the
kernel and each kernel object, which becomes quite inconvenient when the
machine had dozens of kernel modules loaded during the dump.

This patch adds functionality to the dynamic loader so that it loads
symbol files automatically when kernel or kenrel modules are loaded. It
assumes a pseudo sysroot. When kernel is located at
`/foo/boot/kernel/kernel`, it will look for
`foo/usr/lib/debug/boot/kernel/kernel.debug` and same for kernel
modules. In this case, the only thing users need to do is copying the
dumped machine's `/usr/lib/debug/boot` relative to `/boot` that is being
debugged.

Assisted-by: GPT

Added: 
    

Modified: 
    lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
    lldb/source/Plugins/Process/FreeBSD-Kernel-Core/CMakeLists.txt
    lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
index 26ebc5535ce3c..eb08683f4f1e6 100644
--- a/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.cpp
@@ -13,6 +13,7 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Host/StreamFile.h"
 #include "lldb/Interpreter/OptionValueProperties.h"
 #include "lldb/Symbol/ObjectFile.h"
@@ -112,6 +113,35 @@ static bool is_kmod(Module *module) {
   }
 }
 
+static bool set_debug_file(const ModuleSP &module,
+                           llvm::StringRef target_path) {
+  if (!module || module->GetSymbolFileFileSpec())
+    return false;
+
+  FileSpec local_file = module->GetFileSpec();
+
+  FileSpec target_file(target_path);
+  if (!target_file.IsAbsolute())
+    return false;
+
+  std::string local_path = local_file.GetPath();
+  std::string normalized_target_path = target_file.GetPath();
+  llvm::StringRef local_sysroot(local_path);
+  if (!local_sysroot.consume_back(normalized_target_path))
+    return false;
+
+  std::string debug_path = local_sysroot.str();
+  debug_path += "/usr/lib/debug";
+  debug_path += normalized_target_path;
+  debug_path += ".debug";
+  FileSpec debug_file(debug_path);
+  if (!FileSystem::Instance().Exists(debug_file))
+    return false;
+
+  module->SetSymbolFileFileSpec(debug_file);
+  return true;
+}
+
 static bool is_reloc(Module *module) {
   if (!module)
     return false;
@@ -442,6 +472,9 @@ bool DynamicLoaderFreeBSDKernel::KModImageInfo::LoadImageUsingMemoryModule(
       }
     }
 
+    if (m_module_sp && !IsKernel())
+      set_debug_file(m_module_sp, GetPath());
+
     if (m_module_sp) {
       // If the file is not kernel or kmod, the target should be loaded once and
       // don't reload again

diff  --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/CMakeLists.txt b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/CMakeLists.txt
index 3d0509953b6c6..b9487abe105e0 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/CMakeLists.txt
@@ -25,7 +25,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
       Support
     LINK_LIBS
       lldbCore
+      lldbHost
       lldbTarget
+      lldbPluginObjectFileELF
       kvm
     )
 

diff  --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index e99f97f2b0cd6..96594d1ce70b2 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -6,8 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <optional>
+
 #include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Host/FileSystem.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandObjectMultiword.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
@@ -21,6 +25,7 @@
 #include "llvm/Support/SaveAndRestore.h"
 
 #include "Plugins/DynamicLoader/FreeBSD-Kernel/DynamicLoaderFreeBSDKernel.h"
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "ProcessFreeBSDKernelCore.h"
 #include "ThreadFreeBSDKernelCore.h"
 
@@ -65,6 +70,58 @@ static PluginProperties &GetGlobalPluginProperties() {
   return g_settings;
 }
 
+static bool SetKernelDebugFile(const ModuleSP &module) {
+  if (!module)
+    return false;
+
+  FileSpec object_file = module->GetFileSpec();
+  FileSystem::Instance().Resolve(object_file);
+
+  FileSpec symbol_file = module->GetSymbolFileFileSpec();
+  if (symbol_file)
+    FileSystem::Instance().Resolve(symbol_file);
+  if (symbol_file && symbol_file != object_file)
+    return false;
+
+  auto *elf = llvm::dyn_cast_or_null<ObjectFileELF>(module->GetObjectFile());
+  if (!elf)
+    return false;
+
+  // GetDebugLink() returns information collected while parsing section
+  // headers, which might not have happened when a PT_NOTE supplied the UUID.
+  (void)elf->GetSectionList();
+  std::optional<FileSpec> debug_link = elf->GetDebugLink();
+  if (!debug_link || debug_link->GetFilename().empty())
+    return false;
+
+  // The kernel's linker_files list may require symbols from kernel.debug to
+  // locate.  Infer an extracted filesystem's root from the local kernel path
+  // and load its FreeBSD-installed debug file before the dynamic loader runs.
+  std::string object_path = object_file.GetPath();
+  FileSpec sysroot = object_file;
+  while (sysroot.RemoveLastPathComponent()) {
+    std::string sysroot_path = sysroot.GetPath();
+    llvm::StringRef relative_path(object_path);
+    if (!relative_path.consume_front(sysroot_path))
+      continue;
+    relative_path = relative_path.ltrim("/\\");
+
+    FileSpec relative_file(relative_path);
+    FileSpec debug_file = sysroot;
+    debug_file.AppendPathComponent("usr/lib/debug");
+    if (!relative_file.GetDirectory().empty())
+      debug_file.AppendPathComponent(relative_file.GetDirectory());
+    debug_file.AppendPathComponent(debug_link->GetFilename());
+    if (!FileSystem::Instance().Exists(debug_file))
+      continue;
+
+    module->SetSymbolFileFileSpec(debug_file);
+    return true;
+  }
+
+  return false;
+}
+
 class CommandObjectProcessFreeBSDKernelCoreRefreshThreads
     : public CommandObjectParsed {
 public:
@@ -194,6 +251,8 @@ Status ProcessFreeBSDKernelCore::DoLoadCore() {
     return Status::FromErrorString(
         "ProcessFreeBSDKernelCore: no executable module set on target");
 
+  bool symbols_changed = SetKernelDebugFile(executable);
+
   char errbuf[_POSIX2_LINE_MAX];
   const int flags =
       GetGlobalPluginProperties().GetReadOnly() ? O_RDONLY : O_RDWR;
@@ -210,6 +269,12 @@ Status ProcessFreeBSDKernelCore::DoLoadCore() {
 
   SetKernelDisplacement();
 
+  if (symbols_changed) {
+    ModuleList modules;
+    modules.Append(executable);
+    GetTarget().SymbolsDidLoad(modules);
+  }
+
   return Status();
 }
 


        


More information about the lldb-commits mailing list