-
Notifications
You must be signed in to change notification settings - Fork 16.8k
[lldb][Process/FreeBSDKernel] Fix broken debugging on aarch64 #180222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cdb644c
11882f4
1798331
4e0d1c9
ad34bcf
b242e6a
cfe96c0
a5ab620
d25eb3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does the wrong thing for gpr_pc_arm64, it's one past the end, so reads sp. Presumably this is meant to be always
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created fix for this at #183947 |
||
| 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; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.