Replace copyreloc-main.c with copyreloc-main.S
[platform/upstream/binutils.git] / gdb / tracefile.c
1 /* Trace file support in GDB.
2
3    Copyright (C) 1997-2014 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 }