This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project. See the GDB home page for more information.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[leei@ai.sri.com: Re: Preparing for a GDB 4.17 release]


NB it doesn't look like Lee Iverson has an entry in copyright.list,
I wanted to send this in to gdb-patches to get it recorded in the log.

-----Forwarded message from Lee Iverson <leei@ai.sri.com>-----

Message-Id: <199801280306.TAA12441@Canada.AI.SRI.COM>
To: Jason Molenda <jsm@cygnus.com>
Subject: Re: Preparing for a GDB 4.17 release 
In-reply-to: Your message of "Mon, 26 Jan 1998 16:44:04 PST."
             <19980126164404.54169@cygnus.com> 
Date: Tue, 27 Jan 1998 19:06:45 -0800
From: Lee Iverson <leei@ai.sri.com>
Content-Type: text

In message <19980126164404.54169@cygnus.com> you write:
> Hi, I'm going to make a GDB 4.17 release soon.  I will make a branch for
> the release in about a week; we'll shoot for releasing it to the world
> two weeks after that.
> 
> If you have patches that are ready to go in, but have not yet been
> submitted, please send them in now.  If you don't have your FSF copyright
> assignment paperwork submitted and on-file at the FSF, we probably won't
> have time to get significant contributions in for this release.

What follows is a patch to enable hardware watchpoints under Irix and
manage overlapping requests so as to fulfill all requests and avoid
ioctl errors.  I'm currently using this code successfully under Irix
5.3 and 6.3.

I'm not sure whether I have the copyright assignment on file or not.
I have made contributions in the past, and certainly went through the
exercise of filling out an assignment form, but don't know if I
actually submitted it or not.

-------------------------------------------------------------------------------
Lee Iverson     		SRI International
leei@ai.sri.com			333 Ravenswood Ave., Menlo Park CA 94025
http://www.ai.sri.com/~leei/	(650) 859-3307

1998-01-27  Lee Iverson  <leei@Canada.AI.SRI.COM>

	* breakpoint.c (can_use_hardware_watchpoint): Change test for
	valid hw watchpoint to use HARDWARE_WATCHPOINT_TYPE_OK.
	* breakpoint.h: Define HARDWARE_WATCHPOINT_TYPE_OK to default
	value.
	* config/mips/nm-irix4.h (target_insert_watchpoint): Modify type
	argument to reflect change in interpretation in
	procfs_set_watchpoint.
	* config/mips/nm-irix5.h: Enable hardware watchpoints and define
	interface to procfs_set_watchpoint.
	* procfs.c (struct procinfo): Add struct hw_watch for tracking
	hardware watchpoints.
	(init_procinfo): Initialize pi->watchpoints.
	(do_attach): Initialize pi->watchpoints.
	(struct piocswatch): New structure for tracking PIOCSWATCH ioctls.
	(procfs_set_watchpoint): Reconstruct to track hardware watchpoints
	via hw_watch entry in procinfo.  Calls procfs_disable_wp or
	procfs_enable_wp to actually do work.
	(procfs_enable_wp): Enables watchpoint described while ensuring
	that conflicting/overlapping calls are prevented.  This may lead
	to recursive calls or to calls to procfs_disable_wp.
	Non-conflicting enable requests are passed to procfs_piocswatch.
	(procfs_disable_wp): Disables an existing watchpoint by calling
	procfs_piocswatch with zero rwflag for all entries in args chain.
	Frees watchpoint after disabled.
	(procfs_piocswatch): Creates/deletes piocswatch arg entry and
	calls ioctl for each low-level hardware watchpoint.
	
*** gdb/breakpoint.c.orig	Tue Dec 30 23:36:28 1997
--- gdb/breakpoint.c	Mon Jan 26 16:18:41 1998
*************** can_use_hardware_watchpoint (v)
*** 2847,2851 ****
        if (v->lval == lval_memory)
  	{
! 	  if (TYPE_LENGTH (VALUE_TYPE (v)) <= REGISTER_SIZE)
  	    found_memory_cnt++;
          }
--- 2847,2851 ----
        if (v->lval == lval_memory)
  	{
! 	  if (HARDWARE_WATCHPOINT_TYPE_OK (VALUE_TYPE (v)))
  	    found_memory_cnt++;
          }
*** gdb/breakpoint.h.orig	Thu Apr  3 15:19:31 1997
--- gdb/breakpoint.h	Mon Jan 26 16:18:41 1998
*************** enum bptype {
*** 91,94 ****
--- 91,98 ----
  };
  
+ #ifndef HARDWARE_WATCHPOINT_TYPE_OK
+ #  define HARDWARE_WATCHPOINT_TYPE_OK(t) (TYPE_LENGTH (t) <= REGISTER_SIZE)
+ #endif
+ 
  /* States of enablement of breakpoint. */
  
*** gdb/config/mips/nm-irix4.h.orig	Thu Apr 10 13:24:40 1997
--- gdb/config/mips/nm-irix4.h	Tue Jan 27 18:12:36 1998
*************** extern int procfs_stopped_by_watchpoint 
*** 57,61 ****
  /* Use these macros for watchpoint insertion/deletion.  */
  /* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
! #define target_insert_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, len, 2)
  #define target_remove_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, 0, 0)
  extern int procfs_set_watchpoint PARAMS ((int, CORE_ADDR, int, int));
--- 57,61 ----
  /* Use these macros for watchpoint insertion/deletion.  */
  /* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
! #define target_insert_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, len, (((type) >= 1) ? 1 : 0) | (!((type) & 1) ? 2 : 0))
  #define target_remove_watchpoint(addr, len, type) procfs_set_watchpoint (inferior_pid, addr, 0, 0)
  extern int procfs_set_watchpoint PARAMS ((int, CORE_ADDR, int, int));
*** gdb/config/mips/nm-irix5.h.orig	Tue Jan 27 18:02:02 1998
--- gdb/config/mips/nm-irix5.h	Tue Jan 27 18:12:26 1998
*************** Foundation, Inc., 59 Temple Place - Suit
*** 20,21 ****
--- 20,42 ----
  
  #include "nm-sysv4.h"
+ 
+ #define TARGET_HAS_HARDWARE_WATCHPOINTS
+ 
+ /* Temporary new watchpoint stuff */
+ #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ 	((type) == bp_hardware_watchpoint)
+ 
+ /* When a hardware watchpoint fires off the PC will be left at the
+    instruction which caused the watchpoint.  It will be necessary for
+    GDB to step over the watchpoint. */
+ 
+ #define STOPPED_BY_WATCHPOINT(W) \
+   procfs_stopped_by_watchpoint(inferior_pid)
+ 
+ #define HAVE_NONSTEPPABLE_WATCHPOINT
+ 
+ /* Use these macros for watchpoint insertion/deletion.  */
+ /* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
+ #define target_insert_watchpoint(addr, len, rw) procfs_set_watchpoint (inferior_pid, addr, len, (((rw) >= 1) ? 1 : 0) | (!((rw) & 1) ? 2 : 0))
+ #define target_remove_watchpoint(addr, len, rw) procfs_set_watchpoint (inferior_pid, addr, len, 0)
+ extern int procfs_set_watchpoint PARAMS ((int, CORE_ADDR, int, int));
*** gdb/procfs.c.orig	Mon Jul 14 18:05:10 1997
--- gdb/procfs.c	Tue Jan 27 18:59:08 1998
*************** struct procinfo {
*** 187,190 ****
--- 187,199 ----
    struct procfs_syscall_handler *syscall_handlers; 
    int new_child;		/* Non-zero if it's a new thread */
+ 
+ #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+   struct hw_watch {
+     struct hw_watch *next;
+     CORE_ADDR addr;
+     ulong_t len;
+     struct piocswatch *args;
+   } *watchpoints;
+ #endif
  };
  
*************** init_procinfo (pid, kill)
*** 2030,2033 ****
--- 2039,2046 ----
  #endif /* UNIXWARE */
  
+ #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+   pi->watchpoints = 0;
+ #endif
+ 
    if (!procfs_read_status (pi))
      proc_init_failed (pi, "procfs_read_status failed", kill);
*************** do_attach (pid)
*** 2991,2994 ****
--- 3004,3011 ----
    lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
  
+ #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+   pi->watchpoints = 0;
+ #endif
+ 
    if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
      {
*************** procfs_can_run ()
*** 5408,5437 ****
  #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
  
! /* Insert a watchpoint */
  int
! procfs_set_watchpoint(pid, addr, len, rw)
       int		pid;
       CORE_ADDR		addr;
       int		len;
!      int		rw;
  {
    struct procinfo	*pi;
!   prwatch_t		wpt;
  
    pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
!   wpt.pr_vaddr = (caddr_t)addr;
!   wpt.pr_size = len;
!   wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
!   if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
!     {
!       if (errno == E2BIG)
! 	return -1;
!       /* Currently it sometimes happens that the same watchpoint gets
! 	 deleted twice - don't die in this case (FIXME please) */
!       if (errno == ESRCH && len == 0)
! 	return 0;
!       print_sys_errmsg (pi->pathname, errno);
!       error ("PIOCSWATCH failed");
      }
    return 0;
  }
--- 5425,5740 ----
  #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
  
! /*
! 
! GLOBAL FUNCTION
! 
! 	procfs_set_watchpoint -- establish or remove a hardware watchpoint.
! 
! SYNOPSIS
! 
! 	int procfs_set_watchpoint(int pid,
! 				  CORE_ADDR addr,
! 				  int len,
! 				  int rwflags)
! 
! DESCRIPTION
! 
! 	Establish a hardware watchpoint covering the region of memory starting
! 	with addr of length len.  rwflags determines whether it is a read or
! 	write watchpoint (bit 1 = read, bit 2 = write), or whether the
! 	watchpoint is being disabled (rwflags = 0).
! 
! NOTES
! 
! 	For each hardware watchpoint established, a struct hw_watch is
! 	initialize to describe the watchpoint and linked into the chain at
! 	pi->watchpoints.  If it is subsequently disabled, the corresponding
! 	chain element is deleted.
! 
! 	All procfs_set_watchpoint actually does is search the pi->watchpoints
! 	chain to determine if an exact match to (addr,len) is found, in which
! 	case it either reasserts the wp (leading to a warning) or disables it
! 	(when rwflag is zero).  If no match is found, then it creates a new
! 	struct hw_watch, inserts it into the pi->watchpoints chain and the
! 	calls procfs_enable_wp.
! 
!  */
! 
! struct piocswatch {
!   struct piocswatch *next;
!   CORE_ADDR addr;
!   int len;
!   int flags;
! };
! 
! static int
! procfs_enable_wp PARAMS((struct procinfo *pi, struct hw_watch *wp,
! 			 CORE_ADDR addr, int len, int rwflags));
! 
! static int
! procfs_disable_wp PARAMS((struct procinfo *pi, struct hw_watch **prev));
! 
! static int
! procfs_piocswatch PARAMS((struct procinfo *pi, struct hw_watch *wp,
! 			  CORE_ADDR addr, int len, int rwflags));
! 
  int
! procfs_set_watchpoint(pid, addr, len, rwflags)
       int		pid;
       CORE_ADDR		addr;
       int		len;
!      int		rwflags;
  {
    struct procinfo	*pi;
!   struct hw_watch	**prev;
!   struct hw_watch	*wp;
  
    pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
!   
!   /*warning ("set_watchpoint 0x%x[%d] %s", addr, len,
! 	   (rwflags&1 ? (rwflags&2 ? "rw" : "r") : (rwflags&2 ? "w" : "-")));*/
! 
!   /* Find a pre-existing wp descr which matches request. */
!   for (prev = &pi->watchpoints, wp = *prev; wp; prev = &wp->next, wp = *prev)
!     if (wp->addr == addr && wp->len == len)
!       break;
! 
!   if (wp) {
!     if (rwflags)
!       return procfs_piocswatch (pi, wp, wp->addr, wp->len, rwflags);
!     else
!       return procfs_disable_wp (pi, prev);
!   }
! 
!   if (rwflags) {
!     /* If not found, then allocate a new one. */
!     wp = (struct hw_watch *) xmalloc (sizeof (*wp));
!     wp->addr = addr;
!     wp->len = len;
!     wp->next = pi->watchpoints;
!     wp->args = 0;
!     pi->watchpoints = wp;
! 
!     return procfs_enable_wp (pi, wp, addr, len, rwflags);
!   }
! 
!   return 0;
! }
! 
! /*
! 
! LOCAL FUNCTION
! 
! 	procfs_enable_wp -- establish a hardware watchpoint.
! 
! SYNOPSIS
! 
! 	int procfs_enable_wp(struct procinfo *pi,
! 			     struct hw_watch *wp,
! 			     CORE_ADDR addr,
! 			     int len,
! 			     int rwflags)
! 
! DESCRIPTION
! 
! 	Enable a hardware watchpoint covering the region of memory starting
! 	with addr of length len.  Manages conflicts between this request and
! 	previous calls by searching for overlapping requests in the current
! 	pi->watchpoints.  
! 
! NOTES
! 
! 	If no conflicts are found, then it calls procfs_piocswatch to enable
! 	the watchpoint.
! 
! 	If a conflict *is* found, then it recursively calls procfs_disable_wp
! 	and procfs_enable_wp so as to cover the requested area with a hardware
! 	watchpoint.
! 
! 	All bookkeeping is done in procfs_disable_wp and procfs_piocswatch.
! 
!  */
! 
! static int
! procfs_enable_wp (pi, wp, addr, len, rwflags)
!      struct procinfo	*pi;
!      struct hw_watch	*wp;
!      CORE_ADDR		addr;
!      int		len;
!      int		rwflags;
! {
!   struct hw_watch	**prev;
!   struct hw_watch	*wp1;
!   CORE_ADDR		addr_end = addr + len;
!   CORE_ADDR		wp1_end;
! 
!   /*warning ("enable_watchpoint 0x%x[%d] %s", addr, len,
! 	   (rwflags&1 ? (rwflags&2 ? "rw" : "r") : (rwflags&2 ? "w" : "-")));*/
! 
!   /* Find a pre-existing wp descr which overlaps request. */
!   for (prev = &wp->next, wp1 = *prev; wp1; prev = &wp1->next, wp1 = *prev)
!     if (wp1->addr <= addr_end
! 	&& (wp1_end = wp1->addr+wp1->len) >= addr) {
!       if (addr <= wp1->addr && addr_end >= wp1_end) {
! 	int ret = procfs_disable_wp (pi, prev);
! 	return ret || procfs_enable_wp (pi, wp, addr, len, rwflags);
! 
!       } else {
! 	int ret = 0;
! 	if (wp1->addr > addr)
! 	  ret = procfs_enable_wp (pi, wp, addr, wp1->addr-addr, rwflags);
! 	if (!ret && wp1_end < addr_end)
! 	  ret = procfs_enable_wp (pi, wp, wp1_end, addr_end-wp1_end, rwflags);
! 	return ret;
!       }
!     }
! 
!   return procfs_piocswatch (pi, wp, addr, len, rwflags);
! }
! 
! /*
! 
! LOCAL FUNCTION
! 
! 	procfs_disable_wp -- remove a hardware watchpoint.
! 
! SYNOPSIS
! 
! 	int procfs_disable_wp(struct procinfo *pi,
! 			      struct hw_watch **prev)
! 
! DESCRIPTION
! 
! 	Disable the hardware watchpoint which covers the region of memory
! 	starting with addr of length len.
! 
! NOTES
! 
! 	On entry, prev points to the pointer to the struct hw_watch to be
! 	disabled.
! 
! 	Repeatedly calls procfs_piocswatch with zero rwflag for each entry in
! 	the args chain.  This disables the low-level watchpoints and frees the
! 	struct piocswatch elements in the args chain.
! 
! 	Finally frees the now disabled struct hw_watch entry and updates the
! 	cahain pointer in prev to point past it.
! 
!  */
! 
! static int
! procfs_disable_wp (pi, prev)
!      struct procinfo	*pi;
!      struct hw_watch	**prev;
! {
!   struct hw_watch	*wp = *prev;
!   struct piocswatch	*args;
!   int			ret = 0;
! 
!   /*warning ("disable_watchpoint 0x%x[%d]", wp->addr, wp->len);*/
! 
!   /* Each piocswatch will delete wp->args, so reload repeatedly. */
!   while (! ret && (args = wp->args))
!     ret = procfs_piocswatch (pi, wp, args->addr, args->len, 0);
!   if (! ret) {
!     *prev = wp->next;
!     free (wp);
!   }
!   return ret;
! }
! 
! /*
! 
! LOCAL FUNCTION
! 
! 	procfs_piocswatch -- call ioctl (PIOCSWATCH) to enable/disable
! 		watchpoints.
! 
! SYNOPSIS
! 
! 	int procfs_piocswatch (struct procinfo *pi,
! 			       struct hw_watch *wp,
! 			       CORE_ADDR addr,
! 			       int len,
! 			       int rwflags)
! 
! DESCRIPTION
! 
! 	Calls ioctl(PIOCSWATCH) to request a hardware watchpoint covering the
! 	region of memory starting with addr of length len.  If rwflags is
! 	zero, then disables a pre-existing watchpoint.
! 
! NOTES
! 
! 	Searches for matching entries in args chain of struct hw_watch.  If
! 	not found, allocates and initializes a new struct piocswatch and
! 	places it in args chain.
! 
! 	When disabling an existing watchpoint, also frees the struct
! 	piocswatch entry and removes it from args chain.
!  */
! 
! static int
! procfs_piocswatch (pi, wp, addr, len, rwflags)
!      struct procinfo	*pi;
!      struct hw_watch	*wp;
!      CORE_ADDR		addr;
!      int                len;
!      int		rwflags;
! {
!   struct piocswatch *	args;
!   struct piocswatch **	prev;
!   prwatch_t		wpt = {0};
!   
!   for (prev = &wp->args, args = *prev; args; prev = &args->next, args = *prev)
!     if (args->addr == addr && args->len == len)
!       break;
! 
!   if (! args) {
!     args = (struct piocswatch *) xmalloc (sizeof (*args));
!     args->next = wp->args;
!     wp->args = args;
!     prev = &wp->args;
! 
!     args->addr = addr;
!     args->len = len;
!   } else {
!     if (args->flags == rwflags) {
!       warning ("watchpoint ioctl redo 0x%x[%d] %s", addr, len,
! 	       (rwflags&1
! 		? (rwflags&2 ? "rw" : "r")
! 		: (rwflags&2 ? "w"  : "-")));
!       return 0;
      }
+   }
+ 
+   if (! (args->flags = rwflags)) {
+     /* Remove piocswatch entry when disabled. */
+     *prev = args->next;
+     free (args);
+   }
+ 
+   wpt.pr_vaddr  = (caddr_t) addr;
+   wpt.pr_size   = (!!rwflags ? len : 0);
+   wpt.pr_wflags = (((rwflags&1) ? MA_READ : 0) | ((rwflags&2) ? MA_WRITE : 0));
+ 
+ #if 0
+   warning ("wp ioctl 0x%x[%d] 0x%x %s", 
+ 	   wpt.pr_vaddr, wpt.pr_size, wpt.pr_vaddr+wpt.pr_size,
+ 	   (rwflags&1 ? (rwflags&2 ? "rw" : "r") : (rwflags&2 ? "w" : "-")));
+ #endif
+ 
+   if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
+   {
+     if (errno == E2BIG)
+       return -1;
+     /* Currently it sometimes happens that the same watchpoint gets
+        deleted twice - don't die in this case (FIXME please) */
+     if (errno == ESRCH)
+       return 0;
+     print_sys_errmsg (pi->pathname, errno);
+     error ("PIOCSWATCH failed");
+   }
+ 
    return 0;
  }

-----End of forwarded message-----