Notify about breakpoint modification when enabling/disabling single location
[deliverable/binutils-gdb.git] / gdb / tracefile.c
CommitLineData
7951c4eb
YQ
1/* Trace file support in GDB.
2
e2882c85 3 Copyright (C) 1997-2018 Free Software Foundation, Inc.
7951c4eb
YQ
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"
1ca49d37 23#include "exec.h"
48b6e87e 24#include "regcache.h"
7951c4eb
YQ
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
d14b92bf 39/* A unique pointer policy class for trace_file_writer. */
7951c4eb 40
d14b92bf 41struct trace_file_writer_deleter
7951c4eb 42{
d14b92bf
TT
43 void operator() (struct trace_file_writer *writer)
44 {
45 writer->ops->dtor (writer);
46 xfree (writer);
47 }
48};
7951c4eb 49
d14b92bf
TT
50/* A unique_ptr specialization for trace_file_writer. */
51
52typedef std::unique_ptr<trace_file_writer, trace_file_writer_deleter>
53 trace_file_writer_up;
7951c4eb
YQ
54
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. */
59
60static void
61trace_save (const char *filename, struct trace_file_writer *writer,
62 int target_does_save)
63{
64 struct trace_status *ts = current_trace_status ();
7951c4eb
YQ
65 struct uploaded_tp *uploaded_tps = NULL, *utp;
66 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
67
68 ULONGEST offset = 0;
69#define MAX_TRACE_UPLOAD 2000
70 gdb_byte buf[MAX_TRACE_UPLOAD];
7951c4eb
YQ
71 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
72
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. */
75 if (target_does_save)
76 {
77 if (!writer->ops->target_save (writer, filename))
78 error (_("Target failed to save trace data to '%s'."),
79 filename);
80 return;
81 }
82
83 /* Get the trace status first before opening the file, so if the
ac298888
TT
84 target is losing, we can get out without touching files. Since
85 we're just calling this for side effects, we ignore the
86 result. */
87 target_get_trace_status (ts);
7951c4eb
YQ
88
89 writer->ops->start (writer, filename);
90
91 writer->ops->write_header (writer);
92
93 /* Write descriptive info. */
94
95 /* Write out the size of a register block. */
96 writer->ops->write_regblock_type (writer, trace_regblock_size);
97
18d3cec5
MK
98 /* Write out the target description info. */
99 writer->ops->write_tdesc (writer);
100
7951c4eb
YQ
101 /* Write out status of the tracing run (aka "tstatus" info). */
102 writer->ops->write_status (writer, ts);
103
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. */
110
111 /* Get trace state variables first, they may be checked when parsing
112 uploaded commands. */
113
114 target_upload_trace_state_variables (&uploaded_tsvs);
115
116 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
117 writer->ops->write_uploaded_tsv (writer, utsv);
118
119 free_uploaded_tsvs (&uploaded_tsvs);
120
121 target_upload_tracepoints (&uploaded_tps);
122
123 for (utp = uploaded_tps; utp; utp = utp->next)
124 target_get_tracepoint_status (NULL, utp);
125
126 for (utp = uploaded_tps; utp; utp = utp->next)
127 writer->ops->write_uploaded_tp (writer, utp);
128
129 free_uploaded_tps (&uploaded_tps);
130
131 /* Mark the end of the definition section. */
132 writer->ops->write_definition_end (writer);
133
134 /* Get and write the trace data proper. */
135 while (1)
136 {
137 LONGEST gotten = 0;
138
139 /* The writer supports writing the contents of trace buffer
140 directly to trace file. Don't parse the contents of trace
141 buffer. */
142 if (writer->ops->write_trace_buffer != NULL)
143 {
144 /* We ask for big blocks, in the hopes of efficiency, but
145 will take less if the target has packet size limitations
146 or some such. */
147 gotten = target_get_raw_trace_data (buf, offset,
148 MAX_TRACE_UPLOAD);
149 if (gotten < 0)
150 error (_("Failure to get requested trace buffer data"));
151 /* No more data is forthcoming, we're done. */
152 if (gotten == 0)
153 break;
154
155 writer->ops->write_trace_buffer (writer, buf, gotten);
156
157 offset += gotten;
158 }
159 else
160 {
161 uint16_t tp_num;
162 uint32_t tf_size;
163 /* Parse the trace buffers according to how data are stored
164 in trace buffer in GDBserver. */
165
166 gotten = target_get_raw_trace_data (buf, offset, 6);
167
168 if (gotten == 0)
169 break;
170
171 /* Read the first six bytes in, which is the tracepoint
172 number and trace frame size. */
173 tp_num = (uint16_t)
174 extract_unsigned_integer (&buf[0], 2, byte_order);
175
176 tf_size = (uint32_t)
177 extract_unsigned_integer (&buf[2], 4, byte_order);
178
179 writer->ops->frame_ops->start (writer, tp_num);
180 gotten = 6;
181
182 if (tf_size > 0)
183 {
184 unsigned int block;
185
186 offset += 6;
187
188 for (block = 0; block < tf_size; )
189 {
190 gdb_byte block_type;
191
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);
196 if (gotten < 1)
197 error (_("Failure to get requested trace buffer data"));
198
199 gotten = 1;
200 block += 1;
201 offset += 1;
202
203 block_type = buf[0];
204 switch (block_type)
205 {
206 case 'R':
207 gotten
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"
212 " buffer data"));
213
214 TRACE_WRITE_R_BLOCK (writer, buf,
215 trace_regblock_size);
216 break;
217 case 'M':
218 {
219 unsigned short mlen;
220 ULONGEST addr;
221 LONGEST t;
222 int j;
223
224 t = target_get_raw_trace_data (buf,offset, 10);
225 if (t < 10)
226 error (_("Failure to get requested trace"
227 " buffer data"));
228
229 offset += 10;
230 block += 10;
231
232 gotten = 0;
233 addr = (ULONGEST)
234 extract_unsigned_integer (buf, 8,
235 byte_order);
236 mlen = (unsigned short)
237 extract_unsigned_integer (&buf[8], 2,
238 byte_order);
239
240 TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
241 mlen);
242
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; )
247 {
248 unsigned int read_length;
249
250 if (mlen - j > MAX_TRACE_UPLOAD)
251 read_length = MAX_TRACE_UPLOAD;
252 else
253 read_length = mlen - j;
254
255 t = target_get_raw_trace_data (buf,
256 offset + j,
257 read_length);
258 if (t < read_length)
259 error (_("Failure to get requested"
260 " trace buffer data"));
261
262 TRACE_WRITE_M_BLOCK_MEMORY (writer, buf,
263 read_length);
264
265 j += read_length;
266 gotten += read_length;
267 }
268
269 break;
270 }
271 case 'V':
272 {
273 int vnum;
274 LONGEST val;
275
276 gotten
277 = target_get_raw_trace_data (buf, offset,
278 12);
279 if (gotten < 12)
280 error (_("Failure to get requested"
281 " trace buffer data"));
282
283 vnum = (int) extract_signed_integer (buf,
284 4,
285 byte_order);
286 val
287 = extract_signed_integer (&buf[4], 8,
288 byte_order);
289
290 TRACE_WRITE_V_BLOCK (writer, vnum, val);
291 }
292 break;
293 default:
294 error (_("Unknown block type '%c' (0x%x) in"
295 " trace frame"),
296 block_type, block_type);
297 }
298
299 block += gotten;
300 offset += gotten;
301 }
302 }
303 else
304 offset += gotten;
305
306 writer->ops->frame_ops->end (writer);
307 }
308 }
309
310 writer->ops->end (writer);
311}
312
313static void
0b39b52e 314tsave_command (const char *args, int from_tty)
7951c4eb
YQ
315{
316 int target_does_save = 0;
317 char **argv;
318 char *filename = NULL;
7951c4eb 319 int generate_ctf = 0;
7951c4eb
YQ
320
321 if (args == NULL)
322 error_no_arg (_("file in which to save trace data"));
323
773a1edc
TT
324 gdb_argv built_argv (args);
325 argv = built_argv.get ();
7951c4eb
YQ
326
327 for (; *argv; ++argv)
328 {
329 if (strcmp (*argv, "-r") == 0)
330 target_does_save = 1;
4a596fe2 331 else if (strcmp (*argv, "-ctf") == 0)
7951c4eb
YQ
332 generate_ctf = 1;
333 else if (**argv == '-')
334 error (_("unknown option `%s'"), *argv);
335 else
336 filename = *argv;
337 }
338
339 if (!filename)
340 error_no_arg (_("file in which to save trace data"));
341
342 if (generate_ctf)
d14b92bf 343 trace_save_ctf (filename, target_does_save);
7951c4eb 344 else
d14b92bf 345 trace_save_tfile (filename, target_does_save);
7951c4eb
YQ
346
347 if (from_tty)
348 printf_filtered (_("Trace data saved to %s '%s'.\n"),
349 generate_ctf ? "directory" : "file", filename);
7951c4eb
YQ
350}
351
352/* Save the trace data to file FILENAME of tfile format. */
353
354void
355trace_save_tfile (const char *filename, int target_does_save)
356{
d14b92bf
TT
357 trace_file_writer_up writer (tfile_trace_file_writer_new ());
358 trace_save (filename, writer.get (), target_does_save);
7951c4eb
YQ
359}
360
361/* Save the trace data to dir DIRNAME of ctf format. */
362
363void
364trace_save_ctf (const char *dirname, int target_does_save)
365{
d14b92bf
TT
366 trace_file_writer_up writer (ctf_trace_file_writer_new ());
367 trace_save (dirname, writer.get (), target_does_save);
7951c4eb
YQ
368}
369
48b6e87e
YQ
370/* Fetch register data from tracefile, shared for both tfile and
371 ctf. */
372
373void
374tracefile_fetch_registers (struct regcache *regcache, int regno)
375{
ac7936df 376 struct gdbarch *gdbarch = regcache->arch ();
5f034a78
MK
377 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
378 int regn;
48b6e87e
YQ
379
380 /* We get here if no register data has been found. Mark registers
381 as unavailable. */
382 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
73e1c03f 383 regcache->raw_supply (regn, NULL);
48b6e87e
YQ
384
385 /* We can often usefully guess that the PC is going to be the same
386 as the address of the tracepoint. */
c1fc2657 387 if (tp == NULL || tp->loc == NULL)
48b6e87e
YQ
388 return;
389
5f034a78 390 /* But don't try to guess if tracepoint is multi-location... */
c1fc2657 391 if (tp->loc->next)
48b6e87e 392 {
5f034a78
MK
393 warning (_("Tracepoint %d has multiple "
394 "locations, cannot infer $pc"),
c1fc2657 395 tp->number);
5f034a78
MK
396 return;
397 }
398 /* ... or does while-stepping. */
399 else if (tp->step_count > 0)
400 {
401 warning (_("Tracepoint %d does while-stepping, "
402 "cannot infer $pc"),
c1fc2657 403 tp->number);
5f034a78 404 return;
48b6e87e 405 }
5f034a78
MK
406
407 /* Guess what we can from the tracepoint location. */
408 gdbarch_guess_tracepoint_registers (gdbarch, regcache,
c1fc2657 409 tp->loc->address);
48b6e87e
YQ
410}
411
a283690e
YQ
412/* This is the implementation of target_ops method to_has_all_memory. */
413
57810aa7 414bool
f6ac5f3d 415tracefile_target::has_all_memory ()
a283690e
YQ
416{
417 return 1;
418}
419
420/* This is the implementation of target_ops method to_has_memory. */
421
57810aa7 422bool
f6ac5f3d 423tracefile_target::has_memory ()
a283690e
YQ
424{
425 return 1;
426}
427
12e03cd0
YQ
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
430 frame. */
431
57810aa7 432bool
f6ac5f3d 433tracefile_target::has_stack ()
12e03cd0
YQ
434{
435 return get_traceframe_number () != -1;
436}
437
438/* This is the implementation of target_ops method to_has_registers.
439 The target has registers when GDB has already selected one trace
440 frame. */
441
57810aa7 442bool
f6ac5f3d 443tracefile_target::has_registers ()
12e03cd0
YQ
444{
445 return get_traceframe_number () != -1;
446}
447
448/* This is the implementation of target_ops method to_thread_alive.
449 tracefile has one thread faked by GDB. */
450
57810aa7 451bool
f6ac5f3d 452tracefile_target::thread_alive (ptid_t ptid)
12e03cd0
YQ
453{
454 return 1;
455}
456
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. */
459
f6ac5f3d
PA
460int
461tracefile_target::get_trace_status (struct trace_status *ts)
12e03cd0
YQ
462{
463 /* Other bits of trace status were collected as part of opening the
464 trace files, so nothing to do here. */
465
466 return -1;
467}
468
f6ac5f3d 469tracefile_target::tracefile_target ()
12e03cd0 470{
f6ac5f3d 471 this->to_stratum = process_stratum;
12e03cd0
YQ
472}
473
7951c4eb
YQ
474void
475_initialize_tracefile (void)
476{
e5a873b7 477 add_com ("tsave", class_trace, tsave_command, _("\
7951c4eb
YQ
478Save the trace data to a file.\n\
479Use the '-ctf' option to save the data to CTF format.\n\
480Use the '-r' option to direct the target to save directly to the file,\n\
481using its own filesystem."));
482}
This page took 0.516999 seconds and 4 git commands to generate.