Move the context stack to buildsym_compunit
[deliverable/binutils-gdb.git] / gdb / tracefile.c
1 /* Trace file support in GDB.
2
3 Copyright (C) 1997-2018 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 /* A unique pointer policy class for trace_file_writer. */
40
41 struct trace_file_writer_deleter
42 {
43 void operator() (struct trace_file_writer *writer)
44 {
45 writer->ops->dtor (writer);
46 xfree (writer);
47 }
48 };
49
50 /* A unique_ptr specialization for trace_file_writer. */
51
52 typedef std::unique_ptr<trace_file_writer, trace_file_writer_deleter>
53 trace_file_writer_up;
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
60 static void
61 trace_save (const char *filename, struct trace_file_writer *writer,
62 int target_does_save)
63 {
64 struct trace_status *ts = current_trace_status ();
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];
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
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);
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
98 /* Write out the target description info. */
99 writer->ops->write_tdesc (writer);
100
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
313 static void
314 tsave_command (const char *args, int from_tty)
315 {
316 int target_does_save = 0;
317 char **argv;
318 char *filename = NULL;
319 int generate_ctf = 0;
320
321 if (args == NULL)
322 error_no_arg (_("file in which to save trace data"));
323
324 gdb_argv built_argv (args);
325 argv = built_argv.get ();
326
327 for (; *argv; ++argv)
328 {
329 if (strcmp (*argv, "-r") == 0)
330 target_does_save = 1;
331 else if (strcmp (*argv, "-ctf") == 0)
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)
343 trace_save_ctf (filename, target_does_save);
344 else
345 trace_save_tfile (filename, target_does_save);
346
347 if (from_tty)
348 printf_filtered (_("Trace data saved to %s '%s'.\n"),
349 generate_ctf ? "directory" : "file", filename);
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 trace_file_writer_up writer (tfile_trace_file_writer_new ());
358 trace_save (filename, writer.get (), target_does_save);
359 }
360
361 /* Save the trace data to dir DIRNAME of ctf format. */
362
363 void
364 trace_save_ctf (const char *dirname, int target_does_save)
365 {
366 trace_file_writer_up writer (ctf_trace_file_writer_new ());
367 trace_save (dirname, writer.get (), target_does_save);
368 }
369
370 /* Fetch register data from tracefile, shared for both tfile and
371 ctf. */
372
373 void
374 tracefile_fetch_registers (struct regcache *regcache, int regno)
375 {
376 struct gdbarch *gdbarch = regcache->arch ();
377 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
378 int regn;
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++)
383 regcache->raw_supply (regn, NULL);
384
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)
388 return;
389
390 /* But don't try to guess if tracepoint is multi-location... */
391 if (tp->loc->next)
392 {
393 warning (_("Tracepoint %d has multiple "
394 "locations, cannot infer $pc"),
395 tp->number);
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"),
403 tp->number);
404 return;
405 }
406
407 /* Guess what we can from the tracepoint location. */
408 gdbarch_guess_tracepoint_registers (gdbarch, regcache,
409 tp->loc->address);
410 }
411
412 /* This is the implementation of target_ops method to_has_all_memory. */
413
414 bool
415 tracefile_target::has_all_memory ()
416 {
417 return 1;
418 }
419
420 /* This is the implementation of target_ops method to_has_memory. */
421
422 bool
423 tracefile_target::has_memory ()
424 {
425 return 1;
426 }
427
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
432 bool
433 tracefile_target::has_stack ()
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
442 bool
443 tracefile_target::has_registers ()
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
451 bool
452 tracefile_target::thread_alive (ptid_t ptid)
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
460 int
461 tracefile_target::get_trace_status (struct trace_status *ts)
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
469 tracefile_target::tracefile_target ()
470 {
471 this->to_stratum = process_stratum;
472 }
473
474 void
475 _initialize_tracefile (void)
476 {
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."));
482 }
This page took 0.044804 seconds and 4 git commands to generate.