Add target_ops argument to to_traceframe_info
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index 05f51ea428b8d3d674405ee2cc8160104bd55ced..de4f6af2524c6ca849c8af8275525046343526cc 100644 (file)
@@ -1,6 +1,6 @@
 /* Tracing functionality for remote targets in custom GDB protocol
 
-   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+   Copyright (C) 1997-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,8 +26,9 @@
 #include "gdbcmd.h"
 #include "value.h"
 #include "target.h"
+#include "target-dcache.h"
 #include "language.h"
-#include "gdb_string.h"
+#include <string.h>
 #include "inferior.h"
 #include "breakpoint.h"
 #include "tracepoint.h"
@@ -44,7 +45,6 @@
 #include "filenames.h"
 #include "gdbthread.h"
 #include "stack.h"
-#include "gdbcore.h"
 #include "remote.h"
 #include "source.h"
 #include "ax.h"
@@ -54,8 +54,8 @@
 #include "cli/cli-utils.h"
 #include "probe.h"
 #include "ctf.h"
-#include "completer.h"
 #include "filestuff.h"
+#include "rsp-low.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -64,9 +64,7 @@
 /* readline defines this.  */
 #undef savestring
 
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
    large.  (400 - 31)/2 == 184 */
 #define MAX_AGENT_EXPR_LEN     184
 
+#define TFILE_PID (1)
+
 /* A hook used to notify the UI of tracepoint operations.  */
 
 void (*deprecated_trace_find_hook) (char *arg, int from_tty);
 void (*deprecated_trace_start_stop_hook) (int start, int from_tty);
 
-extern void (*deprecated_readline_begin_hook) (char *, ...);
-extern char *(*deprecated_readline_hook) (char *);
-extern void (*deprecated_readline_end_hook) (void);
-
 /* 
    Tracepoint.c:
 
@@ -138,12 +134,6 @@ static int traceframe_number;
 /* Tracepoint for last traceframe collected.  */
 static int tracepoint_number;
 
-/* Symbol for function for last traceframe collected.  */
-static struct symbol *traceframe_fun;
-
-/* Symtab and line for last traceframe collected.  */
-static struct symtab_and_line traceframe_sal;
-
 /* The traceframe info of the current traceframe.  NULL if we haven't
    yet attempted to fetch it, or if the target does not support
    fetching this object, or if we're not inspecting a traceframe
@@ -235,6 +225,7 @@ free_traceframe_info (struct traceframe_info *info)
   if (info != NULL)
     {
       VEC_free (mem_range_s, info->memory);
+      VEC_free (int, info->tvars);
 
       xfree (info);
     }
@@ -273,6 +264,8 @@ static void
 set_traceframe_context (struct frame_info *trace_frame)
 {
   CORE_ADDR trace_pc;
+  struct symbol *traceframe_fun;
+  struct symtab_and_line traceframe_sal;
 
   /* Save as globals for internal use.  */
   if (trace_frame != NULL
@@ -339,6 +332,22 @@ find_trace_state_variable (const char *name)
   return NULL;
 }
 
+/* Look for a trace state variable of the given number.  Return NULL if
+   not found.  */
+
+struct trace_state_variable *
+find_trace_state_variable_by_number (int number)
+{
+  struct trace_state_variable *tsv;
+  int ix;
+
+  for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+    if (tsv->number == number)
+      return tsv;
+
+  return NULL;
+}
+
 static void
 delete_trace_state_variable (const char *name)
 {
@@ -852,29 +861,6 @@ enum {
   memrange_absolute = -1
 };
 
-struct memrange
-{
-  int type;            /* memrange_absolute for absolute memory range,
-                           else basereg number.  */
-  bfd_signed_vma start;
-  bfd_signed_vma end;
-};
-
-struct collection_list
-  {
-    unsigned char regs_mask[32];       /* room for up to 256 regs */
-    long listsize;
-    long next_memrange;
-    struct memrange *list;
-    long aexpr_listsize;       /* size of array pointed to by expr_list elt */
-    long next_aexpr_elt;
-    struct agent_expr **aexpr_list;
-
-    /* True is the user requested a collection of "$_sdata", "static
-       tracepoint data".  */
-    int strace_data;
-  };
-
 /* MEMRANGE functions: */
 
 static int memrange_cmp (const void *, const void *);
@@ -1165,6 +1151,9 @@ do_collect_symbol (const char *print_name,
   collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno,
                  p->frame_offset, p->pc, p->trace_string);
   p->count++;
+
+  VEC_safe_push (char_ptr, p->collect->wholly_collected,
+                xstrdup (print_name));
 }
 
 /* Add all locals (or args) symbols to collection list.  */
@@ -1241,6 +1230,9 @@ clear_collection_list (struct collection_list *list)
 
   xfree (list->aexpr_list);
   xfree (list->list);
+
+  VEC_free (char_ptr, list->wholly_collected);
+  VEC_free (char_ptr, list->computed);
 }
 
 /* A cleanup wrapper for function clear_collection_list.  */
@@ -1391,6 +1383,21 @@ stringify_collection_list (struct collection_list *list)
     return *str_list;
 }
 
+/* Add the printed expression EXP to *LIST.  */
+
+static void
+append_exp (struct expression *exp, VEC(char_ptr) **list)
+{
+  struct ui_file *tmp_stream = mem_fileopen ();
+  char *text;
+
+  print_expression (exp, tmp_stream);
+
+  text = ui_file_xstrdup (tmp_stream, NULL);
+
+  VEC_safe_push (char_ptr, *list, text);
+  ui_file_delete (tmp_stream);
+}
 
 static void
 encode_actions_1 (struct command_line *action,
@@ -1536,16 +1543,25 @@ encode_actions_1 (struct command_line *action,
                      check_typedef (exp->elts[1].type);
                      add_memrange (collect, memrange_absolute, addr,
                                    TYPE_LENGTH (exp->elts[1].type));
+                     append_exp (exp, &collect->computed);
                      break;
 
                    case OP_VAR_VALUE:
-                     collect_symbol (collect,
-                                     exp->elts[2].symbol,
-                                     tloc->gdbarch,
-                                     frame_reg,
-                                     frame_offset,
-                                     tloc->address,
-                                     trace_string);
+                     {
+                       struct symbol *sym = exp->elts[2].symbol;
+                       char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym);
+
+                       collect_symbol (collect,
+                                       exp->elts[2].symbol,
+                                       tloc->gdbarch,
+                                       frame_reg,
+                                       frame_offset,
+                                       tloc->address,
+                                       trace_string);
+                       VEC_safe_push (char_ptr,
+                                      collect->wholly_collected,
+                                      name);
+                     }
                      break;
 
                    default:    /* Full-fledged expression.  */
@@ -1581,6 +1597,8 @@ encode_actions_1 (struct command_line *action,
                                }
                            }
                        }
+
+                     append_exp (exp, &collect->computed);
                      break;
                    }           /* switch */
                  do_cleanups (old_chain);
@@ -1634,46 +1652,64 @@ encode_actions_1 (struct command_line *action,
     }                          /* for */
 }
 
-/* Render all actions into gdb protocol.  */
+/* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST
+   and STEPPING_LIST.  Return a cleanup pointer to clean up both
+   TRACEPOINT_LIST and STEPPING_LIST.  */
 
-void
-encode_actions (struct bp_location *tloc, char ***tdp_actions,
-               char ***stepping_actions)
+struct cleanup *
+encode_actions_and_make_cleanup (struct bp_location *tloc,
+                                struct collection_list *tracepoint_list,
+                                struct collection_list *stepping_list)
 {
   char *default_collect_line = NULL;
   struct command_line *actions;
   struct command_line *default_collect_action = NULL;
   int frame_reg;
   LONGEST frame_offset;
-  struct cleanup *back_to;
-  struct collection_list tracepoint_list, stepping_list;
-
-  back_to = make_cleanup (null_cleanup, NULL);
-
-  init_collection_list (&tracepoint_list);
-  init_collection_list (&stepping_list);
+  struct cleanup *back_to, *return_chain;
 
-  make_cleanup (do_clear_collection_list, &tracepoint_list);
-  make_cleanup (do_clear_collection_list, &stepping_list);
+  return_chain = make_cleanup (null_cleanup, NULL);
+  init_collection_list (tracepoint_list);
+  init_collection_list (stepping_list);
 
-  *tdp_actions = NULL;
-  *stepping_actions = NULL;
+  make_cleanup (do_clear_collection_list, tracepoint_list);
+  make_cleanup (do_clear_collection_list, stepping_list);
 
+  back_to = make_cleanup (null_cleanup, NULL);
   gdbarch_virtual_frame_pointer (tloc->gdbarch,
                                 tloc->address, &frame_reg, &frame_offset);
 
   actions = all_tracepoint_actions_and_cleanup (tloc->owner);
 
   encode_actions_1 (actions, tloc, frame_reg, frame_offset,
-                   &tracepoint_list, &stepping_list);
+                   tracepoint_list, stepping_list);
 
-  memrange_sortmerge (&tracepoint_list);
-  memrange_sortmerge (&stepping_list);
+  memrange_sortmerge (tracepoint_list);
+  memrange_sortmerge (stepping_list);
+
+  do_cleanups (back_to);
+  return return_chain;
+}
+
+/* Render all actions into gdb protocol.  */
+
+void
+encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions,
+                   char ***stepping_actions)
+{
+  struct collection_list tracepoint_list, stepping_list;
+  struct cleanup *cleanup;
+
+  *tdp_actions = NULL;
+  *stepping_actions = NULL;
+
+  cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list,
+                                            &stepping_list);
 
   *tdp_actions = stringify_collection_list (&tracepoint_list);
   *stepping_actions = stringify_collection_list (&stepping_list);
 
-  do_cleanups (back_to);
+  do_cleanups (cleanup);
 }
 
 static void
@@ -2081,20 +2117,20 @@ trace_status_command (char *args, int from_tty)
 
          /* 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);
+                          (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);
+                        (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);
+                    (long int) (ts->stop_time / 1000000),
+                    (long int) (ts->stop_time % 1000000));
 
   /* Now report any per-tracepoint status available.  */
   tp_vec = all_tracepoints ();
@@ -2212,12 +2248,12 @@ trace_status_mi (int on_stop)
     char buf[100];
 
     xsnprintf (buf, sizeof buf, "%ld.%06ld",
-              (long int) ts->start_time / 1000000,
-              (long int) ts->start_time % 1000000);
+              (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);
+              (long int) (ts->stop_time / 1000000),
+              (long int) (ts->stop_time % 1000000));
     ui_out_field_string (uiout, "stop-time", buf);
   }
 }
@@ -2406,7 +2442,7 @@ tfind_1 (enum trace_find_type type, int num,
       else
        print_what = SRC_AND_LOC;
 
-      print_stack_frame (get_selected_frame (NULL), 1, print_what);
+      print_stack_frame (get_selected_frame (NULL), 1, print_what, 1);
       do_displays ();
     }
 }
@@ -2933,6 +2969,48 @@ trace_dump_actions (struct command_line *action,
     }
 }
 
+/* Return bp_location of the tracepoint associated with the current
+   traceframe.  Set *STEPPING_FRAME_P to 1 if the current traceframe
+   is a stepping traceframe.  */
+
+struct bp_location *
+get_traceframe_location (int *stepping_frame_p)
+{
+  struct tracepoint *t;
+  struct bp_location *tloc;
+  struct regcache *regcache;
+
+  if (tracepoint_number == -1)
+    error (_("No current trace frame."));
+
+  t = get_tracepoint (tracepoint_number);
+
+  if (t == NULL)
+    error (_("No known tracepoint matches 'current' tracepoint #%d."),
+          tracepoint_number);
+
+  /* The current frame is a trap frame if the frame PC is equal to the
+     tracepoint PC.  If not, then the current frame was collected
+     during single-stepping.  */
+  regcache = get_current_regcache ();
+
+  /* If the traceframe's address matches any of the tracepoint's
+     locations, assume it is a direct hit rather than a while-stepping
+     frame.  (FIXME this is not reliable, should record each frame's
+     type.)  */
+  for (tloc = t->base.loc; tloc; tloc = tloc->next)
+    if (tloc->address == regcache_read_pc (regcache))
+      {
+       *stepping_frame_p = 0;
+       return tloc;
+      }
+
+  /* If this is a stepping frame, we don't know which location
+     triggered.  The first is as good (or bad) a guess as any...  */
+  *stepping_frame_p = 1;
+  return t->base.loc;
+}
+
 /* Return all the actions, including default collect, of a tracepoint
    T.  It constructs cleanups into the chain, and leaves the caller to
    handle them (call do_cleanups).  */
@@ -2973,43 +3051,25 @@ all_tracepoint_actions_and_cleanup (struct breakpoint *t)
 static void
 trace_dump_command (char *args, int from_tty)
 {
-  struct regcache *regcache;
-  struct tracepoint *t;
   int stepping_frame = 0;
   struct bp_location *loc;
-  char *default_collect_line = NULL;
-  struct command_line *actions, *default_collect_action = NULL;
   struct cleanup *old_chain;
+  struct command_line *actions;
 
-  if (tracepoint_number == -1)
-    error (_("No current trace frame."));
-
-  old_chain = make_cleanup (null_cleanup, NULL);
-  t = get_tracepoint (tracepoint_number);
-
-  if (t == NULL)
-    error (_("No known tracepoint matches 'current' tracepoint #%d."),
-          tracepoint_number);
+  /* This throws an error is not inspecting a trace frame.  */
+  loc = get_traceframe_location (&stepping_frame);
 
   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
                   tracepoint_number, traceframe_number);
 
-  /* The current frame is a trap frame if the frame PC is equal
-     to the tracepoint PC.  If not, then the current frame was
-     collected during single-stepping.  */
-
-  regcache = get_current_regcache ();
+  old_chain = make_cleanup (null_cleanup, NULL);
 
-  /* If the traceframe's address matches any of the tracepoint's
-     locations, assume it is a direct hit rather than a while-stepping
-     frame.  (FIXME this is not reliable, should record each frame's
-     type.)  */
-  stepping_frame = 1;
-  for (loc = t->base.loc; loc; loc = loc->next)
-    if (loc->address == regcache_read_pc (regcache))
-      stepping_frame = 0;
+  /* This command only makes sense for the current frame, not the
+     selected frame.  */
+  make_cleanup_restore_current_thread ();
+  select_frame (get_current_frame ());
 
-  actions = all_tracepoint_actions_and_cleanup (&t->base);
+  actions = all_tracepoint_actions_and_cleanup (loc->owner);
 
   trace_dump_actions (actions, 0, stepping_frame, from_tty);
 
@@ -3032,7 +3092,7 @@ encode_source_string (int tpnum, ULONGEST addr,
           srctype, 0, (int) strlen (src));
   if (strlen (buf) + strlen (src) * 2 >= buf_size)
     error (_("Source string too long for buffer"));
-  bin2hex ((gdb_byte *) src, buf + strlen (buf), 0);
+  bin2hex ((gdb_byte *) src, buf + strlen (buf), strlen (src));
   return -1;
 }
 
@@ -3101,7 +3161,7 @@ tfile_start (struct trace_file_writer *self, const char *filename)
   writer->fp = gdb_fopen_cloexec (writer->pathname, "wb");
   if (writer->fp == NULL)
     error (_("Unable to open file '%s' for saving trace data (%s)"),
-          filename, safe_strerror (errno));
+          writer->pathname, safe_strerror (errno));
 }
 
 /* This is the implementation of trace_file_write_ops method
@@ -3151,7 +3211,7 @@ tfile_write_status (struct trace_file_writer *self,
     {
       char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
 
-      bin2hex ((gdb_byte *) ts->stop_desc, buf, 0);
+      bin2hex ((gdb_byte *) ts->stop_desc, buf, strlen (ts->stop_desc));
       fprintf (writer->fp, ":%s", buf);
     }
   fprintf (writer->fp, ":%x", ts->stopping_tracepoint);
@@ -3167,18 +3227,28 @@ tfile_write_status (struct trace_file_writer *self,
     fprintf (writer->fp, ";disconn:%x", ts->disconnected_tracing);
   if (ts->circular_buffer)
     fprintf (writer->fp, ";circular:%x", ts->circular_buffer);
+  if (ts->start_time)
+    {
+      fprintf (writer->fp, ";starttime:%s",
+      phex_nz (ts->start_time, sizeof (ts->start_time)));
+    }
+  if (ts->stop_time)
+    {
+      fprintf (writer->fp, ";stoptime:%s",
+      phex_nz (ts->stop_time, sizeof (ts->stop_time)));
+    }
   if (ts->notes != NULL)
     {
       char *buf = (char *) alloca (strlen (ts->notes) * 2 + 1);
 
-      bin2hex ((gdb_byte *) ts->notes, buf, 0);
+      bin2hex ((gdb_byte *) ts->notes, buf, strlen (ts->notes));
       fprintf (writer->fp, ";notes:%s", buf);
     }
   if (ts->user_name != NULL)
     {
       char *buf = (char *) alloca (strlen (ts->user_name) * 2 + 1);
 
-      bin2hex ((gdb_byte *) ts->user_name, buf, 0);
+      bin2hex ((gdb_byte *) ts->user_name, buf, strlen (ts->user_name));
       fprintf (writer->fp, ";username:%s", buf);
     }
   fprintf (writer->fp, "\n");
@@ -3198,7 +3268,7 @@ tfile_write_uploaded_tsv (struct trace_file_writer *self,
   if (utsv->name)
     {
       buf = (char *) xmalloc (strlen (utsv->name) * 2 + 1);
-      bin2hex ((gdb_byte *) (utsv->name), buf, 0);
+      bin2hex ((gdb_byte *) (utsv->name), buf, strlen (utsv->name));
     }
 
   fprintf (writer->fp, "tsv %x:%s:%x:%s\n",
@@ -4300,11 +4370,15 @@ tfile_open (char *filename, int from_tty)
     }
   if (ex.reason < 0)
     {
-      /* Pop the partially set up target.  */
-      pop_target ();
+      /* Remove the partially set up target.  */
+      unpush_target (&tfile_ops);
       throw_exception (ex);
     }
 
+  inferior_appeared (current_inferior (), TFILE_PID);
+  inferior_ptid = pid_to_ptid (TFILE_PID);
+  add_thread_silent (inferior_ptid);
+
   if (ts->traceframe_count <= 0)
     warning (_("No traceframes present in this file."));
 
@@ -4315,6 +4389,8 @@ tfile_open (char *filename, int from_tty)
   merge_uploaded_trace_state_variables (&uploaded_tsvs);
 
   merge_uploaded_tracepoints (&uploaded_tps);
+
+  post_create_inferior (&tfile_ops, from_tty);
 }
 
 /* Interpret the given line from the definitions part of the trace
@@ -4680,13 +4756,17 @@ parse_tsv_definition (char *line, struct uploaded_tsv **utsvp)
 /* Close the trace file and generally clean up.  */
 
 static void
-tfile_close (void)
+tfile_close (struct target_ops *self)
 {
   int pid;
 
   if (trace_fd < 0)
     return;
 
+  pid = ptid_get_pid (inferior_ptid);
+  inferior_ptid = null_ptid;   /* Avoid confusion from thread stuff.  */
+  exit_inferior_silent (pid);
+
   close (trace_fd);
   trace_fd = -1;
   xfree (trace_filename);
@@ -4704,7 +4784,7 @@ tfile_files_info (struct target_ops *t)
 /* The trace status for a file is that tracing can never be run.  */
 
 static int
-tfile_get_trace_status (struct trace_status *ts)
+tfile_get_trace_status (struct target_ops *self, struct trace_status *ts)
 {
   /* Other bits of trace status were collected as part of opening the
      trace files, so nothing to do here.  */
@@ -4713,7 +4793,8 @@ tfile_get_trace_status (struct trace_status *ts)
 }
 
 static void
-tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp)
+tfile_get_tracepoint_status (struct target_ops *self,
+                            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.  */
@@ -4758,7 +4839,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
    each.  */
 
 static int
-tfile_trace_find (enum trace_find_type type, int num,
+tfile_trace_find (struct target_ops *self, enum trace_find_type type, int num,
                  CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
 {
   short tpnum;
@@ -4993,7 +5074,17 @@ tfile_fetch_registers (struct target_ops *ops,
   /* 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))
+
+  /* XXX This guessing code below only works if the PC register isn't
+     a pseudo-register.  The value of a pseudo-register isn't stored
+     in the (non-readonly) regcache -- instead it's recomputed
+     (probably from some other cached raw register) whenever the
+     register is read.  This guesswork should probably move to some
+     higher layer.  */
+  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
+    return;
+
+  if (regno == -1 || regno == pc_regno)
     {
       struct tracepoint *tp = get_tracepoint (tracepoint_number);
 
@@ -5024,14 +5115,15 @@ tfile_fetch_registers (struct target_ops *ops,
     }
 }
 
-static LONGEST
+static enum target_xfer_status
 tfile_xfer_partial (struct target_ops *ops, enum target_object object,
                    const char *annex, gdb_byte *readbuf,
-                   const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+                   const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                   ULONGEST *xfered_len)
 {
   /* We're only doing regular memory for now.  */
   if (object != TARGET_OBJECT_MEMORY)
-    return -1;
+    return TARGET_XFER_E_IO;
 
   if (readbuf == NULL)
     error (_("tfile_xfer_partial: trace file is read-only"));
@@ -5068,7 +5160,8 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
              if (maddr != offset)
                lseek (trace_fd, offset - maddr, SEEK_CUR);
              tfile_read (readbuf, amt);
-             return amt;
+             *xfered_len = amt;
+             return TARGET_XFER_OK;
            }
 
          /* Skip over this block.  */
@@ -5102,22 +5195,23 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
              if (amt > len)
                amt = len;
 
-             amt = bfd_get_section_contents (exec_bfd, s,
-                                             readbuf, offset - vma, amt);
-             return amt;
+             *xfered_len = bfd_get_section_contents (exec_bfd, s,
+                                                     readbuf, offset - vma, amt);
+             return TARGET_XFER_OK;
            }
        }
     }
 
   /* Indicate failure to find the requested memory block.  */
-  return -1;
+  return TARGET_XFER_E_IO;
 }
 
 /* Iterate through the blocks of a trace frame, looking for a 'V'
    block with a matching tsv number.  */
 
 static int
-tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
+tfile_get_trace_state_variable_value (struct target_ops *self,
+                                     int tsvnum, LONGEST *val)
 {
   int pos;
   int found = 0;
@@ -5173,6 +5267,12 @@ tfile_has_registers (struct target_ops *ops)
   return traceframe_number != -1;
 }
 
+static int
+tfile_thread_alive (struct target_ops *ops, ptid_t ptid)
+{
+  return 1;
+}
+
 /* Callback for traceframe_walk_blocks.  Builds a traceframe_info
    object for the tfile target's current traceframe.  */
 
@@ -5206,6 +5306,12 @@ build_traceframe_info (char blocktype, void *data)
        break;
       }
     case 'V':
+      {
+       int vnum;
+
+       tfile_read ((gdb_byte *) &vnum, 4);
+       VEC_safe_push (int, info->tvars, vnum);
+      }
     case 'R':
     case 'S':
       {
@@ -5222,7 +5328,7 @@ build_traceframe_info (char blocktype, void *data)
 }
 
 static struct traceframe_info *
-tfile_traceframe_info (void)
+tfile_traceframe_info (struct target_ops *self)
 {
   struct traceframe_info *info = XCNEW (struct traceframe_info);
 
@@ -5253,6 +5359,7 @@ init_tfile_ops (void)
   tfile_ops.to_has_stack = tfile_has_stack;
   tfile_ops.to_has_registers = tfile_has_registers;
   tfile_ops.to_traceframe_info = tfile_traceframe_info;
+  tfile_ops.to_thread_alive = tfile_thread_alive;
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
@@ -5563,6 +5670,21 @@ traceframe_info_start_memory (struct gdb_xml_parser *parser,
   r->length = *length_p;
 }
 
+/* Handle the start of a <tvar> element.  */
+
+static void
+traceframe_info_start_tvar (struct gdb_xml_parser *parser,
+                            const struct gdb_xml_element *element,
+                            void *user_data,
+                            VEC(gdb_xml_value_s) *attributes)
+{
+  struct traceframe_info *info = user_data;
+  const char *id_attrib = xml_find_attribute (attributes, "id")->value;
+  int id = gdb_xml_parse_ulongest (parser, id_attrib);
+
+  VEC_safe_push (int, info->tvars, id);
+}
+
 /* Discard the constructed trace frame info (if an error occurs).  */
 
 static void
@@ -5581,10 +5703,18 @@ static const struct gdb_xml_attribute memory_attributes[] = {
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
+static const struct gdb_xml_attribute tvar_attributes[] = {
+  { "id", GDB_XML_AF_NONE, NULL, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
 static const struct gdb_xml_element traceframe_info_children[] = {
   { "memory", memory_attributes, NULL,
     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
     traceframe_info_start_memory, NULL },
+  { "tvar", tvar_attributes, NULL,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+    traceframe_info_start_tvar, NULL },
   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
@@ -5625,7 +5755,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.  */
 
-static struct traceframe_info *
+struct traceframe_info *
 get_traceframe_info (void)
 {
   if (traceframe_info == NULL)
This page took 0.033277 seconds and 4 git commands to generate.