GDB (xrefs)
/tmp/gdb-7.10/gdb/tracefile.c
Go to the documentation of this file.
1 /* Trace file support in GDB.
2 
3  Copyright (C) 1997-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "defs.h"
21 #include "tracefile.h"
22 #include "ctf.h"
23 #include "exec.h"
24 #include "regcache.h"
25 
26 /* Helper macros. */
27 
28 #define TRACE_WRITE_R_BLOCK(writer, buf, size) \
29  writer->ops->frame_ops->write_r_block ((writer), (buf), (size))
30 #define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size) \
31  writer->ops->frame_ops->write_m_block_header ((writer), (addr), \
32  (size))
33 #define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \
34  writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \
35  (size))
36 #define TRACE_WRITE_V_BLOCK(writer, num, val) \
37  writer->ops->frame_ops->write_v_block ((writer), (num), (val))
38 
39 /* Free trace file writer. */
40 
41 static void
43 {
44  struct trace_file_writer *writer = arg;
45 
46  writer->ops->dtor (writer);
47  xfree (writer);
48 }
49 
50 /* Save tracepoint data to file named FILENAME through WRITER. WRITER
51  determines the trace file format. If TARGET_DOES_SAVE is non-zero,
52  the save is performed on the target, otherwise GDB obtains all trace
53  data and saves it locally. */
54 
55 static void
56 trace_save (const char *filename, struct trace_file_writer *writer,
57  int target_does_save)
58 {
59  struct trace_status *ts = current_trace_status ();
60  int status;
61  struct uploaded_tp *uploaded_tps = NULL, *utp;
62  struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
63 
64  ULONGEST offset = 0;
65 #define MAX_TRACE_UPLOAD 2000
67  int written;
68  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
69 
70  /* If the target is to save the data to a file on its own, then just
71  send the command and be done with it. */
72  if (target_does_save)
73  {
74  if (!writer->ops->target_save (writer, filename))
75  error (_("Target failed to save trace data to '%s'."),
76  filename);
77  return;
78  }
79 
80  /* Get the trace status first before opening the file, so if the
81  target is losing, we can get out without touching files. */
82  status = target_get_trace_status (ts);
83 
84  writer->ops->start (writer, filename);
85 
86  writer->ops->write_header (writer);
87 
88  /* Write descriptive info. */
89 
90  /* Write out the size of a register block. */
91  writer->ops->write_regblock_type (writer, trace_regblock_size);
92 
93  /* Write out status of the tracing run (aka "tstatus" info). */
94  writer->ops->write_status (writer, ts);
95 
96  /* Note that we want to upload tracepoints and save those, rather
97  than simply writing out the local ones, because the user may have
98  changed tracepoints in GDB in preparation for a future tracing
99  run, or maybe just mass-deleted all types of breakpoints as part
100  of cleaning up. So as not to contaminate the session, leave the
101  data in its uploaded form, don't make into real tracepoints. */
102 
103  /* Get trace state variables first, they may be checked when parsing
104  uploaded commands. */
105 
106  target_upload_trace_state_variables (&uploaded_tsvs);
107 
108  for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
109  writer->ops->write_uploaded_tsv (writer, utsv);
110 
111  free_uploaded_tsvs (&uploaded_tsvs);
112 
113  target_upload_tracepoints (&uploaded_tps);
114 
115  for (utp = uploaded_tps; utp; utp = utp->next)
116  target_get_tracepoint_status (NULL, utp);
117 
118  for (utp = uploaded_tps; utp; utp = utp->next)
119  writer->ops->write_uploaded_tp (writer, utp);
120 
121  free_uploaded_tps (&uploaded_tps);
122 
123  /* Mark the end of the definition section. */
124  writer->ops->write_definition_end (writer);
125 
126  /* Get and write the trace data proper. */
127  while (1)
128  {
129  LONGEST gotten = 0;
130 
131  /* The writer supports writing the contents of trace buffer
132  directly to trace file. Don't parse the contents of trace
133  buffer. */
134  if (writer->ops->write_trace_buffer != NULL)
135  {
136  /* We ask for big blocks, in the hopes of efficiency, but
137  will take less if the target has packet size limitations
138  or some such. */
139  gotten = target_get_raw_trace_data (buf, offset,
141  if (gotten < 0)
142  error (_("Failure to get requested trace buffer data"));
143  /* No more data is forthcoming, we're done. */
144  if (gotten == 0)
145  break;
146 
147  writer->ops->write_trace_buffer (writer, buf, gotten);
148 
149  offset += gotten;
150  }
151  else
152  {
153  uint16_t tp_num;
154  uint32_t tf_size;
155  /* Parse the trace buffers according to how data are stored
156  in trace buffer in GDBserver. */
157 
158  gotten = target_get_raw_trace_data (buf, offset, 6);
159 
160  if (gotten == 0)
161  break;
162 
163  /* Read the first six bytes in, which is the tracepoint
164  number and trace frame size. */
165  tp_num = (uint16_t)
166  extract_unsigned_integer (&buf[0], 2, byte_order);
167 
168  tf_size = (uint32_t)
169  extract_unsigned_integer (&buf[2], 4, byte_order);
170 
171  writer->ops->frame_ops->start (writer, tp_num);
172  gotten = 6;
173 
174  if (tf_size > 0)
175  {
176  unsigned int block;
177 
178  offset += 6;
179 
180  for (block = 0; block < tf_size; )
181  {
183 
184  /* We'll fetch one block each time, in order to
185  handle the extremely large 'M' block. We first
186  fetch one byte to get the type of the block. */
187  gotten = target_get_raw_trace_data (buf, offset, 1);
188  if (gotten < 1)
189  error (_("Failure to get requested trace buffer data"));
190 
191  gotten = 1;
192  block += 1;
193  offset += 1;
194 
195  block_type = buf[0];
196  switch (block_type)
197  {
198  case 'R':
199  gotten
200  = target_get_raw_trace_data (buf, offset,
202  if (gotten < trace_regblock_size)
203  error (_("Failure to get requested trace"
204  " buffer data"));
205 
206  TRACE_WRITE_R_BLOCK (writer, buf,
208  break;
209  case 'M':
210  {
211  unsigned short mlen;
212  ULONGEST addr;
213  LONGEST t;
214  int j;
215 
216  t = target_get_raw_trace_data (buf,offset, 10);
217  if (t < 10)
218  error (_("Failure to get requested trace"
219  " buffer data"));
220 
221  offset += 10;
222  block += 10;
223 
224  gotten = 0;
225  addr = (ULONGEST)
226  extract_unsigned_integer (buf, 8,
227  byte_order);
228  mlen = (unsigned short)
229  extract_unsigned_integer (&buf[8], 2,
230  byte_order);
231 
232  TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
233  mlen);
234 
235  /* The memory contents in 'M' block may be
236  very large. Fetch the data from the target
237  and write them into file one by one. */
238  for (j = 0; j < mlen; )
239  {
240  unsigned int read_length;
241 
242  if (mlen - j > MAX_TRACE_UPLOAD)
243  read_length = MAX_TRACE_UPLOAD;
244  else
245  read_length = mlen - j;
246 
247  t = target_get_raw_trace_data (buf,
248  offset + j,
249  read_length);
250  if (t < read_length)
251  error (_("Failure to get requested"
252  " trace buffer data"));
253 
254  TRACE_WRITE_M_BLOCK_MEMORY (writer, buf,
255  read_length);
256 
257  j += read_length;
258  gotten += read_length;
259  }
260 
261  break;
262  }
263  case 'V':
264  {
265  int vnum;
266  LONGEST val;
267 
268  gotten
269  = target_get_raw_trace_data (buf, offset,
270  12);
271  if (gotten < 12)
272  error (_("Failure to get requested"
273  " trace buffer data"));
274 
275  vnum = (int) extract_signed_integer (buf,
276  4,
277  byte_order);
278  val
279  = extract_signed_integer (&buf[4], 8,
280  byte_order);
281 
282  TRACE_WRITE_V_BLOCK (writer, vnum, val);
283  }
284  break;
285  default:
286  error (_("Unknown block type '%c' (0x%x) in"
287  " trace frame"),
288  block_type, block_type);
289  }
290 
291  block += gotten;
292  offset += gotten;
293  }
294  }
295  else
296  offset += gotten;
297 
298  writer->ops->frame_ops->end (writer);
299  }
300  }
301 
302  writer->ops->end (writer);
303 }
304 
305 static void
306 trace_save_command (char *args, int from_tty)
307 {
308  int target_does_save = 0;
309  char **argv;
310  char *filename = NULL;
311  struct cleanup *back_to;
312  int generate_ctf = 0;
313  struct trace_file_writer *writer = NULL;
314 
315  if (args == NULL)
316  error_no_arg (_("file in which to save trace data"));
317 
318  argv = gdb_buildargv (args);
319  back_to = make_cleanup_freeargv (argv);
320 
321  for (; *argv; ++argv)
322  {
323  if (strcmp (*argv, "-r") == 0)
324  target_does_save = 1;
325  if (strcmp (*argv, "-ctf") == 0)
326  generate_ctf = 1;
327  else if (**argv == '-')
328  error (_("unknown option `%s'"), *argv);
329  else
330  filename = *argv;
331  }
332 
333  if (!filename)
334  error_no_arg (_("file in which to save trace data"));
335 
336  if (generate_ctf)
337  writer = ctf_trace_file_writer_new ();
338  else
339  writer = tfile_trace_file_writer_new ();
340 
342 
343  trace_save (filename, writer, target_does_save);
344 
345  if (from_tty)
346  printf_filtered (_("Trace data saved to %s '%s'.\n"),
347  generate_ctf ? "directory" : "file", filename);
348 
349  do_cleanups (back_to);
350 }
351 
352 /* Save the trace data to file FILENAME of tfile format. */
353 
354 void
355 trace_save_tfile (const char *filename, int target_does_save)
356 {
357  struct trace_file_writer *writer;
358  struct cleanup *back_to;
359 
360  writer = tfile_trace_file_writer_new ();
361  back_to = make_cleanup (trace_file_writer_xfree, writer);
362  trace_save (filename, writer, target_does_save);
363  do_cleanups (back_to);
364 }
365 
366 /* Save the trace data to dir DIRNAME of ctf format. */
367 
368 void
369 trace_save_ctf (const char *dirname, int target_does_save)
370 {
371  struct trace_file_writer *writer;
372  struct cleanup *back_to;
373 
374  writer = ctf_trace_file_writer_new ();
375  back_to = make_cleanup (trace_file_writer_xfree, writer);
376 
377  trace_save (dirname, writer, target_does_save);
378  do_cleanups (back_to);
379 }
380 
381 /* Fetch register data from tracefile, shared for both tfile and
382  ctf. */
383 
384 void
386 {
387  struct gdbarch *gdbarch = get_regcache_arch (regcache);
388  int regn, pc_regno;
389 
390  /* We get here if no register data has been found. Mark registers
391  as unavailable. */
392  for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
393  regcache_raw_supply (regcache, regn, NULL);
394 
395  /* We can often usefully guess that the PC is going to be the same
396  as the address of the tracepoint. */
397  pc_regno = gdbarch_pc_regnum (gdbarch);
398 
399  /* XXX This guessing code below only works if the PC register isn't
400  a pseudo-register. The value of a pseudo-register isn't stored
401  in the (non-readonly) regcache -- instead it's recomputed
402  (probably from some other cached raw register) whenever the
403  register is read. This guesswork should probably move to some
404  higher layer. */
405  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
406  return;
407 
408  if (regno == -1 || regno == pc_regno)
409  {
411  gdb_byte *regs;
412 
413  if (tp && tp->base.loc)
414  {
415  /* But don't try to guess if tracepoint is multi-location... */
416  if (tp->base.loc->next)
417  {
418  warning (_("Tracepoint %d has multiple "
419  "locations, cannot infer $pc"),
420  tp->base.number);
421  return;
422  }
423  /* ... or does while-stepping. */
424  if (tp->step_count > 0)
425  {
426  warning (_("Tracepoint %d does while-stepping, "
427  "cannot infer $pc"),
428  tp->base.number);
429  return;
430  }
431 
432  regs = alloca (register_size (gdbarch, pc_regno));
433  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
434  gdbarch_byte_order (gdbarch),
435  tp->base.loc->address);
436  regcache_raw_supply (regcache, pc_regno, regs);
437  }
438  }
439 }
440 
441 /* This is the implementation of target_ops method to_has_all_memory. */
442 
443 static int
445 {
446  return 1;
447 }
448 
449 /* This is the implementation of target_ops method to_has_memory. */
450 
451 static int
453 {
454  return 1;
455 }
456 
457 /* This is the implementation of target_ops method to_has_stack.
458  The target has a stack when GDB has already selected one trace
459  frame. */
460 
461 static int
463 {
464  return get_traceframe_number () != -1;
465 }
466 
467 /* This is the implementation of target_ops method to_has_registers.
468  The target has registers when GDB has already selected one trace
469  frame. */
470 
471 static int
473 {
474  return get_traceframe_number () != -1;
475 }
476 
477 /* This is the implementation of target_ops method to_thread_alive.
478  tracefile has one thread faked by GDB. */
479 
480 static int
482 {
483  return 1;
484 }
485 
486 /* This is the implementation of target_ops method to_get_trace_status.
487  The trace status for a file is that tracing can never be run. */
488 
489 static int
491 {
492  /* Other bits of trace status were collected as part of opening the
493  trace files, so nothing to do here. */
494 
495  return -1;
496 }
497 
498 /* Initialize OPS for tracefile related targets. */
499 
500 void
502 {
510  ops->to_magic = OPS_MAGIC;
511 }
512 
514 
515 void
517 {
518  add_com ("tsave", class_trace, trace_save_command, _("\
519 Save the trace data to a file.\n\
520 Use the '-ctf' option to save the data to CTF format.\n\
521 Use the '-r' option to direct the target to save directly to the file,\n\
522 using its own filesystem."));
523 }
void error_no_arg(const char *why)
Definition: cli-cmds.c:205
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5143
struct cleanup * make_cleanup_freeargv(char **arg)
Definition: utils.c:165
ULONGEST extract_unsigned_integer(const gdb_byte *, int, enum bfd_endian)
Definition: findvar.c:84
int trace_regblock_size
void xfree(void *)
Definition: common-utils.c:97
struct gdbarch * get_regcache_arch(const struct regcache *regcache)
Definition: regcache.c:297
#define target_upload_trace_state_variables(utsvp)
Definition: target.h:2122
const struct trace_file_write_ops * ops
Definition: tracefile.h:108
int(* to_has_memory)(struct target_ops *)
Definition: target.h:652
void warning(const char *fmt,...)
Definition: errors.c:26
void(* write_status)(struct trace_file_writer *self, struct trace_status *ts)
Definition: tracefile.h:76
int(* to_has_stack)(struct target_ops *)
Definition: target.h:653
void free_uploaded_tps(struct uploaded_tp **utpp)
Definition: tracepoint.c:3279
#define target_get_raw_trace_data(buf, offset, len)
Definition: target.h:2125
struct breakpoint base
Definition: breakpoint.h:858
#define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size)
Definition: tracefile.c:30
static int tracefile_has_registers(struct target_ops *ops)
Definition: tracefile.c:472
static int tracefile_has_stack(struct target_ops *ops)
Definition: tracefile.c:462
int gdbarch_num_regs(struct gdbarch *gdbarch)
Definition: gdbarch.c:1898
struct tracepoint * get_tracepoint(int num)
Definition: breakpoint.c:15197
#define _(String)
Definition: gdb_locale.h:40
void(* start)(struct trace_file_writer *self, const char *name)
Definition: tracefile.h:64
#define target_get_tracepoint_status(tp, utp)
Definition: target.h:2102
void free_uploaded_tsvs(struct uploaded_tsv **utsvp)
Definition: tracepoint.c:3311
void(* write_regblock_type)(struct trace_file_writer *self, int size)
Definition: tracefile.h:72
void store_unsigned_integer(gdb_byte *, int, enum bfd_endian, ULONGEST)
Definition: findvar.c:212
void printf_filtered(const char *format,...)
Definition: utils.c:2388
Definition: ptid.h:35
const struct trace_frame_write_ops * frame_ops
Definition: tracefile.h:98
long step_count
Definition: breakpoint.h:862
static void trace_save_command(char *args, int from_tty)
Definition: tracefile.c:306
struct trace_status * current_trace_status(void)
Definition: tracepoint.c:205
void trace_save_ctf(const char *dirname, int target_does_save)
Definition: tracefile.c:369
#define OPS_MAGIC
Definition: target.h:1233
struct bp_location * next
Definition: breakpoint.h:307
void initialize_file_ftype(void)
Definition: defs.h:281
struct uploaded_tsv * next
Definition: tracepoint.h:206
void(* end)(struct trace_file_writer *self)
Definition: tracefile.h:46
#define TRACE_WRITE_V_BLOCK(writer, num, val)
Definition: tracefile.c:36
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int status
Definition: gnu-nat.c:1816
struct uploaded_tp * next
Definition: tracepoint.h:195
block_type
Definition: mdebugread.c:236
static int tracefile_has_all_memory(struct target_ops *ops)
Definition: tracefile.c:444
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition: gdbarch.c:1420
void init_tracefile_ops(struct target_ops *ops)
Definition: tracefile.c:501
int get_traceframe_number(void)
Definition: tracepoint.c:3180
void(* write_uploaded_tsv)(struct trace_file_writer *self, struct uploaded_tsv *tsv)
Definition: tracefile.h:80
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
Definition: cleanups.c:117
initialize_file_ftype _initialize_tracefile
Definition: block.h:60
#define TRACE_WRITE_R_BLOCK(writer, buf, size)
Definition: tracefile.c:28
static int tracefile_thread_alive(struct target_ops *ops, ptid_t ptid)
Definition: tracefile.c:481
static void trace_save(const char *filename, struct trace_file_writer *writer, int target_does_save)
Definition: tracefile.c:56
#define target_get_trace_status(ts)
Definition: target.h:2099
const char const char int
Definition: command.h:229
bfd_byte gdb_byte
Definition: common-types.h:38
int get_tracepoint_number(void)
Definition: tracepoint.c:3186
void tracefile_fetch_registers(struct regcache *regcache, int regno)
Definition: tracefile.c:385
void(* write_header)(struct trace_file_writer *self)
Definition: tracefile.h:68
void(* dtor)(struct trace_file_writer *self)
Definition: tracefile.h:55
static int tracefile_get_trace_status(struct target_ops *self, struct trace_status *ts)
Definition: tracefile.c:490
enum strata to_stratum
Definition: target.h:650
struct bp_location * loc
Definition: breakpoint.h:678
#define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size)
Definition: tracefile.c:33
int offset
Definition: agent.c:65
void(* write_definition_end)(struct trace_file_writer *self)
Definition: tracefile.h:88
struct trace_file_writer * ctf_trace_file_writer_new(void)
Definition: ctf.c:811
char ** gdb_buildargv(const char *s)
Definition: utils.c:3036
int(* to_get_trace_status)(struct target_ops *, struct trace_status *ts) TARGET_DEFAULT_RETURN(-1)
Definition: target.h:967
#define MAX_TRACE_UPLOAD
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
void(* start)(struct trace_file_writer *self, uint16_t tpnum)
Definition: tracefile.h:14
void trace_save_tfile(const char *filename, int target_does_save)
Definition: tracefile.c:355
unsigned long long ULONGEST
Definition: common-types.h:53
static void trace_file_writer_xfree(void *arg)
Definition: tracefile.c:42
int to_magic
Definition: target.h:1224
int register_size(struct gdbarch *gdbarch, int regnum)
Definition: regcache.c:169
void(* end)(struct trace_file_writer *self)
Definition: tracefile.h:101
int(* to_has_all_memory)(struct target_ops *)
Definition: target.h:651
int gdbarch_pc_regnum(struct gdbarch *gdbarch)
Definition: gdbarch.c:1998
CORE_ADDR address
Definition: breakpoint.h:410
int(* to_thread_alive)(struct target_ops *, ptid_t ptid) TARGET_DEFAULT_RETURN(0)
Definition: target.h:627
struct trace_file_writer * tfile_trace_file_writer_new(void)
void(* write_uploaded_tp)(struct trace_file_writer *self, struct uploaded_tp *tp)
Definition: tracefile.h:84
LONGEST extract_signed_integer(const gdb_byte *, int, enum bfd_endian)
Definition: findvar.c:49
void(* write_trace_buffer)(struct trace_file_writer *self, gdb_byte *buf, LONGEST len)
Definition: tracefile.h:92
int(* to_has_registers)(struct target_ops *)
Definition: target.h:654
void error(const char *fmt,...)
Definition: errors.c:38
static int tracefile_has_memory(struct target_ops *ops)
Definition: tracefile.c:452
struct cmd_list_element * add_com(const char *name, enum command_class theclass, cmd_cfunc_ftype *fun, const char *doc)
Definition: cli-decode.c:873
int(* target_save)(struct trace_file_writer *self, const char *name)
Definition: tracefile.h:60
long long LONGEST
Definition: common-types.h:52
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:175
#define target_upload_tracepoints(utpp)
Definition: target.h:2119