This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Target vector for tracepoint operations


Now comes the patch that all you cleanliness fans have been waiting for! This one slices and dices tracepoint.c, moving all the remote protocol encoding and decoding into remote.c where it belongs, and defining a number of new target vector entries. Despite the size, there are no behavioral differences with this change; both testsuite and manual testing show no regressions.

There are all sorts of further cleanup opportunities opened up by this, and I did a few, but then stopped when I reflected that I was probably destroying the context that the next-in-line patches are depending on. :-) (Only about half of this patch applied cleanly for instance, the rest was manual merge bleah).

I'll commit this tomorrow if no one sees any showstoppers.

Stan

2010-01-06 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.

? foo
? tarvec-patch-1
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.378
diff -p -r1.378 remote.c
*** remote.c	6 Jan 2010 20:31:28 -0000	1.378
--- remote.c	7 Jan 2010 01:00:32 -0000
***************
*** 63,68 ****
--- 63,79 ----
  
  #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
*************** struct remote_arch_state
*** 368,373 ****
--- 379,430 ----
    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;
*************** remote_supports_fast_tracepoints (void)
*** 8943,8948 ****
--- 9000,9330 ----
  }
  
  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)
  {
    remote_ops.to_shortname = "remote";
*************** Specify the serial device it is connecte
*** 9005,9010 ****
--- 9387,9402 ----
    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
*************** remote_get_tracing_state (struct remote_
*** 9227,9233 ****
    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)
--- 9619,9624 ----
*************** Show the remote pathname for \"run\""), 
*** 9646,9649 ****
--- 10037,10043 ----
    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: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.235
diff -p -r1.235 target.c
*** target.c	1 Jan 2010 07:31:42 -0000	1.235
--- target.c	7 Jan 2010 01:00:32 -0000
*************** update_current_target (void)
*** 685,690 ****
--- 685,700 ----
        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.  */
*************** update_current_target (void)
*** 833,838 ****
--- 843,878 ----
    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: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.169
diff -p -r1.169 target.h
*** target.h	1 Jan 2010 07:31:42 -0000	1.169
--- target.h	7 Jan 2010 01:00:32 -0000
*************** struct target_ops;
*** 31,36 ****
--- 31,37 ----
  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
*************** enum target_object
*** 258,263 ****
--- 259,276 ----
    /* 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
*************** struct target_ops
*** 597,602 ****
--- 610,656 ----
      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?
       */
*************** extern int target_search_memory (CORE_AD
*** 1238,1243 ****
--- 1292,1329 ----
                                   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: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.136
diff -p -r1.136 tracepoint.c
*** tracepoint.c	6 Jan 2010 20:31:28 -0000	1.136
--- tracepoint.c	7 Jan 2010 01:00:32 -0000
***************
*** 32,41 ****
  #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"
--- 32,37 ----
*************** extern char *unpack_varlen_hex (char *bu
*** 46,51 ****
--- 42,48 ----
  #include "valprint.h"
  #include "gdbcore.h"
  #include "objfiles.h"
+ #include "filenames.h"
  
  #include "ax.h"
  #include "ax-gdb.h"
*************** static struct symtab_and_line traceframe
*** 144,156 ****
  static struct cmd_list_element *tfindlist;
  
  /* List of expressions to collect by default at each tracepoint hit.  */
! static 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);
--- 141,150 ----
  static struct cmd_list_element *tfindlist;
  
  /* List of expressions to collect by default at each tracepoint hit.  */
! char *default_collect = "";
  
  static int disconnected_tracing;
  
  /* ======= Important command functions: ======= */
  static void trace_actions_command (char *, int);
  static void trace_start_command (char *, int);
*************** static char *mem2hex (gdb_byte *, char *
*** 173,242 ****
  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)
--- 167,177 ----
*************** tvariables_info (char *args, int from_tt
*** 449,485 ****
    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;
      }
  
    printf_filtered (_("Name\t\t  Initial\tCurrent\n"));
  
    for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
--- 384,400 ----
    char *reply;
    ULONGEST tval;
  
    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)
*************** stringify_collection_list (struct collec
*** 1293,1320 ****
      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
  encode_actions (struct breakpoint *t, char ***tdp_actions,
  		char ***stepping_actions)
  {
--- 1208,1215 ----
      return *str_list;
  }
  
  /* Render all actions into gdb protocol.  */
! /*static*/ void
  encode_actions (struct breakpoint *t, char ***tdp_actions,
  		char ***stepping_actions)
  {
*************** add_aexpr (struct collection_list *colle
*** 1583,1631 ****
    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.
--- 1478,1483 ----
*************** remote_set_transparent_ranges (void)
*** 1633,1640 ****
     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)
  {
--- 1485,1490 ----
*************** trace_start_command (char *args, int fro
*** 1647,1895 ****
  
    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)
!     {
!       /* 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);
!     }
!   /* 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);
! 	  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 (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);
! 
!   /* 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;
  }
  
  /* 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."));
  }
  
  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);
    trace_running_p = 0;
  }
  
  unsigned long trace_running_p;
  
! void
  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);
  
    /* exported for use by the GUI */
!   trace_running_p = (target_buf[1] == '1');
  }
  
  /* tstatus command */
  static void
  trace_status_command (char *args, int from_tty)
  {
!   if (target_is_remote ())
!     {
!       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"));
! 	}
!       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"));
! 
      }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  void
--- 1497,1589 ----
  
    dont_repeat ();	/* Like "run", dangerous to repeat accidentally.  */
  
!   target_trace_init ();
!   
!   tp_vec = all_tracepoints ();
!   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
      {
!       t->number_on_target = 0;
!       target_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)
! 	target_download_trace_state_variable (tsv);
      }
+   
+   /* Tell target to treat text-like sections as transparent.  */
+   target_trace_set_readonly_regions ();
  
!   /* Now insert traps and begin collecting data.  */
!   target_trace_start ();
  
!   /* 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)
  {
!   stop_tracing ();
  }
  
  void
  stop_tracing ()
  {
!   target_trace_stop ();
    trace_running_p = 0;
  }
  
  unsigned long trace_running_p;
  
! int
  get_trace_status ()
  {
!   int status = target_get_trace_status (NULL);
  
    /* exported for use by the GUI */
!   trace_running_p = (status > 0);
! 
!   return status;
  }
  
  /* tstatus command */
  static void
  trace_status_command (char *args, int from_tty)
  {
!   int status = get_trace_status ();
!   
!   if (status < 0)
!     printf_filtered (_("Trace can not be run on the target.\n"));
!   else 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"));
      }
    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"));
  }
  
  void
*************** disconnect_or_stop_tracing (int from_tty
*** 1912,1919 ****
  
  /* Worker function for the various flavors of the tfind command.  */
  static void
! finish_tfind_command (char **msg,
! 		      long *sizeof_msg,
  		      int from_tty)
  {
    int target_frameno = -1, target_tracept = -1;
--- 1606,1613 ----
  
  /* Worker function for the various flavors of the tfind command.  */
  static void
! finish_tfind_command (enum trace_find_type type, int num,
! 		      ULONGEST addr1, ULONGEST addr2,
  		      int from_tty)
  {
    int target_frameno = -1, target_tracept = -1;
*************** finish_tfind_command (char **msg,
*** 1923,1986 ****
  
    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);
!       }
! 
    tp = get_tracepoint_by_number_on_target (target_tracept);
  
    reinit_frame_cache ();
--- 1617,1668 ----
  
    old_frame_id = get_frame_id (get_current_frame ());
  
!   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 ();
*************** trace_find_command (char *args, int from
*** 2033,2073 ****
  { /* 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 (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 (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."));
  }
  
  /* tfind end */
--- 1715,1749 ----
  { /* this should only be called with a numeric argument */
    int frameno = -1;
  
!   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 (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);
  
!   finish_tfind_command (tfind_number, frameno, 0, 0, from_tty);
  }
  
  /* tfind end */
*************** trace_find_pc_command (char *args, int f
*** 2098,2119 ****
    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);
  
!       sprintf_vma (tmp, pc);
!       sprintf (target_buf, "QTFrame:pc:%s", tmp);
!       finish_tfind_command (&target_buf, &target_buf_size, from_tty);
!     }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  /* tfind tracepoint command */
--- 1774,1788 ----
    CORE_ADDR pc;
    char tmp[40];
  
!   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);
! 
!   finish_tfind_command (tfind_pc, 0, pc, 0, from_tty);
  }
  
  /* tfind tracepoint command */
*************** trace_find_tracepoint_command (char *arg
*** 2123,2155 ****
    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 (args == 0 || *args == 0)
! 	{
! 	  if (tracepoint_number == -1)
! 	    error (_("No current tracepoint -- please supply an argument."));
! 	  else
! 	    tdp = tracepoint_number;	/* default is current TDP */
! 	}
        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);
      }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  /* TFIND LINE command:
--- 1792,1818 ----
    int tdp;
    struct breakpoint *tp;
  
!   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 */
      }
    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;
! 
!   finish_tfind_command (tfind_tp, tdp, 0, 0, from_tty);
  }
  
  /* TFIND LINE command:
*************** trace_find_line_command (char *args, int
*** 2169,2262 ****
    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 ();
! 
! 	  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))
! 	{
! 	  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);
      }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  /* tfind range command */
--- 1832,1909 ----
    struct cleanup *old_chain;
    char   startpc_str[40], endpc_str[40];
  
!   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)
!     {
!       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 (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
!     finish_tfind_command (tfind_outside, 0, start_pc, end_pc - 1, from_tty);
!   do_cleanups (old_chain);
  }
  
  /* tfind range command */
*************** trace_find_range_command (char *args, in
*** 2267,2304 ****
    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 (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;	/* ??? */
! 	}
  
!       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);
      }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  /* tfind outside command */
--- 1914,1943 ----
    char start_str[40], stop_str[40];
    char *tmp;
  
!   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 (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;	/* ??? */
!     }
! 
!   finish_tfind_command (tfind_range, 0, start, stop, from_tty);
  }
  
  /* tfind outside command */
*************** trace_find_outside_command (char *args, 
*** 2309,2346 ****
    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 (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;	/* ??? */
! 	}
  
!       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);
      }
    else
!     error (_("Trace can only be run on remote targets."));
  }
  
  /* info scope command: list the locals for a scope.  */
--- 1948,1977 ----
    char start_str[40], stop_str[40];
    char *tmp;
  
!   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 (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;	/* ??? */
!     }
! 
!   finish_tfind_command (tfind_outside, 0, start, stop, from_tty);
  }
  
  /* info scope command: list the locals for a scope.  */
*************** trace_dump_command (char *args, int from
*** 2511,2522 ****
    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."));
--- 2142,2147 ----
*************** trace_dump_command (char *args, int from
*** 2621,2637 ****
  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."));
  }
  
  static void
--- 2246,2252 ----
  void
  send_disconnected_tracing_value (int value)
  {
!   target_set_disconnected_tracing (value);
  }
  
  static void
*************** trace data collected in the meantime."),
*** 2848,2854 ****
  			   NULL,
  			   &setlist,
  			   &showlist);
- 
-   target_buf_size = 2048;
-   target_buf = xmalloc (target_buf_size);
  }
--- 2463,2466 ----
Index: tracepoint.h
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.h,v
retrieving revision 1.18
diff -p -r1.18 tracepoint.h
*** tracepoint.h	1 Jan 2010 07:31:42 -0000	1.18
--- tracepoint.h	7 Jan 2010 01:00:32 -0000
*************** struct trace_state_variable
*** 65,70 ****
--- 65,72 ----
  
  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);

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