aboutsummaryrefslogtreecommitdiff
path: root/gdbserver
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2024-07-27 10:05:20 +0200
committerTom de Vries <tdevries@suse.de>2024-07-27 10:05:20 +0200
commit8d40cbfde5988ac6d7dad2fc2796d13c9ddb210b (patch)
treeec1a5fd58c7c77b86e753867d360dc463be60523 /gdbserver
parentced7ecee432b1406d198b50f1d9980451d25012a (diff)
downloadbinutils-8d40cbfde5988ac6d7dad2fc2796d13c9ddb210b.zip
binutils-8d40cbfde5988ac6d7dad2fc2796d13c9ddb210b.tar.gz
binutils-8d40cbfde5988ac6d7dad2fc2796d13c9ddb210b.tar.bz2
[gdb/tdep] Fix arm thumb2 hw breakpoint
On an aarch64-linux system with 32-bit userland running in a chroot, and using target board unix/mthumb I get: ... (gdb) hbreak hbreak.c:27^M Hardware assisted breakpoint 2 at 0x4004e2: file hbreak.c, line 27.^M (gdb) PASS: gdb.base/hbreak.exp: hbreak continue^M Continuing.^M Unexpected error setting breakpoint: Invalid argument.^M (gdb) XFAIL: gdb.base/hbreak.exp: continue to break-at-exit after hbreak ... due to this call in arm_linux_nat_target::low_prepare_to_resume: ... if (ptrace (PTRACE_SETHBPREGS, pid, (PTRACE_TYPE_ARG3) ((i << 1) + 1), &bpts[i].address) < 0) perror_with_name (_("Unexpected error setting breakpoint")); ... This problem does not happen if instead we use a 4-byte aligned address. This may or may not be a kernel bug. Work around this by first using an inoffensive address bpts[i].address & ~0x7. Likewise in arm_target::low_prepare_to_resume, which fixes the same fail on target board native-gdbserver/mthumb. While we're at it: - use arm_hwbp_control_is_initialized in arm_linux_nat_target::low_prepare_to_resume, - handle the !arm_hwbp_control_is_initialized case explicitly, - add missing '_()' in arm_target::low_prepare_to_resume, - make error messages identical between arm_target::low_prepare_to_resume and arm_linux_nat_target::low_prepare_to_resume, - factor out sethbpregs_hwbp_address and sethbpregs_hwbp_control to make the implementation more readable. Remove the tentative xfail added in d0af16d5a10 ("[gdb/testsuite] Add xfail in gdb.base/hbreak.exp") by simply reverting the commit. Tested on arm-linux. Approved-By: Luis Machado <luis.machado@arm.com> Tested-By: Luis Machado <luis.machado@arm.com>
Diffstat (limited to 'gdbserver')
-rw-r--r--gdbserver/linux-arm-low.cc65
1 files changed, 53 insertions, 12 deletions
diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
index eec4649..ee89949 100644
--- a/gdbserver/linux-arm-low.cc
+++ b/gdbserver/linux-arm-low.cc
@@ -819,6 +819,34 @@ arm_target::low_new_fork (process_info *parent, process_info *child)
child_lwp_info->wpts_changed[i] = 1;
}
+/* For PID, set the address register of hardware breakpoint pair I to
+ ADDRESS. */
+
+static void
+sethbpregs_hwbp_address (int pid, int i, unsigned int address)
+{
+ PTRACE_TYPE_ARG3 address_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 1);
+
+ errno = 0;
+
+ if (ptrace (PTRACE_SETHBPREGS, pid, address_reg, &address) < 0)
+ perror_with_name (_("Unexpected error updating breakpoint address"));
+}
+
+/* For PID, set the control register of hardware breakpoint pair I to
+ CONTROL. */
+
+static void
+sethbpregs_hwbp_control (int pid, int i, arm_hwbp_control_t control)
+{
+ PTRACE_TYPE_ARG3 control_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 2);
+
+ errno = 0;
+
+ if (ptrace (PTRACE_SETHBPREGS, pid, control_reg, &control) < 0)
+ perror_with_name (_("Unexpected error setting breakpoint control"));
+}
+
/* Called when resuming a thread.
If the debug regs have changed, update the thread's copies. */
void
@@ -834,19 +862,32 @@ arm_target::low_prepare_to_resume (lwp_info *lwp)
for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++)
if (lwp_info->bpts_changed[i])
{
- errno = 0;
+ unsigned int address = proc_info->bpts[i].address;
+ arm_hwbp_control_t control = proc_info->bpts[i].control;
- if (arm_hwbp_control_is_enabled (proc_info->bpts[i].control))
- if (ptrace (PTRACE_SETHBPREGS, pid,
- (PTRACE_TYPE_ARG3) ((i << 1) + 1),
- &proc_info->bpts[i].address) < 0)
- perror_with_name ("Unexpected error setting breakpoint address");
-
- if (arm_hwbp_control_is_initialized (proc_info->bpts[i].control))
- if (ptrace (PTRACE_SETHBPREGS, pid,
- (PTRACE_TYPE_ARG3) ((i << 1) + 2),
- &proc_info->bpts[i].control) < 0)
- perror_with_name ("Unexpected error setting breakpoint");
+ if (!arm_hwbp_control_is_initialized (control))
+ {
+ /* Nothing to do. */
+ }
+ else if (!arm_hwbp_control_is_enabled (control))
+ {
+ /* Disable hardware breakpoint, just write the control
+ register. */
+ sethbpregs_hwbp_control (pid, i, control);
+ }
+ else
+ {
+ /* See arm_linux_nat_target::low_prepare_to_resume for detailed
+ comment. */
+ unsigned int aligned_address = address & ~0x7U;
+ if (aligned_address != address)
+ {
+ sethbpregs_hwbp_address (pid, i, aligned_address);
+ sethbpregs_hwbp_control (pid, i, control);
+ }
+ sethbpregs_hwbp_address (pid, i, address);
+ sethbpregs_hwbp_control (pid, i, control);
+ }
lwp_info->bpts_changed[i] = 0;
}