Make tracepoint operations go through target vector.
authorStan Shebs <shebs@codesourcery.com>
Thu, 7 Jan 2010 19:17:46 +0000 (19:17 +0000)
committerStan Shebs <shebs@codesourcery.com>
Thu, 7 Jan 2010 19:17:46 +0000 (19:17 +0000)
* target.h (enum trace_find_type): New enum.
(struct target_ops): New fields to_trace_init,
to_download_tracepoint, to_download_trace_state_variable,
to_trace_set_readonly_regions, to_trace_start, to_get_trace_status,
to_trace_stop, to_trace_find, to_get_trace_state_variable_value,
to_set_disconnected_tracing.
(target_trace_init): New macro.
(target_download_tracepoint): New macro.
(target_download_trace_state_variable): New macro.
(target_trace_start): New macro.
(target_trace_set_readonly_regions): New macro.
(target_get_trace_status): New macro.
(target_trace_stop): New macro.
(target_trace_find): New macro.
(target_get_trace_state_variable_value): New macro.
(target_set_disconnected_tracing): New macro.
* target.c (update_current_target): Inherit and set defaults for
tracepoint operations.
* tracepoint.c (default_collect): Make globally visible.
(target_is_remote): Remove, along with all calls.
(tvariables_info): Call target_get_trace_state_variable_value.
(remote_set_transparent_ranges): Remove.
(trace_start_command): Call target_trace_init,
target_download_tracepoint, etc.
(download_tracepoint): Remove.
(trace_stop_command): Simplify.
(stop_tracing): Call target_trace_stop.
(get_trace_status): Call target_get_trace_status.
(trace_status_command): Add case for targets that cannot trace.
(finish_tfind_command): Change to take numerical arguments, call
target_trace_find.
(trace_find_command): Update call to finish_tfind_command.
(trace_find_pc_command): Ditto.
(trace_find_tracepoint_command): Ditto.
(trace_find_line_command): Ditto.
(trace_find_range_command): Ditto.
(trace_find_outside_command): Ditto.
(set_disconnected_tracing_value): Call
target_set_disconnected_tracing.
* remote.c: Add protocol encoding bits from tracepoint.c.
(trace_error): Move from tracepoint.c.
(remote_get_noisy_reply): Ditto.
(free_actions_list_cleanup_wrapper): Ditto.
(free_actions_list): Ditto.
(remote_trace_init): New function.
(remote_download_tracepoint): New function.
(remote_download_trace_state_variable): New function.
(remote_trace_set_readonly_regions): New function.
(remote_trace_start): New function.
(remote_get_trace_status): New function.
(remote_trace_stop): New function.
(remote_trace_find): New function.
(remote_download_trace_state_variable): New function.
(remote_set_disconnected_tracing): New function.
(init_remote_ops): Add tracepoint operations.

gdb/ChangeLog
gdb/remote.c
gdb/target.c
gdb/target.h
gdb/tracepoint.c
gdb/tracepoint.h

index 6d3938d01361f3bf35428be558a500e50f2619e1..3430364149a34f83edd18309c3d976c3d4f6b0e0 100644 (file)
@@ -1,5 +1,62 @@
 2010-01-07  Stan Shebs  <stan@codesourcery.com>
 
+       Make tracepoint operations go through target vector.
+       * target.h (enum trace_find_type): New enum.
+       (struct target_ops): New fields to_trace_init,
+       to_download_tracepoint, to_download_trace_state_variable,
+       to_trace_set_readonly_regions, to_trace_start, to_get_trace_status,
+       to_trace_stop, to_trace_find, to_get_trace_state_variable_value,
+       to_set_disconnected_tracing.
+       (target_trace_init): New macro.
+       (target_download_tracepoint): New macro.
+       (target_download_trace_state_variable): New macro.
+       (target_trace_start): New macro.
+       (target_trace_set_readonly_regions): New macro.
+       (target_get_trace_status): New macro.
+       (target_trace_stop): New macro.
+       (target_trace_find): New macro.
+       (target_get_trace_state_variable_value): New macro.
+       (target_set_disconnected_tracing): New macro.
+       * target.c (update_current_target): Inherit and set defaults for
+       tracepoint operations.
+       * tracepoint.c (default_collect): Make globally visible.
+       (target_is_remote): Remove, along with all calls.
+       (tvariables_info): Call target_get_trace_state_variable_value.
+       (remote_set_transparent_ranges): Remove.
+       (trace_start_command): Call target_trace_init,
+       target_download_tracepoint, etc.
+       (download_tracepoint): Remove.
+       (trace_stop_command): Simplify.
+       (stop_tracing): Call target_trace_stop.
+       (get_trace_status): Call target_get_trace_status.
+       (trace_status_command): Add case for targets that cannot trace.
+       (finish_tfind_command): Change to take numerical arguments, call
+       target_trace_find.
+       (trace_find_command): Update call to finish_tfind_command.
+       (trace_find_pc_command): Ditto.
+       (trace_find_tracepoint_command): Ditto.
+       (trace_find_line_command): Ditto.
+       (trace_find_range_command): Ditto.
+       (trace_find_outside_command): Ditto.
+       (set_disconnected_tracing_value): Call
+       target_set_disconnected_tracing.
+       * remote.c: Add protocol encoding bits from tracepoint.c.
+       (trace_error): Move from tracepoint.c.
+       (remote_get_noisy_reply): Ditto.
+       (free_actions_list_cleanup_wrapper): Ditto.
+       (free_actions_list): Ditto.
+       (remote_trace_init): New function.
+       (remote_download_tracepoint): New function.
+       (remote_download_trace_state_variable): New function.
+       (remote_trace_set_readonly_regions): New function.
+       (remote_trace_start): New function.
+       (remote_get_trace_status): New function.
+       (remote_trace_stop): New function.
+       (remote_trace_find): New function.
+       (remote_download_trace_state_variable): New function.
+       (remote_set_disconnected_tracing): New function.
+       (init_remote_ops): Add tracepoint operations.
+
        * tracepoint.c (trace_dump_command): Don't decr_pc_after_break.
 
 2010-01-07  Tristan Gingold  <gingold@adacore.com>
index 262b97ffcd3bd434bfa658af801f7b51246efcfe..9c50f7ef928b983f45c47d3b4b7ef518bfd95dec 100644 (file)
 
 #include "memory-map.h"
 
+#include "tracepoint.h"
+#include "ax.h"
+#include "ax-gdb.h"
+
+/* temp hacks for tracepoint encoding migration */
+static char *target_buf;
+static long target_buf_size;
+/*static*/ void
+encode_actions (struct breakpoint *t, 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
    writes and unaligned writes, but even as a best-effort attempt this
@@ -368,6 +379,52 @@ struct remote_arch_state
   long remote_packet_size;
 };
 
+long sizeof_pkt = 2000;
+
+/* Utility: generate error from an incoming stub packet.  */
+static void
+trace_error (char *buf)
+{
+  if (*buf++ != 'E')
+    return;                    /* not an error msg */
+  switch (*buf)
+    {
+    case '1':                  /* malformed packet error */
+      if (*++buf == '0')       /*   general case: */
+       error (_("remote.c: error in outgoing packet."));
+      else
+       error (_("remote.c: error in outgoing packet at field #%ld."),
+              strtol (buf, NULL, 16));
+    case '2':
+      error (_("trace API error 0x%s."), ++buf);
+    default:
+      error (_("Target returns error code '%s'."), buf);
+    }
+}
+
+/* Utility: wait for reply from stub, while accepting "O" packets.  */
+static char *
+remote_get_noisy_reply (char **buf_p,
+                       long *sizeof_buf)
+{
+  do                           /* Loop on reply from remote stub.  */
+    {
+      char *buf;
+      QUIT;                    /* allow user to bail out with ^C */
+      getpkt (buf_p, sizeof_buf, 0);
+      buf = *buf_p;
+      if (buf[0] == 0)
+       error (_("Target does not support this command."));
+      else if (buf[0] == 'E')
+       trace_error (buf);
+      else if (buf[0] == 'O' &&
+              buf[1] != 'K')
+       remote_console_output (buf + 1);        /* 'O' message from stub */
+      else
+       return buf;             /* here's the actual reply */
+    }
+  while (1);
+}
 
 /* Handle for retreving the remote protocol data from gdbarch.  */
 static struct gdbarch_data *remote_gdbarch_data_handle;
@@ -8942,6 +8999,331 @@ remote_supports_fast_tracepoints (void)
   return rs->fast_tracepoints;
 }
 
+static void
+remote_trace_init ()
+{
+  putpkt ("QTinit");
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (strcmp (target_buf, "OK"))
+    error (_("Target does not support this command."));
+}
+
+static void free_actions_list (char **actions_list);
+static void free_actions_list_cleanup_wrapper (void *);
+static void
+free_actions_list_cleanup_wrapper (void *al)
+{
+  free_actions_list (al);
+}
+
+static void
+free_actions_list (char **actions_list)
+{
+  int ndx;
+
+  if (actions_list == 0)
+    return;
+
+  for (ndx = 0; actions_list[ndx]; ndx++)
+    xfree (actions_list[ndx]);
+
+  xfree (actions_list);
+}
+
+static void
+remote_download_tracepoint (struct breakpoint *t)
+{
+  CORE_ADDR tpaddr;
+  char tmp[40];
+  char buf[2048];
+  char **tdp_actions;
+  char **stepping_actions;
+  int ndx;
+  struct cleanup *old_chain = NULL;
+  struct agent_expr *aexpr;
+  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 ())
+       {
+         int 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
+       /* 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 ())
+       {
+         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);
+       }
+      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->actions && !*default_collect)
+    return;
+
+  /* do_single_steps (t); */
+  if (tdp_actions)
+    {
+      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++)
+       {
+         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);
+  return;
+}
+
+static void
+remote_download_trace_state_variable (struct trace_state_variable *tsv)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  sprintf (rs->buf, "QTDV:%x:%s",
+          tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
+  putpkt (rs->buf);
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+}
+
+static void
+remote_trace_set_readonly_regions ()
+{
+  asection *s;
+  bfd_size_type size;
+  bfd_vma lma;
+  int anysecs = 0;
+
+  if (!exec_bfd)
+    return;                    /* No information to give.  */
+
+  strcpy (target_buf, "QTro");
+  for (s = exec_bfd->sections; s; s = s->next)
+    {
+      char tmp1[40], tmp2[40];
+
+      if ((s->flags & SEC_LOAD) == 0 ||
+      /* (s->flags & SEC_CODE)     == 0 || */
+         (s->flags & SEC_READONLY) == 0)
+       continue;
+
+      anysecs = 1;
+      lma = s->lma;
+      size = bfd_get_section_size (s);
+      sprintf_vma (tmp1, lma);
+      sprintf_vma (tmp2, lma + size);
+      sprintf (target_buf + strlen (target_buf), 
+              ":%s,%s", tmp1, tmp2);
+    }
+  if (anysecs)
+    {
+      putpkt (target_buf);
+      getpkt (&target_buf, &target_buf_size, 0);
+    }
+}
+
+static void
+remote_trace_start ()
+{
+  putpkt ("QTStart");
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (strcmp (target_buf, "OK"))
+    error (_("Bogus reply from target: %s"), target_buf);
+}
+
+static int
+remote_get_trace_status (int *stop_reason)
+{
+  putpkt ("qTStatus");
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+
+  if (target_buf[0] != 'T' ||
+      (target_buf[1] != '0' && target_buf[1] != '1'))
+    error (_("Bogus trace status reply from target: %s"), target_buf);
+
+  return (target_buf[1] == '1');
+}
+
+static void
+remote_trace_stop ()
+{
+  putpkt ("QTStop");
+  remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (strcmp (target_buf, "OK"))
+    error (_("Bogus reply from target: %s"), target_buf);
+}
+
+static int
+remote_trace_find (enum trace_find_type type, int num,
+                  ULONGEST addr1, ULONGEST addr2,
+                  int *tpp)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p, *reply;
+  int target_frameno = -1, target_tracept = -1;
+
+  p = rs->buf;
+  strcpy (p, "QTFrame:");
+  p = strchr (p, '\0');
+  switch (type)
+    {
+    case tfind_number:
+      sprintf (p, "%x", num);
+      break;
+    case tfind_pc:
+      sprintf (p, "pc:%s", paddress (target_gdbarch, addr1));
+      break;
+    case tfind_tp:
+      sprintf (p, "tdp:%x", num);
+      break;
+    case tfind_range:
+      sprintf (p, "range:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+      break;
+    case tfind_outside:
+      sprintf (p, "outside:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+      break;
+    default:
+      error ("Unknown trace find type %d", type);
+    }
+
+  putpkt (rs->buf);
+  reply = remote_get_noisy_reply (&(rs->buf), &sizeof_pkt);
+
+  while (reply && *reply)
+    switch (*reply)
+      {
+      case 'F':
+       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
+         error (_("Target failed to find requested trace frame."));
+       break;
+      case 'T':
+       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
+         error (_("Target failed to find requested trace frame."));
+       break;
+      case 'O':                /* "OK"? */
+       if (reply[1] == 'K' && reply[2] == '\0')
+         reply += 2;
+       else
+         error (_("Bogus reply from target: %s"), reply);
+       break;
+      default:
+       error (_("Bogus reply from target: %s"), reply);
+      }
+  if (tpp)
+    *tpp = target_tracept;
+  return target_frameno;
+}
+
+static int
+remote_get_trace_state_variable_value (int tsvnum, LONGEST *val)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *reply;
+  ULONGEST uval;
+
+  sprintf (rs->buf, "qTV:%x", tsvnum);
+  putpkt (rs->buf);
+  reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+  if (reply && *reply)
+    {
+      if (*reply == 'V')
+       {
+         unpack_varlen_hex (reply + 1, &uval);
+         *val = (LONGEST) uval;
+         return 1;
+       }
+    }
+  return 0;
+}
+
+static void
+remote_set_disconnected_tracing (int val)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  sprintf (rs->buf, "QTDisconnected:%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)
 {
@@ -9005,6 +9387,16 @@ Specify the serial device it is connected to\n\
   remote_ops.to_terminal_ours = remote_terminal_ours;
   remote_ops.to_supports_non_stop = remote_supports_non_stop;
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
+  remote_ops.to_trace_init = remote_trace_init;
+  remote_ops.to_download_tracepoint = remote_download_tracepoint;
+  remote_ops.to_download_trace_state_variable = remote_download_trace_state_variable;
+  remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions;
+  remote_ops.to_trace_start = remote_trace_start;
+  remote_ops.to_get_trace_status = remote_get_trace_status;
+  remote_ops.to_trace_stop = remote_trace_stop;
+  remote_ops.to_trace_find = remote_trace_find;
+  remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value;
+  remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -9227,7 +9619,6 @@ remote_get_tracing_state (struct remote_state *rs)
   struct uploaded_tp *utp;
   struct breakpoint *t;
   extern void get_trace_status ();
-  extern unsigned long trace_running_p;
 
   get_trace_status ();
   if (trace_running_p)
@@ -9646,4 +10037,7 @@ Show the remote pathname for \"run\""), NULL, NULL, NULL,
   magic_null_ptid = ptid_build (42000, 1, -1);
   not_sent_ptid = ptid_build (42000, 1, -2);
   any_thread_ptid = ptid_build (42000, 1, 0);
+
+  target_buf_size = 2048;
+  target_buf = xmalloc (target_buf_size);
 }
index 38cd508e902a24b259111a1fdaedcb83fe1c3a3c..25a2cd736d6ef53461e0c772b2a7956c27c1a7f1 100644 (file)
@@ -685,6 +685,16 @@ update_current_target (void)
       INHERIT (to_get_ada_task_ptid, t);
       /* Do not inherit to_search_memory.  */
       INHERIT (to_supports_multi_process, t);
+      INHERIT (to_trace_init, t);
+      INHERIT (to_download_tracepoint, t);
+      INHERIT (to_download_trace_state_variable, t);
+      INHERIT (to_trace_set_readonly_regions, t);
+      INHERIT (to_trace_start, t);
+      INHERIT (to_get_trace_status, t);
+      INHERIT (to_trace_stop, t);
+      INHERIT (to_trace_find, t);
+      INHERIT (to_get_trace_state_variable_value, t);
+      INHERIT (to_set_disconnected_tracing, t);
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -833,6 +843,36 @@ update_current_target (void)
   de_fault (to_supports_multi_process,
            (int (*) (void))
            return_zero);
+  de_fault (to_trace_init,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_download_tracepoint,
+           (void (*) (struct breakpoint *))
+           tcomplain);
+  de_fault (to_download_trace_state_variable,
+           (void (*) (struct trace_state_variable *))
+           tcomplain);
+  de_fault (to_trace_set_readonly_regions,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_trace_start,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_get_trace_status,
+           (int (*) (int *))
+           return_minus_one);
+  de_fault (to_trace_stop,
+           (void (*) (void))
+           tcomplain);
+  de_fault (to_trace_find,
+           (int (*) (enum trace_find_type, int, ULONGEST, ULONGEST, int *))
+           return_zero);
+  de_fault (to_get_trace_state_variable_value,
+           (int (*) (int, LONGEST *))
+           return_zero);
+  de_fault (to_set_disconnected_tracing,
+           (void (*) (int))
+           tcomplain);
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
index 9a89b93175f68c52470586e71858405c5a84b1a6..20cbe29eb97255d7df49bc7d6b9bc3262e7a0ea6 100644 (file)
@@ -31,6 +31,7 @@ struct target_ops;
 struct bp_target_info;
 struct regcache;
 struct target_section_table;
+struct trace_state_variable;
 
 /* This include file defines the interface between the main part
    of the debugger, and the part which is target-specific, or
@@ -258,6 +259,18 @@ enum target_object
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 
+/* Enumeration of the kinds of traceframe searches that a target may
+   be able to perform.  */
+
+enum trace_find_type
+  {
+    tfind_number,
+    tfind_pc,
+    tfind_tp,
+    tfind_range,
+    tfind_outside,
+  };
+
 /* Request that OPS transfer up to LEN 8-bit bytes of the target's
    OBJECT.  The OFFSET, for a seekable object, specifies the
    starting point.  The ANNEX can be used to provide additional
@@ -597,6 +610,47 @@ struct target_ops
     struct address_space *(*to_thread_address_space) (struct target_ops *,
                                                      ptid_t);
 
+    /* Tracepoint-related operations.  */
+
+    /* Prepare the target for a tracing run.  */
+    void (*to_trace_init) (void);
+
+    /* Send full details of a tracepoint to the target.  */
+    void (*to_download_tracepoint) (struct breakpoint *t);
+
+    /* Send full details of a trace state variable to the target.  */
+    void (*to_download_trace_state_variable) (struct trace_state_variable *tsv);
+
+    /* Inform the target info of memory regions that are readonly
+       (such as text sections), and so it should return data from
+       those rather than look in the trace buffer.  */
+    void (*to_trace_set_readonly_regions) (void);
+
+    /* Start a trace run.  */
+    void (*to_trace_start) (void);
+
+    /* Get the current status of a tracing run.  */
+    int (*to_get_trace_status) (int *stop_reason);
+
+    /* Stop a trace run.  */
+    void (*to_trace_stop) (void);
+
+   /* Ask the target to find a trace frame of the given type TYPE,
+      using NUM, ADDR1, and ADDR2 as search parameters.  Returns the
+      number of the trace frame, and also the tracepoint number at
+      TPP.  */
+    int (*to_trace_find) (enum trace_find_type type, int num,
+                         ULONGEST addr1, ULONGEST addr2, int *tpp);
+
+    /* Get the value of the trace state variable number TSV, returning
+       1 if the value is known and writing the value itself into the
+       location pointed to by VAL, else returning 0.  */
+    int (*to_get_trace_state_variable_value) (int tsv, LONGEST *val);
+
+    /* Set the target's tracing behavior in response to unexpected
+       disconnection - set VAL to 1 to keep tracing, 0 to stop.  */
+    void (*to_set_disconnected_tracing) (int val);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -1238,6 +1292,38 @@ extern int target_search_memory (CORE_ADDR start_addr,
                                  ULONGEST pattern_len,
                                  CORE_ADDR *found_addrp);
 
+/* Tracepoint-related operations.  */
+
+#define target_trace_init() \
+  (*current_target.to_trace_init) ()
+
+#define target_download_tracepoint(t) \
+  (*current_target.to_download_tracepoint) (t)
+
+#define target_download_trace_state_variable(tsv) \
+  (*current_target.to_download_trace_state_variable) (tsv)
+
+#define target_trace_start() \
+  (*current_target.to_trace_start) ()
+
+#define target_trace_set_readonly_regions() \
+  (*current_target.to_trace_set_readonly_regions) ()
+
+#define target_get_trace_status(stop_reason) \
+  (*current_target.to_get_trace_status) (stop_reason)
+
+#define target_trace_stop() \
+  (*current_target.to_trace_stop) ()
+
+#define target_trace_find(type,num,addr1,addr2,tpp) \
+  (*current_target.to_trace_find) ((type), (num), (addr1), (addr2), (tpp))
+
+#define target_get_trace_state_variable_value(tsv,val) \
+  (*current_target.to_get_trace_state_variable_value) ((tsv), (val))
+
+#define target_set_disconnected_tracing(val) \
+  (*current_target.to_set_disconnected_tracing) (val)
+
 /* Command logging facility.  */
 
 #define target_log_command(p)                                          \
index 5d19934d2e0760979b2ef76fc9e6709b782a2a42..0dfe23cdf8a35ada9236eb2fba27af7a26ef4f5d 100644 (file)
 #include "inferior.h"
 #include "breakpoint.h"
 #include "tracepoint.h"
-#include "remote.h"
-extern int remote_supports_cond_tracepoints (void);
-extern int remote_supports_fast_tracepoints (void);
-extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
 #include "linespec.h"
 #include "regcache.h"
 #include "completer.h"
@@ -46,6 +42,7 @@ extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
 #include "valprint.h"
 #include "gdbcore.h"
 #include "objfiles.h"
+#include "filenames.h"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -144,13 +141,10 @@ static struct symtab_and_line traceframe_sal;
 static struct cmd_list_element *tfindlist;
 
 /* List of expressions to collect by default at each tracepoint hit.  */
-static char *default_collect = "";
+char *default_collect = "";
 
 static int disconnected_tracing;
 
-static char *target_buf;
-static long target_buf_size;
-  
 /* ======= Important command functions: ======= */
 static void trace_actions_command (char *, int);
 static void trace_start_command (char *, int);
@@ -173,70 +167,11 @@ static char *mem2hex (gdb_byte *, char *, int);
 static void add_register (struct collection_list *collection,
                          unsigned int regno);
 static struct cleanup *make_cleanup_free_actions (struct breakpoint *t);
-static void free_actions_list (char **actions_list);
-static void free_actions_list_cleanup_wrapper (void *);
 
 extern void send_disconnected_tracing_value (int value);
 
 extern void _initialize_tracepoint (void);
 
-/* Utility: returns true if "target remote" */
-static int
-target_is_remote (void)
-{
-  if (current_target.to_shortname &&
-      (strcmp (current_target.to_shortname, "remote") == 0
-       || strcmp (current_target.to_shortname, "extended-remote") == 0))
-    return 1;
-  else
-    return 0;
-}
-
-/* Utility: generate error from an incoming stub packet.  */
-static void
-trace_error (char *buf)
-{
-  if (*buf++ != 'E')
-    return;                    /* not an error msg */
-  switch (*buf)
-    {
-    case '1':                  /* malformed packet error */
-      if (*++buf == '0')       /*   general case: */
-       error (_("tracepoint.c: error in outgoing packet."));
-      else
-       error (_("tracepoint.c: error in outgoing packet at field #%ld."),
-              strtol (buf, NULL, 16));
-    case '2':
-      error (_("trace API error 0x%s."), ++buf);
-    default:
-      error (_("Target returns error code '%s'."), buf);
-    }
-}
-
-/* Utility: wait for reply from stub, while accepting "O" packets.  */
-static char *
-remote_get_noisy_reply (char **buf_p,
-                       long *sizeof_buf)
-{
-  do                           /* Loop on reply from remote stub.  */
-    {
-      char *buf;
-      QUIT;                    /* allow user to bail out with ^C */
-      getpkt (buf_p, sizeof_buf, 0);
-      buf = *buf_p;
-      if (buf[0] == 0)
-       error (_("Target does not support this command."));
-      else if (buf[0] == 'E')
-       trace_error (buf);
-      else if (buf[0] == 'O' &&
-              buf[1] != 'K')
-       remote_console_output (buf + 1);        /* 'O' message from stub */
-      else
-       return buf;             /* here's the actual reply */
-    }
-  while (1);
-}
-
 /* Set traceframe number to NUM.  */
 static void
 set_traceframe_num (int num)
@@ -449,37 +384,17 @@ tvariables_info (char *args, int from_tty)
   char *reply;
   ULONGEST tval;
 
-  if (target_is_remote ())
-    {
-      char buf[20];
-
-      for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-       {
-         /* We don't know anything about the value until we get a
-            valid packet.  */
-         tsv->value_known = 0;
-         sprintf (buf, "qTV:%x", tsv->number);
-         putpkt (buf);
-         reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
-         if (reply && *reply)
-           {
-             if (*reply == 'V')
-               {
-                 unpack_varlen_hex (reply + 1, &tval);
-                 tsv->value = (LONGEST) tval;
-                 tsv->value_known = 1;
-               }
-             /* FIXME say anything about oddball replies? */
-           }
-       }
-    }
-
   if (VEC_length (tsv_s, tvariables) == 0)
     {
       printf_filtered (_("No trace state variables.\n"));
       return;
     }
 
+  /* Try to acquire values from the target.  */
+  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+    tsv->value_known = target_get_trace_state_variable_value (tsv->number,
+                                                             &(tsv->value));
+
   printf_filtered (_("Name\t\t  Initial\tCurrent\n"));
 
   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
@@ -1293,28 +1208,8 @@ stringify_collection_list (struct collection_list *list, char *string)
     return *str_list;
 }
 
-static void
-free_actions_list_cleanup_wrapper (void *al)
-{
-  free_actions_list (al);
-}
-
-static void
-free_actions_list (char **actions_list)
-{
-  int ndx;
-
-  if (actions_list == 0)
-    return;
-
-  for (ndx = 0; actions_list[ndx]; ndx++)
-    xfree (actions_list[ndx]);
-
-  xfree (actions_list);
-}
-
 /* Render all actions into gdb protocol.  */
-static void
+/*static*/ void
 encode_actions (struct breakpoint *t, char ***tdp_actions,
                char ***stepping_actions)
 {
@@ -1583,49 +1478,6 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
   collect->next_aexpr_elt++;
 }
 
-/* Set "transparent" memory ranges
-
-   Allow trace mechanism to treat text-like sections
-   (and perhaps all read-only sections) transparently, 
-   i.e. don't reject memory requests from these address ranges
-   just because they haven't been collected.  */
-
-static void
-remote_set_transparent_ranges (void)
-{
-  asection *s;
-  bfd_size_type size;
-  bfd_vma lma;
-  int anysecs = 0;
-
-  if (!exec_bfd)
-    return;                    /* No information to give.  */
-
-  strcpy (target_buf, "QTro");
-  for (s = exec_bfd->sections; s; s = s->next)
-    {
-      char tmp1[40], tmp2[40];
-
-      if ((s->flags & SEC_LOAD) == 0 ||
-      /* (s->flags & SEC_CODE)     == 0 || */
-         (s->flags & SEC_READONLY) == 0)
-       continue;
-
-      anysecs = 1;
-      lma = s->lma;
-      size = bfd_get_section_size (s);
-      sprintf_vma (tmp1, lma);
-      sprintf_vma (tmp2, lma + size);
-      sprintf (target_buf + strlen (target_buf), 
-              ":%s,%s", tmp1, tmp2);
-    }
-  if (anysecs)
-    {
-      putpkt (target_buf);
-      getpkt (&target_buf, &target_buf_size, 0);
-    }
-}
-
 /* tstart command:
 
    Tell target to clear any previous trace experiment.
@@ -1633,8 +1485,6 @@ remote_set_transparent_ranges (void)
    to the target.  If no errors, 
    Tell target to start a new trace experiment.  */
 
-int download_tracepoint (struct breakpoint *t);
-
 static void
 trace_start_command (char *args, int from_tty)
 {
@@ -1647,249 +1497,93 @@ trace_start_command (char *args, int from_tty)
 
   dont_repeat ();      /* Like "run", dangerous to repeat accidentally.  */
 
-  if (target_is_remote ())
-    {
-      putpkt ("QTinit");
-      remote_get_noisy_reply (&target_buf, &target_buf_size);
-      if (strcmp (target_buf, "OK"))
-       error (_("Target does not support this command."));
-
-      tp_vec = all_tracepoints ();
-      for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
-       {
-         t->number_on_target = 0;
-         if (download_tracepoint (t))
-           {
-             t->number_on_target = t->number;
-             any_downloaded = 1;
-           }
-       }
-      VEC_free (breakpoint_p, tp_vec);
-
-      /* No point in tracing without any tracepoints... */
-      if (!any_downloaded)
-       error ("No tracepoints downloaded, not starting trace");
-
-      /* Init any trace state variables that start with nonzero values.  */
-
-      for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
-       {
-         if (tsv->initial_value != 0)
-           {
-             sprintf (buf, "QTDV:%x:%s",
-                      tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
-             putpkt (buf);
-             remote_get_noisy_reply (&target_buf, &target_buf_size);
-           }
-       }
-
-      /* Tell target to treat text-like sections as transparent.  */
-      remote_set_transparent_ranges ();
-      /* Now insert traps and begin collecting data.  */
-      putpkt ("QTStart");
-      remote_get_noisy_reply (&target_buf, &target_buf_size);
-      if (strcmp (target_buf, "OK"))
-       error (_("Bogus reply from target: %s"), target_buf);
-      set_traceframe_num (-1); /* All old traceframes invalidated.  */
-      set_tracepoint_num (-1);
-      set_traceframe_context (NULL);
-      trace_running_p = 1;
-      if (deprecated_trace_start_stop_hook)
-       deprecated_trace_start_stop_hook (1, from_tty);
-
-    }
-  else
-    error (_("Trace can only be run on remote targets."));
-}
-
-/* Send the definition of a single tracepoint to the target.  Return 1
-   if successful, 0 if not.  */
-
-int
-download_tracepoint (struct breakpoint *t)
-{
-  CORE_ADDR tpaddr;
-  char tmp[40];
-  char buf[2048];
-  char **tdp_actions;
-  char **stepping_actions;
-  int ndx;
-  struct cleanup *old_chain = NULL;
-  struct agent_expr *aexpr;
-  struct cleanup *aexpr_chain = NULL;
-
-  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)
+  target_trace_init ();
+  
+  tp_vec = all_tracepoints ();
+  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
     {
-      /* 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 (get_current_arch (),
-                                               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
-       /* 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);
+      t->number_on_target = 0;
+      target_download_tracepoint (t);
+      t->number_on_target = t->number;
+      any_downloaded = 1;
     }
-  /* If the tracepoint has a conditional, make it into an agent
-     expression and append to the definition.  */
-  if (t->loc->cond)
+  VEC_free (breakpoint_p, tp_vec);
+  
+  /* No point in tracing without any tracepoints... */
+  if (!any_downloaded)
+    error ("No tracepoints downloaded, not starting trace");
+  
+  /* Init any trace state variables that start with nonzero values.  */
+  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
     {
-      /* 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 (t->loc->address, t->loc->cond);
-         aexpr_chain = make_cleanup_free_agent_expr (aexpr);
-         sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
-         mem2hex (aexpr->buf, buf + strlen (buf), aexpr->len);
-         do_cleanups (aexpr_chain);
-       }
-      else
-       warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
+      if (tsv->initial_value != 0)
+       target_download_trace_state_variable (tsv);
     }
+  
+  /* Tell target to treat text-like sections as transparent.  */
+  target_trace_set_readonly_regions ();
 
-  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->actions && !*default_collect)
-    return 1;
-
-  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);
+  /* Now insert traps and begin collecting data.  */
+  target_trace_start ();
 
-  /* do_single_steps (t); */
-  if (tdp_actions)
-    {
-      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++)
-       {
-         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);
-  return 1;
+  /* Reset our local state.  */
+  set_traceframe_num (-1);
+  set_tracepoint_num (-1);
+  set_traceframe_context (NULL);
+  trace_running_p = 1;
 }
 
 /* tstop command */
 static void
 trace_stop_command (char *args, int from_tty)
 {
-  if (target_is_remote ())
-    {
-      stop_tracing ();
-      if (deprecated_trace_start_stop_hook)
-       deprecated_trace_start_stop_hook (0, from_tty);
-    }
-  else
-    error (_("Trace can only be run on remote targets."));
+  stop_tracing ();
 }
 
 void
 stop_tracing ()
 {
-  putpkt ("QTStop");
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
-  if (strcmp (target_buf, "OK"))
-    error (_("Bogus reply from target: %s"), target_buf);
+  target_trace_stop ();
   trace_running_p = 0;
 }
 
 unsigned long trace_running_p;
 
-void
+int
 get_trace_status ()
 {
-  putpkt ("qTStatus");
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
-
-  if (target_buf[0] != 'T' ||
-      (target_buf[1] != '0' && target_buf[1] != '1'))
-    error (_("Bogus trace status reply from target: %s"), target_buf);
+  int status = target_get_trace_status (NULL);
 
   /* exported for use by the GUI */
-  trace_running_p = (target_buf[1] == '1');
+  trace_running_p = (status > 0);
+
+  return status;
 }
 
 /* tstatus command */
 static void
 trace_status_command (char *args, int from_tty)
 {
-  if (target_is_remote ())
+  int status = get_trace_status ();
+  
+  if (status < 0)
+    printf_filtered (_("Trace can not be run on the target.\n"));
+  else if (trace_running_p)
     {
-      get_trace_status ();
-
-      if (trace_running_p)
-       {
-         printf_filtered (_("Trace is running on the target.\n"));
-         if (disconnected_tracing)
-           printf_filtered (_("Trace will continue if GDB disconnects.\n"));
-         else
-           printf_filtered (_("Trace will stop if GDB disconnects.\n"));
-       }
+      printf_filtered (_("Trace is running on the target.\n"));
+      if (disconnected_tracing)
+       printf_filtered (_("Trace will continue if GDB disconnects.\n"));
       else
-       printf_filtered (_("Trace is not running on the target.\n"));
-
-      if (traceframe_number >= 0)
-       printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
-                        traceframe_number, tracepoint_number);
-      else
-       printf_filtered (_("Not looking at any trace frame.\n"));
-
+       printf_filtered (_("Trace will stop if GDB disconnects.\n"));
     }
   else
-    error (_("Trace can only be run on remote targets."));
+    printf_filtered (_("Trace is not running on the target.\n"));
+
+  if (traceframe_number >= 0)
+    printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
+                    traceframe_number, tracepoint_number);
+  else
+    printf_filtered (_("Not looking at any trace frame.\n"));
 }
 
 void
@@ -1912,8 +1606,8 @@ disconnect_or_stop_tracing (int from_tty)
 
 /* Worker function for the various flavors of the tfind command.  */
 static void
-finish_tfind_command (char **msg,
-                     long *sizeof_msg,
+finish_tfind_command (enum trace_find_type type, int num,
+                     ULONGEST addr1, ULONGEST addr2,
                      int from_tty)
 {
   int target_frameno = -1, target_tracept = -1;
@@ -1923,64 +1617,52 @@ finish_tfind_command (char **msg,
 
   old_frame_id = get_frame_id (get_current_frame ());
 
-  putpkt (*msg);
-  reply = remote_get_noisy_reply (msg, sizeof_msg);
-
-  while (reply && *reply)
-    switch (*reply)
-      {
-      case 'F':
-       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
-         {
-           /* A request for a non-existant trace frame has failed.
-              Our response will be different, depending on FROM_TTY:
-
-              If FROM_TTY is true, meaning that this command was 
-              typed interactively by the user, then give an error
-              and DO NOT change the state of traceframe_number etc.
-
-              However if FROM_TTY is false, meaning that we're either
-              in a script, a loop, or a user-defined command, then 
-              DON'T give an error, but DO change the state of
-              traceframe_number etc. to invalid.
-
-              The rationalle is that if you typed the command, you
-              might just have committed a typo or something, and you'd
-              like to NOT lose your current debugging state.  However
-              if you're in a user-defined command or especially in a
-              loop, then you need a way to detect that the command
-              failed WITHOUT aborting.  This allows you to write
-              scripts that search thru the trace buffer until the end,
-              and then continue on to do something else.  */
-
-           if (from_tty)
-             error (_("Target failed to find requested trace frame."));
-           else
-             {
-               if (info_verbose)
-                 printf_filtered ("End of trace buffer.\n");
-               /* The following will not recurse, since it's
-                  special-cased.  */
-               trace_find_command ("-1", from_tty);
-               reply = NULL;   /* Break out of loop 
-                                  (avoid recursive nonsense).  */
-             }
-         }
-       break;
-      case 'T':
-       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
-         error (_("Target failed to find requested trace frame."));
-       break;
-      case 'O':                /* "OK"? */
-       if (reply[1] == 'K' && reply[2] == '\0')
-         reply += 2;
-       else
-         error (_("Bogus reply from target: %s"), reply);
-       break;
-      default:
-       error (_("Bogus reply from target: %s"), reply);
-      }
-
+  target_frameno = target_trace_find (type, num, addr1, addr2,
+                                     &target_tracept);
+  
+  if (type == tfind_number
+      && num == -1
+      && target_frameno == -1)
+    {
+      /* We told the target to get out of tfind mode, and it did.  */
+    }
+  else if (target_frameno == -1)
+    {
+      /* A request for a non-existant trace frame has failed.
+        Our response will be different, depending on FROM_TTY:
+
+        If FROM_TTY is true, meaning that this command was 
+        typed interactively by the user, then give an error
+        and DO NOT change the state of traceframe_number etc.
+
+        However if FROM_TTY is false, meaning that we're either
+        in a script, a loop, or a user-defined command, then 
+        DON'T give an error, but DO change the state of
+        traceframe_number etc. to invalid.
+
+        The rationalle is that if you typed the command, you
+        might just have committed a typo or something, and you'd
+        like to NOT lose your current debugging state.  However
+        if you're in a user-defined command or especially in a
+        loop, then you need a way to detect that the command
+        failed WITHOUT aborting.  This allows you to write
+        scripts that search thru the trace buffer until the end,
+        and then continue on to do something else.  */
+  
+      if (from_tty)
+       error (_("Target failed to find requested trace frame."));
+      else
+       {
+         if (info_verbose)
+           printf_filtered ("End of trace buffer.\n");
+#if 0 /* dubious now? */
+         /* The following will not recurse, since it's
+            special-cased.  */
+         trace_find_command ("-1", from_tty);
+#endif
+       }
+    }
+  
   tp = get_tracepoint_by_number_on_target (target_tracept);
 
   reinit_frame_cache ();
@@ -2033,41 +1715,35 @@ trace_find_command (char *args, int from_tty)
 { /* this should only be called with a numeric argument */
   int frameno = -1;
 
-  if (target_is_remote ())
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
+  
+  if (args == 0 || *args == 0)
+    { /* TFIND with no args means find NEXT trace frame.  */
+      if (traceframe_number == -1)
+       frameno = 0;    /* "next" is first one */
+        else
+       frameno = traceframe_number + 1;
+    }
+  else if (0 == strcmp (args, "-"))
     {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
-
-      if (deprecated_trace_find_hook)
-       deprecated_trace_find_hook (args, from_tty);
-
-      if (args == 0 || *args == 0)
-       { /* TFIND with no args means find NEXT trace frame.  */
-         if (traceframe_number == -1)
-           frameno = 0;        /* "next" is first one */
-         else
-           frameno = traceframe_number + 1;
-       }
-      else if (0 == strcmp (args, "-"))
-       {
-         if (traceframe_number == -1)
-           error (_("not debugging trace buffer"));
-         else if (from_tty && traceframe_number == 0)
-           error (_("already at start of trace buffer"));
-
-         frameno = traceframe_number - 1;
-       }
-      else
-       frameno = parse_and_eval_long (args);
+      if (traceframe_number == -1)
+       error (_("not debugging trace buffer"));
+      else if (from_tty && traceframe_number == 0)
+       error (_("already at start of trace buffer"));
+      
+      frameno = traceframe_number - 1;
+      }
+  /* A hack to work around eval's need for fp to have been collected.  */
+  else if (0 == strcmp (args, "-1"))
+    frameno = -1;
+  else
+    frameno = parse_and_eval_long (args);
 
-      if (frameno < -1)
-       error (_("invalid input (%d is less than zero)"), frameno);
+  if (frameno < -1)
+    error (_("invalid input (%d is less than zero)"), frameno);
 
-      sprintf (target_buf, "QTFrame:%x", frameno);
-      finish_tfind_command (&target_buf, &target_buf_size, from_tty);
-    }
-  else
-    error (_("Trace can only be run on remote targets."));
+  finish_tfind_command (tfind_number, frameno, 0, 0, from_tty);
 }
 
 /* tfind end */
@@ -2098,22 +1774,15 @@ trace_find_pc_command (char *args, int from_tty)
   CORE_ADDR pc;
   char tmp[40];
 
-  if (target_is_remote ())
-    {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
-
-      if (args == 0 || *args == 0)
-       pc = regcache_read_pc (get_current_regcache ());
-      else
-       pc = parse_and_eval_address (args);
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
 
-      sprintf_vma (tmp, pc);
-      sprintf (target_buf, "QTFrame:pc:%s", tmp);
-      finish_tfind_command (&target_buf, &target_buf_size, from_tty);
-    }
+  if (args == 0 || *args == 0)
+    pc = regcache_read_pc (get_current_regcache ());
   else
-    error (_("Trace can only be run on remote targets."));
+    pc = parse_and_eval_address (args);
+
+  finish_tfind_command (tfind_pc, 0, pc, 0, from_tty);
 }
 
 /* tfind tracepoint command */
@@ -2123,33 +1792,27 @@ trace_find_tracepoint_command (char *args, int from_tty)
   int tdp;
   struct breakpoint *tp;
 
-  if (target_is_remote ())
-    {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
 
-      if (args == 0 || *args == 0)
-       {
-         if (tracepoint_number == -1)
-           error (_("No current tracepoint -- please supply an argument."));
-         else
-           tdp = tracepoint_number;    /* default is current TDP */
-       }
+  if (args == 0 || *args == 0)
+    {
+      if (tracepoint_number == -1)
+       error (_("No current tracepoint -- please supply an argument."));
       else
-       tdp = parse_and_eval_long (args);
-
-      /* If we have the tracepoint on hand, use the number that the
-        target knows about (which may be different if we disconnected
-        and reconnected).  */
-      tp = get_tracepoint (tdp);
-      if (tp)
-       tdp = tp->number_on_target;
-
-      sprintf (target_buf, "QTFrame:tdp:%x", tdp);
-      finish_tfind_command (&target_buf, &target_buf_size, from_tty);
+       tdp = tracepoint_number;        /* default is current TDP */
     }
   else
-    error (_("Trace can only be run on remote targets."));
+    tdp = parse_and_eval_long (args);
+
+  /* If we have the tracepoint on hand, use the number that the
+     target knows about (which may be different if we disconnected
+     and reconnected).  */
+  tp = get_tracepoint (tdp);
+  if (tp)
+    tdp = tp->number_on_target;
+
+  finish_tfind_command (tfind_tp, tdp, 0, 0, from_tty);
 }
 
 /* TFIND LINE command:
@@ -2169,94 +1832,78 @@ trace_find_line_command (char *args, int from_tty)
   struct cleanup *old_chain;
   char   startpc_str[40], endpc_str[40];
 
-  if (target_is_remote ())
-    {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
-
-      if (args == 0 || *args == 0)
-       {
-         sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
-         sals.nelts = 1;
-         sals.sals = (struct symtab_and_line *)
-           xmalloc (sizeof (struct symtab_and_line));
-         sals.sals[0] = sal;
-       }
-      else
-       {
-         sals = decode_line_spec (args, 1);
-         sal = sals.sals[0];
-       }
-
-      old_chain = make_cleanup (xfree, sals.sals);
-      if (sal.symtab == 0)
-       {
-         struct gdbarch *gdbarch = get_current_arch ();
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
 
-         printf_filtered ("TFIND: No line number information available");
-         if (sal.pc != 0)
-           {
-             /* This is useful for "info line *0x7f34".  If we can't
-                tell the user about a source line, at least let them
-                have the symbolic address.  */
-             printf_filtered (" for address ");
-             wrap_here ("  ");
-             print_address (gdbarch, sal.pc, gdb_stdout);
-             printf_filtered (";\n -- will attempt to find by PC. \n");
-           }
-         else
-           {
-             printf_filtered (".\n");
-             return;           /* No line, no PC; what can we do?  */
-           }
-       }
-      else if (sal.line > 0
-              && find_line_pc_range (sal, &start_pc, &end_pc))
+  if (args == 0 || *args == 0)
+    {
+      sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
+      sals.nelts = 1;
+      sals.sals = (struct symtab_and_line *)
+       xmalloc (sizeof (struct symtab_and_line));
+      sals.sals[0] = sal;
+    }
+  else
+      {
+      sals = decode_line_spec (args, 1);
+      sal = sals.sals[0];
+    }
+  
+  old_chain = make_cleanup (xfree, sals.sals);
+  if (sal.symtab == 0)
+    {
+      printf_filtered ("TFIND: No line number information available");
+      if (sal.pc != 0)
        {
-         struct gdbarch *gdbarch = get_objfile_arch (sal.symtab->objfile);
-
-         if (start_pc == end_pc)
-           {
-             printf_filtered ("Line %d of \"%s\"",
-                              sal.line, sal.symtab->filename);
-             wrap_here ("  ");
-             printf_filtered (" is at address ");
-             print_address (gdbarch, start_pc, gdb_stdout);
-             wrap_here ("  ");
-             printf_filtered (" but contains no code.\n");
-             sal = find_pc_line (start_pc, 0);
-             if (sal.line > 0 &&
-                 find_line_pc_range (sal, &start_pc, &end_pc) &&
-                 start_pc != end_pc)
-               printf_filtered ("Attempting to find line %d instead.\n",
-                                sal.line);
-             else
-               error (_("Cannot find a good line."));
-           }
-       }
-      else
-       /* Is there any case in which we get here, and have an address
-          which the user would want to see?  If we have debugging
-          symbols and no line numbers?  */
-       error (_("Line number %d is out of range for \"%s\"."),
-              sal.line, sal.symtab->filename);
-
-      sprintf_vma (startpc_str, start_pc);
-      sprintf_vma (endpc_str, end_pc - 1);
-      /* Find within range of stated line.  */
-      if (args && *args)
-       sprintf (target_buf, "QTFrame:range:%s:%s", 
-                startpc_str, endpc_str);
-      /* Find OUTSIDE OF range of CURRENT line.  */
-      else
-       sprintf (target_buf, "QTFrame:outside:%s:%s", 
-                startpc_str, endpc_str);
-      finish_tfind_command (&target_buf, &target_buf_size,
-                           from_tty);
-      do_cleanups (old_chain);
+         /* This is useful for "info line *0x7f34".  If we can't
+            tell the user about a source line, at least let them
+            have the symbolic address.  */
+         printf_filtered (" for address ");
+         wrap_here ("  ");
+         print_address (get_current_arch (), sal.pc, gdb_stdout);
+         printf_filtered (";\n -- will attempt to find by PC. \n");
+       }
+        else
+       {
+         printf_filtered (".\n");
+         return;               /* No line, no PC; what can we do?  */
+       }
     }
+  else if (sal.line > 0
+          && find_line_pc_range (sal, &start_pc, &end_pc))
+    {
+      if (start_pc == end_pc)
+       {
+         printf_filtered ("Line %d of \"%s\"",
+                          sal.line, sal.symtab->filename);
+         wrap_here ("  ");
+         printf_filtered (" is at address ");
+         print_address (get_current_arch (), start_pc, gdb_stdout);
+         wrap_here ("  ");
+         printf_filtered (" but contains no code.\n");
+         sal = find_pc_line (start_pc, 0);
+         if (sal.line > 0
+             && find_line_pc_range (sal, &start_pc, &end_pc)
+             && start_pc != end_pc)
+           printf_filtered ("Attempting to find line %d instead.\n",
+                            sal.line);
+         else
+           error (_("Cannot find a good line."));
+       }
+      }
+    else
+    /* Is there any case in which we get here, and have an address
+       which the user would want to see?  If we have debugging
+       symbols and no line numbers?  */
+    error (_("Line number %d is out of range for \"%s\"."),
+          sal.line, sal.symtab->filename);
+
+  /* Find within range of stated line.  */
+  if (args && *args)
+    finish_tfind_command (tfind_range, 0, start_pc, end_pc - 1, from_tty);
   else
-    error (_("Trace can only be run on remote targets."));
+    finish_tfind_command (tfind_outside, 0, start_pc, end_pc - 1, from_tty);
+  do_cleanups (old_chain);
 }
 
 /* tfind range command */
@@ -2267,38 +1914,30 @@ trace_find_range_command (char *args, int from_tty)
   char start_str[40], stop_str[40];
   char *tmp;
 
-  if (target_is_remote ())
-    {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
-
-      if (args == 0 || *args == 0)
-       { /* XXX FIXME: what should default behavior be?  */
-         printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
-         return;
-       }
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
 
-      if (0 != (tmp = strchr (args, ',')))
-       {
-         *tmp++ = '\0';        /* terminate start address */
-         while (isspace ((int) *tmp))
-           tmp++;
-         start = parse_and_eval_address (args);
-         stop = parse_and_eval_address (tmp);
-       }
-      else
-       {                       /* no explicit end address? */
-         start = parse_and_eval_address (args);
-         stop = start + 1;     /* ??? */
-       }
+  if (args == 0 || *args == 0)
+    { /* XXX FIXME: what should default behavior be?  */
+      printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
+      return;
+    }
 
-      sprintf_vma (start_str, start);
-      sprintf_vma (stop_str, stop);
-      sprintf (target_buf, "QTFrame:range:%s:%s", start_str, stop_str);
-      finish_tfind_command (&target_buf, &target_buf_size, from_tty);
+  if (0 != (tmp = strchr (args, ',')))
+    {
+      *tmp++ = '\0';   /* terminate start address */
+      while (isspace ((int) *tmp))
+       tmp++;
+      start = parse_and_eval_address (args);
+      stop = parse_and_eval_address (tmp);
     }
   else
-    error (_("Trace can only be run on remote targets."));
+    {                  /* no explicit end address? */
+      start = parse_and_eval_address (args);
+      stop = start + 1;        /* ??? */
+    }
+
+  finish_tfind_command (tfind_range, 0, start, stop, from_tty);
 }
 
 /* tfind outside command */
@@ -2309,38 +1948,30 @@ trace_find_outside_command (char *args, int from_tty)
   char start_str[40], stop_str[40];
   char *tmp;
 
-  if (target_is_remote ())
-    {
-      if (trace_running_p)
-       error ("May not look at trace frames while trace is running.");
-
-      if (args == 0 || *args == 0)
-       { /* XXX FIXME: what should default behavior be? */
-         printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
-         return;
-       }
+  if (trace_running_p)
+    error ("May not look at trace frames while trace is running.");
 
-      if (0 != (tmp = strchr (args, ',')))
-       {
-         *tmp++ = '\0';        /* terminate start address */
-         while (isspace ((int) *tmp))
-           tmp++;
-         start = parse_and_eval_address (args);
-         stop = parse_and_eval_address (tmp);
-       }
-      else
-       {                       /* no explicit end address? */
-         start = parse_and_eval_address (args);
-         stop = start + 1;     /* ??? */
-       }
+  if (args == 0 || *args == 0)
+    { /* XXX FIXME: what should default behavior be? */
+      printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
+      return;
+    }
 
-      sprintf_vma (start_str, start);
-      sprintf_vma (stop_str, stop);
-      sprintf (target_buf, "QTFrame:outside:%s:%s", start_str, stop_str);
-      finish_tfind_command (&target_buf, &target_buf_size, from_tty);
+  if (0 != (tmp = strchr (args, ',')))
+    {
+      *tmp++ = '\0';   /* terminate start address */
+      while (isspace ((int) *tmp))
+       tmp++;
+      start = parse_and_eval_address (args);
+      stop = parse_and_eval_address (tmp);
     }
   else
-    error (_("Trace can only be run on remote targets."));
+    {                  /* no explicit end address? */
+      start = parse_and_eval_address (args);
+      stop = start + 1;        /* ??? */
+    }
+
+  finish_tfind_command (tfind_outside, 0, start, stop, from_tty);
 }
 
 /* info scope command: list the locals for a scope.  */
@@ -2511,12 +2142,6 @@ trace_dump_command (char *args, int from_tty)
   int stepping_actions = 0;
   int stepping_frame = 0;
 
-  if (!target_is_remote ())
-    {
-      error (_("Trace can only be run on remote targets."));
-      return;
-    }
-
   if (tracepoint_number == -1)
     {
       warning (_("No current trace frame."));
@@ -2620,17 +2245,7 @@ trace_dump_command (char *args, int from_tty)
 void
 send_disconnected_tracing_value (int value)
 {
-  char buf[30];
-
-  /* No need to do anything special if target not active.  */
-  if (!target_is_remote ())
-    return;
-
-  sprintf (buf, "QTDisconnected:%x", value);
-  putpkt (buf);
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
-  if (strcmp (target_buf, "OK"))
-    error (_("Target does not support this command."));
+  target_set_disconnected_tracing (value);
 }
 
 static void
@@ -2847,7 +2462,4 @@ trace data collected in the meantime."),
                           NULL,
                           &setlist,
                           &showlist);
-
-  target_buf_size = 2048;
-  target_buf = xmalloc (target_buf_size);
 }
index 0ac2da6abd880a087ed181f3ef2bfc181053e874..5d2862a7b6619fde40a9138a1acfdfe30aa5b2d3 100644 (file)
@@ -65,6 +65,8 @@ struct trace_state_variable
 
 extern unsigned long trace_running_p;
 
+extern char *default_collect;
+
 /* A hook used to notify the UI of tracepoint operations.  */
 
 extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);