diff options
-rw-r--r-- | gdb/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/aarch64-linux-nat.c | 33 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/gdbserver/linux-aarch64-low.c | 10 | ||||
-rw-r--r-- | gdb/nat/aarch64-linux-hw-point.c | 40 | ||||
-rw-r--r-- | gdb/nat/aarch64-linux-hw-point.h | 2 |
6 files changed, 66 insertions, 35 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f8b6874..f03a2fd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +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. + 2015-09-02 Patrick Palka <patrick@parcs.ath.cx> * gdb_obstack.h (obstack_strdup): Declare. diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 9747461..f2ef41b 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -717,38 +717,7 @@ static int aarch64_linux_region_ok_for_hw_watchpoint (struct target_ops *self, CORE_ADDR addr, int len) { - CORE_ADDR aligned_addr; - - /* Can not set watchpoints for zero or negative lengths. */ - if (len <= 0) - return 0; - - /* Must have hardware watchpoint debug register(s). */ - if (aarch64_num_wp_regs == 0) - return 0; - - /* We support unaligned watchpoint address and arbitrary length, - as long as the size of the whole watched area after alignment - doesn't exceed size of the total area that all watchpoint debug - registers can watch cooperatively. - - This is a very relaxed rule, but unfortunately there are - limitations, e.g. false-positive hits, due to limited support of - hardware debug registers in the kernel. See comment above - aarch64_align_watchpoint for more information. */ - - aligned_addr = addr & ~(AARCH64_HWP_MAX_LEN_PER_REG - 1); - if (aligned_addr + aarch64_num_wp_regs * AARCH64_HWP_MAX_LEN_PER_REG - < addr + len) - return 0; - - /* All tests passed so we are likely to be able to set the watchpoint. - The reason that it is 'likely' rather than 'must' is because - we don't check the current usage of the watchpoint registers, and - there may not be enough registers available for this watchpoint. - Ideally we should check the cached debug register state, however - the checking is costly. */ - return 1; + return aarch64_linux_region_ok_for_watchpoint (addr, len); } /* Implement the "to_stopped_data_address" target_ops method. */ diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 28c041c..58a46b7 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,9 @@ +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-08-27 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> * linux-low.c (check_stopped_by_breakpoint): Use diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index da0ea9b..aebf1e3 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -302,9 +302,13 @@ aarch64_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, targ_type = raw_bkpt_type_to_target_hw_bp_type (type); if (targ_type != hw_execute) - ret = - aarch64_handle_watchpoint (targ_type, addr, len, 1 /* is_insert */, - state); + { + if (aarch64_linux_region_ok_for_watchpoint (addr, len)) + ret = aarch64_handle_watchpoint (targ_type, addr, len, + 1 /* is_insert */, state); + else + ret = -1; + } else ret = aarch64_handle_breakpoint (targ_type, addr, len, 1 /* is_insert */, diff --git a/gdb/nat/aarch64-linux-hw-point.c b/gdb/nat/aarch64-linux-hw-point.c index a3c923a..bca6ec1 100644 --- a/gdb/nat/aarch64-linux-hw-point.c +++ b/gdb/nat/aarch64-linux-hw-point.c @@ -645,3 +645,43 @@ aarch64_linux_get_debug_reg_capacity (int tid) aarch64_num_bp_regs = 0; } } + +/* Return true if we can watch a memory region that starts address + ADDR and whose length is LEN in bytes. */ + +int +aarch64_linux_region_ok_for_watchpoint (CORE_ADDR addr, int len) +{ + CORE_ADDR aligned_addr; + + /* Can not set watchpoints for zero or negative lengths. */ + if (len <= 0) + return 0; + + /* Must have hardware watchpoint debug register(s). */ + if (aarch64_num_wp_regs == 0) + return 0; + + /* We support unaligned watchpoint address and arbitrary length, + as long as the size of the whole watched area after alignment + doesn't exceed size of the total area that all watchpoint debug + registers can watch cooperatively. + + This is a very relaxed rule, but unfortunately there are + limitations, e.g. false-positive hits, due to limited support of + hardware debug registers in the kernel. See comment above + aarch64_align_watchpoint for more information. */ + + aligned_addr = addr & ~(AARCH64_HWP_MAX_LEN_PER_REG - 1); + if (aligned_addr + aarch64_num_wp_regs * AARCH64_HWP_MAX_LEN_PER_REG + < addr + len) + return 0; + + /* All tests passed so we are likely to be able to set the watchpoint. + The reason that it is 'likely' rather than 'must' is because + we don't check the current usage of the watchpoint registers, and + there may not be enough registers available for this watchpoint. + Ideally we should check the cached debug register state, however + the checking is costly. */ + return 1; +} diff --git a/gdb/nat/aarch64-linux-hw-point.h b/gdb/nat/aarch64-linux-hw-point.h index a27a201..a3cf7d9 100644 --- a/gdb/nat/aarch64-linux-hw-point.h +++ b/gdb/nat/aarch64-linux-hw-point.h @@ -182,4 +182,6 @@ void aarch64_linux_get_debug_reg_capacity (int tid); struct aarch64_debug_reg_state *aarch64_get_debug_reg_state (pid_t pid); +int aarch64_linux_region_ok_for_watchpoint (CORE_ADDR addr, int len); + #endif /* AARCH64_LINUX_HW_POINT_H */ |