Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [rfa] hardware breakpoints -- remote targets
@ 2002-08-06  9:19 Grace Sainsbury
  2002-08-08 10:06 ` Grace Sainsbury
  0 siblings, 1 reply; 7+ messages in thread
From: Grace Sainsbury @ 2002-08-06  9:19 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1022 bytes --]

I have added the remote breakpoint functions to the remote target
vector.

ok?

grace

2002-08-06  Grace Sainsbury  <graces@redhat.com>

	    * remote.c: (remote_wait, remote_async_wait): Add
              watchpoint
	      support for T-packets.
	      (set_hardware_watchpoint_limit, show_hardware_watchpoint_limit)
	      (set_hardware_breakpoint_limit,show_hardware_breakpoint_limit):
	      New functions. Add commands to call them.
	      (remote_check_watch_resources,remote_stopped_by_watchpoint)
	      (remote_stopped_data_address): New functions, add to target
	      vector.
	      (remote_insert_hw_breakpoint,remote_remove_hw_breakpoint): Change
	      prototypes to match other implementations of this
	      function. replace integer argument with pointer -- the
              length field in the Z-packet is the length of what is pointed
              to, or 1 if the pointer is null. Add to target vector.
	      (remote_insert_watchpoint, remote_remove_watchpoint): Add to 
              target vector.

[-- Attachment #2: watch.patch --]
[-- Type: text/plain, Size: 11514 bytes --]

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.89
diff -u -r1.89 remote.c
--- remote.c	23 Jul 2002 18:55:06 -0000	1.89
+++ remote.c	6 Aug 2002 16:13:57 -0000
@@ -250,6 +250,9 @@
   long remote_packet_size;
 };
 
+static int remote_stopped_by_watchpoint_p;
+static CORE_ADDR remote_watch_data_address;
+
 /* Handle for retreving the remote protocol data from gdbarch.  */
 static struct gdbarch_data *remote_gdbarch_data_handle;
 
@@ -3008,6 +3011,7 @@
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
   int thread_num = -1;
+  int addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3025,6 +3029,8 @@
       if (target_wait_loop_hook)
 	(*target_wait_loop_hook) ();
 
+      remote_stopped_by_watchpoint_p = 0;
+
       switch (buf[0])
 	{
 	case 'E':		/* Error of some sort */
@@ -3048,10 +3054,19 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		LONGEST pnum = 0;
+
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
 
-		/* Read the ``P'' register number.  */
-		LONGEST pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		if (!strstr ((const char *) p, "awatch"))
+		  {
+		    /* Read the ``P'' register number.  */
+		    pnum = strtol ((const char *) p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1=p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
@@ -3066,6 +3081,14 @@
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp ((const char *) p, "watch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "rwatch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
 		  }
 		else
 		  {
@@ -3222,10 +3245,13 @@
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
   int thread_num = -1;
+  int addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
 
+  remote_stopped_by_watchpoint_p = 0;
+
   while (1)
     {
       unsigned char *p;
@@ -3268,10 +3294,19 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		long pnum = 0;
 
-		/* Read the register number */
-		long pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
+		
+		if (!strstr ((const char *) p, "awatch"))
+		  {
+		    /* Read the register number.  */
+		    pnum = strtol ((const char *) p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1=p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
@@ -3286,7 +3321,16 @@
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp ((const char *) p, "watch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "rwatch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
 		  }
+		
 		else
 		  {
 		    struct packet_reg *reg = packet_reg_from_pnum (rs, pnum);
@@ -4797,7 +4841,7 @@
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int
+static int
 remote_insert_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4834,7 +4878,7 @@
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int
+static int
 remote_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4867,16 +4911,109 @@
 		  "remote_remove_watchpoint: reached end of function");
 }
 
+
+int remote_hw_watchpoint_limit = 0;
+int remote_hw_breakpoint_limit = 0;
+
+
+static void
+set_hardware_watchpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+          remote_hw_watchpoint_limit = val;
+	  return;
+	}
+    }
+  error ("Illegal argument for \"set remote hardware-watchpoint-limit\" command");
+}
+
+static void
+show_hardware_watchpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote hardware-watchpoint-limit\" command: `%s'", args);
+  printf_unfiltered ("Remote target supports %d hardware watchpoints.\n",
+		     remote_hw_watchpoint_limit);
+}
+
+static void
+set_hardware_breakpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+          remote_hw_breakpoint_limit = val;
+	  return;
+	}
+    }
+  error ("Illegal argument for \"set remote hardware-breakpoint-limit\" command");
+}
+
+static void
+show_hardware_breakpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote hardware-breakpoint-limit\" command: `%s'", args);
+  printf_unfiltered ("Remote target supports %d hardware breakpoints.\n",
+		     remote_hw_breakpoint_limit);
+}
+
+
+int
+remote_check_watch_resources (int type, int cnt, int ot)
+{
+  if (type == bp_hardware_breakpoint)
+    {
+      if (remote_hw_breakpoint_limit == 0)
+	return 0;
+      else if (cnt <= remote_hw_breakpoint_limit)
+	return 1;
+    }
+  else
+    {
+      if (remote_hw_watchpoint_limit == 0)
+	return 0;
+      else if (ot)
+	return -1;
+      else if (cnt <= remote_hw_watchpoint_limit)
+	return 1;
+    }
+  return -1;
+}
+
+int
+remote_stopped_by_watchpoint (void)
+{
+    return remote_stopped_by_watchpoint_p;
+}
+
+CORE_ADDR
+remote_stopped_data_address (void)
+{
+  return remote_watch_data_address;
+}
+
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int
-remote_insert_hw_breakpoint (CORE_ADDR addr, int len)
+static int
+remote_insert_hw_breakpoint (CORE_ADDR addr, char *shadow)
 {
+  int len=0;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
       
+  len = strlen (shadow);
+  len = len ? len : 1;
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't set hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4902,19 +5039,21 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_insert_hw_breakpoint: reached end of function");
 }
 
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int 
-remote_remove_hw_breakpoint (CORE_ADDR addr, int len)
+static int 
+remote_remove_hw_breakpoint (CORE_ADDR addr, char * shadow)
 {
+  int len;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
   
+  len = sizeof (shadow);
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't clear hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4940,7 +5079,7 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_remove_hw_breakpoint: reached end of function");
 }
 
 /* Some targets are only capable of doing downloads, and afterwards
@@ -5417,6 +5556,13 @@
   remote_ops.to_files_info = remote_files_info;
   remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_ops.to_remove_watchpoint = remote_remove_watchpoint;
   remote_ops.to_kill = remote_kill;
   remote_ops.to_load = generic_load;
   remote_ops.to_mourn_inferior = remote_mourn;
@@ -5832,7 +5978,14 @@
   remote_cisco_ops.to_xfer_memory = remote_xfer_memory;
   remote_cisco_ops.to_files_info = remote_files_info;
   remote_cisco_ops.to_insert_breakpoint = remote_insert_breakpoint;
-  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;  
+  remote_cisco_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_cisco_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_cisco_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_cisco_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_cisco_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_cisco_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_cisco_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
   remote_cisco_ops.to_kill = remote_kill;
   remote_cisco_ops.to_load = generic_load;
   remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn;
@@ -5922,6 +6075,13 @@
   remote_async_ops.to_files_info = remote_files_info;
   remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_async_ops.to_stopped_data_address = remote_stopped_data_address;
   remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior;
   remote_async_ops.to_terminal_ours = remote_async_terminal_ours;
   remote_async_ops.to_kill = remote_async_kill;
@@ -6114,6 +6274,22 @@
   add_cmd ("memory-read-packet-size", no_class,
 	   show_memory_read_packet_size,
 	   "Show the maximum number of bytes per memory-read packet.\n",
+	   &remote_show_cmdlist);
+  add_cmd ("hardware-watchpoint-limit", no_class,
+	   set_hardware_watchpoint_limit,
+	   "Set the maximum number of target hardware watchpoints.\n",
+	   &remote_set_cmdlist);
+  add_cmd ("hardware-watchpoint-limit", no_class,
+	   show_hardware_watchpoint_limit,
+	   "Show the maximum number of target hardware watchpoints.\n",
+	   &remote_show_cmdlist);
+  add_cmd ("hardware-breakpoint-limit", no_class,
+	   set_hardware_breakpoint_limit,
+	   "Set the maximum number of target hardware breakpoints.\n",
+	   &remote_set_cmdlist);
+  add_cmd ("hardware-breakpoint-limit", no_class,
+	   show_hardware_breakpoint_limit,
+	   "Show the maximum number of target hardware breakpoints.\n",
 	   &remote_show_cmdlist);
 
   add_show_from_set

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [rfa] hardware breakpoints -- remote targets
  2002-08-06  9:19 [rfa] hardware breakpoints -- remote targets Grace Sainsbury
@ 2002-08-08 10:06 ` Grace Sainsbury
  2002-08-08 11:30   ` Andrew Cagney
  2002-08-11  6:48   ` Eli Zaretskii
  0 siblings, 2 replies; 7+ messages in thread
From: Grace Sainsbury @ 2002-08-08 10:06 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]

I revised the patch to include Mark Salter's earlier patch, as well as
his documentation changes.

ok to commit?

grace

Changelog:

2002-08-08  Grace Sainsbury  <graces@redhat.com>
	
	* remote.c: (remote_wait, remote_async_wait): Add check for awatch
	T-packets; the 'a' is not taken as a register number.
	(set_hardware_watchpoint_limit, show_hardware_watchpoint_limit)
	(set_hardware_breakpoint_limit, show_hardware_breakpoint_limit):
	New functions. Add commands to call them.
	(remote_check_watch_resources, remote_stopped_by_watchpoint)
	(remote_stopped_data_address): New functions; add to target
	vector.
	(remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Change
	prototypes to match other implementations of this
	function. replace integer argument with pointer -- the length
	field in the Z-packet is the length of what is pointed to or 1 if
	pointer is null. Add to target vector.
	(remote_insert_watchpoint, remote_remove_watchpoint): Add to
	target vector.

	From Mark Salter:
	* remote.c (remote_wait): Add support to extract optional
	watchpoint information from T-packet. Ignore unrecognized
	optional info in T-packet.
	(remote_async_wait): Ditto.

doc/Changelog: 

2002-08-08  Grace Sainsbury  <graces@redhat.com>

	From Mark Salter:            
	* gdb.texinfo (Protocol): Document T packet extension to
	allow watchpoint address reporting.

[-- Attachment #2: watch2.patch --]
[-- Type: text/plain, Size: 13842 bytes --]

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.89
diff -u -r1.89 remote.c
--- remote.c	23 Jul 2002 18:55:06 -0000	1.89
+++ remote.c	8 Aug 2002 17:02:27 -0000
@@ -250,6 +250,7 @@
   long remote_packet_size;
 };
 
+
 /* Handle for retreving the remote protocol data from gdbarch.  */
 static struct gdbarch_data *remote_gdbarch_data_handle;
 
@@ -342,6 +343,14 @@
 
 /* */
 
+/* This is set to the data address of the access causing the target
+ * to stop for a watchpoint. */
+static CORE_ADDR remote_watch_data_address;
+
+/* This is non-zero if taregt stopped for a watchpoint. */
+static int remote_stopped_by_watchpoint_p;
+
+
 static struct target_ops remote_ops;
 
 static struct target_ops extended_remote_ops;
@@ -1107,7 +1116,7 @@
 
 #define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2)
 
-char *unpack_varlen_hex (char *buff, int *result);
+char *unpack_varlen_hex (char *buff, ULONGEST *result);
 
 static char *unpack_nibble (char *buf, int *val);
 
@@ -1228,7 +1237,7 @@
 
 char *
 unpack_varlen_hex (char *buff,	/* packet to parse */
-		   int *result)
+		   ULONGEST *result)
 {
   int nibble;
   int retval = 0;
@@ -3007,7 +3016,8 @@
 {
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
-  int thread_num = -1;
+  ULONGEST thread_num = -1;
+  ULONGEST addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3025,6 +3035,8 @@
       if (target_wait_loop_hook)
 	(*target_wait_loop_hook) ();
 
+      remote_stopped_by_watchpoint_p = 0;
+
       switch (buf[0])
 	{
 	case 'E':		/* Error of some sort */
@@ -3048,10 +3060,19 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		LONGEST pnum = 0;
 
-		/* Read the ``P'' register number.  */
-		LONGEST pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
+
+		if (!strstr ((const char *) p, "awatch"))
+		  {
+		    /* Read the ``P'' register number.  */
+		    pnum = strtol ((const char *) p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1=p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
@@ -3066,6 +3087,21 @@
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp ((const char *) p, "watch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "rwatch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
+		    else
+ 		      {
+ 			/* silently skip unknown optional info */
+ 			p_temp = (unsigned char *) strchr ((const char *) p1+1, ';');
+ 			if (p_temp)
+			  p = p_temp;
+ 		      }
 		  }
 		else
 		  {
@@ -3221,11 +3257,14 @@
 {
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
-  int thread_num = -1;
+  ULONGEST thread_num = -1;
+  ULONGEST addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
 
+  remote_stopped_by_watchpoint_p = 0;
+
   while (1)
     {
       unsigned char *p;
@@ -3268,10 +3307,19 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		long pnum = 0;
 
-		/* Read the register number */
-		long pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
+		
+		if (!strstr ((const char *) p, "awatch"))
+		  {
+		    /* Read the register number.  */
+		    pnum = strtol ((const char *) p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1=p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
@@ -3286,7 +3334,23 @@
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp ((const char *) p, "watch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "rwatch", p1 - p) == 0)
+			     || (strncmp ((const char *) p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
+		    else
+ 		      {
+ 			/* silently skip unknown optional info */
+ 			p_temp = (unsigned char *) strchr ((const char *) p1+1, ';');
+ 			if (p_temp)
+			  p = p_temp;
+ 		      }
 		  }
+		
 		else
 		  {
 		    struct packet_reg *reg = packet_reg_from_pnum (rs, pnum);
@@ -4797,7 +4861,7 @@
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int
+static int
 remote_insert_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4834,7 +4898,7 @@
 /* FIXME: This function should be static and a member of the remote
    target vector. */
 
-int
+static int
 remote_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4867,16 +4931,109 @@
 		  "remote_remove_watchpoint: reached end of function");
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
+
+int remote_hw_watchpoint_limit = 0;
+int remote_hw_breakpoint_limit = 0;
+
+
+static void
+set_hardware_watchpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+          remote_hw_watchpoint_limit = val;
+	  return;
+	}
+    }
+  error ("Illegal argument for \"set remote hardware-watchpoint-limit\" command");
+}
+
+static void
+show_hardware_watchpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote hardware-watchpoint-limit\" command: `%s'", args);
+  printf_unfiltered ("Remote target supports %d hardware watchpoints.\n",
+		     remote_hw_watchpoint_limit);
+}
+
+static void
+set_hardware_breakpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+          remote_hw_breakpoint_limit = val;
+	  return;
+	}
+    }
+  error ("Illegal argument for \"set remote hardware-breakpoint-limit\" command");
+}
+
+static void
+show_hardware_breakpoint_limit (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote hardware-breakpoint-limit\" command: `%s'", args);
+  printf_unfiltered ("Remote target supports %d hardware breakpoints.\n",
+		     remote_hw_breakpoint_limit);
+}
+
 
 int
-remote_insert_hw_breakpoint (CORE_ADDR addr, int len)
+remote_check_watch_resources (int type, int cnt, int ot)
 {
+  if (type == bp_hardware_breakpoint)
+    {
+      if (remote_hw_breakpoint_limit == 0)
+	return 0;
+      else if (cnt <= remote_hw_breakpoint_limit)
+	return 1;
+    }
+  else
+    {
+      if (remote_hw_watchpoint_limit == 0)
+	return 0;
+      else if (ot)
+	return -1;
+      else if (cnt <= remote_hw_watchpoint_limit)
+	return 1;
+    }
+  return -1;
+}
+
+int
+remote_stopped_by_watchpoint (void)
+{
+    return remote_stopped_by_watchpoint_p;
+}
+
+CORE_ADDR
+remote_stopped_data_address (void)
+{
+  if (remote_stopped_by_watchpoint ())
+    return remote_watch_data_address;
+  return (CORE_ADDR)0;
+}
+
+
+static int
+remote_insert_hw_breakpoint (CORE_ADDR addr, char *shadow)
+{
+  int len=0;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
       
+  len = strlen (shadow);
+  len = len ? len : 1;
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't set hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4902,19 +5059,19 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_insert_hw_breakpoint: reached end of function");
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
 
-int 
-remote_remove_hw_breakpoint (CORE_ADDR addr, int len)
+static int 
+remote_remove_hw_breakpoint (CORE_ADDR addr, char * shadow)
 {
+  int len;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
   
+  len = sizeof (shadow);
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't clear hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4940,7 +5097,7 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_remove_hw_breakpoint: reached end of function");
 }
 
 /* Some targets are only capable of doing downloads, and afterwards
@@ -5417,6 +5574,13 @@
   remote_ops.to_files_info = remote_files_info;
   remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_ops.to_remove_watchpoint = remote_remove_watchpoint;
   remote_ops.to_kill = remote_kill;
   remote_ops.to_load = generic_load;
   remote_ops.to_mourn_inferior = remote_mourn;
@@ -5832,7 +5996,14 @@
   remote_cisco_ops.to_xfer_memory = remote_xfer_memory;
   remote_cisco_ops.to_files_info = remote_files_info;
   remote_cisco_ops.to_insert_breakpoint = remote_insert_breakpoint;
-  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;  
+  remote_cisco_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_cisco_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_cisco_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_cisco_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_cisco_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_cisco_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_cisco_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
   remote_cisco_ops.to_kill = remote_kill;
   remote_cisco_ops.to_load = generic_load;
   remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn;
@@ -5922,6 +6093,13 @@
   remote_async_ops.to_files_info = remote_files_info;
   remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_async_ops.to_stopped_data_address = remote_stopped_data_address;
   remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior;
   remote_async_ops.to_terminal_ours = remote_async_terminal_ours;
   remote_async_ops.to_kill = remote_async_kill;
@@ -6114,6 +6292,22 @@
   add_cmd ("memory-read-packet-size", no_class,
 	   show_memory_read_packet_size,
 	   "Show the maximum number of bytes per memory-read packet.\n",
+	   &remote_show_cmdlist);
+  add_cmd ("hardware-watchpoint-limit", no_class,
+	   set_hardware_watchpoint_limit,
+	   "Set the maximum number of target hardware watchpoints.\n",
+	   &remote_set_cmdlist);
+  add_cmd ("hardware-watchpoint-limit", no_class,
+	   show_hardware_watchpoint_limit,
+	   "Show the maximum number of target hardware watchpoints.\n",
+	   &remote_show_cmdlist);
+  add_cmd ("hardware-breakpoint-limit", no_class,
+	   set_hardware_breakpoint_limit,
+	   "Set the maximum number of target hardware breakpoints.\n",
+	   &remote_set_cmdlist);
+  add_cmd ("hardware-breakpoint-limit", no_class,
+	   show_hardware_breakpoint_limit,
+	   "Show the maximum number of target hardware breakpoints.\n",
 	   &remote_show_cmdlist);
 
   add_show_from_set
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.107
diff -u -r1.107 gdb.texinfo
--- doc/gdb.texinfo	3 Aug 2002 23:37:07 -0000	1.107
+++ doc/gdb.texinfo	8 Aug 2002 17:02:33 -0000
@@ -14751,10 +14751,11 @@
 @var{AA} = two hex digit signal number; @var{n...} = register number
 (hex), @var{r...}  = target byte ordered register contents, size defined
 by @code{REGISTER_RAW_SIZE}; @var{n...} = @samp{thread}, @var{r...} =
-thread process ID, this is a hex integer; @var{n...} = other string not
-starting with valid hex digit.  @value{GDBN} should ignore this
-@var{n...}, @var{r...} pair and go on to the next.  This way we can
-extend the protocol.
+thread process ID, this is a hex integer; @var{n...} = (@samp{watch} | 
+@samp{rwatch} | @samp{awatch}, @var{r...} = data address, this is a hex
+integer; @var{n...} = other string not starting with valid hex digit.
+@value{GDBN} should ignore this @var{n...}, @var{r...} pair and go on
+to the next.  This way we can extend the protocol.
 
 @item @code{W}@var{AA}
 @tab

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [rfa] hardware breakpoints -- remote targets
  2002-08-08 10:06 ` Grace Sainsbury
@ 2002-08-08 11:30   ` Andrew Cagney
  2002-08-08 12:44     ` [patch] remote.c: unpack_varlen_hex Grace Sainsbury
  2002-08-09  8:41     ` [rfa] hardware breakpoints -- remote targets Grace Sainsbury
  2002-08-11  6:48   ` Eli Zaretskii
  1 sibling, 2 replies; 7+ messages in thread
From: Andrew Cagney @ 2002-08-08 11:30 UTC (permalink / raw)
  To: Grace Sainsbury; +Cc: gdb-patches, Eli Zaretskii

> I revised the patch to include Mark Salter's earlier patch, as well as
> his documentation changes.

Lets see, Mark's doco patch was previously approved vis:
http://sources.redhat.com/ml/gdb-patches/2000-11/msg00020.html
(Someone (me) has even gone through the table and has a patch to fix the 
formatting pending :-)

Hold back on the commit, though, until we've got the below ok.



> -char *unpack_varlen_hex (char *buff, int *result);
> +char *unpack_varlen_hex (char *buff, ULONGEST *result);

I didn't see a changelog entry for this.  Anyway, this change (and the 
corresponding int->ULONGEST tweaks) should be separated out committed 
independantly.  This part is approved.



> +/* This is set to the data address of the access causing the target
> + * to stop for a watchpoint. */
(NB: no leading ``*'' on the second comment line.)

> +static CORE_ADDR remote_watch_data_address;
> +
> +/* This is non-zero if taregt stopped for a watchpoint. */
> +static int remote_stopped_by_watchpoint_p;
> +
> +

For the above can you please add a ``FIXME: graces/YYYY-MM-DD:'' style 
comment noteing that, like gdbarch_tdep() for ``struct gdbarch'', these 
static variables should be bound to an instance of the target object. 
Only  there isn't such a thing :-(



> @@ -3025,6 +3035,8 @@
>        if (target_wait_loop_hook)
>  	(*target_wait_loop_hook) ();
>  
> +      remote_stopped_by_watchpoint_p = 0;
> +
>        switch (buf[0])
>  	{
>  	case 'E':		/* Error of some sort */
> @@ -3048,10 +3060,19 @@
>  		unsigned char *p1;
>  		char *p_temp;
>  		int fieldsize;
> +		LONGEST pnum = 0;
>  
> -		/* Read the ``P'' register number.  */
> -		LONGEST pnum = strtol ((const char *) p, &p_temp, 16);
> -		p1 = (unsigned char *) p_temp;
> +		/* If this packet is an awatch packet, don't parse the 'a'
> +		   as a register number.  */

Add a comment mentioning that ``p1'' is left pointing to ``p'' if there 
wasn't a register number.



> +		if (!strstr ((const char *) p, "awatch"))

Use ``strncmp (p, "awatch", strlen ("awatch")) != 0''.

This is because the string compare needs to be anchored on the first 
character (otherwize it could miss-parse ``00=a123;awatch''.  BTW, it 
should be possible to safely remove most of those ``(const char*)'' and 
``(char*)'' casts.


> +		  {
> +		    /* Read the ``P'' register number.  */
> +		    pnum = strtol ((const char *) p, &p_temp, 16);
> +		    p1 = (unsigned char *) p_temp;
> +		  }
> +		else 
> +		  p1=p;

Don't forget the spaces:
	p1 = p;



>  		if (p1 == p)	/* No register number present here */
>  		  {
> @@ -3066,6 +3087,21 @@
>  			record_currthread (thread_num);
>  			p = (unsigned char *) p_temp;
>  		      }
> +		    else if ((strncmp ((const char *) p, "watch", p1 - p) == 0)
> +			     || (strncmp ((const char *) p, "rwatch", p1 - p) == 0)
> +			     || (strncmp ((const char *) p, "awatch", p1 - p) == 0))
> +		      {
> +			remote_stopped_by_watchpoint_p = 1;
> +			p = unpack_varlen_hex (++p1, &addr);
> +			remote_watch_data_address = (CORE_ADDR)addr;
> +		      }
> +		    else
> + 		      {
> + 			/* silently skip unknown optional info */
> + 			p_temp = (unsigned char *) strchr ((const char *) p1+1, ';');

Spaces, ``p1 + 1'', no cast.  The comment should be a sentence (hi MarkK 
;-) with period and two spaces after it :-)


> @@ -3268,10 +3307,19 @@
>  		unsigned char *p1;
>  		char *p_temp;
>  		int fieldsize;
> +		long pnum = 0;
>  
> -		/* Read the register number */
> -		long pnum = strtol ((const char *) p, &p_temp, 16);
> -		p1 = (unsigned char *) p_temp;
> +		/* If this packet is an awatch packet, don't parse the 'a'

see the comments above ...



> +static void
> +set_hardware_watchpoint_limit (char *args, int from_tty)
> +{
> +  if (args)
> +    {
> +      char *arg_end;
> +      int val = strtoul (args, &arg_end, 10);
> +      if (*args && *arg_end == '\0')
> +        {
> +          remote_hw_watchpoint_limit = val;
> +	  return;
> +	}
> +    }
> +  error ("Illegal argument for \"set remote hardware-watchpoint-limit\" command");
> +}

Hmm, can you please split out the new commands from the other parts of 
the patch so that they can be considered separatly.  I'm wondering if a 
better way of doing this is to have GDB automatically detect if another 
watchpoint is available.

Anyway new commands would need doco.

Andrew

(And thanks for finally creating a patch that adds watchpoint support to 
the target vector where it belongs!)


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [patch] remote.c: unpack_varlen_hex
  2002-08-08 11:30   ` Andrew Cagney
@ 2002-08-08 12:44     ` Grace Sainsbury
  2002-08-09  8:41     ` [rfa] hardware breakpoints -- remote targets Grace Sainsbury
  1 sibling, 0 replies; 7+ messages in thread
From: Grace Sainsbury @ 2002-08-08 12:44 UTC (permalink / raw)
  To: gdb-patches, Andrew Cagney

[-- Attachment #1: Type: text/plain, Size: 308 bytes --]

I'm commiting the ulongest patch with a separate changelog.

grace

2002-08-08  Grace Sainsbury  <graces@redhat.com>

	    * remote.c (remote_wait, remote_async_wait): Change
            thread_num from int to ULONGEST.
	    (unpack_varlen_hex): Change result parameter from
            int * to ULONGEST *.

[-- Attachment #2: ulongest.patch --]
[-- Type: text/plain, Size: 1179 bytes --]

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.89
diff -u -r1.89 remote.c
--- remote.c	23 Jul 2002 18:55:06 -0000	1.89
+++ remote.c	8 Aug 2002 19:43:18 -0000
@@ -1107,7 +1107,7 @@
 
 #define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2)
 
-char *unpack_varlen_hex (char *buff, int *result);
+char *unpack_varlen_hex (char *buff, ULONGEST *result);
 
 static char *unpack_nibble (char *buf, int *val);
 
@@ -1228,7 +1228,7 @@
 
 char *
 unpack_varlen_hex (char *buff,	/* packet to parse */
-		   int *result)
+		   ULONGEST *result)
 {
   int nibble;
   int retval = 0;
@@ -3007,7 +3007,7 @@
 {
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
-  int thread_num = -1;
+  ULONGEST thread_num = -1;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3221,7 +3221,7 @@
 {
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
-  int thread_num = -1;
+  ULONGEST thread_num = -1;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [rfa] hardware breakpoints -- remote targets
  2002-08-08 11:30   ` Andrew Cagney
  2002-08-08 12:44     ` [patch] remote.c: unpack_varlen_hex Grace Sainsbury
@ 2002-08-09  8:41     ` Grace Sainsbury
  2002-08-09  9:26       ` Andrew Cagney
  1 sibling, 1 reply; 7+ messages in thread
From: Grace Sainsbury @ 2002-08-09  8:41 UTC (permalink / raw)
  To: gdb-patches, Andrew Cagney

[-- Attachment #1: Type: text/plain, Size: 847 bytes --]

I made the sugested changes, and removed the set and show functions
from this patch.

ok?

grace

2002-08-09  Grace Sainsbury  <graces@redhat.com>

        * remote.c: (remote_wait, remote_async_wait): Add check for awatch
        T-packets; the 'a' is not taken as a register number.
	(remote_check_watch_resources, remote_stopped_by_watchpoint)
        (remote_stopped_data_address): New functions; add to target
        vector.
        (remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Change
        prototypes to match other implementations of this
        function. replace integer argument with pointer -- the length
        field in the Z-packet is the length of what is pointed to or 1 if
        pointer is null. Add to target vector.
        (remote_insert_watchpoint, remote_remove_watchpoint): Add to
        target vector.

[-- Attachment #2: watch.patch --]
[-- Type: text/plain, Size: 11247 bytes --]

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.90
diff -u -r1.90 remote.c
--- remote.c	8 Aug 2002 19:45:50 -0000	1.90
+++ remote.c	9 Aug 2002 15:29:38 -0000
@@ -250,6 +250,7 @@
   long remote_packet_size;
 };
 
+
 /* Handle for retreving the remote protocol data from gdbarch.  */
 static struct gdbarch_data *remote_gdbarch_data_handle;
 
@@ -340,7 +341,17 @@
   return NULL;
 }
 
-/* */
+/* FIXME: graces/2002-08-08: These variables should eventually be
+   bound to an instance of the target object (as in gdbarch-tdep()),
+   when such a thing exists.  */
+
+/* This is set to the data address of the access causing the target
+   to stop for a watchpoint.  */
+static CORE_ADDR remote_watch_data_address;
+
+/* This is non-zero if taregt stopped for a watchpoint. */
+static int remote_stopped_by_watchpoint_p;
+
 
 static struct target_ops remote_ops;
 
@@ -3008,6 +3019,7 @@
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
   ULONGEST thread_num = -1;
+  ULONGEST addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3025,6 +3037,8 @@
       if (target_wait_loop_hook)
 	(*target_wait_loop_hook) ();
 
+      remote_stopped_by_watchpoint_p = 0;
+
       switch (buf[0])
 	{
 	case 'E':		/* Error of some sort */
@@ -3048,24 +3062,52 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		LONGEST pnum = 0;
+
+		/* If the packet contains a register number save it in pnum
+		   and set p1 to point to the character following it. 
+		   Otherwise p1 points to p.  */
 
-		/* Read the ``P'' register number.  */
-		LONGEST pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
+
+		if (strncmp (p, "awatch", strlen("awatch")) != 0)
+		  {
+		    /* Read the ``P'' register number.  */
+		    pnum = strtol (p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1 = p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
-		    p1 = (unsigned char *) strchr ((const char *) p, ':');
+		    p1 = (unsigned char *) strchr (p, ':');
 		    if (p1 == NULL)
 		      warning ("Malformed packet(a) (missing colon): %s\n\
 Packet: '%s'\n",
 			       p, buf);
-		    if (strncmp ((const char *) p, "thread", p1 - p) == 0)
+		    if (strncmp (p, "thread", p1 - p) == 0)
 		      {
 			p_temp = unpack_varlen_hex (++p1, &thread_num);
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp (p, "watch", p1 - p) == 0)
+			     || (strncmp (p, "rwatch", p1 - p) == 0)
+			     || (strncmp (p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
+		    else
+ 		      {
+ 			/* Silently skip unknown optional info.  */
+ 			p_temp = strchr (p1 + 1, ';');
+ 			if (p_temp)
+			  p = (unsigned char *) p_temp;
+ 		      }
 		  }
 		else
 		  {
@@ -3222,10 +3264,13 @@
   struct remote_state *rs = get_remote_state ();
   unsigned char *buf = alloca (rs->remote_packet_size);
   ULONGEST thread_num = -1;
+  ULONGEST addr;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
 
+  remote_stopped_by_watchpoint_p = 0;
+
   while (1)
     {
       unsigned char *p;
@@ -3268,25 +3313,54 @@
 		unsigned char *p1;
 		char *p_temp;
 		int fieldsize;
+		long pnum = 0;
 
-		/* Read the register number */
-		long pnum = strtol ((const char *) p, &p_temp, 16);
-		p1 = (unsigned char *) p_temp;
+		/* If the packet contains a register number, save it in pnum
+		   and set p1 to point to the character following it. 
+		   Otherwise p1 points to p.  */
+
+		/* If this packet is an awatch packet, don't parse the 'a'
+		   as a register number.  */
+		
+		if (!strncmp (p, "awatch", strlen ("awatch")) != 0)
+		  {
+		    /* Read the register number.  */
+		    pnum = strtol (p, &p_temp, 16);
+		    p1 = (unsigned char *) p_temp;
+		  }
+		else 
+		  p1 = p;
 
 		if (p1 == p)	/* No register number present here */
 		  {
-		    p1 = (unsigned char *) strchr ((const char *) p, ':');
+		    p1 = (unsigned char *) strchr (p, ':');
 		    if (p1 == NULL)
 		      warning ("Malformed packet(a) (missing colon): %s\n\
 Packet: '%s'\n",
 			       p, buf);
-		    if (strncmp ((const char *) p, "thread", p1 - p) == 0)
+		    if (strncmp (p, "thread", p1 - p) == 0)
 		      {
 			p_temp = unpack_varlen_hex (++p1, &thread_num);
 			record_currthread (thread_num);
 			p = (unsigned char *) p_temp;
 		      }
+		    else if ((strncmp (p, "watch", p1 - p) == 0)
+			     || (strncmp (p, "rwatch", p1 - p) == 0)
+			     || (strncmp (p, "awatch", p1 - p) == 0))
+		      {
+			remote_stopped_by_watchpoint_p = 1;
+			p = unpack_varlen_hex (++p1, &addr);
+			remote_watch_data_address = (CORE_ADDR)addr;
+		      }
+		    else
+ 		      {
+ 			/* Silently skip unknown optional info.  */
+ 			p_temp = (unsigned char *) strchr (p1 + 1, ';');
+ 			if (p_temp)
+			  p = p_temp;
+ 		      }
 		  }
+		
 		else
 		  {
 		    struct packet_reg *reg = packet_reg_from_pnum (rs, pnum);
@@ -4794,10 +4868,7 @@
     }
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
-
-int
+static int
 remote_insert_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4831,10 +4902,8 @@
 		  "remote_insert_watchpoint: reached end of function");
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
 
-int
+static int
 remote_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4867,16 +4936,60 @@
 		  "remote_remove_watchpoint: reached end of function");
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
+
+int remote_hw_watchpoint_limit = 0;
+int remote_hw_breakpoint_limit = 0;
 
 int
-remote_insert_hw_breakpoint (CORE_ADDR addr, int len)
+remote_check_watch_resources (int type, int cnt, int ot)
 {
+  if (type == bp_hardware_breakpoint)
+    {
+      if (remote_hw_breakpoint_limit == 0)
+	return 0;
+      else if (cnt <= remote_hw_breakpoint_limit)
+	return 1;
+    }
+  else
+    {
+      if (remote_hw_watchpoint_limit == 0)
+	return 0;
+      else if (ot)
+	return -1;
+      else if (cnt <= remote_hw_watchpoint_limit)
+	return 1;
+    }
+  return -1;
+}
+
+int
+remote_stopped_by_watchpoint (void)
+{
+    return remote_stopped_by_watchpoint_p;
+}
+
+CORE_ADDR
+remote_stopped_data_address (void)
+{
+  if (remote_stopped_by_watchpoint ())
+    return remote_watch_data_address;
+  return (CORE_ADDR)0;
+}
+
+
+static int
+remote_insert_hw_breakpoint (CORE_ADDR addr, char *shadow)
+{
+  int len = 0;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
       
+  /* The length field should be set to soething so that the packet is
+     well formed.  */
+
+  len = strlen (shadow);
+  len = len ? len : 1;
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't set hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4902,19 +5015,19 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_insert_hw_breakpoint: reached end of function");
 }
 
-/* FIXME: This function should be static and a member of the remote
-   target vector. */
 
-int 
-remote_remove_hw_breakpoint (CORE_ADDR addr, int len)
+static int 
+remote_remove_hw_breakpoint (CORE_ADDR addr, char *shadow)
 {
+  int len;
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
   char *p = buf;
   
+  len = sizeof (shadow);
   if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE)
     error ("Can't clear hardware breakpoint without the '%s' (%s) packet\n",
 	   remote_protocol_Z[Z_PACKET_HARDWARE_BP].name,
@@ -4940,7 +5053,7 @@
       return 0;
     }
   internal_error (__FILE__, __LINE__,
-		  "remote_remove_watchpoint: reached end of function");
+		  "remote_remove_hw_breakpoint: reached end of function");
 }
 
 /* Some targets are only capable of doing downloads, and afterwards
@@ -5417,6 +5530,13 @@
   remote_ops.to_files_info = remote_files_info;
   remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_ops.to_remove_watchpoint = remote_remove_watchpoint;
   remote_ops.to_kill = remote_kill;
   remote_ops.to_load = generic_load;
   remote_ops.to_mourn_inferior = remote_mourn;
@@ -5832,7 +5952,14 @@
   remote_cisco_ops.to_xfer_memory = remote_xfer_memory;
   remote_cisco_ops.to_files_info = remote_files_info;
   remote_cisco_ops.to_insert_breakpoint = remote_insert_breakpoint;
-  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint;  
+  remote_cisco_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_cisco_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_cisco_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_cisco_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_cisco_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_cisco_ops.to_stopped_data_address = remote_stopped_data_address;
+  remote_cisco_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
   remote_cisco_ops.to_kill = remote_kill;
   remote_cisco_ops.to_load = generic_load;
   remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn;
@@ -5922,6 +6049,13 @@
   remote_async_ops.to_files_info = remote_files_info;
   remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint;
   remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint;
+  remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
+  remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
+  remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
+  remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint;
+  remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint;
+  remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
+  remote_async_ops.to_stopped_data_address = remote_stopped_data_address;
   remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior;
   remote_async_ops.to_terminal_ours = remote_async_terminal_ours;
   remote_async_ops.to_kill = remote_async_kill;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [rfa] hardware breakpoints -- remote targets
  2002-08-09  8:41     ` [rfa] hardware breakpoints -- remote targets Grace Sainsbury
@ 2002-08-09  9:26       ` Andrew Cagney
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Cagney @ 2002-08-09  9:26 UTC (permalink / raw)
  To: Grace Sainsbury; +Cc: gdb-patches

> I made the sugested changes, and removed the set and show functions
> from this patch.
> 
> ok?
> 
> grace
> 
> 2002-08-09  Grace Sainsbury  <graces@redhat.com>
> 
>         * remote.c: (remote_wait, remote_async_wait): Add check for awatch
>         T-packets; the 'a' is not taken as a register number.
> 	(remote_check_watch_resources, remote_stopped_by_watchpoint)
>         (remote_stopped_data_address): New functions; add to target
>         vector.
>         (remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Change
>         prototypes to match other implementations of this
>         function. replace integer argument with pointer -- the length
>         field in the Z-packet is the length of what is pointed to or 1 if
>         pointer is null. Add to target vector.
>         (remote_insert_watchpoint, remote_remove_watchpoint): Add to
>         target vector.
> 

Yes.  Thanks!

I suspect the set/show stuff is going to need a bit of brainstorming 
(and knowing GDB's luck, a refinement to the remote protocol).

Hmm, now you get to the tricky bit.  Getting a single native 
i386-unknown-linux-gnu gdb to use remote watchpoints when remote but 
native watchpoints when native ... :-)

enjoy,
Andrew



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [rfa] hardware breakpoints -- remote targets
  2002-08-08 10:06 ` Grace Sainsbury
  2002-08-08 11:30   ` Andrew Cagney
@ 2002-08-11  6:48   ` Eli Zaretskii
  1 sibling, 0 replies; 7+ messages in thread
From: Eli Zaretskii @ 2002-08-11  6:48 UTC (permalink / raw)
  To: graces; +Cc: gdb-patches

> Date: Thu, 8 Aug 2002 13:06:48 -0400
> From: Grace Sainsbury <graces@redhat.com>
> 
> I revised the patch to include Mark Salter's earlier patch, as well as
> his documentation changes.
> 
> ok to commit?

The documentation part is approved.


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-08-11 13:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-06  9:19 [rfa] hardware breakpoints -- remote targets Grace Sainsbury
2002-08-08 10:06 ` Grace Sainsbury
2002-08-08 11:30   ` Andrew Cagney
2002-08-08 12:44     ` [patch] remote.c: unpack_varlen_hex Grace Sainsbury
2002-08-09  8:41     ` [rfa] hardware breakpoints -- remote targets Grace Sainsbury
2002-08-09  9:26       ` Andrew Cagney
2002-08-11  6:48   ` Eli Zaretskii

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox