Update year range in copyright notice of all files owned by the GDB project.
[deliverable/binutils-gdb.git] / gdb / tracefile.c
1 /* Trace file support in GDB.
2
3 Copyright (C) 1997-2015 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 "ctf.h"
23 #include "exec.h"
24 #include "regcache.h"
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
39 /* Free trace file writer. */
40
41 static void
42 trace_file_writer_xfree (void *arg)
43 {
44 struct trace_file_writer *writer = arg;
45
46 writer->ops->dtor (writer);
47 xfree (writer);
48 }
49
50 /* Save tracepoint data to file named FILENAME through WRITER. WRITER
51 determines the trace file format. If TARGET_DOES_SAVE is non-zero,
52 the save is performed on the target, otherwise GDB obtains all trace
53 data and saves it locally. */
54
55 static void
56 trace_save (const char *filename, struct trace_file_writer *writer,
57 int target_does_save)
58 {
59 struct trace_status *ts = current_trace_status ();
60 int status;
61 struct uploaded_tp *uploaded_tps = NULL, *utp;
62 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
63
64 ULONGEST offset = 0;
65 #define MAX_TRACE_UPLOAD 2000
66 gdb_byte buf[MAX_TRACE_UPLOAD];
67 int written;
68 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
69
70 /* If the target is to save the data to a file on its own, then just
71 send the command and be done with it. */
72 if (target_does_save)
73 {
74 if (!writer->ops->target_save (writer, filename))
75 error (_("Target failed to save trace data to '%s'."),
76 filename);
77 return;
78 }
79
80 /* Get the trace status first before opening the file, so if the
81 target is losing, we can get out without touching files. */
82 status = target_get_trace_status (ts);
83
84 writer->ops->start (writer, filename);
85
86 writer->ops->write_header (writer);
87
88 /* Write descriptive info. */
89
90 /* Write out the size of a register block. */
91 writer->ops->write_regblock_type (writer, trace_regblock_size);
92
93 /* Write out status of the tracing run (aka "tstatus" info). */
94 writer->ops->write_status (writer, ts);
95
96 /* Note that we want to upload tracepoints and save those, rather
97 than simply writing out the local ones, because the user may have
98 changed tracepoints in GDB in preparation for a future tracing
99 run, or maybe just mass-deleted all types of breakpoints as part
100 of cleaning up. So as not to contaminate the session, leave the
101 data in its uploaded form, don't make into real tracepoints. */
102
103 /* Get trace state variables first, they may be checked when parsing
104 uploaded commands. */
105
106 target_upload_trace_state_variables (&uploaded_tsvs);
107
108 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
109 writer->ops->write_uploaded_tsv (writer, utsv);
110
111 free_uploaded_tsvs (&uploaded_tsvs);
112
113 target_upload_tracepoints (&uploaded_tps);
114
115 for (utp = uploaded_tps; utp; utp = utp->next)
116 target_get_tracepoint_status (NULL, utp);
117
118 for (utp = uploaded_tps; utp; utp = utp->next)
119 writer->ops->write_uploaded_tp (writer, utp);
120
121 free_uploaded_tps (&uploaded_tps);
122
123 /* Mark the end of the definition section. */
124 writer->ops->write_definition_end (writer);
125
126 /* Get and write the trace data proper. */
127 while (1)
128 {
129 LONGEST gotten = 0;
130
131 /* The writer supports writing the contents of trace buffer
132 directly to trace file. Don't parse the contents of trace
133 buffer. */
134 if (writer->ops->write_trace_buffer != NULL)
135 {
136 /* We ask for big blocks, in the hopes of efficiency, but
137 will take less if the target has packet size limitations
138 or some such. */
139 gotten = target_get_raw_trace_data (buf, offset,
140 MAX_TRACE_UPLOAD);
141 if (gotten < 0)
142 error (_("Failure to get requested trace buffer data"));
143 /* No more data is forthcoming, we're done. */
144 if (gotten == 0)
145 break;
146
147 writer->ops->write_trace_buffer (writer, buf, gotten);
148
149 offset += gotten;
150 }
151 else
152 {
153 uint16_t tp_num;
154 uint32_t tf_size;
155 /* Parse the trace buffers according to how data are stored
156 in trace buffer in GDBserver. */
157
158 gotten = target_get_raw_trace_data (buf, offset, 6);
159
160 if (gotten == 0)
161 break;
162
163 /* Read the first six bytes in, which is the tracepoint
164 number and trace frame size. */
165 tp_num = (uint16_t)
166 extract_unsigned_integer (&buf[0], 2, byte_order);
167
168 tf_size = (uint32_t)
169 extract_unsigned_integer (&buf[2], 4, byte_order);
170
171 writer->ops->frame_ops->start (writer, tp_num);
172 gotten = 6;
173
174 if (tf_size > 0)
175 {
176 unsigned int block;
177
178 offset += 6;
179
180 for (block = 0; block < tf_size; )
181 {
182 gdb_byte block_type;
183
184 /* We'll fetch one block each time, in order to
185 handle the extremely large 'M' block. We first
186 fetch one byte to get the type of the block. */
187 gotten = target_get_raw_trace_data (buf, offset, 1);
188 if (gotten < 1)
189 error (_("Failure to get requested trace buffer data"));
190
191 gotten = 1;
192 block += 1;
193 offset += 1;
194
195 block_type = buf[0];
196 switch (block_type)
197 {
198 case 'R':
199 gotten
200 = target_get_raw_trace_data (buf, offset,
201 trace_regblock_size);
202 if (gotten < trace_regblock_size)
203 error (_("Failure to get requested trace"
204 " buffer data"));
205
206 TRACE_WRITE_R_BLOCK (writer, buf,
207 trace_regblock_size);
208 break;
209 case 'M':
210 {
211 unsigned short mlen;
212 ULONGEST addr;
213 LONGEST t;
214 int j;
215
216 t = target_get_raw_trace_data (buf,offset, 10);
217 if (t < 10)
218 error (_("Failure to get requested trace"
219 " buffer data"));
220
221 offset += 10;
222 block += 10;
223
224 gotten = 0;
225 addr = (ULONGEST)
226 extract_unsigned_integer (buf, 8,
227 byte_order);
228 mlen = (unsigned short)
229 extract_unsigned_integer (&buf[8], 2,
230 byte_order);
231
232 TRACE_WRITE_M_BLOCK_HEADER (writer, addr,
233 mlen);
234
235 /* The memory contents in 'M' block may be
236 very large. Fetch the data from the target
237 and write them into file one by one. */
238 for (j = 0; j < mlen; )
239 {
240 unsigned int read_length;
241
242 if (mlen - j > MAX_TRACE_UPLOAD)
243 read_length = MAX_TRACE_UPLOAD;
244 else
245 read_length = mlen - j;
246
247 t = target_get_raw_trace_data (buf,
248 offset + j,
249 read_length);
250 if (t < read_length)
251 error (_("Failure to get requested"
252 " trace buffer data"));
253
254 TRACE_WRITE_M_BLOCK_MEMORY (writer, buf,
255 read_length);
256
257 j += read_length;
258 gotten += read_length;
259 }
260
261 break;
262 }
263 case 'V':
264 {
265 int vnum;
266 LONGEST val;
267
268 gotten
269 = target_get_raw_trace_data (buf, offset,
270 12);
271 if (gotten < 12)
272 error (_("Failure to get requested"
273 " trace buffer data"));
274
275 vnum = (int) extract_signed_integer (buf,
276 4,
277 byte_order);
278 val
279 = extract_signed_integer (&buf[4], 8,
280 byte_order);
281
282 TRACE_WRITE_V_BLOCK (writer, vnum, val);
283 }
284 break;
285 default:
286 error (_("Unknown block type '%c' (0x%x) in"
287 " trace frame"),
288 block_type, block_type);
289 }
290
291 block += gotten;
292 offset += gotten;
293 }
294 }
295 else
296 offset += gotten;
297
298 writer->ops->frame_ops->end (writer);
299 }
300 }
301
302 writer->ops->end (writer);
303 }
304
305 static void
306 trace_save_command (char *args, int from_tty)
307 {
308 int target_does_save = 0;
309 char **argv;
310 char *filename = NULL;
311 struct cleanup *back_to;
312 int generate_ctf = 0;
313 struct trace_file_writer *writer = NULL;
314
315 if (args == NULL)
316 error_no_arg (_("file in which to save trace data"));
317
318 argv = gdb_buildargv (args);
319 back_to = make_cleanup_freeargv (argv);
320
321 for (; *argv; ++argv)
322 {
323 if (strcmp (*argv, "-r") == 0)
324 target_does_save = 1;
325 if (strcmp (*argv, "-ctf") == 0)
326 generate_ctf = 1;
327 else if (**argv == '-')
328 error (_("unknown option `%s'"), *argv);
329 else
330 filename = *argv;
331 }
332
333 if (!filename)
334 error_no_arg (_("file in which to save trace data"));
335
336 if (generate_ctf)
337 writer = ctf_trace_file_writer_new ();
338 else
339 writer = tfile_trace_file_writer_new ();
340
341 make_cleanup (trace_file_writer_xfree, writer);
342
343 trace_save (filename, writer, target_does_save);
344
345 if (from_tty)
346 printf_filtered (_("Trace data saved to %s '%s'.\n"),
347 generate_ctf ? "directory" : "file", filename);
348
349 do_cleanups (back_to);
350 }
351
352 /* Save the trace data to file FILENAME of tfile format. */
353
354 void
355 trace_save_tfile (const char *filename, int target_does_save)
356 {
357 struct trace_file_writer *writer;
358 struct cleanup *back_to;
359
360 writer = tfile_trace_file_writer_new ();
361 back_to = make_cleanup (trace_file_writer_xfree, writer);
362 trace_save (filename, writer, target_does_save);
363 do_cleanups (back_to);
364 }
365
366 /* Save the trace data to dir DIRNAME of ctf format. */
367
368 void
369 trace_save_ctf (const char *dirname, int target_does_save)
370 {
371 struct trace_file_writer *writer;
372 struct cleanup *back_to;
373
374 writer = ctf_trace_file_writer_new ();
375 back_to = make_cleanup (trace_file_writer_xfree, writer);
376
377 trace_save (dirname, writer, target_does_save);
378 do_cleanups (back_to);
379 }
380
381 /* Fetch register data from tracefile, shared for both tfile and
382 ctf. */
383
384 void
385 tracefile_fetch_registers (struct regcache *regcache, int regno)
386 {
387 struct gdbarch *gdbarch = get_regcache_arch (regcache);
388 int regn, pc_regno;
389
390 /* We get here if no register data has been found. Mark registers
391 as unavailable. */
392 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
393 regcache_raw_supply (regcache, regn, NULL);
394
395 /* We can often usefully guess that the PC is going to be the same
396 as the address of the tracepoint. */
397 pc_regno = gdbarch_pc_regnum (gdbarch);
398
399 /* XXX This guessing code below only works if the PC register isn't
400 a pseudo-register. The value of a pseudo-register isn't stored
401 in the (non-readonly) regcache -- instead it's recomputed
402 (probably from some other cached raw register) whenever the
403 register is read. This guesswork should probably move to some
404 higher layer. */
405 if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
406 return;
407
408 if (regno == -1 || regno == pc_regno)
409 {
410 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
411 gdb_byte *regs;
412
413 if (tp && tp->base.loc)
414 {
415 /* But don't try to guess if tracepoint is multi-location... */
416 if (tp->base.loc->next)
417 {
418 warning (_("Tracepoint %d has multiple "
419 "locations, cannot infer $pc"),
420 tp->base.number);
421 return;
422 }
423 /* ... or does while-stepping. */
424 if (tp->step_count > 0)
425 {
426 warning (_("Tracepoint %d does while-stepping, "
427 "cannot infer $pc"),
428 tp->base.number);
429 return;
430 }
431
432 regs = alloca (register_size (gdbarch, pc_regno));
433 store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
434 gdbarch_byte_order (gdbarch),
435 tp->base.loc->address);
436 regcache_raw_supply (regcache, pc_regno, regs);
437 }
438 }
439 }
440
441 /* This is the implementation of target_ops method to_has_all_memory. */
442
443 static int
444 tracefile_has_all_memory (struct target_ops *ops)
445 {
446 return 1;
447 }
448
449 /* This is the implementation of target_ops method to_has_memory. */
450
451 static int
452 tracefile_has_memory (struct target_ops *ops)
453 {
454 return 1;
455 }
456
457 /* This is the implementation of target_ops method to_has_stack.
458 The target has a stack when GDB has already selected one trace
459 frame. */
460
461 static int
462 tracefile_has_stack (struct target_ops *ops)
463 {
464 return get_traceframe_number () != -1;
465 }
466
467 /* This is the implementation of target_ops method to_has_registers.
468 The target has registers when GDB has already selected one trace
469 frame. */
470
471 static int
472 tracefile_has_registers (struct target_ops *ops)
473 {
474 return get_traceframe_number () != -1;
475 }
476
477 /* This is the implementation of target_ops method to_thread_alive.
478 tracefile has one thread faked by GDB. */
479
480 static int
481 tracefile_thread_alive (struct target_ops *ops, ptid_t ptid)
482 {
483 return 1;
484 }
485
486 /* This is the implementation of target_ops method to_get_trace_status.
487 The trace status for a file is that tracing can never be run. */
488
489 static int
490 tracefile_get_trace_status (struct target_ops *self, struct trace_status *ts)
491 {
492 /* Other bits of trace status were collected as part of opening the
493 trace files, so nothing to do here. */
494
495 return -1;
496 }
497
498 /* Initialize OPS for tracefile related targets. */
499
500 void
501 init_tracefile_ops (struct target_ops *ops)
502 {
503 ops->to_stratum = process_stratum;
504 ops->to_get_trace_status = tracefile_get_trace_status;
505 ops->to_has_all_memory = tracefile_has_all_memory;
506 ops->to_has_memory = tracefile_has_memory;
507 ops->to_has_stack = tracefile_has_stack;
508 ops->to_has_registers = tracefile_has_registers;
509 ops->to_thread_alive = tracefile_thread_alive;
510 ops->to_magic = OPS_MAGIC;
511 }
512
513 extern initialize_file_ftype _initialize_tracefile;
514
515 void
516 _initialize_tracefile (void)
517 {
518 add_com ("tsave", class_trace, trace_save_command, _("\
519 Save the trace data to a file.\n\
520 Use the '-ctf' option to save the data to CTF format.\n\
521 Use the '-r' option to direct the target to save directly to the file,\n\
522 using its own filesystem."));
523 }
This page took 0.041042 seconds and 5 git commands to generate.