PR gas/11395
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index 90691d02a2cffe8111f4881508c0e951344ef0f9..3484d7ad3b61aea01dbeccaac4f479910fc15920 100644 (file)
@@ -46,7 +46,8 @@
 #include "gdbthread.h"
 #include "stack.h"
 #include "gdbcore.h"
-
+#include "remote.h"
+#include "source.h"
 #include "ax.h"
 #include "ax-gdb.h"
 
@@ -382,10 +383,9 @@ trace_variable_command (char *args, int from_tty)
 void
 delete_trace_variable_command (char *args, int from_tty)
 {
-  int i, ix;
+  int ix;
   char **argv;
   struct cleanup *back_to;
-  struct trace_state_variable *tsv;
 
   if (args == NULL)
     {
@@ -398,12 +398,12 @@ delete_trace_variable_command (char *args, int from_tty)
   argv = gdb_buildargv (args);
   back_to = make_cleanup_freeargv (argv);
 
-  for (i = 0; argv[i] != NULL; i++)
+  for (ix = 0; argv[ix] != NULL; ix++)
     {
-      if (*argv[i] == '$')
-       delete_trace_state_variable (argv[i] + 1);
+      if (*argv[ix] == '$')
+       delete_trace_state_variable (argv[ix] + 1);
       else
-       warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[i]);
+       warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]);
     }
 
   do_cleanups (back_to);
@@ -446,7 +446,7 @@ tvariables_info_1 (void)
 
       back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable");
 
-      name = concat ("$", tsv->name, NULL);
+      name = concat ("$", tsv->name, (char *) NULL);
       make_cleanup (xfree, name);
       ui_out_field_string (uiout, "name", name);
       ui_out_field_string (uiout, "initial", plongest (tsv->initial_value));
@@ -560,16 +560,16 @@ trace_actions_command (char *args, int from_tty)
    internal errors.  */
 
 static void
-report_agent_reqs_errors (struct agent_expr *aexpr, struct agent_reqs *areqs)
+report_agent_reqs_errors (struct agent_expr *aexpr)
 {
   /* All of the "flaws" are serious bytecode generation issues that
      should never occur.  */
-  if (areqs->flaw != agent_flaw_none)
+  if (aexpr->flaw != agent_flaw_none)
     internal_error (__FILE__, __LINE__, _("expression is malformed"));
 
   /* If analysis shows a stack underflow, GDB must have done something
      badly wrong in its bytecode generation.  */
-  if (areqs->min_height < 0)
+  if (aexpr->min_height < 0)
     internal_error (__FILE__, __LINE__,
                    _("expression has min height < 0"));
 
@@ -579,7 +579,7 @@ report_agent_reqs_errors (struct agent_expr *aexpr, struct agent_reqs *areqs)
      depth roughly corresponds to parenthesization, so a limit of 20
      amounts to 20 levels of expression nesting, which is actually
      a pretty big hairy expression.  */
-  if (areqs->max_height > 20)
+  if (aexpr->max_height > 20)
     error (_("Expression is too complicated."));
 }
 
@@ -593,7 +593,6 @@ validate_actionline (char **line, struct breakpoint *t)
   char *p, *tmp_p;
   struct bp_location *loc;
   struct agent_expr *aexpr;
-  struct agent_reqs areqs;
 
   /* if EOF is typed, *line is NULL */
   if (*line == NULL)
@@ -623,9 +622,10 @@ validate_actionline (char **line, struct breakpoint *t)
 
          if (*p == '$')        /* look for special pseudo-symbols */
            {
-             if ((0 == strncasecmp ("reg", p + 1, 3)) ||
-                 (0 == strncasecmp ("arg", p + 1, 3)) ||
-                 (0 == strncasecmp ("loc", p + 1, 3)))
+             if (0 == strncasecmp ("reg", p + 1, 3)
+                 || 0 == strncasecmp ("arg", p + 1, 3)
+                 || 0 == strncasecmp ("loc", p + 1, 3)
+                 || 0 == strncasecmp ("_sdata", p + 1, 6))
                {
                  p = strchr (p, ',');
                  continue;
@@ -663,10 +663,9 @@ validate_actionline (char **line, struct breakpoint *t)
              if (aexpr->len > MAX_AGENT_EXPR_LEN)
                error (_("Expression is too complicated."));
 
-             ax_reqs (aexpr, &areqs);
-             (void) make_cleanup (xfree, areqs.reg_mask);
+             ax_reqs (aexpr);
 
-             report_agent_reqs_errors (aexpr, &areqs);
+             report_agent_reqs_errors (aexpr);
 
              do_cleanups (old_chain);
            }
@@ -699,10 +698,8 @@ validate_actionline (char **line, struct breakpoint *t)
              if (aexpr->len > MAX_AGENT_EXPR_LEN)
                error (_("Expression is too complicated."));
 
-             ax_reqs (aexpr, &areqs);
-             (void) make_cleanup (xfree, areqs.reg_mask);
-
-             report_agent_reqs_errors (aexpr, &areqs);
+             ax_reqs (aexpr);
+             report_agent_reqs_errors (aexpr);
 
              do_cleanups (old_chain);
            }
@@ -751,6 +748,9 @@ struct collection_list
     long next_aexpr_elt;
     struct agent_expr **aexpr_list;
 
+    /* True is the user requested a collection of "$_sdata", "static
+       tracepoint data".  */
+    int strace_data;
   }
 tracepoint_list, stepping_list;
 
@@ -974,7 +974,6 @@ collect_symbol (struct collection_list *collect,
     {
       struct agent_expr *aexpr;
       struct cleanup *old_chain1 = NULL;
-      struct agent_reqs areqs;
 
       aexpr = gen_trace_for_var (scope, gdbarch, sym);
 
@@ -990,26 +989,26 @@ collect_symbol (struct collection_list *collect,
 
       old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
-      ax_reqs (aexpr, &areqs);
+      ax_reqs (aexpr);
 
-      report_agent_reqs_errors (aexpr, &areqs);
+      report_agent_reqs_errors (aexpr);
 
       discard_cleanups (old_chain1);
       add_aexpr (collect, aexpr);
 
       /* take care of the registers */
-      if (areqs.reg_mask_len > 0)
+      if (aexpr->reg_mask_len > 0)
        {
          int ndx1, ndx2;
 
-         for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
+         for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
            {
              QUIT;     /* allow user to bail out with ^C */
-             if (areqs.reg_mask[ndx1] != 0)
+             if (aexpr->reg_mask[ndx1] != 0)
                {
                  /* assume chars have 8 bits */
                  for (ndx2 = 0; ndx2 < 8; ndx2++)
-                   if (areqs.reg_mask[ndx1] & (1 << ndx2))
+                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
                      /* it's used -- record it */
                      add_register (collect, ndx1 * 8 + ndx2);
                }
@@ -1091,6 +1090,14 @@ add_local_symbols (struct collection_list *collect,
     }
 }
 
+static void
+add_static_trace_data (struct collection_list *collection)
+{
+  if (info_verbose)
+    printf_filtered ("collect static trace data\n");
+  collection->strace_data = 1;
+}
+
 /* worker function */
 static void
 clear_collection_list (struct collection_list *list)
@@ -1105,6 +1112,7 @@ clear_collection_list (struct collection_list *list)
     }
   list->next_aexpr_elt = 0;
   memset (list->regs_mask, 0, sizeof (list->regs_mask));
+  list->strace_data = 0;
 }
 
 /* reduce a collection list to string form (for gdb protocol) */
@@ -1119,9 +1127,19 @@ stringify_collection_list (struct collection_list *list, char *string)
   char *end;
   long i;
 
-  count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
+  count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
   str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
 
+  if (list->strace_data)
+    {
+      if (info_verbose)
+       printf_filtered ("\nCollecting static trace data\n");
+      end = temp_buf;
+      *end++ = 'L';
+      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
+      ndx++;
+    }
+
   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
     if (list->regs_mask[i] != 0)       /* skip leading zeroes in regs_mask */
       break;
@@ -1231,7 +1249,6 @@ encode_actions_1 (struct command_line *action,
 {
   char *action_exp;
   struct expression *exp = NULL;
-  struct command_line *actions;
   int i;
   struct value *tempval;
   struct cmd_list_element *cmd;
@@ -1282,12 +1299,16 @@ encode_actions_1 (struct command_line *action,
                                     'L');
                  action_exp = strchr (action_exp, ',');        /* more? */
                }
+             else if (0 == strncasecmp ("$_sdata", action_exp, 7))
+               {
+                 add_static_trace_data (collect);
+                 action_exp = strchr (action_exp, ',');        /* more? */
+               }
              else
                {
                  unsigned long addr, len;
                  struct cleanup *old_chain = NULL;
                  struct cleanup *old_chain1 = NULL;
-                 struct agent_reqs areqs;
 
                  exp = parse_exp_1 (&action_exp, 
                                     block_for_pc (tloc->address), 1);
@@ -1333,27 +1354,27 @@ encode_actions_1 (struct command_line *action,
 
                      old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
-                     ax_reqs (aexpr, &areqs);
+                     ax_reqs (aexpr);
 
-                     report_agent_reqs_errors (aexpr, &areqs);
+                     report_agent_reqs_errors (aexpr);
 
                      discard_cleanups (old_chain1);
                      add_aexpr (collect, aexpr);
 
                      /* take care of the registers */
-                     if (areqs.reg_mask_len > 0)
+                     if (aexpr->reg_mask_len > 0)
                        {
                          int ndx1;
                          int ndx2;
 
-                         for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
+                         for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
                            {
                              QUIT;     /* allow user to bail out with ^C */
-                             if (areqs.reg_mask[ndx1] != 0)
+                             if (aexpr->reg_mask[ndx1] != 0)
                                {
                                  /* assume chars have 8 bits */
                                  for (ndx2 = 0; ndx2 < 8; ndx2++)
-                                   if (areqs.reg_mask[ndx1] & (1 << ndx2))
+                                   if (aexpr->reg_mask[ndx1] & (1 << ndx2))
                                      /* it's used -- record it */
                                      add_register (collect, 
                                                    ndx1 * 8 + ndx2);
@@ -1376,10 +1397,8 @@ encode_actions_1 (struct command_line *action,
                action_exp++;
 
                {
-                 unsigned long addr, len;
                  struct cleanup *old_chain = NULL;
                  struct cleanup *old_chain1 = NULL;
-                 struct agent_reqs areqs;
 
                  exp = parse_exp_1 (&action_exp, 
                                     block_for_pc (tloc->address), 1);
@@ -1388,9 +1407,8 @@ encode_actions_1 (struct command_line *action,
                  aexpr = gen_eval_for_expr (tloc->address, exp);
                  old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
-                 ax_reqs (aexpr, &areqs);
-
-                 report_agent_reqs_errors (aexpr, &areqs);
+                 ax_reqs (aexpr);
+                 report_agent_reqs_errors (aexpr);
 
                  discard_cleanups (old_chain1);
                  /* Even though we're not officially collecting, add
@@ -1409,8 +1427,8 @@ encode_actions_1 (struct command_line *action,
             here.  */
          gdb_assert (stepping_list);
 
-         encode_actions_1 (action->body_list[0], t, tloc, frame_reg, frame_offset,
-                           stepping_list, NULL);
+         encode_actions_1 (action->body_list[0], t, tloc, frame_reg,
+                           frame_offset, stepping_list, NULL);
        }
       else
        error (_("Invalid tracepoint command '%s'"), action->line);
@@ -1485,7 +1503,7 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
     {
       collect->aexpr_list =
        xrealloc (collect->aexpr_list,
-               2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
+                 2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
       collect->aexpr_listsize *= 2;
     }
   collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
@@ -1496,12 +1514,11 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
 void
 start_tracing (void)
 {
-  char buf[2048];
   VEC(breakpoint_p) *tp_vec = NULL;
   int ix;
   struct breakpoint *t;
   struct trace_state_variable *tsv;
-  int any_enabled = 0;
+  int any_enabled = 0, num_to_download = 0;
   
   tp_vec = all_tracepoints ();
 
@@ -1515,10 +1532,15 @@ start_tracing (void)
   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
     {
       if (t->enable_state == bp_enabled)
-       {
-         any_enabled = 1;
-         break;
-       }
+       any_enabled = 1;
+
+      if ((t->type == bp_fast_tracepoint
+          ? may_insert_fast_tracepoints
+          : may_insert_tracepoints))
+       ++num_to_download;
+      else
+       warning (_("May not insert %stracepoints, skipping tracepoint %d"),
+                (t->type == bp_fast_tracepoint ? "fast " : ""), t->number);
     }
 
   /* No point in tracing with only disabled tracepoints.  */
@@ -1528,10 +1550,21 @@ start_tracing (void)
       error (_("No tracepoints enabled, not starting trace"));
     }
 
+  if (num_to_download <= 0)
+    {
+      VEC_free (breakpoint_p, tp_vec);
+      error (_("No tracepoints that may be downloaded, not starting trace"));
+    }
+
   target_trace_init ();
 
   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
     {
+      if ((t->type == bp_fast_tracepoint
+          ? !may_insert_fast_tracepoints
+          : !may_insert_tracepoints))
+       continue;
+
       t->number_on_target = 0;
       target_download_tracepoint (t);
       t->number_on_target = t->number;
@@ -1723,7 +1756,6 @@ trace_status_mi (int on_stop)
 {
   struct trace_status *ts = current_trace_status ();
   int status;
-  char *string_status;
 
   status = target_get_trace_status (ts);
 
@@ -1858,7 +1890,6 @@ tfind_1 (enum trace_find_type type, int num,
 {
   int target_frameno = -1, target_tracept = -1;
   struct frame_id old_frame_id = null_frame_id;
-  char *reply;
   struct breakpoint *tp;
 
   /* Only try to get the current stack frame if we have a chance of
@@ -2057,7 +2088,6 @@ static void
 trace_find_pc_command (char *args, int from_tty)
 {
   CORE_ADDR pc;
-  char tmp[40];
 
   if (current_trace_status ()->running && !current_trace_status ()->from_file)
     error ("May not look at trace frames while trace is running.");
@@ -2115,7 +2145,6 @@ trace_find_line_command (char *args, int from_tty)
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
   struct cleanup *old_chain;
-  char   startpc_str[40], endpc_str[40];
 
   if (current_trace_status ()->running && !current_trace_status ()->from_file)
     error ("May not look at trace frames while trace is running.");
@@ -2179,7 +2208,6 @@ static void
 trace_find_range_command (char *args, int from_tty)
 {
   static CORE_ADDR start, stop;
-  char start_str[40], stop_str[40];
   char *tmp;
 
   if (current_trace_status ()->running && !current_trace_status ()->from_file)
@@ -2213,7 +2241,6 @@ static void
 trace_find_outside_command (char *args, int from_tty)
 {
   CORE_ADDR start, stop;
-  char start_str[40], stop_str[40];
   char *tmp;
 
   if (current_trace_status ()->running && !current_trace_status ()->from_file)
@@ -2640,6 +2667,7 @@ trace_save (const char *filename, int target_does_save)
   if (ts->stop_reason == tracepoint_error)
     {
       char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1);
+
       bin2hex ((gdb_byte *) ts->error_desc, buf, 0);
       fprintf (fp, ":%s", buf);
     }
@@ -2706,7 +2734,7 @@ trace_save (const char *filename, int target_does_save)
       for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a)
        fprintf (fp, "tp A%x:%s:%s\n",
                 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
-      for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a)
+      for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a)
        fprintf (fp, "tp S%x:%s:%s\n",
                 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
       if (utp->at_string)
@@ -3111,13 +3139,17 @@ merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
     {
       tsv = find_matching_tsv (utsv);
       if (tsv)
-       printf_filtered (_("Assuming trace state variable $%s is same as target's variable %d.\n"),
-                        tsv->name, utsv->number);
+       {
+         if (info_verbose)
+           printf_filtered (_("Assuming trace state variable $%s is same as target's variable %d.\n"),
+                            tsv->name, utsv->number);
+       }
       else
        {
          tsv = create_tsv_from_upload (utsv);
-         printf_filtered (_("Created trace state variable $%s for target's variable %d.\n"),
-                          tsv->name, utsv->number);
+         if (info_verbose)
+           printf_filtered (_("Created trace state variable $%s for target's variable %d.\n"),
+                            tsv->name, utsv->number);
        }
       /* Give precedence to numberings that come from the target.  */
       if (tsv)
@@ -3179,7 +3211,7 @@ tfile_open (char *filename, int from_tty)
   filename = tilde_expand (filename);
   if (!IS_ABSOLUTE_PATH(filename))
     {
-      temp = concat (current_directory, "/", filename, (char *)NULL);
+      temp = concat (current_directory, "/", filename, (char *) NULL);
       xfree (filename);
       filename = temp;
     }
@@ -3324,8 +3356,6 @@ tfile_interp_line (char *line,
 /* Parse the part of trace status syntax that is shared between
    the remote protocol and the trace file reader.  */
 
-extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
-
 void
 parse_trace_status (char *line, struct trace_status *ts)
 {
@@ -3446,9 +3476,9 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
   char *p;
   char piece;
   ULONGEST num, addr, step, pass, orig_size, xlen, start;
-  int enabled, i, end;
+  int enabled, end;
   enum bptype type;
-  char *cond, *srctype, *src, *buf;
+  char *cond, *srctype, *buf;
   struct uploaded_tp *utp = NULL;
 
   p = line;
@@ -3478,6 +3508,11 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
              p++;
              p = unpack_varlen_hex (p, &orig_size);
            }
+         else if (*p == 'S')
+           {
+             type = bp_static_tracepoint;
+             p++;
+           }
          else if (*p == 'X')
            {
              p++;
@@ -3630,6 +3665,9 @@ tfile_get_traceframe_address (off_t tframe_offset)
     perror_with_name (trace_filename);
   else if (gotten < 2)
     error (_("Premature end of file while reading trace file"));
+  tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
+                                         gdbarch_byte_order
+                                             (target_gdbarch));
 
   tp = get_tracepoint_by_number_on_target (tpnum);
   /* FIXME this is a poor heuristic if multiple locations */
@@ -3653,7 +3691,7 @@ tfile_trace_find (enum trace_find_type type, int num,
 {
   short tpnum;
   int tfnum = 0, found = 0, gotten;
-  int data_size;
+  unsigned int data_size;
   struct breakpoint *tp;
   off_t offset, tframe_offset;
   ULONGEST tfaddr;
@@ -3668,6 +3706,9 @@ tfile_trace_find (enum trace_find_type type, int num,
        perror_with_name (trace_filename);
       else if (gotten < 2)
        error (_("Premature end of file while reading trace file"));
+      tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
+                                             gdbarch_byte_order
+                                                 (target_gdbarch));
       offset += 2;
       if (tpnum == 0)
        break;
@@ -3676,6 +3717,9 @@ tfile_trace_find (enum trace_find_type type, int num,
        perror_with_name (trace_filename);
       else if (gotten < 4)
        error (_("Premature end of file while reading trace file"));
+      data_size = (unsigned int) extract_unsigned_integer
+                                     ((gdb_byte *) &data_size, 4,
+                                     gdbarch_byte_order (target_gdbarch));
       offset += 4;
       switch (type)
        {
@@ -3735,7 +3779,7 @@ tfile_fetch_registers (struct target_ops *ops,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   char block_type;
-  int i, pos, offset, regn, regsize, gotten, pc_regno;
+  int pos, offset, regn, regsize, gotten, pc_regno;
   unsigned short mlen;
   char *regs;
 
@@ -3797,6 +3841,10 @@ tfile_fetch_registers (struct target_ops *ops,
            perror_with_name (trace_filename);
          else if (gotten < 2)
            error (_("Premature end of file while reading trace file"));
+          mlen = (unsigned short)
+                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+                                          gdbarch_byte_order
+                                              (target_gdbarch));
          lseek (trace_fd, mlen, SEEK_CUR);
          pos += (8 + 2 + mlen);
          break;
@@ -3889,12 +3937,18 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
            perror_with_name (trace_filename);
          else if (gotten < 8)
            error (_("Premature end of file while reading trace file"));
-
+          maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
+                                           gdbarch_byte_order
+                                               (target_gdbarch));
          gotten = read (trace_fd, &mlen, 2);
          if (gotten < 0)
            perror_with_name (trace_filename);
          else if (gotten < 2)
            error (_("Premature end of file while reading trace file"));
+          mlen = (unsigned short)
+                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+                                          gdbarch_byte_order
+                                              (target_gdbarch));
          /* If the block includes the first part of the desired
             range, return as much it has; GDB will re-request the
             remainder, which might be in a different block of this
@@ -3937,7 +3991,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
     {
       asection *s;
       bfd_size_type size;
-      bfd_vma lma;
+      bfd_vma vma;
 
       for (s = exec_bfd->sections; s; s = s->next)
        {
@@ -3945,16 +3999,16 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
              (s->flags & SEC_READONLY) == 0)
            continue;
 
-         lma = s->lma;
+         vma = s->vma;
          size = bfd_get_section_size (s);
-         if (lma <= offset && offset < (lma + size))
+         if (vma <= offset && offset < (vma + size))
            {
-             amt = (lma + size) - offset;
+             amt = (vma + size) - offset;
              if (amt > len)
                amt = len;
 
              amt = bfd_get_section_contents (exec_bfd, s,
-                                             readbuf, offset - lma, amt);
+                                             readbuf, offset - vma, amt);
              return amt;
            }
        }
@@ -3997,6 +4051,10 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
            perror_with_name (trace_filename);
          else if (gotten < 2)
            error (_("Premature end of file while reading trace file"));
+          mlen = (unsigned short)
+                extract_unsigned_integer ((gdb_byte *) &mlen, 2,
+                                          gdbarch_byte_order
+                                              (target_gdbarch));
          lseek (trace_fd, mlen, SEEK_CUR);
          pos += (8 + 2 + mlen);
          break;
@@ -4006,6 +4064,9 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
            perror_with_name (trace_filename);
          else if (gotten < 4)
            error (_("Premature end of file while reading trace file"));
+          vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
+                                              gdbarch_byte_order
+                                                  (target_gdbarch));
          if (tsvnum == vnum)
            {
              gotten = read (trace_fd, val, 8);
@@ -4013,6 +4074,9 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
                perror_with_name (trace_filename);
              else if (gotten < 8)
                error (_("Premature end of file while reading trace file"));
+              *val = extract_signed_integer ((gdb_byte *)val, 8,
+                                            gdbarch_byte_order
+                                                (target_gdbarch));
              return 1;
            }
          lseek (trace_fd, 8, SEEK_CUR);
@@ -4067,8 +4131,6 @@ init_tfile_ops (void)
   tfile_ops.to_get_trace_status = tfile_get_trace_status;
   tfile_ops.to_trace_find = tfile_trace_find;
   tfile_ops.to_get_trace_state_variable_value = tfile_get_trace_state_variable_value;
-  /* core_stratum might seem more logical, but GDB doesn't like having
-     more than one core_stratum vector.  */
   tfile_ops.to_stratum = process_stratum;
   tfile_ops.to_has_all_memory = tfile_has_all_memory;
   tfile_ops.to_has_memory = tfile_has_memory;
@@ -4077,12 +4139,266 @@ init_tfile_ops (void)
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
+/* 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
+   the parsed marker definition.  */
+
+void
+parse_static_tracepoint_marker_definition (char *line, char **pp,
+                                          struct static_tracepoint_marker *marker)
+{
+  char *p, *endp;
+  ULONGEST addr;
+  int end;
+
+  p = line;
+  p = unpack_varlen_hex (p, &addr);
+  p++;  /* skip a colon */
+
+  marker->gdbarch = target_gdbarch;
+  marker->address = (CORE_ADDR) addr;
+
+  endp = strchr (p, ':');
+  if (endp == NULL)
+    error (_("bad marker definition: %s"), line);
+
+  marker->str_id = xmalloc (endp - p + 1);
+  end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
+  marker->str_id[end] = '\0';
+
+  p += 2 * end;
+  p++;  /* skip a colon */
+
+  marker->extra = xmalloc (strlen (p) + 1);
+  end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
+  marker->extra[end] = '\0';
+
+  if (pp)
+    *pp = p;
+}
+
+/* Release a static tracepoint marker's contents.  Note that the
+   object itself isn't released here.  There objects are usually on
+   the stack.  */
+
+void
+release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
+{
+  xfree (marker->str_id);
+  marker->str_id = NULL;
+}
+
+/* Print MARKER to gdb_stdout.  */
+
+static void
+print_one_static_tracepoint_marker (int count,
+                                   struct static_tracepoint_marker *marker)
+{
+  struct command_line *l;
+  struct symbol *sym;
+
+  char wrap_indent[80];
+  char extra_field_indent[80];
+  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;
+
+  struct symtab_and_line sal;
+
+  init_sal (&sal);
+
+  sal.pc = marker->address;
+
+  tracepoints = static_tracepoints_here (marker->address);
+
+  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
+
+  /* A counter field to help readability.  This is not a stable
+     identifier!  */
+  ui_out_field_int (uiout, "count", count);
+
+  ui_out_field_string (uiout, "marker-id", marker->str_id);
+
+  ui_out_field_fmt (uiout, "enabled", "%c",
+                   !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
+  ui_out_spaces (uiout, 2);
+
+  strcpy (wrap_indent, "                                   ");
+
+  if (gdbarch_addr_bit (marker->gdbarch) <= 32)
+    strcat (wrap_indent, "           ");
+  else
+    strcat (wrap_indent, "                   ");
+
+  strcpy (extra_field_indent, "         ");
+
+  ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address);
+
+  sal = find_pc_line (marker->address, 0);
+  sym = find_pc_sect_function (marker->address, NULL);
+  if (sym)
+    {
+      ui_out_text (uiout, "in ");
+      ui_out_field_string (uiout, "func",
+                          SYMBOL_PRINT_NAME (sym));
+      ui_out_wrap_hint (uiout, wrap_indent);
+      ui_out_text (uiout, " at ");
+    }
+  else
+    ui_out_field_skip (uiout, "func");
+
+  if (sal.symtab != NULL)
+    {
+      ui_out_field_string (uiout, "file", sal.symtab->filename);
+      ui_out_text (uiout, ":");
+
+      if (ui_out_is_mi_like_p (uiout))
+       {
+         char *fullname = symtab_to_fullname (sal.symtab);
+
+         if (fullname)
+           ui_out_field_string (uiout, "fullname", fullname);
+       }
+      else
+       ui_out_field_skip (uiout, "fullname");
+
+      ui_out_field_int (uiout, "line", sal.line);
+    }
+  else
+    {
+      ui_out_field_skip (uiout, "fullname");
+      ui_out_field_skip (uiout, "line");
+    }
+
+  ui_out_text (uiout, "\n");
+  ui_out_text (uiout, extra_field_indent);
+  ui_out_text (uiout, _("Data: \""));
+  ui_out_field_string (uiout, "extra-data", marker->extra);
+  ui_out_text (uiout, "\"\n");
+
+  if (!VEC_empty (breakpoint_p, tracepoints))
+    {
+      struct cleanup *cleanup_chain;
+      int ix;
+      struct breakpoint *b;
+
+      cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
+                                                          "tracepoints-at");
+
+      ui_out_text (uiout, extra_field_indent);
+      ui_out_text (uiout, _("Probed by static tracepoints: "));
+      for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
+       {
+         if (ix > 0)
+           ui_out_text (uiout, ", ");
+         ui_out_text (uiout, "#");
+         ui_out_field_int (uiout, "tracepoint-id", b->number);
+       }
+
+      do_cleanups (cleanup_chain);
+
+      if (ui_out_is_mi_like_p (uiout))
+       ui_out_field_int (uiout, "number-of-tracepoints",
+                         VEC_length(breakpoint_p, tracepoints));
+      else
+       ui_out_text (uiout, "\n");
+    }
+  VEC_free (breakpoint_p, tracepoints);
+
+  do_cleanups (bkpt_chain);
+  do_cleanups (old_chain);
+}
+
+static void
+info_static_tracepoint_markers_command (char *arg, int from_tty)
+{
+  VEC(static_tracepoint_marker_p) *markers;
+  struct cleanup *old_chain;
+  struct static_tracepoint_marker *marker;
+  int i;
+
+  old_chain
+    = make_cleanup_ui_out_table_begin_end (uiout, 5, -1,
+                                          "StaticTracepointMarkersTable");
+
+  ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt");
+
+  ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID");
+
+  ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
+  if (gdbarch_addr_bit (target_gdbarch) <= 32)
+    ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
+  else
+    ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
+  ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
+
+  ui_out_table_body (uiout);
+
+  markers = target_static_tracepoint_markers_by_strid (NULL);
+  make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers);
+
+  for (i = 0;
+       VEC_iterate (static_tracepoint_marker_p,
+                   markers, i, marker);
+       i++)
+    {
+      print_one_static_tracepoint_marker (i + 1, marker);
+      release_static_tracepoint_marker (marker);
+    }
+
+  do_cleanups (old_chain);
+}
+
+/* The $_sdata convenience variable is a bit special.  We don't know
+   for sure type of the value until we actually have a chance to fetch
+   the data --- the size of the object depends on what has been
+   collected.  We solve this by making $_sdata be an internalvar that
+   creates a new value on access.  */
+
+/* Return a new value with the correct type for the sdata object of
+   the current trace frame.  Return a void value if there's no object
+   available.  */
+
+static struct value *
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+{
+  LONGEST size;
+  gdb_byte *buf;
+
+  /* We need to read the whole object before we know its size.  */
+  size = target_read_alloc (&current_target,
+                           TARGET_OBJECT_STATIC_TRACE_DATA,
+                           NULL, &buf);
+  if (size >= 0)
+    {
+      struct value *v;
+      struct type *type;
+
+      type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
+                              size);
+      v = allocate_value (type);
+      memcpy (value_contents_raw (v), buf, size);
+      xfree (buf);
+      return v;
+    }
+  else
+    return allocate_value (builtin_type (gdbarch)->builtin_void);
+}
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
 {
   struct cmd_list_element *c;
 
+  /* Explicitly create without lookup, since that tries to create a
+     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);
+
   traceframe_number = -1;
   tracepoint_number = -1;
 
@@ -4143,6 +4459,11 @@ If no arguments are supplied, delete all variables."), &deletelist);
 
   add_info ("tvariables", tvariables_info, _("\
 Status of trace state variables and their values.\n\
+"));
+
+  add_info ("static-tracepoint-markers",
+           info_static_tracepoint_markers_command, _("\
+List target static tracepoints markers.\n\
 "));
 
   add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\
@@ -4162,7 +4483,7 @@ Usage: tfind range addr1,addr2"),
 
   add_cmd ("line", class_trace, trace_find_line_command, _("\
 Select a trace frame by source line.\n\
-Argument can be a line number (with optional source file), \n\
+Argument can be a line number (with optional source file),\n\
 a function name, or '*' followed by an address.\n\
 Default argument is 'the next source line that was traced'."),
           &tfindlist);
@@ -4225,6 +4546,7 @@ Also accepts the following special arguments:\n\
     $regs   -- all registers.\n\
     $args   -- all function arguments.\n\
     $locals -- all variables local to the block/function scope.\n\
+    $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
   add_com ("teval", class_trace, teval_pseudocommand, _("\
@@ -4235,8 +4557,8 @@ Note: this command can only be used in a tracepoint \"actions\" list."));
 
   add_com ("actions", class_trace, trace_actions_command, _("\
 Specify the actions to be taken at a tracepoint.\n\
-Tracepoint actions may include collecting of specified data, \n\
-single-stepping, or enabling/disabling other tracepoints, \n\
+Tracepoint actions may include collecting of specified data,\n\
+single-stepping, or enabling/disabling other tracepoints,\n\
 depending on target's capabilities."));
 
   default_collect = xstrdup ("");
This page took 0.03723 seconds and 4 git commands to generate.