From e1457d83a503024ed3834599409f11e1b1b7dabc Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 18 Feb 2004 03:47:35 +0000 Subject: [PATCH] 2004-02-17 Ulrich Weigand Committed by Jim Blandy . * config/s390/nm-linux.h: Update comments. (target_insert_watchpoint, target_remove_watchpoint): Redefine. (STOPPED_BY_WATCHPOINT): Redefine. (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Redefine to 1. (s390_insert_watchpoint, s390_remove_watchpoint): Update prototype. (s390_stopped_by_watchpoint): Likewise. (watch_area_cnt): Remove. * s390-nat.c: Update comments. (watch_area): Remove typedef. Global replace watch_area by struct watch_area. (watch_area_cnt, watch_lo_addr, watch_hi_addr): Remove. (s390_stopped_by_watchpoint): Remove pid argument, use s390_inferior_tid. Add short-cut for the no watchpoint case. (s390_fix_watch_points): Remove pid argument, use s390_inferior_tid. Recompute area spanned by watchpoints. (s390_insert_watchpoint, s390_remove_watchpoint): Remove pid argument. Reimplement. --- gdb/ChangeLog | 19 ++++ gdb/config/s390/nm-linux.h | 41 ++++----- gdb/s390-nat.c | 184 +++++++++++++++---------------------- 3 files changed, 108 insertions(+), 136 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c95392b031c..338b7ae0a91 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,6 +1,25 @@ 2004-02-17 Ulrich Weigand Committed by Jim Blandy . + + * config/s390/nm-linux.h: Update comments. + (target_insert_watchpoint, target_remove_watchpoint): Redefine. + (STOPPED_BY_WATCHPOINT): Redefine. + (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Redefine to 1. + (s390_insert_watchpoint, s390_remove_watchpoint): Update prototype. + (s390_stopped_by_watchpoint): Likewise. + (watch_area_cnt): Remove. + * s390-nat.c: Update comments. + (watch_area): Remove typedef. + Global replace watch_area by struct watch_area. + (watch_area_cnt, watch_lo_addr, watch_hi_addr): Remove. + (s390_stopped_by_watchpoint): Remove pid argument, + use s390_inferior_tid. Add short-cut for the no watchpoint case. + (s390_fix_watch_points): Remove pid argument, + use s390_inferior_tid. Recompute area spanned by watchpoints. + (s390_insert_watchpoint, s390_remove_watchpoint): Remove pid + argument. Reimplement. + * config/s390/nm-linux.h: Update comments. Do not include "solib.h". (KERNEL_U_ADDR, REGISTER_U_ADDR, U_REGS_OFFSET): Remove. (FETCH_INFERIOR_REGISTERS): Define. diff --git a/gdb/config/s390/nm-linux.h b/gdb/config/s390/nm-linux.h index 6931efb4c00..04cd863212a 100644 --- a/gdb/config/s390/nm-linux.h +++ b/gdb/config/s390/nm-linux.h @@ -39,33 +39,24 @@ extern int kernel_u_size (void); -/* WATCHPOINT SPECIFIC STUFF */ +/* Hardware watchpoints. */ + +extern int s390_stopped_by_watchpoint (void); +extern int s390_insert_watchpoint (CORE_ADDR addr, int len); +extern int s390_remove_watchpoint (CORE_ADDR addr, int len); #define TARGET_HAS_HARDWARE_WATCHPOINTS +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1 #define HAVE_CONTINUABLE_WATCHPOINT 1 -#define target_insert_watchpoint(addr, len, type) \ - s390_insert_watchpoint (PIDGET (inferior_ptid), addr, len, type) - -#define target_remove_watchpoint(addr, len, type) \ - s390_remove_watchpoint (PIDGET (inferior_ptid), addr, len) - -extern int watch_area_cnt; -/* gdb if really stupid & calls this all the time without a - watchpoint even being set */ -#define STOPPED_BY_WATCHPOINT(W) \ - (watch_area_cnt&&s390_stopped_by_watchpoint (PIDGET(inferior_ptid))) - -extern CORE_ADDR s390_stopped_by_watchpoint (int); - -/* - Type can be 1 for a read_watchpoint or 2 for an access watchpoint. - */ -extern int s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw); -extern int s390_remove_watchpoint (int pid, CORE_ADDR addr, int len); -#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ - (((type) == bp_hardware_watchpoint)|| \ - ((type) == bp_watchpoint)|| \ - ((type) == bp_read_watchpoint) || \ - ((type) == bp_access_watchpoint)) + +#define STOPPED_BY_WATCHPOINT(w) \ + s390_stopped_by_watchpoint () + +#define target_insert_watchpoint(addr, len, type) \ + s390_insert_watchpoint (addr, len) + +#define target_remove_watchpoint(addr, len, type) \ + s390_remove_watchpoint (addr, len) + #endif /* nm_linux.h */ diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c index ed6c4088b10..a2a7759b822 100644 --- a/gdb/s390-nat.c +++ b/gdb/s390-nat.c @@ -219,55 +219,67 @@ store_inferior_registers (int regnum) } -/* watch_areas are required if you put 2 or more watchpoints on the same - address or overlapping areas gdb will call us to delete the watchpoint - more than once when we try to delete them. - attempted reference counting to reduce the number of areas unfortunately - they didn't shrink when areas had to be split overlapping occurs. */ -struct watch_area; -typedef struct watch_area watch_area; +/* Hardware-assisted watchpoint handling. */ + +/* We maintain a list of all currently active watchpoints in order + to properly handle watchpoint removal. + + The only thing we actually need is the total address space area + spanned by the watchpoints. */ + struct watch_area { - watch_area *next; + struct watch_area *next; CORE_ADDR lo_addr; CORE_ADDR hi_addr; }; -static watch_area *watch_base = NULL; -int watch_area_cnt = 0; -static CORE_ADDR watch_lo_addr = 0, watch_hi_addr = 0; - - +static struct watch_area *watch_base = NULL; -CORE_ADDR -s390_stopped_by_watchpoint (int pid) +int +s390_stopped_by_watchpoint (void) { per_lowcore_bits per_lowcore; ptrace_area parea; + /* Speed up common case. */ + if (!watch_base) + return 0; + parea.len = sizeof (per_lowcore); parea.process_addr = (addr_t) & per_lowcore; parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore); - ptrace (PTRACE_PEEKUSR_AREA, pid, &parea); - return ((per_lowcore.perc_storage_alteration == 1) && - (per_lowcore.perc_store_real_address == 0)); -} + if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0) + perror_with_name ("Couldn't retrieve watchpoint status"); + return per_lowcore.perc_storage_alteration == 1 + && per_lowcore.perc_store_real_address == 0; +} -void -s390_fix_watch_points (int pid) +static void +s390_fix_watch_points (void) { + int tid = s390_inferior_tid (); + per_struct per_info; ptrace_area parea; + CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0; + struct watch_area *area; + + for (area = watch_base; area; area = area->next) + { + watch_lo_addr = min (watch_lo_addr, area->lo_addr); + watch_hi_addr = max (watch_hi_addr, area->hi_addr); + } + parea.len = sizeof (per_info); parea.process_addr = (addr_t) & per_info; - parea.kernel_addr = PT_CR_9; - ptrace (PTRACE_PEEKUSR_AREA, pid, &parea); - /* The kernel automatically sets the psw for per depending */ - /* on whether the per control registers are set for event recording */ - /* & sets cr9 & cr10 appropriately also */ - if (watch_area_cnt) + parea.kernel_addr = offsetof (struct user_regs_struct, per_info); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0) + perror_with_name ("Couldn't retrieve watchpoint status"); + + if (watch_base) { per_info.control_regs.bits.em_storage_alteration = 1; per_info.control_regs.bits.storage_alt_space_ctl = 1; @@ -279,104 +291,54 @@ s390_fix_watch_points (int pid) } per_info.starting_addr = watch_lo_addr; per_info.ending_addr = watch_hi_addr; - ptrace (PTRACE_POKEUSR_AREA, pid, &parea); + + if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0) + perror_with_name ("Couldn't modify watchpoint status"); } int -s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw) +s390_insert_watchpoint (CORE_ADDR addr, int len) { - CORE_ADDR hi_addr = addr + len - 1; - watch_area *newarea = (watch_area *) xmalloc (sizeof (watch_area)); - - - if (newarea) - { - newarea->next = watch_base; - watch_base = newarea; - watch_lo_addr = min (watch_lo_addr, addr); - watch_hi_addr = max (watch_hi_addr, hi_addr); - newarea->lo_addr = addr; - newarea->hi_addr = hi_addr; - if (watch_area_cnt == 0) - { - watch_lo_addr = newarea->lo_addr; - watch_hi_addr = newarea->hi_addr; - } - watch_area_cnt++; - s390_fix_watch_points (pid); - } - return newarea ? 0 : -1; + struct watch_area *area = xmalloc (sizeof (struct watch_area)); + if (!area) + return -1; + + area->lo_addr = addr; + area->hi_addr = addr + len - 1; + + area->next = watch_base; + watch_base = area; + + s390_fix_watch_points (); + return 0; } - int -s390_remove_watchpoint (int pid, CORE_ADDR addr, int len) +s390_remove_watchpoint (CORE_ADDR addr, int len) { - watch_area *curr = watch_base, *prev, *matchCurr; - CORE_ADDR hi_addr = addr + len - 1; - CORE_ADDR watch_second_lo_addr = 0xffffffffUL, watch_second_hi_addr = 0; - int lo_addr_ref_cnt, hi_addr_ref_cnt; - prev = matchCurr = NULL; - lo_addr_ref_cnt = (addr == watch_lo_addr); - hi_addr_ref_cnt = (addr == watch_hi_addr); - while (curr) - { - if (matchCurr == NULL) - { - if (curr->lo_addr == addr && curr->hi_addr == hi_addr) - { - matchCurr = curr; - if (prev) - prev->next = curr->next; - else - watch_base = curr->next; - } - prev = curr; - } - if (lo_addr_ref_cnt) - { - if (watch_lo_addr == curr->lo_addr) - lo_addr_ref_cnt++; - if (curr->lo_addr > watch_lo_addr && - curr->lo_addr < watch_second_lo_addr) - watch_second_lo_addr = curr->lo_addr; - } - if (hi_addr_ref_cnt) - { - if (watch_hi_addr == curr->hi_addr) - hi_addr_ref_cnt++; - if (curr->hi_addr < watch_hi_addr && - curr->hi_addr > watch_second_hi_addr) - watch_second_hi_addr = curr->hi_addr; - } - curr = curr->next; - } - if (matchCurr) - { - xfree (matchCurr); - watch_area_cnt--; - if (watch_area_cnt) - { - if (lo_addr_ref_cnt == 2) - watch_lo_addr = watch_second_lo_addr; - if (hi_addr_ref_cnt == 2) - watch_hi_addr = watch_second_hi_addr; - } - else - { - watch_lo_addr = watch_hi_addr = 0; - } - s390_fix_watch_points (pid); - return 0; - } - else + struct watch_area *area, **parea; + + for (parea = &watch_base; *parea; parea = &(*parea)->next) + if ((*parea)->lo_addr == addr + && (*parea)->hi_addr == addr + len - 1) + break; + + if (!*parea) { fprintf_unfiltered (gdb_stderr, - "Attempt to remove nonexistent watchpoint in s390_remove_watchpoint\n"); + "Attempt to remove nonexistent watchpoint.\n"); return -1; } + + area = *parea; + *parea = area->next; + xfree (area); + + s390_fix_watch_points (); + return 0; } + int kernel_u_size (void) { -- 2.30.2