Author: Minsoo Choo
Date: 2026-02-18T15:20:38-05:00
New Revision: 4f0eb3d3af443ff54425ebafce83b87ee61ee403

URL: 
https://github.com/llvm/llvm-project/commit/4f0eb3d3af443ff54425ebafce83b87ee61ee403
DIFF: 
https://github.com/llvm/llvm-project/commit/4f0eb3d3af443ff54425ebafce83b87ee61ee403.diff

LOG: [lldb][Process/FreeBSDKernel] Fix broken debugging on aarch64 (#180222)

`struct pcb` for arm64 has changed In
https://github.com/freebsd/freebsd-src/commit/1c1f31a5e517ebb940c752c3468b03cdc687c5c7#diff-d07b4e228ca340857a90658e328d65f8dea9c5063e99197fbaaa046d97ae927c,
which broke kernel debugging on AArch64. Add support for FreeBSD 14 and
later by finding `osreldate`.

Until FreeBSD 13 (previous `struct pcb` contained information for all
registers):
```console
(lldb) register read
General Purpose Registers:
        x0 = 0x0000000000000000
        x1 = 0x0000000000000000
        x2 = 0x0000000000000000
        x3 = 0x0000000000000000
        x4 = 0x0000000000000000
        x5 = 0x0000000000000000
        x6 = 0x0000000000000000
        x7 = 0x0000000000000000
        x8 = 0x0000000000000000
        x9 = 0x0000000000000000
       x10 = 0x0000000000000000
       x11 = 0x0000000000000000
       x12 = 0x0000000000000000
       x13 = 0x0000000000000000
       x14 = 0x0000000000000000
       x15 = 0x0000000000000000
       x16 = 0x0000000000000000
       x17 = 0x0000000000000000
       x18 = 0x0000000000000000
       x19 = 0xffff000000b2e000  dumper_configs_mtx_sysuninit_sys_uninit + 16
       x20 = 0x0000000000000000
       x21 = 0xffff000000bce000  vop_spare1_desc + 24
       x22 = 0xffff000000c8a9b8  kernel`db_cmd_table
       x23 = 0xffff000000c8b000  kernel`db_lhistory + 1496
       x24 = 0x000000000000006c
       x25 = 0x0000000000000065
       x26 = 0x0000000000000068
       x27 = 0x0000000000000004
       x28 = 0xffff000000c8b4d1  kernel`db_tok_string + 1
        fp = 0xffff0002d751de60
        sp = 0xffff0002d751de60
        pc = 0xffff00000045ea78  kernel`dump_savectx + 20
2 registers were unavailable.
```

Since FreeBSD 14 (these are defined in the new `struct pcb`):
```console
(lldb) register read
General Purpose Registers:
       x19 = 0xffff000000d65000  M_PLIMIT + 48
       x20 = 0xffff000000e23000  sdta_vfs_vop_vop_inotify_add_watch_return2 + 8
       x21 = 0xffffa7ff822b98a8
       x22 = 0xffff000000e23000  sdta_vfs_vop_vop_inotify_add_watch_return2 + 8
       x23 = 0xffff000000e23000  sdta_vfs_vop_vop_inotify_add_watch_return2 + 8
       x24 = 0xffff000000e23000  sdta_vfs_vop_vop_inotify_add_watch_return2 + 8
       x25 = 0xffff000000dc4000  _mod_metadata_md_its_fdt_gic_on_kernel + 16
       x26 = 0x0000000000000000
       x27 = 0x00004b4ad79674cc
       x28 = 0x0000000000000004
        fp = 0xffff00028f6f8380
        lr = 0xffff000000519e98  kernel`doadump + 60 at kern_shutdown.c:399:2
        sp = 0xffff00028f6f8380
        pc = 0x0000000081144c80
20 registers were unavailable.
```

---------

Signed-off-by: Minsoo Choo <[email protected]>

Added: 
    

Modified: 
    
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
    
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h

Removed: 
    


################################################################################
diff  --git 
a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
 
b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
index e7c5febec8cdc..752cf6c5c035a 100644
--- 
a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
+++ 
b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
@@ -9,8 +9,12 @@
 #include "RegisterContextFreeBSDKernel_arm64.h"
 #include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
 
+#include "lldb/Symbol/Symbol.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
 #include "lldb/Utility/RegisterValue.h"
 #include "llvm/Support/Endian.h"
 
@@ -43,64 +47,120 @@ bool RegisterContextFreeBSDKernel_arm64::ReadRegister(
     return false;
 
   // https://cgit.freebsd.org/src/tree/sys/arm64/include/pcb.h
+  struct {
+    llvm::support::ulittle64_t x[12];
+    llvm::support::ulittle64_t sp;
+  } pcb;
+
+  // https://cgit.freebsd.org/src/tree/sys/arm64/include/pcb.h?h=stable%2F13
   struct {
     llvm::support::ulittle64_t x[30];
     llvm::support::ulittle64_t lr;
     llvm::support::ulittle64_t _reserved;
     llvm::support::ulittle64_t sp;
-  } pcb;
+  } pcb13;
 
   Status error;
-  size_t rd =
-      m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
-  if (rd != sizeof(pcb))
-    return false;
+  constexpr int FBSD14 = 1400084;
+  int osreldate = FBSD14;
 
-  uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
-  switch (reg) {
-  case gpr_x0_arm64:
-  case gpr_x1_arm64:
-  case gpr_x2_arm64:
-  case gpr_x3_arm64:
-  case gpr_x4_arm64:
-  case gpr_x5_arm64:
-  case gpr_x6_arm64:
-  case gpr_x7_arm64:
-  case gpr_x8_arm64:
-  case gpr_x9_arm64:
-  case gpr_x10_arm64:
-  case gpr_x11_arm64:
-  case gpr_x12_arm64:
-  case gpr_x13_arm64:
-  case gpr_x14_arm64:
-  case gpr_x15_arm64:
-  case gpr_x16_arm64:
-  case gpr_x17_arm64:
-  case gpr_x18_arm64:
-  case gpr_x19_arm64:
-  case gpr_x20_arm64:
-  case gpr_x21_arm64:
-  case gpr_x22_arm64:
-  case gpr_x23_arm64:
-  case gpr_x24_arm64:
-  case gpr_x25_arm64:
-  case gpr_x26_arm64:
-  case gpr_x27_arm64:
-  case gpr_x28_arm64:
-  case gpr_fp_arm64:
-    static_assert(gpr_fp_arm64 - gpr_x0_arm64 == 29,
-                  "nonconsecutive arm64 register numbers");
-    value = pcb.x[reg - gpr_x0_arm64];
-    break;
-  case gpr_sp_arm64:
-    value = pcb.sp;
-    break;
-  case gpr_pc_arm64:
-    // The pc of crashing thread is stored in lr.
-    value = pcb.lr;
-    break;
-  default:
-    return false;
+  if (auto osreldate_or_null = GetOsreldate())
+    osreldate = *osreldate_or_null;
+  else
+    LLDB_LOGF(GetLog(LLDBLog::Object),
+              "Cannot find osreldate. Defaulting to %d.", FBSD14);
+
+  // TODO: LLVM 24: Remove FreeBSD 13 support
+  if (osreldate >= FBSD14) {
+    constexpr uint32_t PCB_FP = 10;
+    constexpr uint32_t PCB_LR = 11;
+    size_t rd =
+        m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), 
error);
+    if (rd != sizeof(pcb))
+      return false;
+
+    uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    switch (reg) {
+    case gpr_x19_arm64:
+    case gpr_x20_arm64:
+    case gpr_x21_arm64:
+    case gpr_x22_arm64:
+    case gpr_x23_arm64:
+    case gpr_x24_arm64:
+    case gpr_x25_arm64:
+    case gpr_x26_arm64:
+    case gpr_x27_arm64:
+    case gpr_x28_arm64:
+    case gpr_fp_arm64:
+      static_assert(gpr_fp_arm64 - gpr_x19_arm64 == PCB_FP,
+                    "nonconsecutive arm64 register numbers");
+      value = pcb.x[reg - gpr_x19_arm64];
+      break;
+    case gpr_lr_arm64:
+    case gpr_pc_arm64:
+      // The pc of crashing thread is stored in lr.
+      static_assert(gpr_lr_arm64 - gpr_x19_arm64 == PCB_LR,
+                    "nonconsecutive arm64 register numbers");
+      value = pcb.x[reg - gpr_x19_arm64];
+      break;
+    case gpr_sp_arm64:
+      value = pcb.sp;
+      break;
+    default:
+      return false;
+    }
+  } else {
+    size_t rd = m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb13,
+                                                  sizeof(pcb13), error);
+    if (rd != sizeof(pcb13))
+      return false;
+
+    uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    switch (reg) {
+    case gpr_x0_arm64:
+    case gpr_x1_arm64:
+    case gpr_x2_arm64:
+    case gpr_x3_arm64:
+    case gpr_x4_arm64:
+    case gpr_x5_arm64:
+    case gpr_x6_arm64:
+    case gpr_x7_arm64:
+    case gpr_x8_arm64:
+    case gpr_x9_arm64:
+    case gpr_x10_arm64:
+    case gpr_x11_arm64:
+    case gpr_x12_arm64:
+    case gpr_x13_arm64:
+    case gpr_x14_arm64:
+    case gpr_x15_arm64:
+    case gpr_x16_arm64:
+    case gpr_x17_arm64:
+    case gpr_x18_arm64:
+    case gpr_x19_arm64:
+    case gpr_x20_arm64:
+    case gpr_x21_arm64:
+    case gpr_x22_arm64:
+    case gpr_x23_arm64:
+    case gpr_x24_arm64:
+    case gpr_x25_arm64:
+    case gpr_x26_arm64:
+    case gpr_x27_arm64:
+    case gpr_x28_arm64:
+    case gpr_fp_arm64:
+      static_assert(gpr_fp_arm64 - gpr_x0_arm64 == 29,
+                    "nonconsecutive arm64 register numbers");
+      value = pcb13.x[reg - gpr_x0_arm64];
+      break;
+    case gpr_sp_arm64:
+      value = pcb13.sp;
+      break;
+    case gpr_pc_arm64:
+      // The pc of crashing thread is stored in lr.
+      value = pcb13.lr;
+      break;
+    default:
+      return false;
+    }
   }
   return true;
 }
@@ -109,3 +169,35 @@ bool RegisterContextFreeBSDKernel_arm64::WriteRegister(
     const RegisterInfo *reg_info, const RegisterValue &value) {
   return false;
 }
+
+std::optional<int> RegisterContextFreeBSDKernel_arm64::GetOsreldate() {
+  ProcessSP process_sp = m_thread.GetProcess();
+  if (!process_sp)
+    return std::nullopt;
+
+  Target &target = process_sp->GetTarget();
+
+  SymbolContextList sc_list;
+  target.GetImages().FindSymbolsWithNameAndType(ConstString("osreldate"),
+                                                lldb::eSymbolTypeData, 
sc_list);
+  if (sc_list.GetSize() == 0)
+    return std::nullopt;
+
+  SymbolContext sc;
+  sc_list.GetContextAtIndex(0, sc);
+  if (!sc.symbol)
+    return std::nullopt;
+
+  lldb::addr_t addr = sc.symbol->GetLoadAddress(&target);
+  if (addr == LLDB_INVALID_ADDRESS)
+    return std::nullopt;
+
+  Status error;
+  int osreldate = 0;
+  size_t bytes_read =
+      process_sp->ReadMemory(addr, &osreldate, sizeof(osreldate), error);
+  if (bytes_read == sizeof(osreldate) && error.Success())
+    return osreldate;
+
+  return std::nullopt;
+}

diff  --git 
a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
 
b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
index 155dda6e748f5..8d2a9c33639e3 100644
--- 
a/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
+++ 
b/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
@@ -12,6 +12,8 @@
 #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
 #include "Plugins/Process/elf-core/RegisterUtilities.h"
 
+#include <optional>
+
 class RegisterContextFreeBSDKernel_arm64 : public RegisterContextPOSIX_arm64 {
 public:
   RegisterContextFreeBSDKernel_arm64(
@@ -36,6 +38,8 @@ class RegisterContextFreeBSDKernel_arm64 : public 
RegisterContextPOSIX_arm64 {
 
 private:
   lldb::addr_t m_pcb_addr;
+
+  std::optional<int> GetOsreldate();
 };
 
 #endif // 
LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to