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
