From 5009afc5ba7a0d57f28fbc834757145fe1f45549 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Fri, 2 May 2008 11:07:25 +0000 Subject: [PATCH] * target.h (struct target_ops): Add to_watchpoint_addr_within_range. (target_watchpoint_addr_within_range): New function. * target.c (update_current_target): Inherit to_watchpoint_addr_within_range, defaulting to default_watchpoint_addr_within_range. (default_watchpoint_addr_within_range): New function. (debug_to_watchpoint_addr_within_range): New function. (setup_target_debug): Set to_watchpoint_addr_within_range. * ppc-linux-nat.c (ppc_linux_watchpoint_addr_within_range): New function. (_initialize_ppc_linux_nat): Set to_watchpoint_addr_within_range. * breakpoint.c (watchpoints_triggered): Use target_watchpoint_addr_within_range. * gdbint.texinfo (Algorithms): Describe target_watchpoint_addr_within_range. --- gdb/ChangeLog | 19 ++++++++++++++++++- gdb/breakpoint.c | 5 +++-- gdb/doc/ChangeLog | 5 +++++ gdb/doc/gdbint.texinfo | 13 +++++++++++-- gdb/ppc-linux-nat.c | 11 +++++++++++ gdb/target.c | 37 ++++++++++++++++++++++++++++++++++++- gdb/target.h | 5 +++++ 7 files changed, 89 insertions(+), 6 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5efa58e..8b51c3b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2008-05-02 Andreas Schwab + + * target.h (struct target_ops): Add + to_watchpoint_addr_within_range. + (target_watchpoint_addr_within_range): New function. + * target.c (update_current_target): Inherit + to_watchpoint_addr_within_range, defaulting to + default_watchpoint_addr_within_range. + (default_watchpoint_addr_within_range): New function. + (debug_to_watchpoint_addr_within_range): New function. + (setup_target_debug): Set to_watchpoint_addr_within_range. + * ppc-linux-nat.c (ppc_linux_watchpoint_addr_within_range): + New function. + (_initialize_ppc_linux_nat): Set to_watchpoint_addr_within_range. + * breakpoint.c (watchpoints_triggered): Use + target_watchpoint_addr_within_range. + 2008-05-01 Pedro Alves * configure.tgt: Add i[34567]86-*-dicos* and x86_64-*-dicos*. @@ -32,7 +49,7 @@ (print_one_exception_catchpoint): Print if no loc available. (handle_gnu_v3_exceptions): Call generic breakpoint code to insert catch and throw catchpoints. - + 2008-05-01 Aleksandar Riswtovski PR gdb/2343 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 9dc2ca2..11d9187 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2616,8 +2616,9 @@ watchpoints_triggered (struct target_waitstatus *ws) for (loc = b->loc; loc; loc = loc->next) /* Exact match not required. Within range is sufficient. */ - if (addr >= loc->address - && addr < loc->address + loc->length) + if (target_watchpoint_addr_within_range (¤t_target, + addr, loc->address, + loc->length)) { b->watchpoint_triggered = watch_triggered_yes; break; diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 2285c83..2b5b662 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-05-02 Andreas Schwab + + * gdbint.texinfo (Algorithms): Describe + target_watchpoint_addr_within_range. + 2008-04-30 Daniel Jacobowitz * gdbint.texinfo (Stack Frames): New chapter. diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 39cb031..d020f5b 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -9,7 +9,7 @@ @ifinfo This file documents the internals of the GNU debugger @value{GDBN}. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006 + 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. Contributed by Cygnus Solutions. Written by John Gilmore. Second Edition by Stan Shebs. @@ -711,10 +711,19 @@ target's watchpoint indication is sticky, i.e., stays set after resuming, this method should clear it. For instance, the x86 debug control register has sticky triggered flags. +@findex target_watchpoint_addr_within_range +@item target_watchpoint_addr_within_range (@var{target}, @var{addr}, @var{start}, @var{length}) +Check whether @var{addr} (as returned by @code{target_stopped_data_address}) +lies within the hardware-defined watchpoint region described by +@var{start} and @var{length}. This only needs to be provided if the +granularity of a watchpoint is greater than one byte, i.e., if the +watchpoint can also trigger on nearby addresses outside of the watched +region. + @findex HAVE_STEPPABLE_WATCHPOINT @item HAVE_STEPPABLE_WATCHPOINT If defined to a non-zero value, it is not necessary to disable a -watchpoint to step over it. Like @code{gdbarch_have_nonsteppable_watchpoint}, +watchpoint to step over it. Like @code{gdbarch_have_nonsteppable_watchpoint}, this is usually set when watchpoints trigger at the instruction which will perform an interesting read or write. It should be set if there is a temporary disable bit which allows the processor diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 53bc4ae..5486588 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -889,6 +889,16 @@ ppc_linux_stopped_by_watchpoint (void) return ppc_linux_stopped_data_address (¤t_target, &addr); } +static int +ppc_linux_watchpoint_addr_within_range (struct target_ops *target, + CORE_ADDR addr, + CORE_ADDR start, int length) +{ + addr &= ~7; + /* Check whether [start, start+length-1] intersects [addr, addr+7]. */ + return start <= addr + 7 && start + length - 1 >= addr; +} + static void ppc_linux_store_inferior_registers (struct regcache *regcache, int regno) { @@ -997,6 +1007,7 @@ _initialize_ppc_linux_nat (void) t->to_remove_watchpoint = ppc_linux_remove_watchpoint; t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint; t->to_stopped_data_address = ppc_linux_stopped_data_address; + t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range; t->to_read_description = ppc_linux_read_description; diff --git a/gdb/target.c b/gdb/target.c index 944d601..a8f1afb 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -49,6 +49,9 @@ static void kill_or_be_killed (int); static void default_terminal_info (char *, int); +static int default_watchpoint_addr_within_range (struct target_ops *, + CORE_ADDR, CORE_ADDR, int); + static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int); static int nosymbol (char *, CORE_ADDR *); @@ -131,6 +134,9 @@ static int debug_to_stopped_by_watchpoint (void); static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *); +static int debug_to_watchpoint_addr_within_range (struct target_ops *, + CORE_ADDR, CORE_ADDR, int); + static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int); static void debug_to_terminal_init (void); @@ -416,9 +422,10 @@ update_current_target (void) INHERIT (to_insert_watchpoint, t); INHERIT (to_remove_watchpoint, t); INHERIT (to_stopped_data_address, t); - INHERIT (to_stopped_by_watchpoint, t); INHERIT (to_have_steppable_watchpoint, t); INHERIT (to_have_continuable_watchpoint, t); + INHERIT (to_stopped_by_watchpoint, t); + INHERIT (to_watchpoint_addr_within_range, t); INHERIT (to_region_ok_for_hw_watchpoint, t); INHERIT (to_terminal_init, t); INHERIT (to_terminal_inferior, t); @@ -544,6 +551,8 @@ update_current_target (void) de_fault (to_stopped_data_address, (int (*) (struct target_ops *, CORE_ADDR *)) return_zero); + de_fault (to_watchpoint_addr_within_range, + default_watchpoint_addr_within_range); de_fault (to_region_ok_for_hw_watchpoint, default_region_ok_for_hw_watchpoint); de_fault (to_terminal_init, @@ -1881,6 +1890,14 @@ default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) } static int +default_watchpoint_addr_within_range (struct target_ops *target, + CORE_ADDR addr, + CORE_ADDR start, int length) +{ + return addr >= start && addr < start + length; +} + +static int return_zero (void) { return 0; @@ -2448,6 +2465,23 @@ debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr) } static int +debug_to_watchpoint_addr_within_range (struct target_ops *target, + CORE_ADDR addr, + CORE_ADDR start, int length) +{ + int retval; + + retval = debug_target.to_watchpoint_addr_within_range (target, addr, + start, length); + + fprintf_filtered (gdb_stdlog, + "target_watchpoint_addr_within_range (0x%lx, 0x%lx, %d) = %d\n", + (unsigned long) addr, (unsigned long) start, length, + retval); + return retval; +} + +static int debug_to_insert_hw_breakpoint (struct bp_target_info *bp_tgt) { int retval; @@ -2790,6 +2824,7 @@ setup_target_debug (void) current_target.to_remove_watchpoint = debug_to_remove_watchpoint; current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint; current_target.to_stopped_data_address = debug_to_stopped_data_address; + current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range; current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint; current_target.to_terminal_init = debug_to_terminal_init; current_target.to_terminal_inferior = debug_to_terminal_inferior; diff --git a/gdb/target.h b/gdb/target.h index 84cd008..8e7d112 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -367,6 +367,8 @@ struct target_ops int to_have_steppable_watchpoint; int to_have_continuable_watchpoint; int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *); + int (*to_watchpoint_addr_within_range) (struct target_ops *, + CORE_ADDR, CORE_ADDR, int); int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int); void (*to_terminal_init) (void); void (*to_terminal_inferior) (void); @@ -1093,6 +1095,9 @@ extern int target_stopped_data_address_p (struct target_ops *); #define target_stopped_data_address_p(CURRENT_TARGET) (1) #endif +#define target_watchpoint_addr_within_range(target, addr, start, length) \ + (*target.to_watchpoint_addr_within_range) (target, addr, start, length) + extern const struct target_desc *target_read_description (struct target_ops *); /* Command logging facility. */ -- 2.7.4