Remove AT_SYMBOL
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index e1555158d6db17cac6522c722679c55dcbb25eda..6e47a0a7dee642032dc4388015a4118e352e85db 100644 (file)
@@ -1,7 +1,6 @@
 /* Tracing functionality for remote targets in custom GDB protocol
 
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1997-2012 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -53,6 +52,7 @@
 #include "memrange.h"
 #include "exceptions.h"
 #include "cli/cli-utils.h"
+#include "probe.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -178,6 +178,18 @@ static int disconnected_tracing;
 
 static int circular_trace_buffer;
 
+/* Textual notes applying to the current and/or future trace runs.  */
+
+char *trace_user = NULL;
+
+/* Textual notes applying to the current and/or future trace runs.  */
+
+char *trace_notes = NULL;
+
+/* Textual notes applying to the stopping of a trace.  */
+
+char *trace_stop_notes = NULL;
+
 /* ======= Important command functions: ======= */
 static void trace_actions_command (char *, int);
 static void trace_start_command (char *, int);
@@ -199,8 +211,6 @@ static char *mem2hex (gdb_byte *, char *, int);
 static void add_register (struct collection_list *collection,
                          unsigned int regno);
 
-extern void send_disconnected_tracing_value (int value);
-
 static void free_uploaded_tps (struct uploaded_tp **utpp);
 static void free_uploaded_tsvs (struct uploaded_tsv **utsvp);
 
@@ -338,7 +348,7 @@ find_trace_state_variable (const char *name)
   return NULL;
 }
 
-void
+static void
 delete_trace_state_variable (const char *name)
 {
   struct trace_state_variable *tsv;
@@ -358,7 +368,7 @@ delete_trace_state_variable (const char *name)
 /* The 'tvariable' command collects a name and optional expression to
    evaluate into an initial value.  */
 
-void
+static void
 trace_variable_command (char *args, int from_tty)
 {
   struct expression *expr;
@@ -420,7 +430,7 @@ trace_variable_command (char *args, int from_tty)
   do_cleanups (old_chain);
 }
 
-void
+static void
 delete_trace_variable_command (char *args, int from_tty)
 {
   int ix;
@@ -731,10 +741,10 @@ validate_actionline (char **line, struct breakpoint *b)
                {
                  if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
                    {
-                     error (_("constant `%s' (value %ld) "
+                     error (_("constant `%s' (value %s) "
                               "will not be collected."),
                             SYMBOL_PRINT_NAME (exp->elts[2].symbol),
-                            SYMBOL_VALUE (exp->elts[2].symbol));
+                            plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
                    }
                  else if (SYMBOL_CLASS (exp->elts[2].symbol)
                           == LOC_OPTIMIZED_OUT)
@@ -971,8 +981,8 @@ collect_symbol (struct collection_list *collect,
                       SYMBOL_CLASS (sym));
       break;
     case LOC_CONST:
-      printf_filtered ("constant %s (value %ld) will not be collected.\n",
-                      SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE (sym));
+      printf_filtered ("constant %s (value %s) will not be collected.\n",
+                      SYMBOL_PRINT_NAME (sym), plongest (SYMBOL_VALUE (sym)));
       break;
     case LOC_STATIC:
       offset = SYMBOL_VALUE_ADDRESS (sym);
@@ -1568,7 +1578,8 @@ encode_actions_1 (struct command_line *action,
 }
 
 /* Render all actions into gdb protocol.  */
-/*static*/ void
+
+void
 encode_actions (struct breakpoint *t, struct bp_location *tloc,
                char ***tdp_actions, char ***stepping_actions)
 {
@@ -1642,16 +1653,59 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
   collect->next_aexpr_elt++;
 }
 
+static void
+process_tracepoint_on_disconnect (void)
+{
+  VEC(breakpoint_p) *tp_vec = NULL;
+  int ix;
+  struct breakpoint *b;
+  int has_pending_p = 0;
+
+  /* Check whether we still have pending tracepoint.  If we have, warn the
+     user that pending tracepoint will no longer work.  */
+  tp_vec = all_tracepoints ();
+  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
+    {
+      if (b->loc == NULL)
+       {
+         has_pending_p = 1;
+         break;
+       }
+      else
+       {
+         struct bp_location *loc1;
+
+         for (loc1 = b->loc; loc1; loc1 = loc1->next)
+           {
+             if (loc1->shlib_disabled)
+               {
+                 has_pending_p = 1;
+                 break;
+               }
+           }
+
+         if (has_pending_p)
+           break;
+       }
+    }
+  VEC_free (breakpoint_p, tp_vec);
+
+  if (has_pending_p)
+    warning (_("Pending tracepoints will not be resolved while"
+              " GDB is disconnected\n"));
+}
+
 
 void
-start_tracing (void)
+start_tracing (char *notes)
 {
   VEC(breakpoint_p) *tp_vec = NULL;
   int ix;
   struct breakpoint *b;
   struct trace_state_variable *tsv;
   int any_enabled = 0, num_to_download = 0;
-  
+  int ret;
+
   tp_vec = all_tracepoints ();
 
   /* No point in tracing without any tracepoints...  */
@@ -1664,6 +1718,7 @@ start_tracing (void)
   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
     {
       struct tracepoint *t = (struct tracepoint *) b;
+      struct bp_location *loc;
 
       if (b->enable_state == bp_enabled)
        any_enabled = 1;
@@ -1703,6 +1758,10 @@ start_tracing (void)
       struct tracepoint *t = (struct tracepoint *) b;
       struct bp_location *loc;
 
+      /* Clear `inserted' flag.  */
+      for (loc = b->loc; loc; loc = loc->next)
+       loc->inserted = 0;
+
       if ((b->type == bp_fast_tracepoint
           ? !may_insert_fast_tracepoints
           : !may_insert_tracepoints))
@@ -1722,6 +1781,10 @@ start_tracing (void)
        }
 
       t->number_on_target = b->number;
+
+      for (loc = b->loc; loc; loc = loc->next)
+       if (loc->probe != NULL)
+         loc->probe->pops->set_semaphore (loc->probe, loc->gdbarch);
     }
   VEC_free (breakpoint_p, tp_vec);
 
@@ -1737,6 +1800,13 @@ start_tracing (void)
   target_set_disconnected_tracing (disconnected_tracing);
   target_set_circular_trace_buffer (circular_trace_buffer);
 
+  if (!notes)
+    notes = trace_notes;
+  ret = target_set_trace_notes (trace_user, notes, NULL);
+
+  if (!ret && (trace_user || notes))
+    warning ("Target does not support trace user/notes, info ignored");
+
   /* Now insert traps and begin collecting data.  */
   target_trace_start ();
 
@@ -1748,12 +1818,11 @@ start_tracing (void)
   clear_traceframe_info ();
 }
 
-/* tstart command:
-
-   Tell target to clear any previous trace experiment.
-   Walk the list of tracepoints, and send them (and their actions)
-   to the target.  If no errors,
-   Tell target to start a new trace experiment.  */
+/* The tstart command requests the target to start a new trace run.
+   The command passes any arguments it has to the target verbatim, as
+   an optional "trace note".  This is useful as for instance a warning
+   to other users if the trace runs disconnected, and you don't want
+   anybody else messing with the target.  */
 
 static void
 trace_start_command (char *args, int from_tty)
@@ -1767,23 +1836,63 @@ trace_start_command (char *args, int from_tty)
        error (_("New trace run not started."));
     }
 
-  start_tracing ();
+  start_tracing (args);
 }
 
-/* tstop command */
+/* The tstop command stops the tracing run.  The command passes any
+   supplied arguments to the target verbatim as a "stop note"; if the
+   target supports trace notes, then it will be reported back as part
+   of the trace run's status.  */
+
 static void
 trace_stop_command (char *args, int from_tty)
 {
   if (!current_trace_status ()->running)
     error (_("Trace is not running."));
 
-  stop_tracing ();
+  stop_tracing (args);
 }
 
 void
-stop_tracing (void)
+stop_tracing (char *note)
 {
+  int ret;
+  VEC(breakpoint_p) *tp_vec = NULL;
+  int ix;
+  struct breakpoint *t;
+
   target_trace_stop ();
+
+  tp_vec = all_tracepoints ();
+  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+    {
+      struct bp_location *loc;
+
+      if ((t->type == bp_fast_tracepoint
+          ? !may_insert_fast_tracepoints
+          : !may_insert_tracepoints))
+       continue;
+
+      for (loc = t->loc; loc; loc = loc->next)
+       {
+         /* GDB can be totally absent in some disconnected trace scenarios,
+            but we don't really care if this semaphore goes out of sync.
+            That's why we are decrementing it here, but not taking care
+            in other places.  */
+         if (loc->probe != NULL)
+           loc->probe->pops->clear_semaphore (loc->probe, loc->gdbarch);
+       }
+    }
+
+  VEC_free (breakpoint_p, tp_vec);
+
+  if (!note)
+    note = trace_stop_notes;
+  ret = target_set_trace_notes (NULL, NULL, note);
+
+  if (!ret && note)
+    warning ("Target does not support trace notes, note ignored");
+
   /* Should change in response to reply?  */
   current_trace_status ()->running = 0;
 }
@@ -1793,7 +1902,9 @@ static void
 trace_status_command (char *args, int from_tty)
 {
   struct trace_status *ts = current_trace_status ();
-  int status;
+  int status, ix;
+  VEC(breakpoint_p) *tp_vec = NULL;
+  struct breakpoint *t;
   
   status = target_get_trace_status (ts);
 
@@ -1824,7 +1935,11 @@ trace_status_command (char *args, int from_tty)
          printf_filtered (_("No trace has been run on the target.\n"));
          break;
        case tstop_command:
-         printf_filtered (_("Trace stopped by a tstop command.\n"));
+         if (ts->stop_desc)
+           printf_filtered (_("Trace stopped by a tstop command (%s).\n"),
+                            ts->stop_desc);
+         else
+           printf_filtered (_("Trace stopped by a tstop command.\n"));
          break;
        case trace_buffer_full:
          printf_filtered (_("Trace stopped because the buffer was full.\n"));
@@ -1840,10 +1955,10 @@ trace_status_command (char *args, int from_tty)
          if (ts->stopping_tracepoint)
            printf_filtered (_("Trace stopped by an "
                               "error (%s, tracepoint %d).\n"),
-                            ts->error_desc, ts->stopping_tracepoint);
+                            ts->stop_desc, ts->stopping_tracepoint);
          else
            printf_filtered (_("Trace stopped by an error (%s).\n"),
-                            ts->error_desc);
+                            ts->stop_desc);
          break;
        case trace_stop_reason_unknown:
          printf_filtered (_("Trace stopped for an unknown reason.\n"));
@@ -1894,12 +2009,50 @@ trace_status_command (char *args, int from_tty)
   if (ts->circular_buffer)
     printf_filtered (_("Trace buffer is circular.\n"));
 
+  if (ts->user_name && strlen (ts->user_name) > 0)
+    printf_filtered (_("Trace user is %s.\n"), ts->user_name);
+
+  if (ts->notes && strlen (ts->notes) > 0)
+    printf_filtered (_("Trace notes: %s.\n"), ts->notes);
+
   /* Now report on what we're doing with tfind.  */
   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"));
+
+  /* Report start/stop times if supplied.  */
+  if (ts->start_time)
+    {
+      if (ts->stop_time)
+       {
+         LONGEST run_time = ts->stop_time - ts->start_time;
+
+         /* Reporting a run time is more readable than two long numbers.  */
+         printf_filtered (_("Trace started at %ld.%06ld secs, stopped %ld.%06ld secs later.\n"),
+                          (long int) ts->start_time / 1000000,
+                          (long int) ts->start_time % 1000000,
+                          (long int) run_time / 1000000,
+                          (long int) run_time % 1000000);
+       }
+      else
+       printf_filtered (_("Trace started at %ld.%06ld secs.\n"),
+                        (long int) ts->start_time / 1000000,
+                        (long int) ts->start_time % 1000000);
+    }
+  else if (ts->stop_time)
+    printf_filtered (_("Trace stopped at %ld.%06ld secs.\n"),
+                    (long int) ts->stop_time / 1000000,
+                    (long int) ts->stop_time % 1000000);
+
+  /* Now report any per-tracepoint status available.  */
+  tp_vec = all_tracepoints ();
+
+  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+    target_get_tracepoint_status (t, NULL);
+
+  VEC_free (breakpoint_p, tp_vec);
 }
 
 /* Report the trace status to uiout, in a way suitable for MI, and not
@@ -1982,7 +2135,7 @@ trace_status_mi (int on_stop)
                                  stopping_tracepoint);
              if (ts->stop_reason == tracepoint_error)
                ui_out_field_string (uiout, "error-description",
-                                    ts->error_desc);
+                                    ts->stop_desc);
            }
        }
     }
@@ -1998,6 +2151,22 @@ trace_status_mi (int on_stop)
 
   ui_out_field_int (uiout, "disconnected",  ts->disconnected_tracing);
   ui_out_field_int (uiout, "circular",  ts->circular_buffer);
+
+  ui_out_field_string (uiout, "user-name", ts->user_name);
+  ui_out_field_string (uiout, "notes", ts->notes);
+
+  {
+    char buf[100];
+
+    xsnprintf (buf, sizeof buf, "%ld.%06ld",
+              (long int) ts->start_time / 1000000,
+              (long int) ts->start_time % 1000000);
+    ui_out_field_string (uiout, "start-time", buf);
+    xsnprintf (buf, sizeof buf, "%ld.%06ld",
+              (long int) ts->stop_time / 1000000,
+              (long int) ts->stop_time % 1000000);
+    ui_out_field_string (uiout, "stop-time", buf);
+  }
 }
 
 /* This function handles the details of what to do about an ongoing
@@ -2020,6 +2189,8 @@ disconnect_tracing (int from_tty)
      disconnected-tracing.  */
   if (current_trace_status ()->running && from_tty)
     {
+      process_tracepoint_on_disconnect ();
+
       if (current_trace_status ()->disconnected_tracing)
        {
          if (!query (_("Trace is running and will "
@@ -2321,7 +2492,7 @@ trace_find_line_command (char *args, int from_tty)
     }
   else
     {
-      sals = decode_line_spec (args, 1);
+      sals = decode_line_spec (args, DECODE_LINE_FUNFIRSTLINE);
       sal = sals.sals[0];
     }
   
@@ -2439,7 +2610,8 @@ scope_info (char *args, int from_tty)
   struct symbol *sym;
   struct minimal_symbol *msym;
   struct block *block;
-  char *symname, *save_args = args;
+  const char *symname;
+  char *save_args = args;
   struct dict_iterator iter;
   int j, count = 0;
   struct gdbarch *gdbarch;
@@ -2449,7 +2621,7 @@ scope_info (char *args, int from_tty)
     error (_("requires an argument (function, "
             "line or *addr) to define a scope"));
 
-  sals = decode_line_1 (&args, 1, NULL, 0, NULL);
+  sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
   if (sals.nelts == 0)
     return;            /* Presumably decode_line_1 has already warned.  */
 
@@ -2483,8 +2655,9 @@ scope_info (char *args, int from_tty)
              count--;          /* Don't count this one.  */
              continue;
            case LOC_CONST:
-             printf_filtered ("a constant with value %ld (0x%lx)",
-                              SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
+             printf_filtered ("a constant with value %s (%s)",
+                              plongest (SYMBOL_VALUE (sym)),
+                              hex_string (SYMBOL_VALUE (sym)));
              break;
            case LOC_CONST_BYTES:
              printf_filtered ("constant bytes: ");
@@ -2517,16 +2690,16 @@ scope_info (char *args, int from_tty)
                                 gdbarch_register_name (gdbarch, regno));
              break;
            case LOC_ARG:
-             printf_filtered ("an argument at stack/frame offset %ld",
-                              SYMBOL_VALUE (sym));
+             printf_filtered ("an argument at stack/frame offset %s",
+                              plongest (SYMBOL_VALUE (sym)));
              break;
            case LOC_LOCAL:
-             printf_filtered ("a local variable at frame offset %ld",
-                              SYMBOL_VALUE (sym));
+             printf_filtered ("a local variable at frame offset %s",
+                              plongest (SYMBOL_VALUE (sym)));
              break;
            case LOC_REF_ARG:
-             printf_filtered ("a reference argument at offset %ld",
-                              SYMBOL_VALUE (sym));
+             printf_filtered ("a reference argument at offset %s",
+                              plongest (SYMBOL_VALUE (sym)));
              break;
            case LOC_REGPARM_ADDR:
              /* Note comment at LOC_REGISTER.  */
@@ -2837,9 +3010,9 @@ trace_save (const char *filename, int target_does_save)
           (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
   if (ts->stop_reason == tracepoint_error)
     {
-      char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1);
+      char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
 
-      bin2hex ((gdb_byte *) ts->error_desc, buf, 0);
+      bin2hex ((gdb_byte *) ts->stop_desc, buf, 0);
       fprintf (fp, ":%s", buf);
     }
   fprintf (fp, ":%x", ts->stopping_tracepoint);
@@ -2891,6 +3064,9 @@ trace_save (const char *filename, int target_does_save)
 
   target_upload_tracepoints (&uploaded_tps);
 
+  for (utp = uploaded_tps; utp; utp = utp->next)
+    target_get_tracepoint_status (NULL, utp);
+
   for (utp = uploaded_tps; utp; utp = utp->next)
     {
       fprintf (fp, "tp T%x:%s:%c:%x:%x",
@@ -2927,6 +3103,11 @@ trace_save (const char *filename, int target_does_save)
                                buf, MAX_TRACE_UPLOAD);
          fprintf (fp, "tp Z%s\n", buf);
        }
+      fprintf (fp, "tp V%x:%s:%x:%s\n",
+              utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
+              utp->hit_count,
+              phex_nz (utp->traceframe_usage,
+                       sizeof (utp->traceframe_usage)));
     }
 
   free_uploaded_tps (&uploaded_tps);
@@ -2997,17 +3178,11 @@ trace_save_command (char *args, int from_tty)
 /* Tell the target what to do with an ongoing tracing run if GDB
    disconnects for some reason.  */
 
-void
-send_disconnected_tracing_value (int value)
-{
-  target_set_disconnected_tracing (value);
-}
-
 static void
 set_disconnected_tracing (char *args, int from_tty,
                          struct cmd_list_element *c)
 {
-  send_disconnected_tracing_value (disconnected_tracing);
+  target_set_disconnected_tracing (disconnected_tracing);
 }
 
 static void
@@ -3017,6 +3192,42 @@ set_circular_trace_buffer (char *args, int from_tty,
   target_set_circular_trace_buffer (circular_trace_buffer);
 }
 
+static void
+set_trace_user (char *args, int from_tty,
+               struct cmd_list_element *c)
+{
+  int ret;
+
+  ret = target_set_trace_notes (trace_user, NULL, NULL);
+
+  if (!ret)
+    warning ("Target does not support trace notes, user ignored");
+}
+
+static void
+set_trace_notes (char *args, int from_tty,
+                struct cmd_list_element *c)
+{
+  int ret;
+
+  ret = target_set_trace_notes (NULL, trace_notes, NULL);
+
+  if (!ret)
+    warning ("Target does not support trace notes, note ignored");
+}
+
+static void
+set_trace_stop_notes (char *args, int from_tty,
+                     struct cmd_list_element *c)
+{
+  int ret;
+
+  ret = target_set_trace_notes (NULL, NULL, trace_stop_notes);
+
+  if (!ret)
+    warning ("Target does not support trace notes, stop note ignored");
+}
+
 /* Convert the memory pointed to by mem into hex, placing result in buf.
  * Return a pointer to the last char put in buf (null)
  * "stolen" from sparc-stub.c
@@ -3166,7 +3377,7 @@ free_uploaded_tps (struct uploaded_tp **utpp)
 /* Given a number and address, return an uploaded tracepoint with that
    number, creating if necessary.  */
 
-struct uploaded_tsv *
+static struct uploaded_tsv *
 get_uploaded_tsv (int num, struct uploaded_tsv **utsvp)
 {
   struct uploaded_tsv *utsv;
@@ -3213,7 +3424,7 @@ cond_string_is_same (char *str1, char *str2)
    toggle that freely, and may have done so in anticipation of the
    next trace run.  Return the location of matched tracepoint.  */
 
-struct bp_location *
+static struct bp_location *
 find_matching_tracepoint_location (struct uploaded_tp *utp)
 {
   VEC(breakpoint_p) *tp_vec = all_tracepoints ();
@@ -3296,7 +3507,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
 /* Trace state variables don't have much to identify them beyond their
    name, so just use that to detect matches.  */
 
-struct trace_state_variable *
+static struct trace_state_variable *
 find_matching_tsv (struct uploaded_tsv *utsv)
 {
   if (!utsv->name)
@@ -3305,35 +3516,43 @@ find_matching_tsv (struct uploaded_tsv *utsv)
   return find_trace_state_variable (utsv->name);
 }
 
-struct trace_state_variable *
+static struct trace_state_variable *
 create_tsv_from_upload (struct uploaded_tsv *utsv)
 {
   const char *namebase;
-  char buf[20];
+  char *buf;
   int try_num = 0;
   struct trace_state_variable *tsv;
+  struct cleanup *old_chain;
 
   if (utsv->name)
     {
       namebase = utsv->name;
-      sprintf (buf, "%s", namebase);
+      buf = xstrprintf ("%s", namebase);
     }
   else
     {
       namebase = "__tsv";
-      sprintf (buf, "%s_%d", namebase, try_num++);
+      buf = xstrprintf ("%s_%d", namebase, try_num++);
     }
 
   /* Fish for a name that is not in use.  */
   /* (should check against all internal vars?)  */
   while (find_trace_state_variable (buf))
-    sprintf (buf, "%s_%d", namebase, try_num++);
+    {
+      xfree (buf);
+      buf = xstrprintf ("%s_%d", namebase, try_num++);
+    }
+
+  old_chain = make_cleanup (xfree, buf);
 
   /* We have an available name, create the variable.  */
   tsv = create_trace_state_variable (buf);
   tsv->initial_value = utsv->initial_value;
   tsv->builtin = utsv->builtin;
 
+  do_cleanups (old_chain);
+
   return tsv;
 }
 
@@ -3594,20 +3813,26 @@ tfile_interp_line (char *line,
 void
 parse_trace_status (char *line, struct trace_status *ts)
 {
-  char *p = line, *p1, *p2, *p_temp;
+  char *p = line, *p1, *p2, *p3, *p_temp;
+  int end;
   ULONGEST val;
 
   ts->running_known = 1;
   ts->running = (*p++ == '1');
   ts->stop_reason = trace_stop_reason_unknown;
-  xfree (ts->error_desc);
-  ts->error_desc = NULL;
+  xfree (ts->stop_desc);
+  ts->stop_desc = NULL;
   ts->traceframe_count = -1;
   ts->traceframes_created = -1;
   ts->buffer_free = -1;
   ts->buffer_size = -1;
   ts->disconnected_tracing = 0;
   ts->circular_buffer = 0;
+  xfree (ts->user_name);
+  ts->user_name = NULL;
+  xfree (ts->notes);
+  ts->notes = NULL;
+  ts->start_time = ts->stop_time = 0;
 
   while (*p++)
     {
@@ -3615,6 +3840,9 @@ parse_trace_status (char *line, struct trace_status *ts)
       if (p1 == NULL)
        error (_("Malformed trace status, at %s\n\
 Status line: '%s'\n"), p, line);
+      p3 = strchr (p, ';');
+      if (p3 == NULL)
+       p3 = p + strlen (p);
       if (strncmp (p, stop_reason_names[trace_buffer_full], p1 - p) == 0)
        {
          p = unpack_varlen_hex (++p1, &val);
@@ -3634,7 +3862,22 @@ Status line: '%s'\n"), p, line);
        }
       else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0)
        {
-         p = unpack_varlen_hex (++p1, &val);
+         p2 = strchr (++p1, ':');
+         if (!p2 || p2 > p3)
+           {
+             /*older style*/
+             p2 = p1;
+           }
+         else if (p2 != p1)
+           {
+             ts->stop_desc = xmalloc (strlen (line));
+             end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
+             ts->stop_desc[end] = '\0';
+           }
+         else
+           ts->stop_desc = xstrdup ("");
+
+         p = unpack_varlen_hex (++p2, &val);
          ts->stop_reason = tstop_command;
        }
       else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0)
@@ -3647,14 +3890,12 @@ Status line: '%s'\n"), p, line);
          p2 = strchr (++p1, ':');
          if (p2 != p1)
            {
-             int end;
-
-             ts->error_desc = xmalloc ((p2 - p1) / 2 + 1);
-             end = hex2bin (p1, ts->error_desc, (p2 - p1) / 2);
-             ts->error_desc[end] = '\0';
+             ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1);
+             end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
+             ts->stop_desc[end] = '\0';
            }
          else
-           ts->error_desc = xstrdup ("");
+           ts->stop_desc = xstrdup ("");
 
          p = unpack_varlen_hex (++p2, &val);
          ts->stopping_tracepoint = val;
@@ -3690,6 +3931,32 @@ Status line: '%s'\n"), p, line);
          p = unpack_varlen_hex (++p1, &val);
          ts->circular_buffer = val;
        }
+      else if (strncmp (p, "starttime", p1 - p) == 0)
+       {
+         p = unpack_varlen_hex (++p1, &val);
+         ts->start_time = val;
+       }
+      else if (strncmp (p, "stoptime", p1 - p) == 0)
+       {
+         p = unpack_varlen_hex (++p1, &val);
+         ts->stop_time = val;
+       }
+      else if (strncmp (p, "username", p1 - p) == 0)
+       {
+         ++p1;
+         ts->user_name = xmalloc (strlen (p) / 2);
+         end = hex2bin (p1, ts->user_name, (p3 - p1)  / 2);
+         ts->user_name[end] = '\0';
+         p = p3;
+       }
+      else if (strncmp (p, "notes", p1 - p) == 0)
+       {
+         ++p1;
+         ts->notes = xmalloc (strlen (p) / 2);
+         end = hex2bin (p1, ts->notes, (p3 - p1) / 2);
+         ts->notes[end] = '\0';
+         p = p3;
+       }
       else
        {
          /* Silently skip unknown optional info.  */
@@ -3703,6 +3970,26 @@ Status line: '%s'\n"), p, line);
     }
 }
 
+void
+parse_tracepoint_status (char *p, struct breakpoint *bp,
+                        struct uploaded_tp *utp)
+{
+  ULONGEST uval;
+  struct tracepoint *tp = (struct tracepoint *) bp;
+
+  p = unpack_varlen_hex (p, &uval);
+  if (tp)
+    tp->base.hit_count += uval;
+  else
+    utp->hit_count += uval;
+  p = unpack_varlen_hex (p + 1, &uval);
+  if (tp)
+    tp->traceframe_usage += uval;
+  else
+    utp->traceframe_usage += uval;
+  /* Ignore any extra, allowing for future extensions.  */
+}
+
 /* Given a line of text defining a part of a tracepoint, parse it into
    an "uploaded tracepoint".  */
 
@@ -3804,6 +4091,12 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
       else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
        VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
     }
+  else if (piece == 'V')
+    {
+      utp = get_uploaded_tp (num, addr, utpp);
+
+      parse_tracepoint_status (p, NULL, utp);
+    }
   else
     {
       /* Don't error out, the target might be sending us optional
@@ -3879,6 +4172,13 @@ tfile_get_trace_status (struct trace_status *ts)
   return -1;
 }
 
+static void
+tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp)
+{
+  /* Other bits of trace status were collected as part of opening the
+     trace files, so nothing to do here.  */
+}
+
 /* Given the position of a traceframe in the file, figure out what
    address the frame was collected at.  This would normally be the
    value of a collected PC register, but if not available, we
@@ -4420,6 +4720,7 @@ init_tfile_ops (void)
   tfile_ops.to_xfer_partial = tfile_xfer_partial;
   tfile_ops.to_files_info = tfile_files_info;
   tfile_ops.to_get_trace_status = tfile_get_trace_status;
+  tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status;
   tfile_ops.to_trace_find = tfile_trace_find;
   tfile_ops.to_get_trace_state_variable_value
     = tfile_get_trace_state_variable_value;
@@ -4433,6 +4734,20 @@ init_tfile_ops (void)
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
+void
+free_current_marker (void *arg)
+{
+  struct static_tracepoint_marker **marker_p = arg;
+
+  if (*marker_p != NULL)
+    {
+      release_static_tracepoint_marker (*marker_p);
+      xfree (*marker_p);
+    }
+  else
+    *marker_p = NULL;
+}
+
 /* Given a line of text defining a static tracepoint marker, parse it
    into a "static tracepoint marker" object.  Throws an error is
    parsing fails.  If PP is non-null, it points to one past the end of
@@ -4495,8 +4810,6 @@ print_one_static_tracepoint_marker (int count,
   char wrap_indent[80];
   char extra_field_indent[80];
   struct ui_out *uiout = current_uiout;
-  struct ui_stream *stb = ui_out_stream_new (uiout);
-  struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
   struct cleanup *bkpt_chain;
   VEC(breakpoint_p) *tracepoints;
 
@@ -4603,7 +4916,6 @@ print_one_static_tracepoint_marker (int count,
   VEC_free (breakpoint_p, tracepoints);
 
   do_cleanups (bkpt_chain);
-  do_cleanups (old_chain);
 }
 
 static void
@@ -4615,6 +4927,12 @@ info_static_tracepoint_markers_command (char *arg, int from_tty)
   struct ui_out *uiout = current_uiout;
   int i;
 
+  /* We don't have to check target_can_use_agent and agent's capability on
+     static tracepoint here, in order to be compatible with older GDBserver.
+     We don't check USE_AGENT is true or not, because static tracepoints
+     don't work without in-process agent, so we don't bother users to type
+     `set agent on' when to use static tracepoint.  */
+
   old_chain
     = make_cleanup_ui_out_table_begin_end (uiout, 5, -1,
                                           "StaticTracepointMarkersTable");
@@ -4658,7 +4976,8 @@ info_static_tracepoint_markers_command (char *arg, int from_tty)
    available.  */
 
 static struct value *
-sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+                 void *ignore)
 {
   LONGEST size;
   gdb_byte *buf;
@@ -4784,7 +5103,7 @@ parse_traceframe_info (const char *tframe_info)
    This is where we avoid re-fetching the object from the target if we
    already have it cached.  */
 
-struct traceframe_info *
+static struct traceframe_info *
 get_traceframe_info (void)
 {
   if (traceframe_info == NULL)
@@ -4837,6 +5156,15 @@ traceframe_available_memory (VEC(mem_range_s) **result,
   return 0;
 }
 
+/* Implementation of `sdata' variable.  */
+
+static const struct internalvar_funcs sdata_funcs =
+{
+  sdata_make_value,
+  NULL,
+  NULL
+};
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
@@ -4847,7 +5175,7 @@ _initialize_tracepoint (void)
      value with a void typed value, and when we get here, gdbarch
      isn't initialized yet.  At this point, we're quite sure there
      isn't another convenience variable of the same name.  */
-  create_internalvar_type_lazy ("_sdata", sdata_make_value);
+  create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL);
 
   traceframe_number = -1;
   tracepoint_number = -1;
@@ -4964,11 +5292,17 @@ De-select any trace frame and resume 'live' debugging."),
   add_com ("tstatus", class_trace, trace_status_command,
           _("Display the status of the current trace data collection."));
 
-  add_com ("tstop", class_trace, trace_stop_command,
-          _("Stop trace data collection."));
+  add_com ("tstop", class_trace, trace_stop_command, _("\
+Stop trace data collection.\n\
+Usage: tstop [ <notes> ... ]\n\
+Any arguments supplied are recorded with the trace as a stop reason and\n\
+reported by tstatus (if the target supports trace notes)."));
 
-  add_com ("tstart", class_trace, trace_start_command,
-          _("Start trace data collection."));
+  add_com ("tstart", class_trace, trace_start_command, _("\
+Start trace data collection.\n\
+Usage: tstart [ <notes> ... ]\n\
+Any arguments supplied are recorded with the trace as a note and\n\
+reported by tstatus (if the target supports trace notes)."));
 
   add_com ("end", class_trace, end_actions_pseudocommand, _("\
 Ends a list of commands or actions.\n\
@@ -5043,6 +5377,27 @@ up and stopping the trace run."),
                           &setlist,
                           &showlist);
 
+  add_setshow_string_cmd ("trace-user", class_trace,
+                         &trace_user, _("\
+Set the user name to use for current and future trace runs"), _("\
+Show the user name to use for current and future trace runs"), NULL,
+                         set_trace_user, NULL,
+                         &setlist, &showlist);
+
+  add_setshow_string_cmd ("trace-notes", class_trace,
+                         &trace_notes, _("\
+Set notes string to use for current and future trace runs"), _("\
+Show the notes string to use for current and future trace runs"), NULL,
+                         set_trace_notes, NULL,
+                         &setlist, &showlist);
+
+  add_setshow_string_cmd ("trace-stop-notes", class_trace,
+                         &trace_stop_notes, _("\
+Set notes string to use for future tstop commands"), _("\
+Show the notes string to use for future tstop commands"), NULL,
+                         set_trace_stop_notes, NULL,
+                         &setlist, &showlist);
+
   init_tfile_ops ();
 
   add_target (&tfile_ops);
This page took 0.036516 seconds and 4 git commands to generate.