From b62e2b271b25eafdafdb3bafd654bf69b72b6c95 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 1 Aug 2012 13:02:41 +0000 Subject: [PATCH] gdbserver/ChangeLog: * linux-arm-low.c (arm_linux_hw_point_initialize): Distinguish between unsupported TYPE and unimplementable ADDR/LEN combination. (arm_insert_point): Act on new return value. testsuite/ChangeLog: * gdb.base/watchpoint.exp (test_wide_location_1): Expect software watchpoints on ARM. When expecting software watchpoints, tolerate (remote) targets that report unsupported hardware watchpoint only at continue time. (test_wide_location_2): Likewise. --- gdb/gdbserver/ChangeLog | 6 ++++ gdb/gdbserver/linux-arm-low.c | 15 ++++----- gdb/testsuite/ChangeLog | 8 +++++ gdb/testsuite/gdb.base/watchpoint.exp | 44 ++++++++++++++++++++++----- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 4e40aa92821..6a1259b0889 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,9 @@ +2012-08-01 Ulrich Weigand + + * linux-arm-low.c (arm_linux_hw_point_initialize): Distinguish + between unsupported TYPE and unimplementable ADDR/LEN combination. + (arm_insert_point): Act on new return value. + 2012-07-31 Pedro Alves * server.c (process_point_options): Only skip tokens if we find diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 10370834fcf..2718cecbe19 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -432,8 +432,9 @@ arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1, /* Initialize the hardware breakpoint structure P for a breakpoint or watchpoint at ADDR to LEN. The type of watchpoint is given in TYPE. - Returns -1 if TYPE is unsupported, 0 if TYPE represents a breakpoint, - and 1 if type represents a watchpoint. */ + Returns -1 if TYPE is unsupported, or -2 if the particular combination + of ADDR and LEN cannot be implemented. Otherwise, returns 0 if TYPE + represents a breakpoint and 1 if type represents a watchpoint. */ static int arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len, struct arm_linux_hw_breakpoint *p) @@ -483,7 +484,7 @@ arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len, break; default: /* Unsupported. */ - return -1; + return -2; } } else @@ -493,17 +494,17 @@ arm_linux_hw_point_initialize (char type, CORE_ADDR addr, int len, /* Can not set watchpoints for zero or negative lengths. */ if (len <= 0) - return -1; + return -2; /* The current ptrace interface can only handle watchpoints that are a power of 2. */ if ((len & (len - 1)) != 0) - return -1; + return -2; /* Test that the range [ADDR, ADDR + LEN) fits into the largest address range covered by a watchpoint. */ aligned_addr = addr & ~(max_wp_length - 1); if (aligned_addr + max_wp_length < addr + len) - return -1; + return -2; mask = (1 << len) - 1; } @@ -560,7 +561,7 @@ arm_insert_point (char type, CORE_ADDR addr, int len) if (watch < 0) { /* Unsupported. */ - return 1; + return watch == -1 ? 1 : -1; } if (watch) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1a4262cb3a9..b63868116e4 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-08-01 Ulrich Weigand + + * gdb.base/watchpoint.exp (test_wide_location_1): Expect software + watchpoints on ARM. When expecting software watchpoints, tolerate + (remote) targets that report unsupported hardware watchpoint only + at continue time. + (test_wide_location_2): Likewise. + 2012-08-01 Jan Kratochvil * gdb.base/valgrind-infcall.exp: Relax the UNSUPPORTED check for more diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.base/watchpoint.exp index 2941fbf4520..a461cb2977f 100644 --- a/gdb/testsuite/gdb.base/watchpoint.exp +++ b/gdb/testsuite/gdb.base/watchpoint.exp @@ -603,13 +603,15 @@ proc test_watch_location {} { proc test_wide_location_1 {} { global no_hw + global gdb_prompt # This test watches two words on most 32-bit ABIs, and one word on # most 64-bit ABIs. # Platforms where the target can't watch such a large region # should clear hw_expected below. - if { $no_hw || [target_info exists gdb,no_hardware_watchpoints] } { + if { $no_hw || [target_info exists gdb,no_hardware_watchpoints] + || [istarget arm*-*-*] } { set hw_expected 0 } else { set hw_expected 1 @@ -625,9 +627,21 @@ proc test_wide_location_1 {} { "continue with watch foo2" } else { gdb_test "watch foo2" "atchpoint .*: .*" "watch foo2" - gdb_test "continue" \ - "Continuing.*\[Ww\]atchpoint .*: .*New value = \\\{val = \\\{0, 11\\\}\\\}.*" \ - "continue with watch foo2" + set test "continue with watch foo2" + gdb_test_multiple "cont" $test { + -re "Continuing.*\[Ww\]atchpoint .*: .*New value = \\\{val = \\\{0, 11\\\}\\\}.*$gdb_prompt $" { + pass $test + } + -re "Could not insert hardware breakpoints:.*You may have requested too many hardware breakpoints/watchpoints.*$gdb_prompt $" { + # This may happen with remote targets that support + # hardware watchpoints. We only find out the + # watchpoint was too large, for example, at insert + # time. If GDB is ever adjusted to downgrade the + # watchpoint automatically in this case, this match + # should be removed. + pass $test + } + } } gdb_test_no_output "delete \$bpnum" "delete watch foo2" @@ -635,13 +649,15 @@ proc test_wide_location_1 {} { proc test_wide_location_2 {} { global no_hw + global gdb_prompt # This test watches four words on most 32-bit ABIs, and two words # on 64-bit ABIs. # Platforms where the target can't watch such a large region # should clear hw_expected below. - if { $no_hw || [target_info exists gdb,no_hardware_watchpoints] } { + if { $no_hw || [target_info exists gdb,no_hardware_watchpoints] + || [istarget arm*-*-*] } { set hw_expected 0 } else { set hw_expected 1 @@ -657,9 +673,21 @@ proc test_wide_location_2 {} { "continue with watch foo4" } else { gdb_test "watch foo4" "atchpoint .*: .*" "watch foo4" - gdb_test "continue" \ - "Continuing.*\[Ww\]atchpoint .*: .*New value = \\\{val = \\\{0, 0, 0, 33\\\}\\\}.*" \ - "continue with watch foo4" + set test "continue with watch foo4" + gdb_test_multiple "cont" $test { + -re "Continuing.*\[Ww\]atchpoint .*: .*New value = \\\{val = \\\{0, 0, 0, 33\\\}\\\}.*$gdb_prompt $" { + pass $test + } + -re "Could not insert hardware breakpoints:.*You may have requested too many hardware breakpoints/watchpoints.*$gdb_prompt $" { + # This may happen with remote targets that support + # hardware watchpoints. We only find out the + # watchpoint was too large, for example, at insert + # time. If GDB is ever adjusted to downgrade the + # watchpoint automatically in this case, this match + # should be removed. + pass $test + } + } } gdb_test_no_output "delete \$bpnum" "delete watch foo4" -- 2.30.2