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