daily update
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index 1b418060bb99c66aa5e20a8785ec006941f4d0ef..3aff49b2d4aef1c1d6d7bb6f45768f841de94e64 100644 (file)
@@ -45,6 +45,8 @@
 #include "filenames.h"
 #include "gdbthread.h"
 #include "stack.h"
+#include "gdbcore.h"
+#include "remote.h"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -364,6 +366,7 @@ trace_variable_command (char *args, int from_tty)
       tsv->initial_value = initval;
       printf_filtered (_("Trace state variable $%s now has initial value %s.\n"),
                       tsv->name, plongest (tsv->initial_value));
+      do_cleanups (old_chain);
       return;
     }
 
@@ -380,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)
     {
@@ -396,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);
@@ -444,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));
@@ -558,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"));
 
@@ -577,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."));
 }
 
@@ -591,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)
@@ -661,10 +662,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);
            }
@@ -697,10 +697,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);
            }
@@ -972,7 +970,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);
 
@@ -988,26 +985,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);
                }
@@ -1229,7 +1226,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;
@@ -1285,7 +1281,6 @@ encode_actions_1 (struct command_line *action,
                  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);
@@ -1331,27 +1326,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);
@@ -1374,10 +1369,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);
@@ -1386,9 +1379,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
@@ -1407,8 +1399,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);
@@ -1483,7 +1475,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;
@@ -1494,12 +1486,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 ();
 
@@ -1513,10 +1504,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.  */
@@ -1526,10 +1522,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;
@@ -1625,10 +1632,6 @@ trace_status_command (char *args, int from_tty)
   else if (ts->running)
     {
       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
     {
@@ -1698,6 +1701,14 @@ trace_status_command (char *args, int from_tty)
                         ts->buffer_free);
     }
 
+  if (ts->disconnected_tracing)
+    printf_filtered (_("Trace will continue if GDB disconnects.\n"));
+  else
+    printf_filtered (_("Trace will stop if GDB disconnects.\n"));
+
+  if (ts->circular_buffer)
+    printf_filtered (_("Trace buffer is circular.\n"));
+
   /* Now report on what we're doing with tfind.  */
   if (traceframe_number >= 0)
     printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
@@ -1717,7 +1728,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);
 
@@ -1791,18 +1801,24 @@ trace_status_mi (int on_stop)
        }
     }
 
-
-  if ((int) ts->traceframe_count != -1)
+  if (ts->traceframe_count != -1)
     ui_out_field_int (uiout, "frames", ts->traceframe_count);
-  if ((int) ts->buffer_size != -1)
-    ui_out_field_int (uiout, "buffer-size",  (int) ts->buffer_size);
-  if ((int) ts->buffer_free != -1)
-    ui_out_field_int (uiout, "buffer-free",  (int) ts->buffer_free);
+  if (ts->traceframes_created != -1)
+    ui_out_field_int (uiout, "frames-created", ts->traceframes_created);
+  if (ts->buffer_size != -1)
+    ui_out_field_int (uiout, "buffer-size", ts->buffer_size);
+  if (ts->buffer_free != -1)
+    ui_out_field_int (uiout, "buffer-free", ts->buffer_free);
+
+  ui_out_field_int (uiout, "disconnected",  ts->disconnected_tracing);
+  ui_out_field_int (uiout, "circular",  ts->circular_buffer);
 }
 
-
+/* This function handles the details of what to do about an ongoing
+   tracing run if the user has asked to detach or otherwise disconnect
+   from the target.  */
 void
-disconnect_or_stop_tracing (int from_tty)
+disconnect_tracing (int from_tty)
 {
   /* It can happen that the target that was tracing went away on its
      own, and we didn't notice.  Get a status update, and if the
@@ -1811,18 +1827,23 @@ disconnect_or_stop_tracing (int from_tty)
   if (target_get_trace_status (current_trace_status ()) < 0)
     current_trace_status ()->running = 0;
 
+  /* If running interactively, give the user the option to cancel and
+     then decide what to do differently with the run.  Scripts are
+     just going to disconnect and let the target deal with it,
+     according to how it's been instructed previously via
+     disconnected-tracing.  */
   if (current_trace_status ()->running && from_tty)
     {
-      int cont = query (_("Trace is running.  Continue tracing after detach? "));
-      /* Note that we send the query result without affecting the
-        user's setting of disconnected_tracing, so that the answer is
-        a one-time-only.  */
-      send_disconnected_tracing_value (cont);
-
-      /* Also ensure that we do the equivalent of a tstop command if
-        tracing is not to continue after the detach.  */
-      if (!cont)
-       stop_tracing ();
+      if (current_trace_status ()->disconnected_tracing)
+       {
+         if (!query (_("Trace is running and will continue after detach; detach anyway? ")))
+           error (_("Not confirmed."));
+       }
+      else
+       {
+         if (!query (_("Trace is running but will stop on detach; detach anyway? ")))
+           error (_("Not confirmed."));
+       }
     }
 
   /* Also we want to be out of tfind mode, otherwise things can get
@@ -1840,11 +1861,18 @@ tfind_1 (enum trace_find_type type, int num,
         int from_tty)
 {
   int target_frameno = -1, target_tracept = -1;
-  struct frame_id old_frame_id;
-  char *reply;
+  struct frame_id old_frame_id = null_frame_id;
   struct breakpoint *tp;
 
-  old_frame_id = get_frame_id (get_current_frame ());
+  /* Only try to get the current stack frame if we have a chance of
+     succeeding.  In particular, if we're trying to get a first trace
+     frame while all threads are running, it's not going to succeed,
+     so leave it with a default value and let the frame comparison
+     below (correctly) decide to print out the source location of the
+     trace frame.  */
+  if (!(type == tfind_number && num == -1)
+      && (has_stack_frames () || traceframe_number >= 0))
+    old_frame_id = get_frame_id (get_current_frame ());
 
   target_frameno = target_trace_find (type, num, addr1, addr2,
                                      &target_tracept);
@@ -1857,7 +1885,7 @@ tfind_1 (enum trace_find_type type, int num,
     }
   else if (target_frameno == -1)
     {
-      /* A request for a non-existant trace frame has failed.
+      /* A request for a non-existent trace frame has failed.
         Our response will be different, depending on FROM_TTY:
 
         If FROM_TTY is true, meaning that this command was 
@@ -1924,8 +1952,10 @@ tfind_1 (enum trace_find_type type, int num,
     {
       if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string (uiout, "found", "0");
-      else
-       printf_unfiltered (_("No trace frame found"));
+      else if (type == tfind_number && num == -1)
+       printf_unfiltered (_("No longer looking at any trace frame\n"));
+      else /* this case may never occur, check */
+       printf_unfiltered (_("No trace frame found\n"));
     }
 
   /* If we're in nonstop mode and getting out of looking at trace
@@ -1936,7 +1966,7 @@ tfind_1 (enum trace_find_type type, int num,
     {
       enum print_what print_what;
 
-      /* NOTE: in immitation of the step command, try to determine
+      /* NOTE: in imitation of the step command, try to determine
          whether we have made a transition from one function to
          another.  If so, we'll print the "stack frame" (ie. the new
          function and it's arguments) -- otherwise we'll just show the
@@ -2030,7 +2060,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.");
@@ -2088,7 +2117,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.");
@@ -2152,7 +2180,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)
@@ -2186,7 +2213,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)
@@ -2345,7 +2371,9 @@ scope_info (char *args, int from_tty)
              printf_filtered ("optimized out.\n");
              continue;
            case LOC_COMPUTED:
-             SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, gdb_stdout);
+             SYMBOL_COMPUTED_OPS (sym)->describe_location (sym,
+                                                           BLOCK_START (block),
+                                                           gdb_stdout);
              break;
            }
          if (SYMBOL_TYPE (sym))
@@ -2467,6 +2495,9 @@ trace_dump_command (char *args, int from_tty)
   struct breakpoint *t;
   int stepping_frame = 0;
   struct bp_location *loc;
+  char *line, *default_collect_line = NULL;
+  struct command_line *actions, *default_collect_action = NULL;
+  struct cleanup *old_chain = NULL;
 
   if (tracepoint_number == -1)
     {
@@ -2498,7 +2529,29 @@ trace_dump_command (char *args, int from_tty)
     if (loc->address == regcache_read_pc (regcache))
       stepping_frame = 0;
 
-  trace_dump_actions (breakpoint_commands (t), 0, stepping_frame, from_tty);
+  actions = breakpoint_commands (t);
+
+  /* If there is a default-collect list, make up a collect command,
+     prepend to the tracepoint's commands, and pass the whole mess to
+     the trace dump scanner.  We need to validate because
+     default-collect might have been junked since the trace run.  */
+  if (*default_collect)
+    {
+      default_collect_line = xstrprintf ("collect %s", default_collect);
+      old_chain = make_cleanup (xfree, default_collect_line);
+      line = default_collect_line;
+      validate_actionline (&line, t);
+      default_collect_action = xmalloc (sizeof (struct command_line));
+      make_cleanup (xfree, default_collect_action);
+      default_collect_action->next = actions;
+      default_collect_action->line = line;
+      actions = default_collect_action;
+    }
+
+  trace_dump_actions (actions, 0, stepping_frame, from_tty);
+
+  if (*default_collect)
+    do_cleanups (old_chain);
 }
 
 /* Encode a piece of a tracepoint's source-level definition in a form
@@ -2537,7 +2590,7 @@ trace_save (const char *filename, int target_does_save)
   struct uploaded_tp *uploaded_tps = NULL, *utp;
   struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
   int a;
-  struct uploaded_string *cmd;
+  char *act;
   LONGEST gotten = 0;
   ULONGEST offset = 0;
 #define MAX_TRACE_UPLOAD 2000
@@ -2562,7 +2615,7 @@ trace_save (const char *filename, int target_does_save)
   pathname = tilde_expand (filename);
   cleanup = make_cleanup (xfree, pathname);
 
-  fp = fopen (pathname, "w");
+  fp = fopen (pathname, "wb");
   if (!fp)
     error (_("Unable to open file '%s' for saving trace data (%s)"),
           filename, safe_strerror (errno));
@@ -2586,6 +2639,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);
     }
@@ -2598,6 +2652,10 @@ trace_save (const char *filename, int target_does_save)
     fprintf (fp, ";tfree:%x", ts->buffer_free);
   if (ts->buffer_size >= 0)
     fprintf (fp, ";tsize:%x", ts->buffer_size);
+  if (ts->disconnected_tracing)
+    fprintf (fp, ";disconn:%x", ts->disconnected_tracing);
+  if (ts->circular_buffer)
+    fprintf (fp, ";circular:%x", ts->circular_buffer);
   fprintf (fp, "\n");
 
   /* Note that we want to upload tracepoints and save those, rather
@@ -2645,14 +2703,12 @@ trace_save (const char *filename, int target_does_save)
        fprintf (fp, ":X%x,%s", (unsigned int) strlen (utp->cond) / 2,
                 utp->cond);
       fprintf (fp, "\n");
-      for (a = 0; a < utp->numactions; ++a)
+      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)),
-                utp->actions[a]);
-      for (a = 0; a < utp->num_step_actions; ++a)
+                utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
+      for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a)
        fprintf (fp, "tp S%x:%s:%s\n",
-                utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
-                utp->step_actions[a]);
+                utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
       if (utp->at_string)
        {
          encode_source_string (utp->number, utp->addr,
@@ -2665,9 +2721,9 @@ trace_save (const char *filename, int target_does_save)
                                "cond", utp->cond_string, buf, MAX_TRACE_UPLOAD);
          fprintf (fp, "tp Z%s\n", buf);
        }
-      for (cmd = utp->cmd_strings; cmd; cmd = cmd->next)
+      for (a = 0; VEC_iterate (char_ptr, utp->cmd_strings, a, act); ++a)
        {
-         encode_source_string (utp->number, utp->addr, "cmd", cmd->str,
+         encode_source_string (utp->number, utp->addr, "cmd", act,
                                buf, MAX_TRACE_UPLOAD);
          fprintf (fp, "tp Z%s\n", buf);
        }
@@ -2869,6 +2925,9 @@ get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp)
   memset (utp, 0, sizeof (struct uploaded_tp));
   utp->number = num;
   utp->addr = addr;
+  utp->actions = NULL;
+  utp->step_actions = NULL;
+  utp->cmd_strings = NULL;
   utp->next = *utpp;
   *utpp = utp;
   return utp;
@@ -3120,7 +3179,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;
     }
@@ -3165,6 +3224,8 @@ tfile_open (char *filename, int from_tty)
   ts->stop_reason = trace_stop_reason_unknown;
   ts->traceframe_count = -1;
   ts->buffer_free = 0;
+  ts->disconnected_tracing = 0;
+  ts->circular_buffer = 0;
 
   /* Read through a section of newline-terminated lines that
      define things like tracepoints.  */
@@ -3263,8 +3324,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)
 {
@@ -3280,6 +3339,8 @@ parse_trace_status (char *line, struct trace_status *ts)
   ts->traceframes_created = -1;
   ts->buffer_free = -1;
   ts->buffer_size = -1;
+  ts->disconnected_tracing = 0;
+  ts->circular_buffer = 0;
 
   while (*p++)
     {
@@ -3308,6 +3369,11 @@ Status line: '%s'\n"), p, line);
          p = unpack_varlen_hex (++p1, &val);
          ts->stop_reason = tstop_command;
        }
+      else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0)
+       {
+         p = unpack_varlen_hex (++p1, &val);
+         ts->stop_reason = trace_disconnected;
+       }
       else if (strncmp (p, stop_reason_names[tracepoint_error], p1 - p) == 0)
        {
          p2 = strchr (++p1, ':');
@@ -3346,6 +3412,16 @@ Status line: '%s'\n"), p, line);
          p = unpack_varlen_hex (++p1, &val);
          ts->buffer_size = val;
        }
+      else if (strncmp (p, "disconn", p1 - p) == 0)
+       {
+         p = unpack_varlen_hex (++p1, &val);
+         ts->disconnected_tracing = val;
+       }
+      else if (strncmp (p, "circular", p1 - p) == 0)
+       {
+         p = unpack_varlen_hex (++p1, &val);
+         ts->circular_buffer = val;
+       }
       else
        {
          /* Silently skip unknown optional info.  */
@@ -3368,9 +3444,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;
@@ -3423,12 +3499,12 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
   else if (piece == 'A')
     {
       utp = get_uploaded_tp (num, addr, utpp);
-      utp->actions[utp->numactions++] = xstrdup (p);
+      VEC_safe_push (char_ptr, utp->actions, xstrdup (p));
     }
   else if (piece == 'S')
     {
       utp = get_uploaded_tp (num, addr, utpp);
-      utp->step_actions[utp->num_step_actions++] = xstrdup (p);
+      VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p));
     }
   else if (piece == 'Z')
     {
@@ -3452,21 +3528,7 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
       else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
        utp->cond_string = xstrdup (buf);
       else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
-       {
-         /* FIXME consider using a vector? */
-         struct uploaded_string *last, *newlast;
-         newlast = (struct uploaded_string *) xmalloc (sizeof (struct uploaded_string));
-         newlast->str = xstrdup (buf);
-         newlast->next = NULL;
-         if (utp->cmd_strings)
-           {
-             for (last = utp->cmd_strings; last->next; last = last->next)
-               ;
-             last->next = newlast;
-           }
-         else
-           utp->cmd_strings = newlast;
-       }
+       VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
     }
   else
     {
@@ -3671,7 +3733,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;
+  int pos, offset, regn, regsize, gotten, pc_regno;
   unsigned short mlen;
   char *regs;
 
@@ -3746,6 +3808,44 @@ tfile_fetch_registers (struct target_ops *ops,
          break;
        }
     }
+
+  /* We get here if no register data has been found.  Although we
+     don't like making up numbers, GDB has all manner of troubles when
+     the target says some register is not available.  Filling in with
+     zeroes is a reasonable fallback.  */
+  for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
+    regcache_raw_supply (regcache, regn, NULL);
+
+  /* We can often usefully guess that the PC is going to be the same
+     as the address of the tracepoint.  */
+  pc_regno = gdbarch_pc_regnum (gdbarch);
+  if (pc_regno >= 0 && (regno == -1 || regno == pc_regno))
+    {
+      struct breakpoint *tp = get_tracepoint (tracepoint_number);
+
+      if (tp && tp->loc)
+       {
+         /* But don't try to guess if tracepoint is multi-location...  */
+         if (tp->loc->next)
+           {
+             warning ("Tracepoint %d has multiple locations, cannot infer $pc",
+                      tp->number);
+             return;
+           }
+         /* ... or does while-stepping.  */
+         if (tp->step_count > 0)
+           {
+             warning ("Tracepoint %d does while-stepping, cannot infer $pc",
+                      tp->number);
+             return;
+           }
+
+         store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
+                                 gdbarch_byte_order (gdbarch),
+                                 tp->loc->address);
+         regcache_raw_supply (regcache, pc_regno, regs);
+       }
+    }
 }
 
 static LONGEST
@@ -3755,7 +3855,7 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
 {
   char block_type;
   int pos, gotten;
-  ULONGEST maddr;
+  ULONGEST maddr, amt;
   unsigned short mlen;
 
   /* We're only doing regular memory for now.  */
@@ -3793,16 +3893,26 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
            perror_with_name (trace_filename);
          else if (gotten < 2)
            error (_("Premature end of file while reading trace file"));
-         if (maddr <= offset && (offset + len) <= (maddr + mlen))
-           {
-             gotten = read (trace_fd, readbuf, mlen);
+         /* 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
+            trace frame.  */
+         if (maddr <= offset && offset < (maddr + mlen))
+           {
+             amt = (maddr + mlen) - offset;
+             if (amt > len)
+               amt = len;
+
+             gotten = read (trace_fd, readbuf, amt);
              if (gotten < 0)
                perror_with_name (trace_filename);
-             else if (gotten < mlen)
-               error (_("Premature end of file qwhile reading trace file"));
-
-             return mlen;
-           }
+             /* While it's acceptable to return less than was
+                originally asked for, it's not acceptable to return
+                less than what this block claims to contain.  */
+             else if (gotten < amt)
+               error (_("Premature end of file while reading trace file"));
+             return amt;
+           }
          lseek (trace_fd, mlen, SEEK_CUR);
          pos += (8 + 2 + mlen);
          break;
@@ -3816,6 +3926,38 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
          break;
        }
     }
+
+  /* It's unduly pedantic to refuse to look at the executable for
+     read-only pieces; so do the equivalent of readonly regions aka
+     QTro packet.  */
+  /* FIXME account for relocation at some point */
+  if (exec_bfd)
+    {
+      asection *s;
+      bfd_size_type size;
+      bfd_vma lma;
+
+      for (s = exec_bfd->sections; s; s = s->next)
+       {
+         if ((s->flags & SEC_LOAD) == 0 ||
+             (s->flags & SEC_READONLY) == 0)
+           continue;
+
+         lma = s->lma;
+         size = bfd_get_section_size (s);
+         if (lma <= offset && offset < (lma + size))
+           {
+             amt = (lma + size) - offset;
+             if (amt > len)
+               amt = len;
+
+             amt = bfd_get_section_contents (exec_bfd, s,
+                                             readbuf, offset - lma, amt);
+             return amt;
+           }
+       }
+    }
+
   /* Indicate failure to find the requested memory block.  */
   return -1;
 }
@@ -3884,6 +4026,12 @@ tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
   return 0;
 }
 
+static int
+tfile_has_all_memory (struct target_ops *ops)
+{
+  return 1;
+}
+
 static int
 tfile_has_memory (struct target_ops *ops)
 {
@@ -3920,6 +4068,7 @@ init_tfile_ops (void)
   /* 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;
   tfile_ops.to_has_stack = tfile_has_stack;
   tfile_ops.to_has_registers = tfile_has_registers;
This page took 0.036539 seconds and 4 git commands to generate.