Automatic date update in version.in
[binutils-gdb.git] / gdb / tracefile.c
blob9db68bbac510e0071f9eeacb6cc6b9ed5d4ea6fb
1 /* Trace file support in GDB.
3 Copyright (C) 1997-2024 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/>. */
20 #include "tracefile.h"
21 #include "tracectf.h"
22 #include "exec.h"
23 #include "regcache.h"
24 #include "gdbsupport/byte-vector.h"
25 #include "gdbarch.h"
26 #include "gdbsupport/buildargv.h"
27 #include "inferior.h"
29 /* Helper macros. */
31 #define TRACE_WRITE_R_BLOCK(writer, buf, size) \
32 writer->ops->frame_ops->write_r_block ((writer), (buf), (size))
33 #define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size) \
34 writer->ops->frame_ops->write_m_block_header ((writer), (addr), \
35 (size))
36 #define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \
37 writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \
38 (size))
39 #define TRACE_WRITE_V_BLOCK(writer, num, val) \
40 writer->ops->frame_ops->write_v_block ((writer), (num), (val))
42 /* A unique pointer policy class for trace_file_writer. */
44 struct trace_file_writer_deleter
46 void operator() (struct trace_file_writer *writer)
48 writer->ops->dtor (writer);
49 xfree (writer);
53 /* A unique_ptr specialization for trace_file_writer. */
55 typedef std::unique_ptr<trace_file_writer, trace_file_writer_deleter>
56 trace_file_writer_up;
58 /* Save tracepoint data to file named FILENAME through WRITER. WRITER
59 determines the trace file format. If TARGET_DOES_SAVE is non-zero,
60 the save is performed on the target, otherwise GDB obtains all trace
61 data and saves it locally. */
63 static void
64 trace_save (const char *filename, struct trace_file_writer *writer,
65 int target_does_save)
67 struct trace_status *ts = current_trace_status ();
68 struct uploaded_tp *uploaded_tps = NULL, *utp;
69 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
71 ULONGEST offset = 0;
72 #define MAX_TRACE_UPLOAD 2000
73 gdb::byte_vector buf (std::max (MAX_TRACE_UPLOAD, trace_regblock_size));
74 bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
76 /* If the target is to save the data to a file on its own, then just
77 send the command and be done with it. */
78 if (target_does_save)
80 if (!writer->ops->target_save (writer, filename))
81 error (_("Target failed to save trace data to '%s'."),
82 filename);
83 return;
86 /* Get the trace status first before opening the file, so if the
87 target is losing, we can get out without touching files. Since
88 we're just calling this for side effects, we ignore the
89 result. */
90 target_get_trace_status (ts);
92 writer->ops->start (writer, filename);
94 writer->ops->write_header (writer);
96 /* Write descriptive info. */
98 /* Write out the size of a register block. */
99 writer->ops->write_regblock_type (writer, trace_regblock_size);
101 /* Write out the target description info. */
102 writer->ops->write_tdesc (writer);
104 /* Write out status of the tracing run (aka "tstatus" info). */
105 writer->ops->write_status (writer, ts);
107 /* Note that we want to upload tracepoints and save those, rather
108 than simply writing out the local ones, because the user may have
109 changed tracepoints in GDB in preparation for a future tracing
110 run, or maybe just mass-deleted all types of breakpoints as part
111 of cleaning up. So as not to contaminate the session, leave the
112 data in its uploaded form, don't make into real tracepoints. */
114 /* Get trace state variables first, they may be checked when parsing
115 uploaded commands. */
117 target_upload_trace_state_variables (&uploaded_tsvs);
119 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
120 writer->ops->write_uploaded_tsv (writer, utsv);
122 free_uploaded_tsvs (&uploaded_tsvs);
124 target_upload_tracepoints (&uploaded_tps);
126 for (utp = uploaded_tps; utp; utp = utp->next)
127 target_get_tracepoint_status (NULL, utp);
129 for (utp = uploaded_tps; utp; utp = utp->next)
130 writer->ops->write_uploaded_tp (writer, utp);
132 free_uploaded_tps (&uploaded_tps);
134 /* Mark the end of the definition section. */
135 writer->ops->write_definition_end (writer);
137 /* Get and write the trace data proper. */
138 while (1)
140 LONGEST gotten = 0;
142 /* The writer supports writing the contents of trace buffer
143 directly to trace file. Don't parse the contents of trace
144 buffer. */
145 if (writer->ops->write_trace_buffer != NULL)
147 /* We ask for big blocks, in the hopes of efficiency, but
148 will take less if the target has packet size limitations
149 or some such. */
150 gotten = target_get_raw_trace_data (buf.data (), offset,
151 MAX_TRACE_UPLOAD);
152 if (gotten < 0)
153 error (_("Failure to get requested trace buffer data"));
154 /* No more data is forthcoming, we're done. */
155 if (gotten == 0)
156 break;
158 writer->ops->write_trace_buffer (writer, buf.data (), gotten);
160 offset += gotten;
162 else
164 uint16_t tp_num;
165 uint32_t tf_size;
166 /* Parse the trace buffers according to how data are stored
167 in trace buffer in GDBserver. */
169 gotten = target_get_raw_trace_data (buf.data (), offset, 6);
171 if (gotten == 0)
172 break;
174 /* Read the first six bytes in, which is the tracepoint
175 number and trace frame size. */
176 tp_num = (uint16_t)
177 extract_unsigned_integer (&((buf.data ())[0]), 2, byte_order);
179 tf_size = (uint32_t)
180 extract_unsigned_integer (&((buf.data ())[2]), 4, byte_order);
182 writer->ops->frame_ops->start (writer, tp_num);
183 gotten = 6;
185 if (tf_size > 0)
187 unsigned int block;
189 offset += 6;
191 for (block = 0; block < tf_size; )
193 gdb_byte block_type;
195 /* We'll fetch one block each time, in order to
196 handle the extremely large 'M' block. We first
197 fetch one byte to get the type of the block. */
198 gotten = target_get_raw_trace_data (buf.data (),
199 offset, 1);
200 if (gotten < 1)
201 error (_("Failure to get requested trace buffer data"));
203 gotten = 1;
204 block += 1;
205 offset += 1;
207 block_type = buf[0];
208 switch (block_type)
210 case 'R':
211 gotten
212 = target_get_raw_trace_data (buf.data (), offset,
213 trace_regblock_size);
214 if (gotten < trace_regblock_size)
215 error (_("Failure to get requested trace"
216 " buffer data"));
218 TRACE_WRITE_R_BLOCK (writer, buf.data (),
219 trace_regblock_size);
220 break;
221 case 'M':
223 unsigned short mlen;
224 ULONGEST addr;
225 LONGEST t;
226 int j;
228 t = target_get_raw_trace_data (buf.data (),
229 offset, 10);
230 if (t < 10)
231 error (_("Failure to get requested trace"
232 " buffer data"));
234 offset += 10;
235 block += 10;
237 gotten = 0;
238 addr = (ULONGEST)
239 extract_unsigned_integer (buf.data (), 8,
240 byte_order);
241 mlen = (unsigned short)
242 extract_unsigned_integer (&((buf.data ())[8]), 2,
243 byte_order);
245 TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
246 mlen);
248 /* The memory contents in 'M' block may be
249 very large. Fetch the data from the target
250 and write them into file one by one. */
251 for (j = 0; j < mlen; )
253 unsigned int read_length;
255 if (mlen - j > MAX_TRACE_UPLOAD)
256 read_length = MAX_TRACE_UPLOAD;
257 else
258 read_length = mlen - j;
260 t = target_get_raw_trace_data (buf.data (),
261 offset + j,
262 read_length);
263 if (t < read_length)
264 error (_("Failure to get requested"
265 " trace buffer data"));
267 TRACE_WRITE_M_BLOCK_MEMORY (writer,
268 buf.data (),
269 read_length);
271 j += read_length;
272 gotten += read_length;
275 break;
277 case 'V':
279 int vnum;
280 LONGEST val;
282 gotten
283 = target_get_raw_trace_data (buf.data (),
284 offset, 12);
285 if (gotten < 12)
286 error (_("Failure to get requested"
287 " trace buffer data"));
289 vnum = (int) extract_signed_integer (buf.data (),
291 byte_order);
293 = extract_signed_integer (&((buf.data ())[4]),
294 8, byte_order);
296 TRACE_WRITE_V_BLOCK (writer, vnum, val);
298 break;
299 default:
300 error (_("Unknown block type '%c' (0x%x) in"
301 " trace frame"),
302 block_type, block_type);
305 block += gotten;
306 offset += gotten;
309 else
310 offset += gotten;
312 writer->ops->frame_ops->end (writer);
316 writer->ops->end (writer);
319 static void
320 tsave_command (const char *args, int from_tty)
322 int target_does_save = 0;
323 char **argv;
324 char *filename = NULL;
325 int generate_ctf = 0;
327 if (args == NULL)
328 error_no_arg (_("file in which to save trace data"));
330 gdb_argv built_argv (args);
331 argv = built_argv.get ();
333 for (; *argv; ++argv)
335 if (strcmp (*argv, "-r") == 0)
336 target_does_save = 1;
337 else if (strcmp (*argv, "-ctf") == 0)
338 generate_ctf = 1;
339 else if (**argv == '-')
340 error (_("unknown option `%s'"), *argv);
341 else
342 filename = *argv;
345 if (!filename)
346 error_no_arg (_("file in which to save trace data"));
348 if (generate_ctf)
349 trace_save_ctf (filename, target_does_save);
350 else
351 trace_save_tfile (filename, target_does_save);
353 if (from_tty)
354 gdb_printf (_("Trace data saved to %s '%s'.\n"),
355 generate_ctf ? "directory" : "file", filename);
358 /* Save the trace data to file FILENAME of tfile format. */
360 void
361 trace_save_tfile (const char *filename, int target_does_save)
363 trace_file_writer_up writer (tfile_trace_file_writer_new ());
364 trace_save (filename, writer.get (), target_does_save);
367 /* Save the trace data to dir DIRNAME of ctf format. */
369 void
370 trace_save_ctf (const char *dirname, int target_does_save)
372 trace_file_writer_up writer (ctf_trace_file_writer_new ());
373 trace_save (dirname, writer.get (), target_does_save);
376 /* Fetch register data from tracefile, shared for both tfile and
377 ctf. */
379 void
380 tracefile_fetch_registers (struct regcache *regcache, int regno)
382 struct gdbarch *gdbarch = regcache->arch ();
383 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
384 int regn;
386 /* We get here if no register data has been found. Mark registers
387 as unavailable. */
388 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
389 regcache->raw_supply (regn, NULL);
391 /* We can often usefully guess that the PC is going to be the same
392 as the address of the tracepoint. */
393 if (tp == nullptr || !tp->has_locations ())
394 return;
396 /* But don't try to guess if tracepoint is multi-location... */
397 if (tp->has_multiple_locations ())
399 warning (_("Tracepoint %d has multiple "
400 "locations, cannot infer $pc"),
401 tp->number);
402 return;
404 /* ... or does while-stepping. */
405 else if (tp->step_count > 0)
407 warning (_("Tracepoint %d does while-stepping, "
408 "cannot infer $pc"),
409 tp->number);
410 return;
413 /* Guess what we can from the tracepoint location. */
414 gdbarch_guess_tracepoint_registers (gdbarch, regcache,
415 tp->first_loc ().address);
418 /* This is the implementation of target_ops method to_has_all_memory. */
420 bool
421 tracefile_target::has_all_memory ()
423 return true;
426 /* This is the implementation of target_ops method to_has_memory. */
428 bool
429 tracefile_target::has_memory ()
431 return true;
434 /* This is the implementation of target_ops method to_has_stack.
435 The target has a stack when GDB has already selected one trace
436 frame. */
438 bool
439 tracefile_target::has_stack ()
441 return get_traceframe_number () != -1;
444 /* This is the implementation of target_ops method to_has_registers.
445 The target has registers when GDB has already selected one trace
446 frame. */
448 bool
449 tracefile_target::has_registers ()
451 return get_traceframe_number () != -1;
454 /* This is the implementation of target_ops method to_thread_alive.
455 tracefile has one thread faked by GDB. */
457 bool
458 tracefile_target::thread_alive (ptid_t ptid)
460 return true;
463 /* This is the implementation of target_ops method to_get_trace_status.
464 The trace status for a file is that tracing can never be run. */
467 tracefile_target::get_trace_status (struct trace_status *ts)
469 /* Other bits of trace status were collected as part of opening the
470 trace files, so nothing to do here. */
472 return -1;
475 void _initialize_tracefile ();
476 void
477 _initialize_tracefile ()
479 add_com ("tsave", class_trace, tsave_command, _("\
480 Save the trace data to a file.\n\
481 Use the '-ctf' option to save the data to CTF format.\n\
482 Use the '-r' option to direct the target to save directly to the file,\n\
483 using its own filesystem."));