-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[lldb][AArch64] Fix arm64 hardware breakpoint/watchpoint to arm32 process. #147198
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
base: main
Are you sure you want to change the base?
Conversation
…cess. This bug skips the test because the wrong ptrace call to detect avaliable hardware/breakpoint number that resuls in 0. After tracing linux's compat_ptrace in arch/arm64/kernel/ptrace.c, found that arm64 lldb-server should just keep using the ptrace commands for 64bit tracees. See: torvalds/linux@5d220ff So the solution is copying the implementation in NativeRegisterContextLinux_arm64.cpp.
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-lldb Author: None (b10902118) ChangesThis bug skips the test because the wrong ptrace call to detect avaliable hardware/breakpoint number that resuls in 0. After tracing linux's compat_ptrace in arch/arm64/kernel/ptrace.c, found that arm64 lldb-server should just keep using the ptrace commands for 64bit tracees. See: torvalds/linux@5d220ff So the solution is copying the implementation in NativeRegisterContextLinux_arm64.cpp. Full diff: https://github.com/llvm/llvm-project/pull/147198.diff 2 Files Affected:
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index dc7fb103e87c0..9123a577008bd 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -23,13 +23,18 @@
#include <elf.h>
#include <sys/uio.h>
+#if defined(__arm64__) || defined(__aarch64__)
+#include "lldb/Host/linux/Ptrace.h"
+#include <asm/ptrace.h>
+#endif
+
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr))
#ifndef PTRACE_GETVFPREGS
#define PTRACE_GETVFPREGS 27
#define PTRACE_SETVFPREGS 28
#endif
-#ifndef PTRACE_GETHBPREGS
+#if defined(__arm__) && !defined(PTRACE_GETHBPREGS)
#define PTRACE_GETHBPREGS 29
#define PTRACE_SETHBPREGS 30
#endif
@@ -723,6 +728,7 @@ Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
return Status();
}
+#ifdef __arm__
unsigned int cap_val;
error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(),
@@ -737,12 +743,43 @@ Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
m_refresh_hwdebug_info = false;
return error;
+#else // __aarch64__
+ ::pid_t tid = m_thread.GetID();
+
+ int regset = NT_ARM_HW_WATCH;
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof(dreg_state);
+
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set,
+ &ioVec, ioVec.iov_len);
+
+ if (error.Fail())
+ return error;
+
+ m_max_hwp_supported = dreg_state.dbg_info & 0xff;
+
+ regset = NT_ARM_HW_BREAK;
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set,
+ &ioVec, ioVec.iov_len);
+
+ if (error.Fail())
+ return error;
+
+ m_max_hbp_supported = dreg_state.dbg_info & 0xff;
+ m_refresh_hwdebug_info = false;
+
+ return error;
+#endif // __arm__
}
-Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
+Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(DREGType hwbType,
int hwb_index) {
Status error;
+#ifdef __arm__
lldb::addr_t *addr_buf;
uint32_t *ctrl_buf;
@@ -781,6 +818,40 @@ Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
}
return error;
+#else // __aarch64__
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ int regset;
+
+ memset(&dreg_state, 0, sizeof(dreg_state));
+ ioVec.iov_base = &dreg_state;
+
+ switch (hwbType) {
+ case eDREGTypeWATCH:
+ regset = NT_ARM_HW_WATCH;
+ ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
+ (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
+
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
+ }
+ break;
+ case eDREGTypeBREAK:
+ regset = NT_ARM_HW_BREAK;
+ ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
+ (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control;
+ }
+ break;
+ }
+
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+ ®set, &ioVec, ioVec.iov_len);
+#endif // __arm__
}
uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset(
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 15b46609c286b..6d0ad38d7eb75 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -125,7 +125,7 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux {
Status ReadHardwareDebugInfo();
- Status WriteHardwareDebugRegs(int hwbType, int hwb_index);
+ Status WriteHardwareDebugRegs(DREGType hwbType, int hwb_index);
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
|
Your analysis is correct -- the kernel uses the bitwidth of the tracer (not the tracee) when deciding whether to use the compatibility interface. However, copying the code sounds like a fairly fragile solution. It'd be better to figure out a way to share the code somehow. The x86 classes don't have this problem because NativeRegisterContextLinux_x86_64 knows how to debug both 32 and 64-bit processes. That may not be the right solution here, but it's one thing you can use for inspiration. |
This bug skips the test because the wrong ptrace call to detect avaliable hardware/breakpoint number that resuls in 0.
After tracing linux's compat_ptrace in arch/arm64/kernel/ptrace.c, found that arm64 lldb-server should just keep using the ptrace commands for 64bit tracees. See: torvalds/linux@5d220ff
So the solution is copying the implementation in NativeRegisterContextLinux_arm64.cpp.