[Lldb-commits] [lldb] 4f0eb3d - [lldb][Process/FreeBSDKernel] Fix broken debugging on aarch64 (#180222)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Feb 18 12:20:43 PST 2026
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 <minsoochoo0122 at proton.me>
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
More information about the lldb-commits
mailing list