GDB (xrefs)
/tmp/gdb-8.1/gdb/tracefile-tfile.c
Go to the documentation of this file.
1 /* Trace file TFILE format support in GDB.
2 
3  Copyright (C) 1997-2018 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 "readline/tilde.h"
23 #include "filestuff.h"
24 #include "rsp-low.h" /* bin2hex */
25 #include "regcache.h"
26 #include "inferior.h"
27 #include "gdbthread.h"
28 #include "exec.h" /* exec_bfd */
29 #include "completer.h"
30 #include "filenames.h"
31 #include "remote.h"
32 #include "xml-tdesc.h"
33 #include "target-descriptions.h"
34 #include "buffer.h"
35 #include <algorithm>
36 
37 #ifndef O_LARGEFILE
38 #define O_LARGEFILE 0
39 #endif
40 
41 /* TFILE trace writer. */
42 
44 {
46 
47  /* File pointer to tfile trace file. */
48  FILE *fp;
49  /* Path name of the tfile trace file. */
50  char *pathname;
51 };
52 
53 /* This is the implementation of trace_file_write_ops method
54  target_save. We just call the generic target
55  target_save_trace_data to do target-side saving. */
56 
57 static int
59  const char *filename)
60 {
61  int err = target_save_trace_data (filename);
62 
63  return (err >= 0);
64 }
65 
66 /* This is the implementation of trace_file_write_ops method
67  dtor. */
68 
69 static void
71 {
72  struct tfile_trace_file_writer *writer
73  = (struct tfile_trace_file_writer *) self;
74 
75  xfree (writer->pathname);
76 
77  if (writer->fp != NULL)
78  fclose (writer->fp);
79 }
80 
81 /* This is the implementation of trace_file_write_ops method
82  start. It creates the trace file FILENAME and registers some
83  cleanups. */
84 
85 static void
86 tfile_start (struct trace_file_writer *self, const char *filename)
87 {
88  struct tfile_trace_file_writer *writer
89  = (struct tfile_trace_file_writer *) self;
90 
91  writer->pathname = tilde_expand (filename);
92  writer->fp = gdb_fopen_cloexec (writer->pathname, "wb").release ();
93  if (writer->fp == NULL)
94  error (_("Unable to open file '%s' for saving trace data (%s)"),
95  writer->pathname, safe_strerror (errno));
96 }
97 
98 /* This is the implementation of trace_file_write_ops method
99  write_header. Write the TFILE header. */
100 
101 static void
103 {
104  struct tfile_trace_file_writer *writer
105  = (struct tfile_trace_file_writer *) self;
106  int written;
107 
108  /* Write a file header, with a high-bit-set char to indicate a
109  binary file, plus a hint as what this file is, and a version
110  number in case of future needs. */
111  written = fwrite ("\x7fTRACE0\n", 8, 1, writer->fp);
112  if (written < 1)
113  perror_with_name (writer->pathname);
114 }
115 
116 /* This is the implementation of trace_file_write_ops method
117  write_regblock_type. Write the size of register block. */
118 
119 static void
121 {
122  struct tfile_trace_file_writer *writer
123  = (struct tfile_trace_file_writer *) self;
124 
125  fprintf (writer->fp, "R %x\n", size);
126 }
127 
128 /* This is the implementation of trace_file_write_ops method
129  write_status. */
130 
131 static void
133  struct trace_status *ts)
134 {
135  struct tfile_trace_file_writer *writer
136  = (struct tfile_trace_file_writer *) self;
137 
138  fprintf (writer->fp, "status %c;%s",
139  (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
140  if (ts->stop_reason == tracepoint_error
142  {
143  char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
144 
145  bin2hex ((gdb_byte *) ts->stop_desc, buf, strlen (ts->stop_desc));
146  fprintf (writer->fp, ":%s", buf);
147  }
148  fprintf (writer->fp, ":%x", ts->stopping_tracepoint);
149  if (ts->traceframe_count >= 0)
150  fprintf (writer->fp, ";tframes:%x", ts->traceframe_count);
151  if (ts->traceframes_created >= 0)
152  fprintf (writer->fp, ";tcreated:%x", ts->traceframes_created);
153  if (ts->buffer_free >= 0)
154  fprintf (writer->fp, ";tfree:%x", ts->buffer_free);
155  if (ts->buffer_size >= 0)
156  fprintf (writer->fp, ";tsize:%x", ts->buffer_size);
157  if (ts->disconnected_tracing)
158  fprintf (writer->fp, ";disconn:%x", ts->disconnected_tracing);
159  if (ts->circular_buffer)
160  fprintf (writer->fp, ";circular:%x", ts->circular_buffer);
161  if (ts->start_time)
162  {
163  fprintf (writer->fp, ";starttime:%s",
164  phex_nz (ts->start_time, sizeof (ts->start_time)));
165  }
166  if (ts->stop_time)
167  {
168  fprintf (writer->fp, ";stoptime:%s",
169  phex_nz (ts->stop_time, sizeof (ts->stop_time)));
170  }
171  if (ts->notes != NULL)
172  {
173  char *buf = (char *) alloca (strlen (ts->notes) * 2 + 1);
174 
175  bin2hex ((gdb_byte *) ts->notes, buf, strlen (ts->notes));
176  fprintf (writer->fp, ";notes:%s", buf);
177  }
178  if (ts->user_name != NULL)
179  {
180  char *buf = (char *) alloca (strlen (ts->user_name) * 2 + 1);
181 
182  bin2hex ((gdb_byte *) ts->user_name, buf, strlen (ts->user_name));
183  fprintf (writer->fp, ";username:%s", buf);
184  }
185  fprintf (writer->fp, "\n");
186 }
187 
188 /* This is the implementation of trace_file_write_ops method
189  write_uploaded_tsv. */
190 
191 static void
193  struct uploaded_tsv *utsv)
194 {
195  char *buf = NULL;
196  struct tfile_trace_file_writer *writer
197  = (struct tfile_trace_file_writer *) self;
198 
199  if (utsv->name)
200  {
201  buf = (char *) xmalloc (strlen (utsv->name) * 2 + 1);
202  bin2hex ((gdb_byte *) (utsv->name), buf, strlen (utsv->name));
203  }
204 
205  fprintf (writer->fp, "tsv %x:%s:%x:%s\n",
206  utsv->number, phex_nz (utsv->initial_value, 8),
207  utsv->builtin, buf != NULL ? buf : "");
208 
209  if (utsv->name)
210  xfree (buf);
211 }
212 
213 #define MAX_TRACE_UPLOAD 2000
214 
215 /* This is the implementation of trace_file_write_ops method
216  write_uploaded_tp. */
217 
218 static void
220  struct uploaded_tp *utp)
221 {
222  struct tfile_trace_file_writer *writer
223  = (struct tfile_trace_file_writer *) self;
224  int a;
225  char *act;
226  char buf[MAX_TRACE_UPLOAD];
227 
228  fprintf (writer->fp, "tp T%x:%s:%c:%x:%x",
229  utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
230  (utp->enabled ? 'E' : 'D'), utp->step, utp->pass);
231  if (utp->type == bp_fast_tracepoint)
232  fprintf (writer->fp, ":F%x", utp->orig_size);
233  if (utp->cond)
234  fprintf (writer->fp,
235  ":X%x,%s", (unsigned int) strlen (utp->cond) / 2,
236  utp->cond);
237  fprintf (writer->fp, "\n");
238  for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a)
239  fprintf (writer->fp, "tp A%x:%s:%s\n",
240  utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
241  for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a)
242  fprintf (writer->fp, "tp S%x:%s:%s\n",
243  utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
244  if (utp->at_string)
245  {
246  encode_source_string (utp->number, utp->addr,
247  "at", utp->at_string, buf, MAX_TRACE_UPLOAD);
248  fprintf (writer->fp, "tp Z%s\n", buf);
249  }
250  if (utp->cond_string)
251  {
252  encode_source_string (utp->number, utp->addr,
253  "cond", utp->cond_string,
254  buf, MAX_TRACE_UPLOAD);
255  fprintf (writer->fp, "tp Z%s\n", buf);
256  }
257  for (a = 0; VEC_iterate (char_ptr, utp->cmd_strings, a, act); ++a)
258  {
259  encode_source_string (utp->number, utp->addr, "cmd", act,
260  buf, MAX_TRACE_UPLOAD);
261  fprintf (writer->fp, "tp Z%s\n", buf);
262  }
263  fprintf (writer->fp, "tp V%x:%s:%x:%s\n",
264  utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
265  utp->hit_count,
267  sizeof (utp->traceframe_usage)));
268 }
269 
270 /* This is the implementation of trace_file_write_ops method
271  write_tdesc. */
272 
273 static void
275 {
276  struct tfile_trace_file_writer *writer
277  = (struct tfile_trace_file_writer *) self;
278 
281 
282  if (!tdesc)
283  return;
284 
285  const char *ptr = tdesc->c_str ();
286 
287  /* Write tdesc line by line, prefixing each line with "tdesc ". */
288  while (ptr != NULL)
289  {
290  const char *next = strchr (ptr, '\n');
291  if (next != NULL)
292  {
293  fprintf (writer->fp, "tdesc %.*s\n", (int) (next - ptr), ptr);
294  /* Skip the \n. */
295  next++;
296  }
297  else if (*ptr != '\0')
298  {
299  /* Last line, doesn't have a newline. */
300  fprintf (writer->fp, "tdesc %s\n", ptr);
301  }
302  ptr = next;
303  }
304 }
305 
306 /* This is the implementation of trace_file_write_ops method
307  write_definition_end. */
308 
309 static void
311 {
312  struct tfile_trace_file_writer *writer
313  = (struct tfile_trace_file_writer *) self;
314 
315  fprintf (writer->fp, "\n");
316 }
317 
318 /* This is the implementation of trace_file_write_ops method
319  write_raw_data. */
320 
321 static void
323  LONGEST len)
324 {
325  struct tfile_trace_file_writer *writer
326  = (struct tfile_trace_file_writer *) self;
327 
328  if (fwrite (buf, len, 1, writer->fp) < 1)
329  perror_with_name (writer->pathname);
330 }
331 
332 /* This is the implementation of trace_file_write_ops method
333  end. */
334 
335 static void
337 {
338  struct tfile_trace_file_writer *writer
339  = (struct tfile_trace_file_writer *) self;
340  uint32_t gotten = 0;
341 
342  /* Mark the end of trace data. */
343  if (fwrite (&gotten, 4, 1, writer->fp) < 1)
344  perror_with_name (writer->pathname);
345 }
346 
347 /* Operations to write trace buffers into TFILE format. */
348 
350 {
351  tfile_dtor,
353  tfile_start,
362  NULL,
363  tfile_end,
364 };
365 
366 /* Return a trace writer for TFILE format. */
367 
368 struct trace_file_writer *
370 {
371  struct tfile_trace_file_writer *writer
372  = XNEW (struct tfile_trace_file_writer);
373 
374  writer->base.ops = &tfile_write_ops;
375  writer->fp = NULL;
376  writer->pathname = NULL;
377 
378  return (struct trace_file_writer *) writer;
379 }
380 
381 /* target tfile command */
382 
383 static struct target_ops tfile_ops;
384 
385 /* Fill in tfile_ops with its defined operations and properties. */
386 
387 #define TRACE_HEADER_SIZE 8
388 
389 #define TFILE_PID (1)
390 
391 static char *trace_filename;
392 static int trace_fd = -1;
393 static off_t trace_frames_offset;
394 static off_t cur_offset;
395 static int cur_data_size;
397 static struct buffer trace_tdesc;
398 
399 static void tfile_append_tdesc_line (const char *line);
400 static void tfile_interp_line (char *line,
401  struct uploaded_tp **utpp,
402  struct uploaded_tsv **utsvp);
403 
404 /* Read SIZE bytes into READBUF from the trace frame, starting at
405  TRACE_FD's current position. Note that this call `read'
406  underneath, hence it advances the file's seek position. Throws an
407  error if the `read' syscall fails, or less than SIZE bytes are
408  read. */
409 
410 static void
411 tfile_read (gdb_byte *readbuf, int size)
412 {
413  int gotten;
414 
415  gotten = read (trace_fd, readbuf, size);
416  if (gotten < 0)
418  else if (gotten < size)
419  error (_("Premature end of file while reading trace file"));
420 }
421 
422 static void
423 tfile_open (const char *arg, int from_tty)
424 {
425  int flags;
426  int scratch_chan;
427  char header[TRACE_HEADER_SIZE];
428  char linebuf[1000]; /* Should be max remote packet size or so. */
429  gdb_byte byte;
430  int bytes, i;
431  struct trace_status *ts;
432  struct uploaded_tp *uploaded_tps = NULL;
433  struct uploaded_tsv *uploaded_tsvs = NULL;
434 
435  target_preopen (from_tty);
436  if (!arg)
437  error (_("No trace file specified."));
438 
439  gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
440  if (!IS_ABSOLUTE_PATH (filename.get ()))
441  filename.reset (concat (current_directory, "/", filename.get (),
442  (char *) NULL));
443 
445  flags |= O_RDONLY;
446  scratch_chan = gdb_open_cloexec (filename.get (), flags, 0);
447  if (scratch_chan < 0)
448  perror_with_name (filename.get ());
449 
450  /* Looks semi-reasonable. Toss the old trace file and work on the new. */
451 
453 
454  trace_filename = filename.release ();
455  trace_fd = scratch_chan;
456 
457  /* Make sure this is clear. */
459 
460  bytes = 0;
461  /* Read the file header and test for validity. */
462  tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE);
463 
464  bytes += TRACE_HEADER_SIZE;
465  if (!(header[0] == 0x7f
466  && (startswith (header + 1, "TRACE0\n"))))
467  error (_("File is not a valid trace file."));
468 
470 
472  ts = current_trace_status ();
473  /* We know we're working with a file. Record its name. */
474  ts->filename = trace_filename;
475  /* Set defaults in case there is no status line. */
476  ts->running_known = 0;
478  ts->traceframe_count = -1;
479  ts->buffer_free = 0;
480  ts->disconnected_tracing = 0;
481  ts->circular_buffer = 0;
482 
483  TRY
484  {
485  /* Read through a section of newline-terminated lines that
486  define things like tracepoints. */
487  i = 0;
488  while (1)
489  {
490  tfile_read (&byte, 1);
491 
492  ++bytes;
493  if (byte == '\n')
494  {
495  /* Empty line marks end of the definition section. */
496  if (i == 0)
497  break;
498  linebuf[i] = '\0';
499  i = 0;
500  tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs);
501  }
502  else
503  linebuf[i++] = byte;
504  if (i >= 1000)
505  error (_("Excessively long lines in trace file"));
506  }
507 
508  /* By now, tdesc lines have been read from tfile - let's parse them. */
510 
511  /* Record the starting offset of the binary trace data. */
512  trace_frames_offset = bytes;
513 
514  /* If we don't have a blocksize, we can't interpret the
515  traceframes. */
516  if (trace_regblock_size == 0)
517  error (_("No register block size recorded in trace file"));
518  }
519  CATCH (ex, RETURN_MASK_ALL)
520  {
521  /* Remove the partially set up target. */
523  throw_exception (ex);
524  }
525  END_CATCH
526 
530 
531  if (ts->traceframe_count <= 0)
532  warning (_("No traceframes present in this file."));
533 
534  /* Add the file's tracepoints and variables into the current mix. */
535 
536  /* Get trace state variables first, they may be checked when parsing
537  uploaded commands. */
538  merge_uploaded_trace_state_variables (&uploaded_tsvs);
539 
540  merge_uploaded_tracepoints (&uploaded_tps);
541 
542  post_create_inferior (&tfile_ops, from_tty);
543 }
544 
545 /* Interpret the given line from the definitions part of the trace
546  file. */
547 
548 static void
549 tfile_interp_line (char *line, struct uploaded_tp **utpp,
550  struct uploaded_tsv **utsvp)
551 {
552  char *p = line;
553 
554  if (startswith (p, "R "))
555  {
556  p += strlen ("R ");
557  trace_regblock_size = strtol (p, &p, 16);
558  }
559  else if (startswith (p, "status "))
560  {
561  p += strlen ("status ");
563  }
564  else if (startswith (p, "tp "))
565  {
566  p += strlen ("tp ");
567  parse_tracepoint_definition (p, utpp);
568  }
569  else if (startswith (p, "tsv "))
570  {
571  p += strlen ("tsv ");
572  parse_tsv_definition (p, utsvp);
573  }
574  else if (startswith (p, "tdesc "))
575  {
576  p += strlen ("tdesc ");
578  }
579  else
580  warning (_("Ignoring trace file definition \"%s\""), line);
581 }
582 
583 /* Close the trace file and generally clean up. */
584 
585 static void
586 tfile_close (struct target_ops *self)
587 {
588  int pid;
589 
590  if (trace_fd < 0)
591  return;
592 
594  inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */
596 
597  close (trace_fd);
598  trace_fd = -1;
600  trace_filename = NULL;
602 
604 }
605 
606 static void
608 {
609  printf_filtered ("\t`%s'\n", trace_filename);
610 }
611 
612 static void
614  struct breakpoint *tp, struct uploaded_tp *utp)
615 {
616  /* Other bits of trace status were collected as part of opening the
617  trace files, so nothing to do here. */
618 }
619 
620 /* Given the position of a traceframe in the file, figure out what
621  address the frame was collected at. This would normally be the
622  value of a collected PC register, but if not available, we
623  improvise. */
624 
625 static CORE_ADDR
626 tfile_get_traceframe_address (off_t tframe_offset)
627 {
628  CORE_ADDR addr = 0;
629  short tpnum;
630  struct tracepoint *tp;
631  off_t saved_offset = cur_offset;
632 
633  /* FIXME dig pc out of collected registers. */
634 
635  /* Fall back to using tracepoint address. */
636  lseek (trace_fd, tframe_offset, SEEK_SET);
637  tfile_read ((gdb_byte *) &tpnum, 2);
638  tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
640  (target_gdbarch ()));
641 
643  /* FIXME this is a poor heuristic if multiple locations. */
644  if (tp && tp->loc)
645  addr = tp->loc->address;
646 
647  /* Restore our seek position. */
648  cur_offset = saved_offset;
649  lseek (trace_fd, cur_offset, SEEK_SET);
650  return addr;
651 }
652 
653 /* Given a type of search and some parameters, scan the collection of
654  traceframes in the file looking for a match. When found, return
655  both the traceframe and tracepoint number, otherwise -1 for
656  each. */
657 
658 static int
659 tfile_trace_find (struct target_ops *self, enum trace_find_type type, int num,
660  CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
661 {
662  short tpnum;
663  int tfnum = 0, found = 0;
664  unsigned int data_size;
665  struct tracepoint *tp;
666  off_t offset, tframe_offset;
667  CORE_ADDR tfaddr;
668 
669  if (num == -1)
670  {
671  if (tpp)
672  *tpp = -1;
673  return -1;
674  }
675 
678  while (1)
679  {
680  tframe_offset = offset;
681  tfile_read ((gdb_byte *) &tpnum, 2);
682  tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
684  (target_gdbarch ()));
685  offset += 2;
686  if (tpnum == 0)
687  break;
688  tfile_read ((gdb_byte *) &data_size, 4);
689  data_size = (unsigned int) extract_unsigned_integer
690  ((gdb_byte *) &data_size, 4,
692  offset += 4;
693 
694  if (type == tfind_number)
695  {
696  /* Looking for a specific trace frame. */
697  if (tfnum == num)
698  found = 1;
699  }
700  else
701  {
702  /* Start from the _next_ trace frame. */
703  if (tfnum > get_traceframe_number ())
704  {
705  switch (type)
706  {
707  case tfind_pc:
708  tfaddr = tfile_get_traceframe_address (tframe_offset);
709  if (tfaddr == addr1)
710  found = 1;
711  break;
712  case tfind_tp:
713  tp = get_tracepoint (num);
714  if (tp && tpnum == tp->number_on_target)
715  found = 1;
716  break;
717  case tfind_range:
718  tfaddr = tfile_get_traceframe_address (tframe_offset);
719  if (addr1 <= tfaddr && tfaddr <= addr2)
720  found = 1;
721  break;
722  case tfind_outside:
723  tfaddr = tfile_get_traceframe_address (tframe_offset);
724  if (!(addr1 <= tfaddr && tfaddr <= addr2))
725  found = 1;
726  break;
727  default:
728  internal_error (__FILE__, __LINE__, _("unknown tfind type"));
729  }
730  }
731  }
732 
733  if (found)
734  {
735  if (tpp)
736  *tpp = tpnum;
737  cur_offset = offset;
738  cur_data_size = data_size;
739 
740  return tfnum;
741  }
742  /* Skip past the traceframe's data. */
743  lseek (trace_fd, data_size, SEEK_CUR);
744  offset += data_size;
745  /* Update our own count of traceframes. */
746  ++tfnum;
747  }
748  /* Did not find what we were looking for. */
749  if (tpp)
750  *tpp = -1;
751  return -1;
752 }
753 
754 /* Prototype of the callback passed to tframe_walk_blocks. */
755 typedef int (*walk_blocks_callback_func) (char blocktype, void *data);
756 
757 /* Callback for traceframe_walk_blocks, used to find a given block
758  type in a traceframe. */
759 
760 static int
761 match_blocktype (char blocktype, void *data)
762 {
763  char *wantedp = (char *) data;
764 
765  if (*wantedp == blocktype)
766  return 1;
767 
768  return 0;
769 }
770 
771 /* Walk over all traceframe block starting at POS offset from
772  CUR_OFFSET, and call CALLBACK for each block found, passing in DATA
773  unmodified. If CALLBACK returns true, this returns the position in
774  the traceframe where the block is found, relative to the start of
775  the traceframe (cur_offset). Returns -1 if no callback call
776  returned true, indicating that all blocks have been walked. */
777 
778 static int
780  int pos, void *data)
781 {
782  /* Iterate through a traceframe's blocks, looking for a block of the
783  requested type. */
784 
785  lseek (trace_fd, cur_offset + pos, SEEK_SET);
786  while (pos < cur_data_size)
787  {
788  unsigned short mlen;
789  char block_type;
790 
791  tfile_read ((gdb_byte *) &block_type, 1);
792 
793  ++pos;
794 
795  if ((*callback) (block_type, data))
796  return pos;
797 
798  switch (block_type)
799  {
800  case 'R':
802  pos += trace_regblock_size;
803  break;
804  case 'M':
805  lseek (trace_fd, cur_offset + pos + 8, SEEK_SET);
806  tfile_read ((gdb_byte *) &mlen, 2);
807  mlen = (unsigned short)
808  extract_unsigned_integer ((gdb_byte *) &mlen, 2,
810  (target_gdbarch ()));
811  lseek (trace_fd, mlen, SEEK_CUR);
812  pos += (8 + 2 + mlen);
813  break;
814  case 'V':
815  lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET);
816  pos += (4 + 8);
817  break;
818  default:
819  error (_("Unknown block type '%c' (0x%x) in trace frame"),
821  break;
822  }
823  }
824 
825  return -1;
826 }
827 
828 /* Convenience wrapper around traceframe_walk_blocks. Looks for the
829  position offset of a block of type TYPE_WANTED in the current trace
830  frame, starting at POS. Returns -1 if no such block was found. */
831 
832 static int
833 traceframe_find_block_type (char type_wanted, int pos)
834 {
835  return traceframe_walk_blocks (match_blocktype, pos, &type_wanted);
836 }
837 
838 /* Look for a block of saved registers in the traceframe, and get the
839  requested register from it. */
840 
841 static void
843  struct regcache *regcache, int regno)
844 {
845  struct gdbarch *gdbarch = regcache->arch ();
846  int offset, regn, regsize, dummy;
847 
848  /* An uninitialized reg size says we're not going to be
849  successful at getting register blocks. */
850  if (!trace_regblock_size)
851  return;
852 
853  if (traceframe_find_block_type ('R', 0) >= 0)
854  {
855  gdb_byte *regs = (gdb_byte *) alloca (trace_regblock_size);
856 
858 
859  for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
860  {
862  regn, &dummy, &offset))
863  continue;
864 
865  regsize = register_size (gdbarch, regn);
866  /* Make sure we stay within block bounds. */
867  if (offset + regsize > trace_regblock_size)
868  break;
870  {
871  if (regno == regn)
872  {
873  regcache_raw_supply (regcache, regno, regs + offset);
874  break;
875  }
876  else if (regno == -1)
877  {
878  regcache_raw_supply (regcache, regn, regs + offset);
879  }
880  }
881  }
882  }
883  else
885 }
886 
887 static enum target_xfer_status
888 tfile_xfer_partial_features (struct target_ops *ops, const char *annex,
889  gdb_byte *readbuf, const gdb_byte *writebuf,
890  ULONGEST offset, ULONGEST len,
891  ULONGEST *xfered_len)
892 {
893  if (strcmp (annex, "target.xml"))
894  return TARGET_XFER_E_IO;
895 
896  if (readbuf == NULL)
897  error (_("tfile_xfer_partial: tdesc is read-only"));
898 
899  if (trace_tdesc.used_size == 0)
900  return TARGET_XFER_E_IO;
901 
903  return TARGET_XFER_EOF;
904 
905  if (len > trace_tdesc.used_size - offset)
906  len = trace_tdesc.used_size - offset;
907 
908  memcpy (readbuf, trace_tdesc.buffer + offset, len);
909  *xfered_len = len;
910 
911  return TARGET_XFER_OK;
912 }
913 
914 static enum target_xfer_status
915 tfile_xfer_partial (struct target_ops *ops, enum target_object object,
916  const char *annex, gdb_byte *readbuf,
917  const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
918  ULONGEST *xfered_len)
919 {
920  /* We're only doing regular memory and tdesc for now. */
921  if (object == TARGET_OBJECT_AVAILABLE_FEATURES)
922  return tfile_xfer_partial_features (ops, annex, readbuf, writebuf,
923  offset, len, xfered_len);
924  if (object != TARGET_OBJECT_MEMORY)
925  return TARGET_XFER_E_IO;
926 
927  if (readbuf == NULL)
928  error (_("tfile_xfer_partial: trace file is read-only"));
929 
930  if (get_traceframe_number () != -1)
931  {
932  int pos = 0;
933  enum target_xfer_status res;
934  /* Records the lowest available address of all blocks that
935  intersects the requested range. */
936  ULONGEST low_addr_available = 0;
937 
938  /* Iterate through the traceframe's blocks, looking for
939  memory. */
940  while ((pos = traceframe_find_block_type ('M', pos)) >= 0)
941  {
942  ULONGEST maddr, amt;
943  unsigned short mlen;
944  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
945 
946  tfile_read ((gdb_byte *) &maddr, 8);
947  maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
948  byte_order);
949  tfile_read ((gdb_byte *) &mlen, 2);
950  mlen = (unsigned short)
952 
953  /* If the block includes the first part of the desired
954  range, return as much it has; GDB will re-request the
955  remainder, which might be in a different block of this
956  trace frame. */
957  if (maddr <= offset && offset < (maddr + mlen))
958  {
959  amt = (maddr + mlen) - offset;
960  if (amt > len)
961  amt = len;
962 
963  if (maddr != offset)
964  lseek (trace_fd, offset - maddr, SEEK_CUR);
965  tfile_read (readbuf, amt);
966  *xfered_len = amt;
967  return TARGET_XFER_OK;
968  }
969 
970  if (offset < maddr && maddr < (offset + len))
971  if (low_addr_available == 0 || low_addr_available > maddr)
972  low_addr_available = maddr;
973 
974  /* Skip over this block. */
975  pos += (8 + 2 + mlen);
976  }
977 
978  /* Requested memory is unavailable in the context of traceframes,
979  and this address falls within a read-only section, fallback
980  to reading from executable, up to LOW_ADDR_AVAILABLE. */
981  if (offset < low_addr_available)
982  len = std::min (len, low_addr_available - offset);
983  res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
984 
985  if (res == TARGET_XFER_OK)
986  return TARGET_XFER_OK;
987  else
988  {
989  /* No use trying further, we know some memory starting
990  at MEMADDR isn't available. */
991  *xfered_len = len;
993  }
994  }
995  else
996  {
997  /* Fallback to reading from read-only sections. */
998  return section_table_read_available_memory (readbuf, offset, len,
999  xfered_len);
1000  }
1001 }
1002 
1003 /* Iterate through the blocks of a trace frame, looking for a 'V'
1004  block with a matching tsv number. */
1005 
1006 static int
1008  int tsvnum, LONGEST *val)
1009 {
1010  int pos;
1011  int found = 0;
1012 
1013  /* Iterate over blocks in current frame and find the last 'V'
1014  block in which tsv number is TSVNUM. In one trace frame, there
1015  may be multiple 'V' blocks created for a given trace variable,
1016  and the last matched 'V' block contains the updated value. */
1017  pos = 0;
1018  while ((pos = traceframe_find_block_type ('V', pos)) >= 0)
1019  {
1020  int vnum;
1021 
1022  tfile_read ((gdb_byte *) &vnum, 4);
1023  vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
1025  (target_gdbarch ()));
1026  if (tsvnum == vnum)
1027  {
1028  tfile_read ((gdb_byte *) val, 8);
1029  *val = extract_signed_integer ((gdb_byte *) val, 8,
1031  (target_gdbarch ()));
1032  found = 1;
1033  }
1034  pos += (4 + 8);
1035  }
1036 
1037  return found;
1038 }
1039 
1040 /* Callback for traceframe_walk_blocks. Builds a traceframe_info
1041  object for the tfile target's current traceframe. */
1042 
1043 static int
1044 build_traceframe_info (char blocktype, void *data)
1045 {
1046  struct traceframe_info *info = (struct traceframe_info *) data;
1047 
1048  switch (blocktype)
1049  {
1050  case 'M':
1051  {
1052  ULONGEST maddr;
1053  unsigned short mlen;
1054 
1055  tfile_read ((gdb_byte *) &maddr, 8);
1056  maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
1058  (target_gdbarch ()));
1059  tfile_read ((gdb_byte *) &mlen, 2);
1060  mlen = (unsigned short)
1063  (target_gdbarch ()));
1064 
1065  info->memory.emplace_back (maddr, mlen);
1066  break;
1067  }
1068  case 'V':
1069  {
1070  int vnum;
1071 
1072  tfile_read ((gdb_byte *) &vnum, 4);
1073  info->tvars.push_back (vnum);
1074  }
1075  case 'R':
1076  case 'S':
1077  {
1078  break;
1079  }
1080  default:
1081  warning (_("Unhandled trace block type (%d) '%c ' "
1082  "while building trace frame info."),
1083  blocktype, blocktype);
1084  break;
1085  }
1086 
1087  return 0;
1088 }
1089 
1090 static traceframe_info_up
1092 {
1094 
1096 
1097  return info;
1098 }
1099 
1100 /* Handles tdesc lines from tfile by appending the payload to
1101  a global trace_tdesc variable. */
1102 
1103 static void
1104 tfile_append_tdesc_line (const char *line)
1105 {
1106  buffer_grow_str (&trace_tdesc, line);
1107  buffer_grow_str (&trace_tdesc, "\n");
1108 }
1109 
1110 static void
1112 {
1114 
1115  tfile_ops.to_shortname = "tfile";
1116  tfile_ops.to_longname = "Local trace dump file";
1118  = "Use a trace file as a target. Specify the filename of the trace file.";
1129 }
1130 
1131 void
1133 {
1134  init_tfile_ops ();
1135 
1137 }
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5467
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t err
Definition: gnu-nat.c:1822
static CORE_ADDR tfile_get_traceframe_address(off_t tframe_offset)
ssize_t read(int fd, void *buf, size_t count)
Definition: expect-read1.c:26
std::vector< mem_range > memory
Definition: tracepoint.h:34
bp_location * loc
Definition: breakpoint.h:702
static off_t trace_frames_offset
int trace_regblock_size
const char * to_longname
Definition: target.h:416
static off_t cur_offset
static void tfile_dtor(struct trace_file_writer *self)
#define MAX_TRACE_UPLOAD
void post_create_inferior(struct target_ops *target, int from_tty)
Definition: infcmd.c:435
bfd_vma CORE_ADDR
Definition: common-types.h:41
static int tfile_get_trace_state_variable_value(struct target_ops *self, int tsvnum, LONGEST *val)
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
LONGEST initial_value
Definition: tracepoint.h:208
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
Definition: gnu-nat.c:1824
void xfree(void *)
static void tfile_write_uploaded_tsv(struct trace_file_writer *self, struct uploaded_tsv *utsv)
static int tfile_trace_find(struct target_ops *self, enum trace_find_type type, int num, CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
const struct trace_file_write_ops * ops
Definition: tracefile.h:111
void warning(const char *fmt,...)
Definition: errors.c:26
static void tfile_append_tdesc_line(const char *line)
void push_target(struct target_ops *t)
Definition: target.c:642
int bin2hex(const gdb_byte *bin, char *hex, int count)
Definition: rsp-low.c:173
std::vector< int > tvars
Definition: tracepoint.h:37
int circular_buffer
Definition: tracepoint.h:137
void buffer_free(struct buffer *buffer)
Definition: buffer.c:48
static void tfile_close(struct target_ops *self)
int unpush_target(struct target_ops *t)
Definition: target.c:689
void internal_error(const char *file, int line, const char *fmt,...)
Definition: errors.c:50
char * buffer
Definition: buffer.h:25
void(* to_close)(struct target_ops *)
Definition: target.h:431
int traceframes_created
Definition: tracepoint.h:119
static int match_blocktype(char blocktype, void *data)
void filename_completer(struct cmd_list_element *ignore, completion_tracker &tracker, const char *text, const char *word)
Definition: completer.c:152
static void tfile_write_regblock_type(struct trace_file_writer *self, int size)
const breakpoint_ops * ops
Definition: breakpoint.h:689
int gdbarch_num_regs(struct gdbarch *gdbarch)
Definition: gdbarch.c:2039
struct tracepoint * get_tracepoint(int num)
Definition: breakpoint.c:15018
#define _(String)
Definition: gdb_locale.h:35
ULONGEST traceframe_usage
Definition: tracepoint.h:197
static void tfile_read(gdb_byte *readbuf, int size)
char * char_ptr
Definition: gdb_vecs.h:25
static struct buffer trace_tdesc
size_t used_size
Definition: buffer.h:27
#define END_CATCH
LONGEST stop_time
Definition: tracepoint.h:153
int(* to_get_trace_state_variable_value)(struct target_ops *, int tsv, LONGEST *val) TARGET_DEFAULT_RETURN(0)
Definition: target.h:1013
void printf_filtered(const char *format,...)
Definition: utils.c:2045
#define XNEW(T)
Definition: poison.h:109
trace_find_type
Definition: tracepoint.h:384
void(* to_files_info)(struct target_ops *) TARGET_DEFAULT_IGNORE()
Definition: target.h:464
struct trace_status * current_trace_status(void)
Definition: tracepoint.c:189
char * at_string
Definition: tracepoint.h:185
mach_port_t kern_return_t mach_port_t msgports mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition: gnu-nat.c:1891
static void tfile_files_info(struct target_ops *t)
#define TRY
static void tfile_get_tracepoint_status(struct target_ops *self, struct breakpoint *tp, struct uploaded_tp *utp)
#define VEC_iterate(T, V, I, P)
Definition: vec.h:181
struct tracepoint * get_tracepoint_by_number_on_target(int num)
Definition: breakpoint.c:15034
enum bptype type
Definition: tracepoint.h:169
#define CATCH(EXCEPTION, MASK)
void merge_uploaded_tracepoints(struct uploaded_tp **uploaded_tps)
Definition: tracepoint.c:3176
static struct target_ops tfile_ops
std::unique_ptr< T, xfree_deleter< T > > unique_xmalloc_ptr
static void tfile_write_definition_end(struct trace_file_writer *self)
struct target_ops current_target
#define O_LARGEFILE
int(* to_trace_find)(struct target_ops *, enum trace_find_type type, int num, CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) TARGET_DEFAULT_RETURN(-1)
Definition: target.h:1005
char * cond_string
Definition: tracepoint.h:188
void merge_uploaded_trace_state_variables(struct uploaded_tsv **uploaded_tsvs)
Definition: tracepoint.c:3299
struct trace_file_writer base
static enum target_xfer_status tfile_xfer_partial_features(struct target_ops *ops, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
const char * name
Definition: tracepoint.h:206
static ULONGEST extract_unsigned_integer(const gdb_byte *addr, int len, enum bfd_endian byte_order)
Definition: defs.h:577
static void tfile_interp_line(char *line, struct uploaded_tp **utpp, struct uploaded_tsv **utsvp)
static int tfile_target_save(struct trace_file_writer *self, const char *filename)
#define target_save_trace_data(filename)
Definition: target.h:2169
void trace_reset_local_state(void)
Definition: tracepoint.c:1563
static int cur_data_size
enum trace_stop_reason stop_reason
Definition: tracepoint.h:100
block_type
Definition: mdebugread.c:235
ptid_t pid_to_ptid(int pid)
Definition: ptid.c:39
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition: gdbarch.c:1509
void init_tracefile_ops(struct target_ops *ops)
Definition: tracefile.c:486
int get_traceframe_number(void)
Definition: tracepoint.c:2976
void parse_trace_status(const char *line, struct trace_status *ts)
Definition: tracepoint.c:3352
target_xfer_status
Definition: target.h:206
void add_target_with_completer(struct target_ops *t, completer_ftype *completer)
Definition: target.c:368
void _initialize_tracefile_tfile(void)
Definition: gdbtypes.h:749
const char * filename
Definition: tracepoint.h:92
enum target_xfer_status exec_read_partial_read_only(gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
Definition: exec.c:650
static void tfile_write_tdesc(struct trace_file_writer *self)
static void tfile_fetch_registers(struct target_ops *ops, struct regcache *regcache, int regno)
void(* to_get_tracepoint_status)(struct target_ops *, struct breakpoint *tp, struct uploaded_tp *utp) TARGET_DEFAULT_NORETURN(tcomplain())
Definition: target.h:991
char * user_name
Definition: tracepoint.h:142
int number_on_target
Definition: breakpoint.h:885
unsigned dummy
Definition: go32-nat.c:1073
gdb_file_up gdb_fopen_cloexec(const char *filename, const char *opentype)
Definition: filestuff.c:296
static void tfile_open(const char *arg, int from_tty)
const char * to_doc
Definition: target.h:417
static int startswith(const char *string, const char *pattern)
Definition: common-utils.h:107
int stopping_tracepoint
Definition: tracepoint.h:105
struct thread_info * add_thread_silent(ptid_t ptid)
Definition: thread.c:266
enum target_xfer_status(* to_xfer_partial)(struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) TARGET_DEFAULT_RETURN(TARGET_XFER_E_IO)
Definition: target.h:739
static void tfile_write_header(struct trace_file_writer *self)
traceframe_info_up(* to_traceframe_info)(struct target_ops *) TARGET_DEFAULT_NORETURN(tcomplain())
Definition: target.h:1099
#define buffer_grow_str(BUFFER, STRING)
Definition: buffer.h:63
static void tfile_write_uploaded_tp(struct trace_file_writer *self, struct uploaded_tp *utp)
void * xmalloc(YYSIZE_T)
const char * stop_reason_names[]
enum target_xfer_status section_table_read_available_memory(gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
Definition: exec.c:736
target_object
Definition: target.h:132
static int traceframe_find_block_type(char type_wanted, int pos)
static void tfile_end(struct trace_file_writer *self)
gdb::optional< std::string > target_fetch_description_xml(struct target_ops *ops)
Definition: xml-tdesc.c:725
int(* walk_blocks_callback_func)(char blocktype, void *data)
CORE_ADDR address
Definition: breakpoint.h:427
static int trace_fd
int running_known
Definition: tracepoint.h:95
char * stop_desc
Definition: tracepoint.h:111
char * current_directory
Definition: top.c:133
void throw_exception(struct gdb_exception exception)
bfd_byte gdb_byte
Definition: common-types.h:38
static void init_tfile_ops(void)
int traceframe_count
Definition: tracepoint.h:115
char * notes
Definition: tracepoint.h:147
std::unique_ptr< traceframe_info > traceframe_info_up
Definition: tracepoint.h:40
#define O_BINARY
Definition: defs.h:106
void tracefile_fetch_registers(struct regcache *regcache, int regno)
Definition: tracefile.c:388
ptid_t null_ptid
Definition: ptid.c:25
void(* to_fetch_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE()
Definition: target.h:457
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, ULONGEST len, ULONGEST *xfered_len)
void void void void void void void void void perror_with_name(const char *string) ATTRIBUTE_NORETURN
Definition: utils.c:692
int encode_source_string(int tpnum, ULONGEST addr, const char *srctype, const char *src, char *buf, int buf_size)
Definition: tracepoint.c:2875
enum register_status regcache_register_status(const struct regcache *regcache, int regnum)
Definition: regcache.c:359
#define TFILE_PID
#define SEEK_SET
Definition: defs.h:93
ptid_t inferior_ptid
Definition: infcmd.c:94
char * cond
Definition: tracepoint.h:177
char * safe_strerror(int)
static const struct trace_file_write_ops tfile_write_ops
int disconnected_tracing
Definition: tracepoint.h:132
void(* to_open)(const char *, int)
Definition: target.h:426
int offset
Definition: agent.c:65
Definition: buffer.h:23
gdbarch * arch() const
Definition: regcache.c:221
void parse_tsv_definition(const char *line, struct uploaded_tsv **utsvp)
Definition: tracepoint.c:3651
static LONGEST extract_signed_integer(const gdb_byte *addr, int len, enum bfd_endian byte_order)
Definition: defs.h:570
static int build_traceframe_info(char blocktype, void *data)
ULONGEST addr
Definition: tracepoint.h:170
static void tfile_start(struct trace_file_writer *self, const char *filename)
void ** data
Definition: gdbarch.c:148
int gdb_open_cloexec(const char *filename, int flags, unsigned long mode)
Definition: filestuff.c:283
static char * trace_filename
struct inferior * current_inferior(void)
Definition: inferior.c:58
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1004
const char * to_shortname
Definition: target.h:415
unsigned long long ULONGEST
Definition: common-types.h:53
void exit_inferior_silent(int pid)
Definition: inferior.c:241
int register_size(struct gdbarch *gdbarch, int regnum)
Definition: regcache.c:164
#define SEEK_CUR
Definition: defs.h:96
static traceframe_info_up tfile_traceframe_info(struct target_ops *self)
int remote_register_number_and_offset(struct gdbarch *gdbarch, int regnum, int *pnum, int *poffset)
Definition: remote.c:794
struct trace_file_writer * tfile_trace_file_writer_new(void)
void target_preopen(int from_tty)
Definition: target.c:2121
void target_find_description(void)
enum bfd_endian byte_order
Definition: gdbarch.c:137
void error(const char *fmt,...)
Definition: errors.c:38
size_t size
Definition: go32-nat.c:242
void parse_tracepoint_definition(const char *line, struct uploaded_tp **utpp)
Definition: tracepoint.c:3535
static int traceframe_walk_blocks(walk_blocks_callback_func callback, int pos, void *data)
static void tfile_write_raw_data(struct trace_file_writer *self, gdb_byte *buf, LONGEST len)
long long LONGEST
Definition: common-types.h:52
void inferior_appeared(struct inferior *inf, int pid)
Definition: inferior.c:268
static void tfile_write_status(struct trace_file_writer *self, struct trace_status *ts)
#define TRACE_HEADER_SIZE
LONGEST start_time
Definition: tracepoint.h:152