1 /* Trace file TFILE format support in GDB.
3 Copyright (C) 1997-2016 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "tracefile.h"
22 #include "readline/tilde.h"
23 #include "filestuff.h"
24 #include "rsp-low.h" /* bin2hex */
27 #include "gdbthread.h"
28 #include "exec.h" /* exec_bfd */
29 #include "completer.h"
30 #include "filenames.h"
32 #include "xml-tdesc.h"
38 /* TFILE trace writer. */
40 struct tfile_trace_file_writer
42 struct trace_file_writer base
;
44 /* File pointer to tfile trace file. */
46 /* Path name of the tfile trace file. */
50 /* This is the implementation of trace_file_write_ops method
51 target_save. We just call the generic target
52 target_save_trace_data to do target-side saving. */
55 tfile_target_save (struct trace_file_writer
*self
,
58 int err
= target_save_trace_data (filename
);
63 /* This is the implementation of trace_file_write_ops method
67 tfile_dtor (struct trace_file_writer
*self
)
69 struct tfile_trace_file_writer
*writer
70 = (struct tfile_trace_file_writer
*) self
;
72 xfree (writer
->pathname
);
74 if (writer
->fp
!= NULL
)
78 /* This is the implementation of trace_file_write_ops method
79 start. It creates the trace file FILENAME and registers some
83 tfile_start (struct trace_file_writer
*self
, const char *filename
)
85 struct tfile_trace_file_writer
*writer
86 = (struct tfile_trace_file_writer
*) self
;
88 writer
->pathname
= tilde_expand (filename
);
89 writer
->fp
= gdb_fopen_cloexec (writer
->pathname
, "wb");
90 if (writer
->fp
== NULL
)
91 error (_("Unable to open file '%s' for saving trace data (%s)"),
92 writer
->pathname
, safe_strerror (errno
));
95 /* This is the implementation of trace_file_write_ops method
96 write_header. Write the TFILE header. */
99 tfile_write_header (struct trace_file_writer
*self
)
101 struct tfile_trace_file_writer
*writer
102 = (struct tfile_trace_file_writer
*) self
;
105 /* Write a file header, with a high-bit-set char to indicate a
106 binary file, plus a hint as what this file is, and a version
107 number in case of future needs. */
108 written
= fwrite ("\x7fTRACE0\n", 8, 1, writer
->fp
);
110 perror_with_name (writer
->pathname
);
113 /* This is the implementation of trace_file_write_ops method
114 write_regblock_type. Write the size of register block. */
117 tfile_write_regblock_type (struct trace_file_writer
*self
, int size
)
119 struct tfile_trace_file_writer
*writer
120 = (struct tfile_trace_file_writer
*) self
;
122 fprintf (writer
->fp
, "R %x\n", size
);
125 /* This is the implementation of trace_file_write_ops method
129 tfile_write_status (struct trace_file_writer
*self
,
130 struct trace_status
*ts
)
132 struct tfile_trace_file_writer
*writer
133 = (struct tfile_trace_file_writer
*) self
;
135 fprintf (writer
->fp
, "status %c;%s",
136 (ts
->running
? '1' : '0'), stop_reason_names
[ts
->stop_reason
]);
137 if (ts
->stop_reason
== tracepoint_error
138 || ts
->stop_reason
== tstop_command
)
140 char *buf
= (char *) alloca (strlen (ts
->stop_desc
) * 2 + 1);
142 bin2hex ((gdb_byte
*) ts
->stop_desc
, buf
, strlen (ts
->stop_desc
));
143 fprintf (writer
->fp
, ":%s", buf
);
145 fprintf (writer
->fp
, ":%x", ts
->stopping_tracepoint
);
146 if (ts
->traceframe_count
>= 0)
147 fprintf (writer
->fp
, ";tframes:%x", ts
->traceframe_count
);
148 if (ts
->traceframes_created
>= 0)
149 fprintf (writer
->fp
, ";tcreated:%x", ts
->traceframes_created
);
150 if (ts
->buffer_free
>= 0)
151 fprintf (writer
->fp
, ";tfree:%x", ts
->buffer_free
);
152 if (ts
->buffer_size
>= 0)
153 fprintf (writer
->fp
, ";tsize:%x", ts
->buffer_size
);
154 if (ts
->disconnected_tracing
)
155 fprintf (writer
->fp
, ";disconn:%x", ts
->disconnected_tracing
);
156 if (ts
->circular_buffer
)
157 fprintf (writer
->fp
, ";circular:%x", ts
->circular_buffer
);
160 fprintf (writer
->fp
, ";starttime:%s",
161 phex_nz (ts
->start_time
, sizeof (ts
->start_time
)));
165 fprintf (writer
->fp
, ";stoptime:%s",
166 phex_nz (ts
->stop_time
, sizeof (ts
->stop_time
)));
168 if (ts
->notes
!= NULL
)
170 char *buf
= (char *) alloca (strlen (ts
->notes
) * 2 + 1);
172 bin2hex ((gdb_byte
*) ts
->notes
, buf
, strlen (ts
->notes
));
173 fprintf (writer
->fp
, ";notes:%s", buf
);
175 if (ts
->user_name
!= NULL
)
177 char *buf
= (char *) alloca (strlen (ts
->user_name
) * 2 + 1);
179 bin2hex ((gdb_byte
*) ts
->user_name
, buf
, strlen (ts
->user_name
));
180 fprintf (writer
->fp
, ";username:%s", buf
);
182 fprintf (writer
->fp
, "\n");
185 /* This is the implementation of trace_file_write_ops method
186 write_uploaded_tsv. */
189 tfile_write_uploaded_tsv (struct trace_file_writer
*self
,
190 struct uploaded_tsv
*utsv
)
193 struct tfile_trace_file_writer
*writer
194 = (struct tfile_trace_file_writer
*) self
;
198 buf
= (char *) xmalloc (strlen (utsv
->name
) * 2 + 1);
199 bin2hex ((gdb_byte
*) (utsv
->name
), buf
, strlen (utsv
->name
));
202 fprintf (writer
->fp
, "tsv %x:%s:%x:%s\n",
203 utsv
->number
, phex_nz (utsv
->initial_value
, 8),
210 #define MAX_TRACE_UPLOAD 2000
212 /* This is the implementation of trace_file_write_ops method
213 write_uploaded_tp. */
216 tfile_write_uploaded_tp (struct trace_file_writer
*self
,
217 struct uploaded_tp
*utp
)
219 struct tfile_trace_file_writer
*writer
220 = (struct tfile_trace_file_writer
*) self
;
223 char buf
[MAX_TRACE_UPLOAD
];
225 fprintf (writer
->fp
, "tp T%x:%s:%c:%x:%x",
226 utp
->number
, phex_nz (utp
->addr
, sizeof (utp
->addr
)),
227 (utp
->enabled
? 'E' : 'D'), utp
->step
, utp
->pass
);
228 if (utp
->type
== bp_fast_tracepoint
)
229 fprintf (writer
->fp
, ":F%x", utp
->orig_size
);
232 ":X%x,%s", (unsigned int) strlen (utp
->cond
) / 2,
234 fprintf (writer
->fp
, "\n");
235 for (a
= 0; VEC_iterate (char_ptr
, utp
->actions
, a
, act
); ++a
)
236 fprintf (writer
->fp
, "tp A%x:%s:%s\n",
237 utp
->number
, phex_nz (utp
->addr
, sizeof (utp
->addr
)), act
);
238 for (a
= 0; VEC_iterate (char_ptr
, utp
->step_actions
, a
, act
); ++a
)
239 fprintf (writer
->fp
, "tp S%x:%s:%s\n",
240 utp
->number
, phex_nz (utp
->addr
, sizeof (utp
->addr
)), act
);
243 encode_source_string (utp
->number
, utp
->addr
,
244 "at", utp
->at_string
, buf
, MAX_TRACE_UPLOAD
);
245 fprintf (writer
->fp
, "tp Z%s\n", buf
);
247 if (utp
->cond_string
)
249 encode_source_string (utp
->number
, utp
->addr
,
250 "cond", utp
->cond_string
,
251 buf
, MAX_TRACE_UPLOAD
);
252 fprintf (writer
->fp
, "tp Z%s\n", buf
);
254 for (a
= 0; VEC_iterate (char_ptr
, utp
->cmd_strings
, a
, act
); ++a
)
256 encode_source_string (utp
->number
, utp
->addr
, "cmd", act
,
257 buf
, MAX_TRACE_UPLOAD
);
258 fprintf (writer
->fp
, "tp Z%s\n", buf
);
260 fprintf (writer
->fp
, "tp V%x:%s:%x:%s\n",
261 utp
->number
, phex_nz (utp
->addr
, sizeof (utp
->addr
)),
263 phex_nz (utp
->traceframe_usage
,
264 sizeof (utp
->traceframe_usage
)));
267 /* This is the implementation of trace_file_write_ops method
271 tfile_write_tdesc (struct trace_file_writer
*self
)
273 struct tfile_trace_file_writer
*writer
274 = (struct tfile_trace_file_writer
*) self
;
275 char *tdesc
= target_fetch_description_xml (¤t_target
);
282 /* Write tdesc line by line, prefixing each line with "tdesc ". */
285 next
= strchr (ptr
, '\n');
288 fprintf (writer
->fp
, "tdesc %.*s\n", (int) (next
- ptr
), ptr
);
292 else if (*ptr
!= '\0')
294 /* Last line, doesn't have a newline. */
295 fprintf (writer
->fp
, "tdesc %s\n", ptr
);
303 /* This is the implementation of trace_file_write_ops method
304 write_definition_end. */
307 tfile_write_definition_end (struct trace_file_writer
*self
)
309 struct tfile_trace_file_writer
*writer
310 = (struct tfile_trace_file_writer
*) self
;
312 fprintf (writer
->fp
, "\n");
315 /* This is the implementation of trace_file_write_ops method
319 tfile_write_raw_data (struct trace_file_writer
*self
, gdb_byte
*buf
,
322 struct tfile_trace_file_writer
*writer
323 = (struct tfile_trace_file_writer
*) self
;
325 if (fwrite (buf
, len
, 1, writer
->fp
) < 1)
326 perror_with_name (writer
->pathname
);
329 /* This is the implementation of trace_file_write_ops method
333 tfile_end (struct trace_file_writer
*self
)
335 struct tfile_trace_file_writer
*writer
336 = (struct tfile_trace_file_writer
*) self
;
339 /* Mark the end of trace data. */
340 if (fwrite (&gotten
, 4, 1, writer
->fp
) < 1)
341 perror_with_name (writer
->pathname
);
344 /* Operations to write trace buffers into TFILE format. */
346 static const struct trace_file_write_ops tfile_write_ops
=
352 tfile_write_regblock_type
,
354 tfile_write_uploaded_tsv
,
355 tfile_write_uploaded_tp
,
357 tfile_write_definition_end
,
358 tfile_write_raw_data
,
363 /* Return a trace writer for TFILE format. */
365 struct trace_file_writer
*
366 tfile_trace_file_writer_new (void)
368 struct tfile_trace_file_writer
*writer
369 = XNEW (struct tfile_trace_file_writer
);
371 writer
->base
.ops
= &tfile_write_ops
;
373 writer
->pathname
= NULL
;
375 return (struct trace_file_writer
*) writer
;
378 /* target tfile command */
380 static struct target_ops tfile_ops
;
382 /* Fill in tfile_ops with its defined operations and properties. */
384 #define TRACE_HEADER_SIZE 8
386 #define TFILE_PID (1)
388 static char *trace_filename
;
389 static int trace_fd
= -1;
390 static off_t trace_frames_offset
;
391 static off_t cur_offset
;
392 static int cur_data_size
;
393 int trace_regblock_size
;
395 static void tfile_interp_line (char *line
,
396 struct uploaded_tp
**utpp
,
397 struct uploaded_tsv
**utsvp
);
399 /* Read SIZE bytes into READBUF from the trace frame, starting at
400 TRACE_FD's current position. Note that this call `read'
401 underneath, hence it advances the file's seek position. Throws an
402 error if the `read' syscall fails, or less than SIZE bytes are
406 tfile_read (gdb_byte
*readbuf
, int size
)
410 gotten
= read (trace_fd
, readbuf
, size
);
412 perror_with_name (trace_filename
);
413 else if (gotten
< size
)
414 error (_("Premature end of file while reading trace file"));
418 tfile_open (const char *arg
, int from_tty
)
421 struct cleanup
*old_chain
;
424 char header
[TRACE_HEADER_SIZE
];
425 char linebuf
[1000]; /* Should be max remote packet size or so. */
428 struct trace_status
*ts
;
429 struct uploaded_tp
*uploaded_tps
= NULL
;
430 struct uploaded_tsv
*uploaded_tsvs
= NULL
;
433 target_preopen (from_tty
);
435 error (_("No trace file specified."));
437 filename
= tilde_expand (arg
);
438 if (!IS_ABSOLUTE_PATH(filename
))
440 temp
= concat (current_directory
, "/", filename
, (char *) NULL
);
445 old_chain
= make_cleanup (xfree
, filename
);
447 flags
= O_BINARY
| O_LARGEFILE
;
449 scratch_chan
= gdb_open_cloexec (filename
, flags
, 0);
450 if (scratch_chan
< 0)
451 perror_with_name (filename
);
453 /* Looks semi-reasonable. Toss the old trace file and work on the new. */
455 discard_cleanups (old_chain
); /* Don't free filename any more. */
456 unpush_target (&tfile_ops
);
458 trace_filename
= xstrdup (filename
);
459 trace_fd
= scratch_chan
;
462 /* Read the file header and test for validity. */
463 tfile_read ((gdb_byte
*) &header
, TRACE_HEADER_SIZE
);
465 bytes
+= TRACE_HEADER_SIZE
;
466 if (!(header
[0] == 0x7f
467 && (startswith (header
+ 1, "TRACE0\n"))))
468 error (_("File is not a valid trace file."));
470 push_target (&tfile_ops
);
472 trace_regblock_size
= 0;
473 ts
= current_trace_status ();
474 /* We know we're working with a file. Record its name. */
475 ts
->filename
= trace_filename
;
476 /* Set defaults in case there is no status line. */
477 ts
->running_known
= 0;
478 ts
->stop_reason
= trace_stop_reason_unknown
;
479 ts
->traceframe_count
= -1;
481 ts
->disconnected_tracing
= 0;
482 ts
->circular_buffer
= 0;
486 /* Read through a section of newline-terminated lines that
487 define things like tracepoints. */
491 tfile_read (&byte
, 1);
496 /* Empty line marks end of the definition section. */
501 tfile_interp_line (linebuf
, &uploaded_tps
, &uploaded_tsvs
);
506 error (_("Excessively long lines in trace file"));
509 /* Record the starting offset of the binary trace data. */
510 trace_frames_offset
= bytes
;
512 /* If we don't have a blocksize, we can't interpret the
514 if (trace_regblock_size
== 0)
515 error (_("No register block size recorded in trace file"));
517 CATCH (ex
, RETURN_MASK_ALL
)
519 /* Remove the partially set up target. */
520 unpush_target (&tfile_ops
);
521 throw_exception (ex
);
525 inferior_appeared (current_inferior (), TFILE_PID
);
526 inferior_ptid
= pid_to_ptid (TFILE_PID
);
527 add_thread_silent (inferior_ptid
);
529 if (ts
->traceframe_count
<= 0)
530 warning (_("No traceframes present in this file."));
532 /* Add the file's tracepoints and variables into the current mix. */
534 /* Get trace state variables first, they may be checked when parsing
535 uploaded commands. */
536 merge_uploaded_trace_state_variables (&uploaded_tsvs
);
538 merge_uploaded_tracepoints (&uploaded_tps
);
540 post_create_inferior (&tfile_ops
, from_tty
);
543 /* Interpret the given line from the definitions part of the trace
547 tfile_interp_line (char *line
, struct uploaded_tp
**utpp
,
548 struct uploaded_tsv
**utsvp
)
552 if (startswith (p
, "R "))
555 trace_regblock_size
= strtol (p
, &p
, 16);
557 else if (startswith (p
, "status "))
559 p
+= strlen ("status ");
560 parse_trace_status (p
, current_trace_status ());
562 else if (startswith (p
, "tp "))
565 parse_tracepoint_definition (p
, utpp
);
567 else if (startswith (p
, "tsv "))
569 p
+= strlen ("tsv ");
570 parse_tsv_definition (p
, utsvp
);
573 warning (_("Ignoring trace file definition \"%s\""), line
);
576 /* Close the trace file and generally clean up. */
579 tfile_close (struct target_ops
*self
)
586 pid
= ptid_get_pid (inferior_ptid
);
587 inferior_ptid
= null_ptid
; /* Avoid confusion from thread stuff. */
588 exit_inferior_silent (pid
);
592 xfree (trace_filename
);
593 trace_filename
= NULL
;
595 trace_reset_local_state ();
599 tfile_files_info (struct target_ops
*t
)
601 printf_filtered ("\t`%s'\n", trace_filename
);
605 tfile_get_tracepoint_status (struct target_ops
*self
,
606 struct breakpoint
*tp
, struct uploaded_tp
*utp
)
608 /* Other bits of trace status were collected as part of opening the
609 trace files, so nothing to do here. */
612 /* Given the position of a traceframe in the file, figure out what
613 address the frame was collected at. This would normally be the
614 value of a collected PC register, but if not available, we
618 tfile_get_traceframe_address (off_t tframe_offset
)
622 struct tracepoint
*tp
;
623 off_t saved_offset
= cur_offset
;
625 /* FIXME dig pc out of collected registers. */
627 /* Fall back to using tracepoint address. */
628 lseek (trace_fd
, tframe_offset
, SEEK_SET
);
629 tfile_read ((gdb_byte
*) &tpnum
, 2);
630 tpnum
= (short) extract_signed_integer ((gdb_byte
*) &tpnum
, 2,
632 (target_gdbarch ()));
634 tp
= get_tracepoint_by_number_on_target (tpnum
);
635 /* FIXME this is a poor heuristic if multiple locations. */
636 if (tp
&& tp
->base
.loc
)
637 addr
= tp
->base
.loc
->address
;
639 /* Restore our seek position. */
640 cur_offset
= saved_offset
;
641 lseek (trace_fd
, cur_offset
, SEEK_SET
);
645 /* Given a type of search and some parameters, scan the collection of
646 traceframes in the file looking for a match. When found, return
647 both the traceframe and tracepoint number, otherwise -1 for
651 tfile_trace_find (struct target_ops
*self
, enum trace_find_type type
, int num
,
652 CORE_ADDR addr1
, CORE_ADDR addr2
, int *tpp
)
655 int tfnum
= 0, found
= 0;
656 unsigned int data_size
;
657 struct tracepoint
*tp
;
658 off_t offset
, tframe_offset
;
668 lseek (trace_fd
, trace_frames_offset
, SEEK_SET
);
669 offset
= trace_frames_offset
;
672 tframe_offset
= offset
;
673 tfile_read ((gdb_byte
*) &tpnum
, 2);
674 tpnum
= (short) extract_signed_integer ((gdb_byte
*) &tpnum
, 2,
676 (target_gdbarch ()));
680 tfile_read ((gdb_byte
*) &data_size
, 4);
681 data_size
= (unsigned int) extract_unsigned_integer
682 ((gdb_byte
*) &data_size
, 4,
683 gdbarch_byte_order (target_gdbarch ()));
686 if (type
== tfind_number
)
688 /* Looking for a specific trace frame. */
694 /* Start from the _next_ trace frame. */
695 if (tfnum
> get_traceframe_number ())
700 tfaddr
= tfile_get_traceframe_address (tframe_offset
);
705 tp
= get_tracepoint (num
);
706 if (tp
&& tpnum
== tp
->number_on_target
)
710 tfaddr
= tfile_get_traceframe_address (tframe_offset
);
711 if (addr1
<= tfaddr
&& tfaddr
<= addr2
)
715 tfaddr
= tfile_get_traceframe_address (tframe_offset
);
716 if (!(addr1
<= tfaddr
&& tfaddr
<= addr2
))
720 internal_error (__FILE__
, __LINE__
, _("unknown tfind type"));
730 cur_data_size
= data_size
;
734 /* Skip past the traceframe's data. */
735 lseek (trace_fd
, data_size
, SEEK_CUR
);
737 /* Update our own count of traceframes. */
740 /* Did not find what we were looking for. */
746 /* Prototype of the callback passed to tframe_walk_blocks. */
747 typedef int (*walk_blocks_callback_func
) (char blocktype
, void *data
);
749 /* Callback for traceframe_walk_blocks, used to find a given block
750 type in a traceframe. */
753 match_blocktype (char blocktype
, void *data
)
755 char *wantedp
= (char *) data
;
757 if (*wantedp
== blocktype
)
763 /* Walk over all traceframe block starting at POS offset from
764 CUR_OFFSET, and call CALLBACK for each block found, passing in DATA
765 unmodified. If CALLBACK returns true, this returns the position in
766 the traceframe where the block is found, relative to the start of
767 the traceframe (cur_offset). Returns -1 if no callback call
768 returned true, indicating that all blocks have been walked. */
771 traceframe_walk_blocks (walk_blocks_callback_func callback
,
774 /* Iterate through a traceframe's blocks, looking for a block of the
777 lseek (trace_fd
, cur_offset
+ pos
, SEEK_SET
);
778 while (pos
< cur_data_size
)
783 tfile_read ((gdb_byte
*) &block_type
, 1);
787 if ((*callback
) (block_type
, data
))
793 lseek (trace_fd
, cur_offset
+ pos
+ trace_regblock_size
, SEEK_SET
);
794 pos
+= trace_regblock_size
;
797 lseek (trace_fd
, cur_offset
+ pos
+ 8, SEEK_SET
);
798 tfile_read ((gdb_byte
*) &mlen
, 2);
799 mlen
= (unsigned short)
800 extract_unsigned_integer ((gdb_byte
*) &mlen
, 2,
802 (target_gdbarch ()));
803 lseek (trace_fd
, mlen
, SEEK_CUR
);
804 pos
+= (8 + 2 + mlen
);
807 lseek (trace_fd
, cur_offset
+ pos
+ 4 + 8, SEEK_SET
);
811 error (_("Unknown block type '%c' (0x%x) in trace frame"),
812 block_type
, block_type
);
820 /* Convenience wrapper around traceframe_walk_blocks. Looks for the
821 position offset of a block of type TYPE_WANTED in the current trace
822 frame, starting at POS. Returns -1 if no such block was found. */
825 traceframe_find_block_type (char type_wanted
, int pos
)
827 return traceframe_walk_blocks (match_blocktype
, pos
, &type_wanted
);
830 /* Look for a block of saved registers in the traceframe, and get the
831 requested register from it. */
834 tfile_fetch_registers (struct target_ops
*ops
,
835 struct regcache
*regcache
, int regno
)
837 struct gdbarch
*gdbarch
= get_regcache_arch (regcache
);
838 int offset
, regn
, regsize
, dummy
;
840 /* An uninitialized reg size says we're not going to be
841 successful at getting register blocks. */
842 if (!trace_regblock_size
)
845 if (traceframe_find_block_type ('R', 0) >= 0)
847 gdb_byte
*regs
= (gdb_byte
*) alloca (trace_regblock_size
);
849 tfile_read (regs
, trace_regblock_size
);
851 for (regn
= 0; regn
< gdbarch_num_regs (gdbarch
); regn
++)
853 if (!remote_register_number_and_offset (get_regcache_arch (regcache
),
854 regn
, &dummy
, &offset
))
857 regsize
= register_size (gdbarch
, regn
);
858 /* Make sure we stay within block bounds. */
859 if (offset
+ regsize
> trace_regblock_size
)
861 if (regcache_register_status (regcache
, regn
) == REG_UNKNOWN
)
865 regcache_raw_supply (regcache
, regno
, regs
+ offset
);
868 else if (regno
== -1)
870 regcache_raw_supply (regcache
, regn
, regs
+ offset
);
876 tracefile_fetch_registers (regcache
, regno
);
879 static enum target_xfer_status
880 tfile_xfer_partial (struct target_ops
*ops
, enum target_object object
,
881 const char *annex
, gdb_byte
*readbuf
,
882 const gdb_byte
*writebuf
, ULONGEST offset
, ULONGEST len
,
883 ULONGEST
*xfered_len
)
885 /* We're only doing regular memory for now. */
886 if (object
!= TARGET_OBJECT_MEMORY
)
887 return TARGET_XFER_E_IO
;
890 error (_("tfile_xfer_partial: trace file is read-only"));
892 if (get_traceframe_number () != -1)
895 enum target_xfer_status res
;
896 /* Records the lowest available address of all blocks that
897 intersects the requested range. */
898 ULONGEST low_addr_available
= 0;
900 /* Iterate through the traceframe's blocks, looking for
902 while ((pos
= traceframe_find_block_type ('M', pos
)) >= 0)
906 enum bfd_endian byte_order
= gdbarch_byte_order (target_gdbarch ());
908 tfile_read ((gdb_byte
*) &maddr
, 8);
909 maddr
= extract_unsigned_integer ((gdb_byte
*) &maddr
, 8,
911 tfile_read ((gdb_byte
*) &mlen
, 2);
912 mlen
= (unsigned short)
913 extract_unsigned_integer ((gdb_byte
*) &mlen
, 2, byte_order
);
915 /* If the block includes the first part of the desired
916 range, return as much it has; GDB will re-request the
917 remainder, which might be in a different block of this
919 if (maddr
<= offset
&& offset
< (maddr
+ mlen
))
921 amt
= (maddr
+ mlen
) - offset
;
926 lseek (trace_fd
, offset
- maddr
, SEEK_CUR
);
927 tfile_read (readbuf
, amt
);
929 return TARGET_XFER_OK
;
932 if (offset
< maddr
&& maddr
< (offset
+ len
))
933 if (low_addr_available
== 0 || low_addr_available
> maddr
)
934 low_addr_available
= maddr
;
936 /* Skip over this block. */
937 pos
+= (8 + 2 + mlen
);
940 /* Requested memory is unavailable in the context of traceframes,
941 and this address falls within a read-only section, fallback
942 to reading from executable, up to LOW_ADDR_AVAILABLE. */
943 if (offset
< low_addr_available
)
944 len
= min (len
, low_addr_available
- offset
);
945 res
= exec_read_partial_read_only (readbuf
, offset
, len
, xfered_len
);
947 if (res
== TARGET_XFER_OK
)
948 return TARGET_XFER_OK
;
951 /* No use trying further, we know some memory starting
952 at MEMADDR isn't available. */
954 return TARGET_XFER_UNAVAILABLE
;
959 /* Fallback to reading from read-only sections. */
960 return section_table_read_available_memory (readbuf
, offset
, len
,
965 /* Iterate through the blocks of a trace frame, looking for a 'V'
966 block with a matching tsv number. */
969 tfile_get_trace_state_variable_value (struct target_ops
*self
,
970 int tsvnum
, LONGEST
*val
)
975 /* Iterate over blocks in current frame and find the last 'V'
976 block in which tsv number is TSVNUM. In one trace frame, there
977 may be multiple 'V' blocks created for a given trace variable,
978 and the last matched 'V' block contains the updated value. */
980 while ((pos
= traceframe_find_block_type ('V', pos
)) >= 0)
984 tfile_read ((gdb_byte
*) &vnum
, 4);
985 vnum
= (int) extract_signed_integer ((gdb_byte
*) &vnum
, 4,
987 (target_gdbarch ()));
990 tfile_read ((gdb_byte
*) val
, 8);
991 *val
= extract_signed_integer ((gdb_byte
*) val
, 8,
993 (target_gdbarch ()));
1002 /* Callback for traceframe_walk_blocks. Builds a traceframe_info
1003 object for the tfile target's current traceframe. */
1006 build_traceframe_info (char blocktype
, void *data
)
1008 struct traceframe_info
*info
= (struct traceframe_info
*) data
;
1014 struct mem_range
*r
;
1016 unsigned short mlen
;
1018 tfile_read ((gdb_byte
*) &maddr
, 8);
1019 maddr
= extract_unsigned_integer ((gdb_byte
*) &maddr
, 8,
1021 (target_gdbarch ()));
1022 tfile_read ((gdb_byte
*) &mlen
, 2);
1023 mlen
= (unsigned short)
1024 extract_unsigned_integer ((gdb_byte
*) &mlen
,
1025 2, gdbarch_byte_order
1026 (target_gdbarch ()));
1028 r
= VEC_safe_push (mem_range_s
, info
->memory
, NULL
);
1038 tfile_read ((gdb_byte
*) &vnum
, 4);
1039 VEC_safe_push (int, info
->tvars
, vnum
);
1047 warning (_("Unhandled trace block type (%d) '%c ' "
1048 "while building trace frame info."),
1049 blocktype
, blocktype
);
1056 static struct traceframe_info
*
1057 tfile_traceframe_info (struct target_ops
*self
)
1059 struct traceframe_info
*info
= XCNEW (struct traceframe_info
);
1061 traceframe_walk_blocks (build_traceframe_info
, 0, info
);
1066 init_tfile_ops (void)
1068 init_tracefile_ops (&tfile_ops
);
1070 tfile_ops
.to_shortname
= "tfile";
1071 tfile_ops
.to_longname
= "Local trace dump file";
1073 = "Use a trace file as a target. Specify the filename of the trace file.";
1074 tfile_ops
.to_open
= tfile_open
;
1075 tfile_ops
.to_close
= tfile_close
;
1076 tfile_ops
.to_fetch_registers
= tfile_fetch_registers
;
1077 tfile_ops
.to_xfer_partial
= tfile_xfer_partial
;
1078 tfile_ops
.to_files_info
= tfile_files_info
;
1079 tfile_ops
.to_get_tracepoint_status
= tfile_get_tracepoint_status
;
1080 tfile_ops
.to_trace_find
= tfile_trace_find
;
1081 tfile_ops
.to_get_trace_state_variable_value
1082 = tfile_get_trace_state_variable_value
;
1083 tfile_ops
.to_traceframe_info
= tfile_traceframe_info
;
1086 extern initialize_file_ftype _initialize_tracefile_tfile
;
1089 _initialize_tracefile_tfile (void)
1093 add_target_with_completer (&tfile_ops
, filename_completer
);