2010-03-25 Doug Kwan <dougkwan@google.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index 0ed49b9e5164553533fa0a1c84885018a0105cab..0c791aa220f345d3fa3735d822f61d73a56d9f74 100644 (file)
@@ -72,8 +72,8 @@
 static char *target_buf;
 static long target_buf_size;
 /*static*/ void
-encode_actions (struct breakpoint *t, char ***tdp_actions,
-               char ***stepping_actions);
+encode_actions (struct breakpoint *t, struct bp_location *tloc,
+               char ***tdp_actions, char ***stepping_actions);
 
 /* The size to align memory write packets, when practical.  The protocol
    does not guarantee any alignment, and gdb will generate short
@@ -173,8 +173,6 @@ static CORE_ADDR remote_address_masked (CORE_ADDR);
 
 static void print_packet (char *);
 
-static unsigned long crc32 (unsigned char *, int, unsigned int);
-
 static void compare_sections_command (char *, int);
 
 static void packet_command (char *, int);
@@ -2682,6 +2680,15 @@ remote_threads_extra_info (struct thread_info *tp)
 }
 \f
 
+/* Implement the to_get_ada_task_ptid function for the remote targets.  */
+
+static ptid_t
+remote_get_ada_task_ptid (long lwp, long thread)
+{
+  return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
+}
+\f
+
 /* Restart the remote side; this is an extended protocol operation.  */
 
 static void
@@ -4637,26 +4644,23 @@ do_stop_reply_xfree (void *arg)
 static struct stop_reply *
 queued_stop_reply (ptid_t ptid)
 {
-  struct stop_reply *it, *prev;
-  struct stop_reply head;
-
-  head.next = stop_reply_queue;
-  prev = &head;
-
-  it = head.next;
-
-  if (!ptid_equal (ptid, minus_one_ptid))
-    for (; it; prev = it, it = it->next)
-      if (ptid_equal (ptid, it->ptid))
-       break;
+  struct stop_reply *it;
+  struct stop_reply **it_link;
 
-  if (it)
+  it = stop_reply_queue;
+  it_link = &stop_reply_queue;
+  while (it)
     {
-      prev->next = it->next;
-      it->next = NULL;
-    }
+      if (ptid_match (it->ptid, ptid))
+       {
+         *it_link = it->next;
+         it->next = NULL;
+         break;
+       }
 
-  stop_reply_queue = head.next;
+      it_link = &it->next;
+      it = *it_link;
+    }
 
   if (stop_reply_queue)
     /* There's still at least an event left.  */
@@ -6169,10 +6173,13 @@ handle_notification (char *buf, size_t length)
   if (strncmp (buf, "Stop:", 5) == 0)
     {
       if (pending_stop_reply)
-       /* We've already parsed the in-flight stop-reply, but the stub
-          for some reason thought we didn't, possibly due to timeout
-          on its side.  Just ignore it.  */
-       ;
+       {
+         /* We've already parsed the in-flight stop-reply, but the
+            stub for some reason thought we didn't, possibly due to
+            timeout on its side.  Just ignore it.  */
+         if (remote_debug)
+           fprintf_unfiltered (gdb_stdlog, "ignoring resent notification\n");
+       }
       else
        {
          struct cleanup *old_chain;
@@ -6190,6 +6197,9 @@ handle_notification (char *buf, size_t length)
          /* Notify the event loop there's a stop reply to acknowledge
             and that there may be more events to fetch.  */
          mark_async_event_handler (remote_async_get_pending_events_token);
+
+         if (remote_debug)
+           fprintf_unfiltered (gdb_stdlog, "stop notification captured\n");
        }
     }
   else
@@ -7530,7 +7540,7 @@ static unsigned long crc32_table[256] =
 {0, 0};
 
 static unsigned long
-crc32 (unsigned char *buf, int len, unsigned int crc)
+crc32 (const unsigned char *buf, int len, unsigned int crc)
 {
   if (!crc32_table[1])
     {
@@ -7554,38 +7564,59 @@ crc32 (unsigned char *buf, int len, unsigned int crc)
   return crc;
 }
 
+/* Verify memory using the "qCRC:" request.  */
+
+static int
+remote_verify_memory (struct target_ops *ops,
+                     const gdb_byte *data, CORE_ADDR lma, ULONGEST size)
+{
+  struct remote_state *rs = get_remote_state ();
+  unsigned long host_crc, target_crc;
+  char *tmp;
+
+  /* FIXME: assumes lma can fit into long.  */
+  xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx",
+            (long) lma, (long) size);
+  putpkt (rs->buf);
+
+  /* Be clever; compute the host_crc before waiting for target
+     reply.  */
+  host_crc = crc32 (data, size, 0xffffffff);
+
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  if (rs->buf[0] == 'E')
+    return -1;
+
+  if (rs->buf[0] != 'C')
+    error (_("remote target does not support this operation"));
+
+  for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++)
+    target_crc = target_crc * 16 + fromhex (*tmp);
+
+  return (host_crc == target_crc);
+}
+
 /* compare-sections command
 
    With no arguments, compares each loadable section in the exec bfd
    with the same memory range on the target, and reports mismatches.
-   Useful for verifying the image on the target against the exec file.
-   Depends on the target understanding the new "qCRC:" request.  */
-
-/* FIXME: cagney/1999-10-26: This command should be broken down into a
-   target method (target verify memory) and generic version of the
-   actual command.  This will allow other high-level code (especially
-   generic_load()) to make use of this target functionality.  */
+   Useful for verifying the image on the target against the exec file.  */
 
 static void
 compare_sections_command (char *args, int from_tty)
 {
-  struct remote_state *rs = get_remote_state ();
   asection *s;
-  unsigned long host_crc, target_crc;
   struct cleanup *old_chain;
-  char *tmp;
   char *sectdata;
   const char *sectname;
   bfd_size_type size;
   bfd_vma lma;
   int matched = 0;
   int mismatched = 0;
+  int res;
 
   if (!exec_bfd)
     error (_("command cannot be used without an exec file"));
-  if (!current_target.to_shortname ||
-      strcmp (current_target.to_shortname, "remote") != 0)
-    error (_("command can only be used with remote target"));
 
   for (s = exec_bfd->sections; s; s = s->next)
     {
@@ -7602,33 +7633,22 @@ compare_sections_command (char *args, int from_tty)
 
       matched = 1;             /* do this section */
       lma = s->lma;
-      /* FIXME: assumes lma can fit into long.  */
-      xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx",
-                (long) lma, (long) size);
-      putpkt (rs->buf);
 
-      /* Be clever; compute the host_crc before waiting for target
-        reply.  */
       sectdata = xmalloc (size);
       old_chain = make_cleanup (xfree, sectdata);
       bfd_get_section_contents (exec_bfd, s, sectdata, 0, size);
-      host_crc = crc32 ((unsigned char *) sectdata, size, 0xffffffff);
 
-      getpkt (&rs->buf, &rs->buf_size, 0);
-      if (rs->buf[0] == 'E')
+      res = target_verify_memory (sectdata, lma, size);
+
+      if (res == -1)
        error (_("target memory fault, section %s, range %s -- %s"), sectname,
               paddress (target_gdbarch, lma),
               paddress (target_gdbarch, lma + size));
-      if (rs->buf[0] != 'C')
-       error (_("remote target does not support this operation"));
-
-      for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++)
-       target_crc = target_crc * 16 + fromhex (*tmp);
 
       printf_filtered ("Section %s, range %s -- %s: ", sectname,
                       paddress (target_gdbarch, lma),
                       paddress (target_gdbarch, lma + size));
-      if (host_crc == target_crc)
+      if (res)
        printf_filtered ("matched.\n");
       else
        {
@@ -9250,6 +9270,7 @@ free_actions_list (char **actions_list)
 static void
 remote_download_tracepoint (struct breakpoint *t)
 {
+  struct bp_location *loc;
   CORE_ADDR tpaddr;
   char tmp[40];
   char buf[2048];
@@ -9261,111 +9282,116 @@ remote_download_tracepoint (struct breakpoint *t)
   struct cleanup *aexpr_chain = NULL;
   char *pkt;
 
-  encode_actions (t, &tdp_actions, &stepping_actions);
-  old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
-                           tdp_actions);
-  (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
-
-  tpaddr = t->loc->address;
-  sprintf_vma (tmp, (t->loc ? tpaddr : 0));
-  sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, 
-          tmp, /* address */
-          (t->enable_state == bp_enabled ? 'E' : 'D'),
-          t->step_count, t->pass_count);
-  /* Fast tracepoints are mostly handled by the target, but we can
-     tell the target how big of an instruction block should be moved
-     around.  */
-  if (t->type == bp_fast_tracepoint)
-    {
-      /* Only test for support at download time; we may not know
-        target capabilities at definition time.  */
-      if (remote_supports_fast_tracepoints ())
+  /* Iterate over all the tracepoint locations.  It's up to the target to
+     notice multiple tracepoint packets with the same number but different
+     addresses, and treat them as multiple locations.  */
+  for (loc = t->loc; loc; loc = loc->next)
+    {
+      encode_actions (t, loc, &tdp_actions, &stepping_actions);
+      old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
+                               tdp_actions);
+      (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
+
+      tpaddr = loc->address;
+      sprintf_vma (tmp, (loc ? tpaddr : 0));
+      sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, 
+              tmp, /* address */
+              (t->enable_state == bp_enabled ? 'E' : 'D'),
+              t->step_count, t->pass_count);
+      /* Fast tracepoints are mostly handled by the target, but we can
+        tell the target how big of an instruction block should be moved
+        around.  */
+      if (t->type == bp_fast_tracepoint)
        {
-         int isize;
+         /* Only test for support at download time; we may not know
+            target capabilities at definition time.  */
+         if (remote_supports_fast_tracepoints ())
+           {
+             int isize;
 
-         if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
-                                               tpaddr, &isize, NULL))
-           sprintf (buf + strlen (buf), ":F%x", isize);
+             if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
+                                                   tpaddr, &isize, NULL))
+               sprintf (buf + strlen (buf), ":F%x", isize);
+             else
+               /* If it passed validation at definition but fails now,
+                  something is very wrong.  */
+               internal_error (__FILE__, __LINE__,
+                               "Fast tracepoint not valid during download");
+           }
          else
-           /* If it passed validation at definition but fails now,
-              something is very wrong.  */
-           internal_error (__FILE__, __LINE__,
-                           "Fast tracepoint not valid during download");
+           /* Fast tracepoints are functionally identical to regular
+              tracepoints, so don't take lack of support as a reason to
+              give up on the trace run.  */
+           warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
        }
-      else
-       /* Fast tracepoints are functionally identical to regular
-          tracepoints, so don't take lack of support as a reason to
-          give up on the trace run.  */
-       warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
-    }
-  /* If the tracepoint has a conditional, make it into an agent
-     expression and append to the definition.  */
-  if (t->loc->cond)
-    {
-      /* Only test support at download time, we may not know target
-        capabilities at definition time.  */
-      if (remote_supports_cond_tracepoints ())
+      /* If the tracepoint has a conditional, make it into an agent
+        expression and append to the definition.  */
+      if (loc->cond)
        {
-         aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
-         aexpr_chain = make_cleanup_free_agent_expr (aexpr);
-         sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
-         pkt = buf + strlen (buf);
-         for (ndx = 0; ndx < aexpr->len; ++ndx)
-           pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
-         *pkt = '\0';
-         do_cleanups (aexpr_chain);
+         /* Only test support at download time, we may not know target
+            capabilities at definition time.  */
+         if (remote_supports_cond_tracepoints ())
+           {
+             aexpr = gen_eval_for_expr (tpaddr, loc->cond);
+             aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+             sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
+             pkt = buf + strlen (buf);
+             for (ndx = 0; ndx < aexpr->len; ++ndx)
+               pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
+             *pkt = '\0';
+             do_cleanups (aexpr_chain);
+           }
+         else
+           warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
        }
-      else
-       warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
-    }
 
-  if (t->actions || *default_collect)
-    strcat (buf, "-");
-  putpkt (buf);
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
-  if (strcmp (target_buf, "OK"))
-    error (_("Target does not support tracepoints."));
+  if (t->commands || *default_collect)
+       strcat (buf, "-");
+      putpkt (buf);
+      remote_get_noisy_reply (&target_buf, &target_buf_size);
+      if (strcmp (target_buf, "OK"))
+       error (_("Target does not support tracepoints."));
 
-  if (!t->actions && !*default_collect)
-    return;
+  if (!t->commands && !*default_collect)
+       continue;
 
-  /* do_single_steps (t); */
-  if (tdp_actions)
-    {
-      for (ndx = 0; tdp_actions[ndx]; ndx++)
+      /* do_single_steps (t); */
+      if (tdp_actions)
        {
-         QUIT; /* allow user to bail out with ^C */
-         sprintf (buf, "QTDP:-%x:%s:%s%c",
-                  t->number, tmp, /* address */
-                  tdp_actions[ndx],
-                  ((tdp_actions[ndx + 1] || stepping_actions)
-                   ? '-' : 0));
-         putpkt (buf);
-         remote_get_noisy_reply (&target_buf,
-                                 &target_buf_size);
-         if (strcmp (target_buf, "OK"))
-           error (_("Error on target while setting tracepoints."));
+         for (ndx = 0; tdp_actions[ndx]; ndx++)
+           {
+             QUIT;     /* allow user to bail out with ^C */
+             sprintf (buf, "QTDP:-%x:%s:%s%c",
+                      t->number, tmp, /* address */
+                      tdp_actions[ndx],
+                      ((tdp_actions[ndx + 1] || stepping_actions)
+                       ? '-' : 0));
+             putpkt (buf);
+             remote_get_noisy_reply (&target_buf,
+                                     &target_buf_size);
+             if (strcmp (target_buf, "OK"))
+               error (_("Error on target while setting tracepoints."));
+           }
        }
-    }
-  if (stepping_actions)
-    {
-      for (ndx = 0; stepping_actions[ndx]; ndx++)
+      if (stepping_actions)
        {
-         QUIT; /* allow user to bail out with ^C */
-         sprintf (buf, "QTDP:-%x:%s:%s%s%s",
-                  t->number, tmp, /* address */
-                  ((ndx == 0) ? "S" : ""),
-                  stepping_actions[ndx],
-                  (stepping_actions[ndx + 1] ? "-" : ""));
-         putpkt (buf);
-         remote_get_noisy_reply (&target_buf,
-                                 &target_buf_size);
-         if (strcmp (target_buf, "OK"))
-           error (_("Error on target while setting tracepoints."));
+         for (ndx = 0; stepping_actions[ndx]; ndx++)
+           {
+             QUIT;     /* allow user to bail out with ^C */
+             sprintf (buf, "QTDP:-%x:%s:%s%s%s",
+                      t->number, tmp, /* address */
+                      ((ndx == 0) ? "S" : ""),
+                      stepping_actions[ndx],
+                      (stepping_actions[ndx + 1] ? "-" : ""));
+             putpkt (buf);
+             remote_get_noisy_reply (&target_buf,
+                                     &target_buf_size);
+             if (strcmp (target_buf, "OK"))
+               error (_("Error on target while setting tracepoints."));
+           }
        }
+      do_cleanups (old_chain);
     }
-  do_cleanups (old_chain);
-  return;
 }
 
 static void
@@ -9515,12 +9541,18 @@ remote_trace_find (enum trace_find_type type, int num,
     switch (*reply)
       {
       case 'F':
-       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
-         error (_("Target failed to find requested trace frame."));
+       p = ++reply;
+       target_frameno = (int) strtol (p, &reply, 16);
+       if (reply == p)
+         error (_("Unable to parse trace frame number"));
+       if (target_frameno == -1)
+         return -1;
        break;
       case 'T':
-       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
-         error (_("Target failed to find requested trace frame."));
+       p = ++reply;
+       target_tracept = (int) strtol (p, &reply, 16);
+       if (reply == p)
+         error (_("Unable to parse tracepoint number"));
        break;
       case 'O':                /* "OK"? */
        if (reply[1] == 'K' && reply[2] == '\0')
@@ -9559,7 +9591,7 @@ remote_get_trace_state_variable_value (int tsvnum, LONGEST *val)
 }
 
 static int
-remote_save_trace_data (char *filename)
+remote_save_trace_data (const char *filename)
 {
   struct remote_state *rs = get_remote_state ();
   char *p, *reply;
@@ -9640,6 +9672,18 @@ remote_core_of_thread (struct target_ops *ops, ptid_t ptid)
   return -1;
 }
 
+static void
+remote_set_circular_trace_buffer (int val)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  sprintf (rs->buf, "QTBuffer:circular:%x", val);
+  putpkt (rs->buf);
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (strcmp (target_buf, "OK"))
+    error (_("Target does not support this command."));
+}
+
 static void
 init_remote_ops (void)
 {
@@ -9676,6 +9720,7 @@ Specify the serial device it is connected to\n\
   remote_ops.to_find_new_threads = remote_threads_info;
   remote_ops.to_pid_to_str = remote_pid_to_str;
   remote_ops.to_extra_thread_info = remote_threads_extra_info;
+  remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;
   remote_ops.to_stop = remote_stop;
   remote_ops.to_xfer_partial = remote_xfer_partial;
   remote_ops.to_rcmd = remote_rcmd;
@@ -9717,7 +9762,9 @@ Specify the serial device it is connected to\n\
   remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables;
   remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data;
   remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
+  remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer;
   remote_ops.to_core_of_thread = remote_core_of_thread;
+  remote_ops.to_verify_memory = remote_verify_memory;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -10235,3 +10282,4 @@ Show the remote pathname for \"run\""), NULL, NULL, NULL,
   target_buf_size = 2048;
   target_buf = xmalloc (target_buf_size);
 }
+
This page took 0.051649 seconds and 4 git commands to generate.