old-cross-binutils/gdb/nat
Yao Qi 39edd165f4 [aarch64] Check region OK for HW watchpoint in GDBserver
Nowadays, if user requests HW watchpoint to monitor a large memory area
or unaligned area, aarch64 GDB will split into multiple aligned areas,
and use multiple debugging registers to watch them.  However, the
registers are not updated in a transaction way.  GDBserver doesn't revert
updates in previous iterations if some debugging registers fail to update
due to some reason, like no free debugging registers available, in the
latter iteration.  For example, if we have a char buf[34], and watch buf
in gdb,

(gdb) watch buf
Hardware watchpoint 2: buf
(gdb) c
Continuing.
infrun: clear_proceed_status_thread (Thread 13466)
infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT)
infrun: step-over queue now empty
infrun: resuming [Thread 13466] for step-over
Sending packet: $m410838,22#35...Packet received: 00000000000000000000000000000000000000000000000000000000000000000000
infrun: skipping breakpoint: stepping past insn at: 0x400524
infrun: skipping breakpoint: stepping past insn at: 0x400524
Sending packet: $Z2,410838,22#80...Packet received: E01 <----- [1]
Packet Z2 (write-watchpoint) is supported
Sending packet: $Z0,7fb7fe0a8c,4#43...Packet received: OK
Warning:
Could not insert hardware watchpoint 2.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

GDB receives E01 for Z2 packet [1] but GDBserver updates the debugging
register status,

insert_point (addr=0x00410838, len=34, type=hw-write-watchpoint):
	BREAKPOINTs:
	BP0: addr=0x0, ctrl=0x00000000, ref.count=0
	BP1: addr=0x0, ctrl=0x00000000, ref.count=0
	BP2: addr=0x0, ctrl=0x00000000, ref.count=0
	BP3: addr=0x0, ctrl=0x00000000, ref.count=0
	BP4: addr=0x0, ctrl=0x00000000, ref.count=0
	BP5: addr=0x0, ctrl=0x00000000, ref.count=0
	WATCHPOINTs:
	WP0: addr=0x410850, ctrl=0x00001ff5, ref.count=1
	WP1: addr=0x410848, ctrl=0x00001ff5, ref.count=1
	WP2: addr=0x410840, ctrl=0x00001ff5, ref.count=1
	WP3: addr=0x410838, ctrl=0x00001ff5, ref.count=1

four debugging registers can not monitor 34-byte long area, so the last
iteration of updating debugging register state fails but previous
iterations succeed.  This makes GDB think no HW watchpoint is inserted
but some debugging registers are used.

This problem was exposed by "watch buf" gdb.base/watchpoint.exp with
aarch64 GDBserver debugging arm 32-bit program.  The buf is 30-byte long
but 4-byte aligned, and four debugging registers can't cover 34-byte
(extend 4 bytes to be 8-byte aligned) area.  However, this problem
does exist on non-multi-arch debugging scenario as well.

This patch moves code in aarch64_linux_region_ok_for_hw_watchpoint to
aarch64_linux_region_ok_for_watchpoint in nat/aarch64-linux-hw-point.c.
Then, checks with aarch64_linux_region_ok_for_watchpoint, like what we
are doing in GDB.  If the region is OK, call aarch64_handle_watchpoint.

Regression tested on aarch64 with both 64-bit program and 32-bit
program.  Some fails in gdb.base/watchpoint.exp are fixed.

gdb:

2015-09-03  Yao Qi  <yao.qi@linaro.org>

	* aarch64-linux-nat.c (aarch64_linux_region_ok_for_hw_watchpoint):
	Move code to aarch64_linux_region_ok_for_watchpoint.  Call
	aarch64_linux_region_ok_for_watchpoint.
	* nat/aarch64-linux-hw-point.c (aarch64_linux_region_ok_for_watchpoint):
	New function.
	* nat/aarch64-linux-hw-point.h (aarch64_linux_region_ok_for_watchpoint):
	Declare it.

gdb/gdbserver:

2015-09-03  Yao Qi  <yao.qi@linaro.org>

	* linux-aarch64-low.c (aarch64_insert_point): Call
	aarch64_handle_watchpoint if aarch64_linux_region_ok_for_watchpoint
	returns true.
2015-09-03 14:01:49 +01:00
..
aarch64-linux-hw-point.c [aarch64] Check region OK for HW watchpoint in GDBserver 2015-09-03 14:01:49 +01:00
aarch64-linux-hw-point.h [aarch64] Check region OK for HW watchpoint in GDBserver 2015-09-03 14:01:49 +01:00
aarch64-linux.c Replace some xmalloc-family functions with XNEW-family ones 2015-08-26 17:18:12 -04:00
aarch64-linux.h Move aarch64_linux_new_thread to nat/aarch64-linux.c 2015-08-25 11:39:14 +01:00
gdb_ptrace.h C++: handle glibc's ptrace(enum __ptrace_request, ...) 2015-07-24 15:12:15 +01:00
gdb_thread_db.h Protect nat/gdb_thread_db.h against multiple inclusion. 2015-08-05 16:30:57 +02:00
glibc_thread_db.h
linux-btrace.c Replace some xmalloc-family functions with XNEW-family ones 2015-08-26 17:18:12 -04:00
linux-btrace.h ari, btrace: avoid unsigned long long 2015-07-15 08:40:57 +02:00
linux-namespaces.c Fix stale cleanup left by linux_mntns_access_fs 2015-08-21 16:56:22 +01:00
linux-namespaces.h Introduce nat/linux-namespaces.[ch] 2015-06-10 14:28:43 +01:00
linux-nat.h Include header for enum target_stop_reason 2015-05-15 16:00:40 +01:00
linux-osdata.c Replace some xmalloc-family functions with XNEW-family ones 2015-08-26 17:18:12 -04:00
linux-osdata.h
linux-personality.c
linux-personality.h
linux-procfs.c Remove linux_proc_pid_get_ns 2015-06-10 14:28:43 +01:00
linux-procfs.h Remove linux_proc_pid_get_ns 2015-06-10 14:28:43 +01:00
linux-ptrace.c Linux: sys/ptrace.h -> nat/gdb_ptrace.h everywhere 2015-07-24 15:14:47 +01:00
linux-ptrace.h Detect SW breakpoints in Cell/B.E. combined debugging 2015-08-27 19:26:31 +02:00
linux-waitpid.c Fix gdbserver --debug issues caught by Valgrind 2015-08-06 13:32:27 +01:00
linux-waitpid.h
mips-linux-watch.c Mostly trivial enum fixes 2015-07-31 13:19:53 -04:00
mips-linux-watch.h Mostly trivial enum fixes 2015-07-31 13:19:53 -04:00
ppc-linux.c
ppc-linux.h
x86-cpuid.h
x86-dregs.c
x86-dregs.h Add x86_debug_reg_state to gdbserver 2015-03-24 14:05:43 +00:00
x86-gcc-cpuid.h
x86-linux-dregs.c Linux: sys/ptrace.h -> nat/gdb_ptrace.h everywhere 2015-07-24 15:14:47 +01:00
x86-linux-dregs.h Move low-level Linux x86 debug register code to a shared file 2015-03-24 14:05:45 +00:00
x86-linux.c Move duplicated Linux x86 code to nat/x86-linux.c 2015-03-24 14:05:45 +00:00
x86-linux.h Move duplicated Linux x86 code to nat/x86-linux.c 2015-03-24 14:05:45 +00:00