1 /* Trace file support in GDB.
3 Copyright (C) 1997-2018 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"
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), \
33 #define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \
34 writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \
36 #define TRACE_WRITE_V_BLOCK(writer, num, val) \
37 writer->ops->frame_ops->write_v_block ((writer), (num), (val))
39 /* A unique pointer policy class for trace_file_writer. */
41 struct trace_file_writer_deleter
43 void operator() (struct trace_file_writer *writer)
45 writer->ops->dtor (writer);
50 /* A unique_ptr specialization for trace_file_writer. */
52 typedef std::unique_ptr<trace_file_writer, trace_file_writer_deleter>
55 /* Save tracepoint data to file named FILENAME through WRITER. WRITER
56 determines the trace file format. If TARGET_DOES_SAVE is non-zero,
57 the save is performed on the target, otherwise GDB obtains all trace
58 data and saves it locally. */
61 trace_save (const char *filename, struct trace_file_writer *writer,
64 struct trace_status *ts = current_trace_status ();
65 struct uploaded_tp *uploaded_tps = NULL, *utp;
66 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
69 #define MAX_TRACE_UPLOAD 2000
70 gdb_byte buf[MAX_TRACE_UPLOAD];
71 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
73 /* If the target is to save the data to a file on its own, then just
74 send the command and be done with it. */
77 if (!writer->ops->target_save (writer, filename))
78 error (_("Target failed to save trace data to '%s'."),
83 /* Get the trace status first before opening the file, so if the
84 target is losing, we can get out without touching files. Since
85 we're just calling this for side effects, we ignore the
87 target_get_trace_status (ts);
89 writer->ops->start (writer, filename);
91 writer->ops->write_header (writer);
93 /* Write descriptive info. */
95 /* Write out the size of a register block. */
96 writer->ops->write_regblock_type (writer, trace_regblock_size);
98 /* Write out the target description info. */
99 writer->ops->write_tdesc (writer);
101 /* Write out status of the tracing run (aka "tstatus" info). */
102 writer->ops->write_status (writer, ts);
104 /* Note that we want to upload tracepoints and save those, rather
105 than simply writing out the local ones, because the user may have
106 changed tracepoints in GDB in preparation for a future tracing
107 run, or maybe just mass-deleted all types of breakpoints as part
108 of cleaning up. So as not to contaminate the session, leave the
109 data in its uploaded form, don't make into real tracepoints. */
111 /* Get trace state variables first, they may be checked when parsing
112 uploaded commands. */
114 target_upload_trace_state_variables (&uploaded_tsvs);
116 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
117 writer->ops->write_uploaded_tsv (writer, utsv);
119 free_uploaded_tsvs (&uploaded_tsvs);
121 target_upload_tracepoints (&uploaded_tps);
123 for (utp = uploaded_tps; utp; utp = utp->next)
124 target_get_tracepoint_status (NULL, utp);
126 for (utp = uploaded_tps; utp; utp = utp->next)
127 writer->ops->write_uploaded_tp (writer, utp);
129 free_uploaded_tps (&uploaded_tps);
131 /* Mark the end of the definition section. */
132 writer->ops->write_definition_end (writer);
134 /* Get and write the trace data proper. */
139 /* The writer supports writing the contents of trace buffer
140 directly to trace file. Don't parse the contents of trace
142 if (writer->ops->write_trace_buffer != NULL)
144 /* We ask for big blocks, in the hopes of efficiency, but
145 will take less if the target has packet size limitations
147 gotten = target_get_raw_trace_data (buf, offset,
150 error (_("Failure to get requested trace buffer data"));
151 /* No more data is forthcoming, we're done. */
155 writer->ops->write_trace_buffer (writer, buf, gotten);
163 /* Parse the trace buffers according to how data are stored
164 in trace buffer in GDBserver. */
166 gotten = target_get_raw_trace_data (buf, offset, 6);
171 /* Read the first six bytes in, which is the tracepoint
172 number and trace frame size. */
174 extract_unsigned_integer (&buf[0], 2, byte_order);
177 extract_unsigned_integer (&buf[2], 4, byte_order);
179 writer->ops->frame_ops->start (writer, tp_num);
188 for (block = 0; block < tf_size; )
192 /* We'll fetch one block each time, in order to
193 handle the extremely large 'M' block. We first
194 fetch one byte to get the type of the block. */
195 gotten = target_get_raw_trace_data (buf, offset, 1);
197 error (_("Failure to get requested trace buffer data"));
208 = target_get_raw_trace_data (buf, offset,
209 trace_regblock_size);
210 if (gotten < trace_regblock_size)
211 error (_("Failure to get requested trace"
214 TRACE_WRITE_R_BLOCK (writer, buf,
215 trace_regblock_size);
224 t = target_get_raw_trace_data (buf,offset, 10);
226 error (_("Failure to get requested trace"
234 extract_unsigned_integer (buf, 8,
236 mlen = (unsigned short)
237 extract_unsigned_integer (&buf[8], 2,
240 TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
243 /* The memory contents in 'M' block may be
244 very large. Fetch the data from the target
245 and write them into file one by one. */
246 for (j = 0; j < mlen; )
248 unsigned int read_length;
250 if (mlen - j > MAX_TRACE_UPLOAD)
251 read_length = MAX_TRACE_UPLOAD;
253 read_length = mlen - j;
255 t = target_get_raw_trace_data (buf,
259 error (_("Failure to get requested"
260 " trace buffer data"));
262 TRACE_WRITE_M_BLOCK_MEMORY (writer, buf,
266 gotten += read_length;
277 = target_get_raw_trace_data (buf, offset,
280 error (_("Failure to get requested"
281 " trace buffer data"));
283 vnum = (int) extract_signed_integer (buf,
287 = extract_signed_integer (&buf[4], 8,
290 TRACE_WRITE_V_BLOCK (writer, vnum, val);
294 error (_("Unknown block type '%c' (0x%x) in"
296 block_type, block_type);
306 writer->ops->frame_ops->end (writer);
310 writer->ops->end (writer);
314 tsave_command (const char *args, int from_tty)
316 int target_does_save = 0;
318 char *filename = NULL;
319 int generate_ctf = 0;
322 error_no_arg (_("file in which to save trace data"));
324 gdb_argv built_argv (args);
325 argv = built_argv.get ();
327 for (; *argv; ++argv)
329 if (strcmp (*argv, "-r") == 0)
330 target_does_save = 1;
331 else if (strcmp (*argv, "-ctf") == 0)
333 else if (**argv == '-')
334 error (_("unknown option `%s'"), *argv);
340 error_no_arg (_("file in which to save trace data"));
343 trace_save_ctf (filename, target_does_save);
345 trace_save_tfile (filename, target_does_save);
348 printf_filtered (_("Trace data saved to %s '%s'.\n"),
349 generate_ctf ? "directory" : "file", filename);
352 /* Save the trace data to file FILENAME of tfile format. */
355 trace_save_tfile (const char *filename, int target_does_save)
357 trace_file_writer_up writer (tfile_trace_file_writer_new ());
358 trace_save (filename, writer.get (), target_does_save);
361 /* Save the trace data to dir DIRNAME of ctf format. */
364 trace_save_ctf (const char *dirname, int target_does_save)
366 trace_file_writer_up writer (ctf_trace_file_writer_new ());
367 trace_save (dirname, writer.get (), target_does_save);
370 /* Fetch register data from tracefile, shared for both tfile and
374 tracefile_fetch_registers (struct regcache *regcache, int regno)
376 struct gdbarch *gdbarch = regcache->arch ();
377 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
380 /* We get here if no register data has been found. Mark registers
382 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
383 regcache->raw_supply (regn, NULL);
385 /* We can often usefully guess that the PC is going to be the same
386 as the address of the tracepoint. */
387 if (tp == NULL || tp->loc == NULL)
390 /* But don't try to guess if tracepoint is multi-location... */
393 warning (_("Tracepoint %d has multiple "
394 "locations, cannot infer $pc"),
398 /* ... or does while-stepping. */
399 else if (tp->step_count > 0)
401 warning (_("Tracepoint %d does while-stepping, "
407 /* Guess what we can from the tracepoint location. */
408 gdbarch_guess_tracepoint_registers (gdbarch, regcache,
412 /* This is the implementation of target_ops method to_has_all_memory. */
415 tracefile_target::has_all_memory ()
420 /* This is the implementation of target_ops method to_has_memory. */
423 tracefile_target::has_memory ()
428 /* This is the implementation of target_ops method to_has_stack.
429 The target has a stack when GDB has already selected one trace
433 tracefile_target::has_stack ()
435 return get_traceframe_number () != -1;
438 /* This is the implementation of target_ops method to_has_registers.
439 The target has registers when GDB has already selected one trace
443 tracefile_target::has_registers ()
445 return get_traceframe_number () != -1;
448 /* This is the implementation of target_ops method to_thread_alive.
449 tracefile has one thread faked by GDB. */
452 tracefile_target::thread_alive (ptid_t ptid)
457 /* This is the implementation of target_ops method to_get_trace_status.
458 The trace status for a file is that tracing can never be run. */
461 tracefile_target::get_trace_status (struct trace_status *ts)
463 /* Other bits of trace status were collected as part of opening the
464 trace files, so nothing to do here. */
469 tracefile_target::tracefile_target ()
471 this->to_stratum = process_stratum;
475 _initialize_tracefile (void)
477 add_com ("tsave", class_trace, tsave_command, _("\
478 Save the trace data to a file.\n\
479 Use the '-ctf' option to save the data to CTF format.\n\
480 Use the '-r' option to direct the target to save directly to the file,\n\
481 using its own filesystem."));