* remote.c: (remote_wait, remote_async_wait): Add check for awatch
authorGrace Sainsbury <graces@redhat.com>
Fri, 9 Aug 2002 16:41:25 +0000 (16:41 +0000)
committerGrace Sainsbury <graces@redhat.com>
Fri, 9 Aug 2002 16:41:25 +0000 (16:41 +0000)
        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.

        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:
From Mark Salter:
* gdb.texinfo (Protocol): Document T packet extension to
allow watchpoint address reporting.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/remote.c

index 673a6291e3ce35c880eed69ea3ee036e668d6296..659e8b041fdfa52b058f58fcea9811ab462954d2 100644 (file)
@@ -1,3 +1,24 @@
+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.
+
+        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.
+
 2002-08-09  Corinna Vinschen  <vinschen@redhat.com>
 
        * cli/cli-dump.c: Change fopen modes to use binary open modes
 
 2002-08-08  Grace Sainsbury  <graces@redhat.com>
 
-       * remote.c (remote_wait, remote_async_wait): Change thread_num
-       ULONGEST.
-       * (unpack_varlen_hex): Change result prameter to ULONGEST *.
+       * remote.c (remote_wait, remote_async_wait): Change
+        thread_num from int to ULONGEST.
+       (unpack_varlen_hex): Change result parameter from
+       int * to ULONGEST *.
 
 2002-08-08  Andrew Cagney  <ac131313@redhat.com>
 
index 384117a193c0d5ac54a00c73b08204c4b6c6168e..b9d82f09765a8ad8c825685e66ba4b043f4d5166 100644 (file)
@@ -1,3 +1,10 @@
+2002-08-08  Grace Sainsbury  <graces@redhat.com>
+
+       From Mark Salter:            
+       * gdb.texinfo (Protocol): Document T packet extension to
+       allow watchpoint address reporting.
+
+
 2002-08-03  Andrew Cagney  <ac131313@redhat.com>
 
        * gdb.texinfo (Dump/Restore Files): Move `[]' to outside of @var.
index bd205626ed120cb3ac1562c06ca880daad326479..dd5e7aa3c6ee207c480bd0f6cf6b1f17f25939a7 100644 (file)
@@ -14751,10 +14751,11 @@ conventions is used.
 @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
index 6bda0842c8f9c80e1f95962253711768e8449fa7..0c3f23a527eb0ad93438507feac6530a95df888c 100644 (file)
@@ -250,6 +250,7 @@ struct remote_state
   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 @@ packet_reg_from_pnum (struct remote_state *rs, LONGEST pnum)
   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 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
   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 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
       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 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
                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 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
   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 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
                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 @@ watchpoint_to_Z_packet (int type)
     }
 }
 
-/* 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 (CORE_ADDR addr, int len, int type)
                  "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 (CORE_ADDR addr, int len, int type)
                  "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 @@ remote_insert_hw_breakpoint (CORE_ADDR addr, int len)
       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 @@ remote_remove_hw_breakpoint (CORE_ADDR addr, int len)
       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 @@ Specify the serial device it is connected to\n\
   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 @@ Specify the serial device it is connected to (e.g. host:2020).";
   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 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   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;