GDB (xrefs)
Loading...
Searching...
No Matches
tracefile-tfile.c
Go to the documentation of this file.
1/* Trace file TFILE format support in GDB.
2
3 Copyright (C) 1997-2023 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 "readline/tilde.h"
23#include "gdbsupport/filestuff.h"
24#include "gdbsupport/rsp-low.h"
25#include "regcache.h"
26#include "inferior.h"
27#include "gdbthread.h"
28#include "exec.h"
29#include "completer.h"
30#include "filenames.h"
31#include "remote.h"
32#include "xml-tdesc.h"
33#include "target-descriptions.h"
34#include "gdbsupport/pathstuff.h"
35#include <algorithm>
36
37#ifndef O_LARGEFILE
38#define O_LARGEFILE 0
39#endif
40
41/* The tfile target. */
42
44 "tfile",
45 N_("Local trace dump file"),
46 N_("Use a trace file as a target.\n\
47Specify the filename of the trace file.")
48};
49
50class tfile_target final : public tracefile_target
51{
52 public:
53 const target_info &info () const override
54 { return tfile_target_info; }
55
56 void close () override;
57 void fetch_registers (struct regcache *, int) override;
59 const char *annex,
60 gdb_byte *readbuf,
61 const gdb_byte *writebuf,
62 ULONGEST offset, ULONGEST len,
63 ULONGEST *xfered_len) override;
64 void files_info () override;
65 int trace_find (enum trace_find_type type, int num,
66 CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) override;
67 bool get_trace_state_variable_value (int tsv, LONGEST *val) override;
69
71 struct uploaded_tp *utp) override;
72};
73
74/* TFILE trace writer. */
75
77{
79
80 /* File pointer to tfile trace file. */
81 FILE *fp;
82 /* Path name of the tfile trace file. */
83 char *pathname;
84};
85
86/* This is the implementation of trace_file_write_ops method
87 target_save. We just call the generic target
88 target_save_trace_data to do target-side saving. */
89
90static int
92 const char *filename)
93{
94 int err = target_save_trace_data (filename);
95
96 return (err >= 0);
97}
98
99/* This is the implementation of trace_file_write_ops method
100 dtor. */
101
102static void
104{
105 struct tfile_trace_file_writer *writer
106 = (struct tfile_trace_file_writer *) self;
107
108 xfree (writer->pathname);
109
110 if (writer->fp != NULL)
111 fclose (writer->fp);
112}
113
114/* This is the implementation of trace_file_write_ops method
115 start. It creates the trace file FILENAME and registers some
116 cleanups. */
117
118static void
119tfile_start (struct trace_file_writer *self, const char *filename)
120{
121 struct tfile_trace_file_writer *writer
122 = (struct tfile_trace_file_writer *) self;
123
124 writer->pathname = tilde_expand (filename);
125 writer->fp = gdb_fopen_cloexec (writer->pathname, "wb").release ();
126 if (writer->fp == NULL)
127 error (_("Unable to open file '%s' for saving trace data (%s)"),
128 writer->pathname, safe_strerror (errno));
129}
130
131/* This is the implementation of trace_file_write_ops method
132 write_header. Write the TFILE header. */
133
134static void
136{
137 struct tfile_trace_file_writer *writer
138 = (struct tfile_trace_file_writer *) self;
139 int written;
140
141 /* Write a file header, with a high-bit-set char to indicate a
142 binary file, plus a hint as what this file is, and a version
143 number in case of future needs. */
144 written = fwrite ("\x7fTRACE0\n", 8, 1, writer->fp);
145 if (written < 1)
146 perror_with_name (writer->pathname);
147}
148
149/* This is the implementation of trace_file_write_ops method
150 write_regblock_type. Write the size of register block. */
151
152static void
154{
155 struct tfile_trace_file_writer *writer
156 = (struct tfile_trace_file_writer *) self;
157
158 fprintf (writer->fp, "R %x\n", size);
159}
160
161/* This is the implementation of trace_file_write_ops method
162 write_status. */
163
164static void
166 struct trace_status *ts)
167{
168 struct tfile_trace_file_writer *writer
169 = (struct tfile_trace_file_writer *) self;
170
171 fprintf (writer->fp, "status %c;%s",
172 (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
175 {
176 char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
177
178 bin2hex ((gdb_byte *) ts->stop_desc, buf, strlen (ts->stop_desc));
179 fprintf (writer->fp, ":%s", buf);
180 }
181 fprintf (writer->fp, ":%x", ts->stopping_tracepoint);
182 if (ts->traceframe_count >= 0)
183 fprintf (writer->fp, ";tframes:%x", ts->traceframe_count);
184 if (ts->traceframes_created >= 0)
185 fprintf (writer->fp, ";tcreated:%x", ts->traceframes_created);
186 if (ts->buffer_free >= 0)
187 fprintf (writer->fp, ";tfree:%x", ts->buffer_free);
188 if (ts->buffer_size >= 0)
189 fprintf (writer->fp, ";tsize:%x", ts->buffer_size);
190 if (ts->disconnected_tracing)
191 fprintf (writer->fp, ";disconn:%x", ts->disconnected_tracing);
192 if (ts->circular_buffer)
193 fprintf (writer->fp, ";circular:%x", ts->circular_buffer);
194 if (ts->start_time)
195 {
196 fprintf (writer->fp, ";starttime:%s",
197 phex_nz (ts->start_time, sizeof (ts->start_time)));
198 }
199 if (ts->stop_time)
200 {
201 fprintf (writer->fp, ";stoptime:%s",
202 phex_nz (ts->stop_time, sizeof (ts->stop_time)));
203 }
204 if (ts->notes != NULL)
205 {
206 char *buf = (char *) alloca (strlen (ts->notes) * 2 + 1);
207
208 bin2hex ((gdb_byte *) ts->notes, buf, strlen (ts->notes));
209 fprintf (writer->fp, ";notes:%s", buf);
210 }
211 if (ts->user_name != NULL)
212 {
213 char *buf = (char *) alloca (strlen (ts->user_name) * 2 + 1);
214
215 bin2hex ((gdb_byte *) ts->user_name, buf, strlen (ts->user_name));
216 fprintf (writer->fp, ";username:%s", buf);
217 }
218 fprintf (writer->fp, "\n");
219}
220
221/* This is the implementation of trace_file_write_ops method
222 write_uploaded_tsv. */
223
224static void
226 struct uploaded_tsv *utsv)
227{
228 gdb::unique_xmalloc_ptr<char> buf;
229 struct tfile_trace_file_writer *writer
230 = (struct tfile_trace_file_writer *) self;
231
232 if (utsv->name)
233 {
234 buf.reset ((char *) xmalloc (strlen (utsv->name) * 2 + 1));
235 bin2hex ((gdb_byte *) (utsv->name), buf.get (), strlen (utsv->name));
236 }
237
238 fprintf (writer->fp, "tsv %x:%s:%x:%s\n",
239 utsv->number, phex_nz (utsv->initial_value, 8),
240 utsv->builtin, buf != NULL ? buf.get () : "");
241}
242
243#define MAX_TRACE_UPLOAD 2000
244
245/* This is the implementation of trace_file_write_ops method
246 write_uploaded_tp. */
247
248static void
250 struct uploaded_tp *utp)
251{
252 struct tfile_trace_file_writer *writer
253 = (struct tfile_trace_file_writer *) self;
254 char buf[MAX_TRACE_UPLOAD];
255
256 fprintf (writer->fp, "tp T%x:%s:%c:%x:%x",
257 utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
258 (utp->enabled ? 'E' : 'D'), utp->step, utp->pass);
259 if (utp->type == bp_fast_tracepoint)
260 fprintf (writer->fp, ":F%x", utp->orig_size);
261 if (utp->cond)
262 fprintf (writer->fp,
263 ":X%x,%s", (unsigned int) strlen (utp->cond.get ()) / 2,
264 utp->cond.get ());
265 fprintf (writer->fp, "\n");
266 for (const auto &act : utp->actions)
267 fprintf (writer->fp, "tp A%x:%s:%s\n",
268 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act.get ());
269 for (const auto &act : utp->step_actions)
270 fprintf (writer->fp, "tp S%x:%s:%s\n",
271 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act.get ());
272 if (utp->at_string)
273 {
274 encode_source_string (utp->number, utp->addr,
275 "at", utp->at_string.get (),
276 buf, MAX_TRACE_UPLOAD);
277 fprintf (writer->fp, "tp Z%s\n", buf);
278 }
279 if (utp->cond_string)
280 {
281 encode_source_string (utp->number, utp->addr,
282 "cond", utp->cond_string.get (),
283 buf, MAX_TRACE_UPLOAD);
284 fprintf (writer->fp, "tp Z%s\n", buf);
285 }
286 for (const auto &act : utp->cmd_strings)
287 {
288 encode_source_string (utp->number, utp->addr, "cmd", act.get (),
289 buf, MAX_TRACE_UPLOAD);
290 fprintf (writer->fp, "tp Z%s\n", buf);
291 }
292 fprintf (writer->fp, "tp V%x:%s:%x:%s\n",
293 utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
294 utp->hit_count,
295 phex_nz (utp->traceframe_usage,
296 sizeof (utp->traceframe_usage)));
297}
298
299/* This is the implementation of trace_file_write_ops method
300 write_tdesc. */
301
302static void
304{
305 struct tfile_trace_file_writer *writer
306 = (struct tfile_trace_file_writer *) self;
307
308 gdb::optional<std::string> tdesc
310
311 if (!tdesc)
312 return;
313
314 const char *ptr = tdesc->c_str ();
315
316 /* Write tdesc line by line, prefixing each line with "tdesc ". */
317 while (ptr != NULL)
318 {
319 const char *next = strchr (ptr, '\n');
320 if (next != NULL)
321 {
322 fprintf (writer->fp, "tdesc %.*s\n", (int) (next - ptr), ptr);
323 /* Skip the \n. */
324 next++;
325 }
326 else if (*ptr != '\0')
327 {
328 /* Last line, doesn't have a newline. */
329 fprintf (writer->fp, "tdesc %s\n", ptr);
330 }
331 ptr = next;
332 }
333}
334
335/* This is the implementation of trace_file_write_ops method
336 write_definition_end. */
337
338static void
340{
341 struct tfile_trace_file_writer *writer
342 = (struct tfile_trace_file_writer *) self;
343
344 fprintf (writer->fp, "\n");
345}
346
347/* This is the implementation of trace_file_write_ops method
348 write_raw_data. */
349
350static void
351tfile_write_raw_data (struct trace_file_writer *self, gdb_byte *buf,
352 LONGEST len)
353{
354 struct tfile_trace_file_writer *writer
355 = (struct tfile_trace_file_writer *) self;
356
357 if (fwrite (buf, len, 1, writer->fp) < 1)
358 perror_with_name (writer->pathname);
359}
360
361/* This is the implementation of trace_file_write_ops method
362 end. */
363
364static void
366{
367 struct tfile_trace_file_writer *writer
368 = (struct tfile_trace_file_writer *) self;
369 uint32_t gotten = 0;
370
371 /* Mark the end of trace data. */
372 if (fwrite (&gotten, 4, 1, writer->fp) < 1)
373 perror_with_name (writer->pathname);
374}
375
376/* Operations to write trace buffers into TFILE format. */
377
394
395/* Return a trace writer for TFILE format. */
396
397struct trace_file_writer *
399{
400 struct tfile_trace_file_writer *writer
401 = XNEW (struct tfile_trace_file_writer);
402
403 writer->base.ops = &tfile_write_ops;
404 writer->fp = NULL;
405 writer->pathname = NULL;
406
407 return (struct trace_file_writer *) writer;
408}
409
410/* target tfile command */
411
413
414#define TRACE_HEADER_SIZE 8
415
416#define TFILE_PID (1)
417
418static gdb::unique_xmalloc_ptr<char> trace_filename;
419static int trace_fd = -1;
421static off_t cur_offset;
422static int cur_data_size;
424static std::string trace_tdesc;
425
426static void tfile_append_tdesc_line (const char *line);
427static void tfile_interp_line (const char *line,
428 struct uploaded_tp **utpp,
429 struct uploaded_tsv **utsvp);
430
431/* Read SIZE bytes into READBUF from the trace frame, starting at
432 TRACE_FD's current position. Note that this call `read'
433 underneath, hence it advances the file's seek position. Throws an
434 error if the `read' syscall fails, or less than SIZE bytes are
435 read. */
436
437static void
438tfile_read (gdb_byte *readbuf, int size)
439{
440 int gotten;
441
442 gotten = read (trace_fd, readbuf, size);
443 if (gotten < 0)
444 perror_with_name (trace_filename.get ());
445 else if (gotten < size)
446 error (_("Premature end of file while reading trace file"));
447}
448
449/* Open the tfile target. */
450
451static void
452tfile_target_open (const char *arg, int from_tty)
453{
454 int flags;
455 int scratch_chan;
456 char header[TRACE_HEADER_SIZE];
457 char linebuf[1000]; /* Should be max remote packet size or so. */
458 gdb_byte byte;
459 int bytes, i;
460 struct trace_status *ts;
461 struct uploaded_tp *uploaded_tps = NULL;
462 struct uploaded_tsv *uploaded_tsvs = NULL;
463
464 target_preopen (from_tty);
465 if (!arg)
466 error (_("No trace file specified."));
467
468 gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
469 if (!IS_ABSOLUTE_PATH (filename.get ()))
470 filename = make_unique_xstrdup (gdb_abspath (filename.get ()).c_str ());
471
473 flags |= O_RDONLY;
474 scratch_chan = gdb_open_cloexec (filename.get (), flags, 0).release ();
475 if (scratch_chan < 0)
476 perror_with_name (filename.get ());
477
478 /* Looks semi-reasonable. Toss the old trace file and work on the new. */
479
481
482 trace_filename = std::move (filename);
483 trace_fd = scratch_chan;
484
485 /* Make sure this is clear. */
486 trace_tdesc.clear ();
487
488 bytes = 0;
489 /* Read the file header and test for validity. */
490 tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE);
491
492 bytes += TRACE_HEADER_SIZE;
493 if (!(header[0] == 0x7f
494 && (startswith (header + 1, "TRACE0\n"))))
495 error (_("File is not a valid trace file."));
496
498
500 ts = current_trace_status ();
501 /* We know we're working with a file. Record its name. */
502 ts->filename = trace_filename.get ();
503 /* Set defaults in case there is no status line. */
504 ts->running_known = 0;
506 ts->traceframe_count = -1;
507 ts->buffer_free = 0;
508 ts->disconnected_tracing = 0;
509 ts->circular_buffer = 0;
510
511 try
512 {
513 /* Read through a section of newline-terminated lines that
514 define things like tracepoints. */
515 i = 0;
516 while (1)
517 {
518 tfile_read (&byte, 1);
519
520 ++bytes;
521 if (byte == '\n')
522 {
523 /* Empty line marks end of the definition section. */
524 if (i == 0)
525 break;
526 linebuf[i] = '\0';
527 i = 0;
528 tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs);
529 }
530 else
531 linebuf[i++] = byte;
532 if (i >= 1000)
533 error (_("Excessively long lines in trace file"));
534 }
535
536 /* By now, tdesc lines have been read from tfile - let's parse them. */
538
539 /* Record the starting offset of the binary trace data. */
540 trace_frames_offset = bytes;
541
542 /* If we don't have a blocksize, we can't interpret the
543 traceframes. */
544 if (trace_regblock_size == 0)
545 error (_("No register block size recorded in trace file"));
546 }
547 catch (const gdb_exception &ex)
548 {
549 /* Remove the partially set up target. */
551 throw;
552 }
553
555
557 switch_to_thread (thr);
558
559 if (ts->traceframe_count <= 0)
560 warning (_("No traceframes present in this file."));
561
562 /* Add the file's tracepoints and variables into the current mix. */
563
564 /* Get trace state variables first, they may be checked when parsing
565 uploaded commands. */
567
568 merge_uploaded_tracepoints (&uploaded_tps);
569
570 post_create_inferior (from_tty);
571}
572
573/* Interpret the given line from the definitions part of the trace
574 file. */
575
576static void
577tfile_interp_line (const char *line, struct uploaded_tp **utpp,
578 struct uploaded_tsv **utsvp)
579{
580 const char *p = line;
581
582 if (startswith (p, "R "))
583 {
584 p += strlen ("R ");
585 trace_regblock_size = strtol (p, nullptr, 16);
586 }
587 else if (startswith (p, "status "))
588 {
589 p += strlen ("status ");
591 }
592 else if (startswith (p, "tp "))
593 {
594 p += strlen ("tp ");
596 }
597 else if (startswith (p, "tsv "))
598 {
599 p += strlen ("tsv ");
600 parse_tsv_definition (p, utsvp);
601 }
602 else if (startswith (p, "tdesc "))
603 {
604 p += strlen ("tdesc ");
606 }
607 else
608 warning (_("Ignoring trace file definition \"%s\""), line);
609}
610
611/* Close the trace file and generally clean up. */
612
613void
615{
616 gdb_assert (trace_fd != -1);
617
618 switch_to_no_thread (); /* Avoid confusion from thread stuff. */
620
622 trace_fd = -1;
623 trace_filename.reset ();
624 trace_tdesc.clear ();
625
627}
628
629void
631{
632 gdb_printf ("\t`%s'\n", trace_filename.get ());
633}
634
635void
637{
638 /* Other bits of trace status were collected as part of opening the
639 trace files, so nothing to do here. */
640}
641
642/* Given the position of a traceframe in the file, figure out what
643 address the frame was collected at. This would normally be the
644 value of a collected PC register, but if not available, we
645 improvise. */
646
647static CORE_ADDR
648tfile_get_traceframe_address (off_t tframe_offset)
649{
650 CORE_ADDR addr = 0;
651 short tpnum;
652 struct tracepoint *tp;
653 off_t saved_offset = cur_offset;
654
655 /* FIXME dig pc out of collected registers. */
656
657 /* Fall back to using tracepoint address. */
658 lseek (trace_fd, tframe_offset, SEEK_SET);
659 tfile_read ((gdb_byte *) &tpnum, 2);
660 tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
662 (target_gdbarch ()));
663
665 /* FIXME this is a poor heuristic if multiple locations. */
666 if (tp != nullptr && tp->has_locations ())
667 addr = tp->first_loc ().address;
668
669 /* Restore our seek position. */
670 cur_offset = saved_offset;
671 lseek (trace_fd, cur_offset, SEEK_SET);
672 return addr;
673}
674
675/* Given a type of search and some parameters, scan the collection of
676 traceframes in the file looking for a match. When found, return
677 both the traceframe and tracepoint number, otherwise -1 for
678 each. */
679
680int
682 CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
683{
684 short tpnum;
685 int tfnum = 0, found = 0;
686 unsigned int data_size;
687 struct tracepoint *tp;
688 off_t offset, tframe_offset;
689 CORE_ADDR tfaddr;
690
691 if (num == -1)
692 {
693 if (tpp)
694 *tpp = -1;
695 return -1;
696 }
697
699 offset = trace_frames_offset;
700 while (1)
701 {
702 tframe_offset = offset;
703 tfile_read ((gdb_byte *) &tpnum, 2);
704 tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
706 (target_gdbarch ()));
707 offset += 2;
708 if (tpnum == 0)
709 break;
710 tfile_read ((gdb_byte *) &data_size, 4);
711 data_size = (unsigned int) extract_unsigned_integer
712 ((gdb_byte *) &data_size, 4,
714 offset += 4;
715
716 if (type == tfind_number)
717 {
718 /* Looking for a specific trace frame. */
719 if (tfnum == num)
720 found = 1;
721 }
722 else
723 {
724 /* Start from the _next_ trace frame. */
725 if (tfnum > get_traceframe_number ())
726 {
727 switch (type)
728 {
729 case tfind_pc:
730 tfaddr = tfile_get_traceframe_address (tframe_offset);
731 if (tfaddr == addr1)
732 found = 1;
733 break;
734 case tfind_tp:
735 tp = get_tracepoint (num);
736 if (tp && tpnum == tp->number_on_target)
737 found = 1;
738 break;
739 case tfind_range:
740 tfaddr = tfile_get_traceframe_address (tframe_offset);
741 if (addr1 <= tfaddr && tfaddr <= addr2)
742 found = 1;
743 break;
744 case tfind_outside:
745 tfaddr = tfile_get_traceframe_address (tframe_offset);
746 if (!(addr1 <= tfaddr && tfaddr <= addr2))
747 found = 1;
748 break;
749 default:
750 internal_error (_("unknown tfind type"));
751 }
752 }
753 }
754
755 if (found)
756 {
757 if (tpp)
758 *tpp = tpnum;
759 cur_offset = offset;
760 cur_data_size = data_size;
761
762 return tfnum;
763 }
764 /* Skip past the traceframe's data. */
765 lseek (trace_fd, data_size, SEEK_CUR);
766 offset += data_size;
767 /* Update our own count of traceframes. */
768 ++tfnum;
769 }
770 /* Did not find what we were looking for. */
771 if (tpp)
772 *tpp = -1;
773 return -1;
774}
775
776/* Walk over all traceframe block starting at POS offset from
777 CUR_OFFSET, and call CALLBACK for each block found. If CALLBACK
778 returns true, this returns the position in the traceframe where the
779 block is found, relative to the start of the traceframe
780 (cur_offset). Returns -1 if no callback call returned true,
781 indicating that all blocks have been walked. */
782
783static int
784traceframe_walk_blocks (gdb::function_view<bool (char)> callback, int pos)
785{
786 /* Iterate through a traceframe's blocks, looking for a block of the
787 requested type. */
788
789 lseek (trace_fd, cur_offset + pos, SEEK_SET);
790 while (pos < cur_data_size)
791 {
792 unsigned short mlen;
793 char block_type;
794
795 tfile_read ((gdb_byte *) &block_type, 1);
796
797 ++pos;
798
799 if (callback (block_type))
800 return pos;
801
802 switch (block_type)
803 {
804 case 'R':
806 pos += trace_regblock_size;
807 break;
808 case 'M':
809 lseek (trace_fd, cur_offset + pos + 8, SEEK_SET);
810 tfile_read ((gdb_byte *) &mlen, 2);
811 mlen = (unsigned short)
812 extract_unsigned_integer ((gdb_byte *) &mlen, 2,
814 (target_gdbarch ()));
815 lseek (trace_fd, mlen, SEEK_CUR);
816 pos += (8 + 2 + mlen);
817 break;
818 case 'V':
819 lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET);
820 pos += (4 + 8);
821 break;
822 default:
823 error (_("Unknown block type '%c' (0x%x) in trace frame"),
825 break;
826 }
827 }
828
829 return -1;
830}
831
832/* Convenience wrapper around traceframe_walk_blocks. Looks for the
833 position offset of a block of type TYPE_WANTED in the current trace
834 frame, starting at POS. Returns -1 if no such block was found. */
835
836static int
837traceframe_find_block_type (char type_wanted, int pos)
838{
839 return traceframe_walk_blocks ([&] (char blocktype)
840 {
841 return blocktype == type_wanted;
842 }, pos);
843}
844
845/* Look for a block of saved registers in the traceframe, and get the
846 requested register from it. */
847
848void
850{
851 struct gdbarch *gdbarch = regcache->arch ();
852 int offset, regn, regsize, dummy;
853
854 /* An uninitialized reg size says we're not going to be
855 successful at getting register blocks. */
857 return;
858
859 if (traceframe_find_block_type ('R', 0) >= 0)
860 {
861 gdb_byte *regs = (gdb_byte *) alloca (trace_regblock_size);
862
864
865 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
866 {
868 regn, &dummy, &offset))
869 continue;
870
871 regsize = register_size (gdbarch, regn);
872 /* Make sure we stay within block bounds. */
873 if (offset + regsize > trace_regblock_size)
874 break;
875 if (regcache->get_register_status (regn) == REG_UNKNOWN)
876 {
877 if (regno == regn)
878 {
879 regcache->raw_supply (regno, regs + offset);
880 break;
881 }
882 else if (regno == -1)
883 {
884 regcache->raw_supply (regn, regs + offset);
885 }
886 }
887 }
888 }
889 else
891}
892
893static enum target_xfer_status
895 gdb_byte *readbuf, const gdb_byte *writebuf,
896 ULONGEST offset, ULONGEST len,
897 ULONGEST *xfered_len)
898{
899 if (strcmp (annex, "target.xml"))
900 return TARGET_XFER_E_IO;
901
902 if (readbuf == NULL)
903 error (_("tfile_xfer_partial: tdesc is read-only"));
904
905 if (trace_tdesc.empty ())
906 return TARGET_XFER_E_IO;
907
908 if (offset >= trace_tdesc.length ())
909 return TARGET_XFER_EOF;
910
911 if (len > trace_tdesc.length () - offset)
912 len = trace_tdesc.length () - offset;
913
914 memcpy (readbuf, trace_tdesc.c_str () + offset, len);
915 *xfered_len = len;
916
917 return TARGET_XFER_OK;
918}
919
922 const char *annex, gdb_byte *readbuf,
923 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
924 ULONGEST *xfered_len)
925{
926 /* We're only doing regular memory and tdesc for now. */
928 return tfile_xfer_partial_features (annex, readbuf, writebuf,
929 offset, len, xfered_len);
930 if (object != TARGET_OBJECT_MEMORY)
931 return TARGET_XFER_E_IO;
932
933 if (readbuf == NULL)
934 error (_("tfile_xfer_partial: trace file is read-only"));
935
936 if (get_traceframe_number () != -1)
937 {
938 int pos = 0;
939 enum target_xfer_status res;
940 /* Records the lowest available address of all blocks that
941 intersects the requested range. */
942 ULONGEST low_addr_available = 0;
943
944 /* Iterate through the traceframe's blocks, looking for
945 memory. */
946 while ((pos = traceframe_find_block_type ('M', pos)) >= 0)
947 {
948 ULONGEST maddr, amt;
949 unsigned short mlen;
950 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
951
952 tfile_read ((gdb_byte *) &maddr, 8);
953 maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
954 byte_order);
955 tfile_read ((gdb_byte *) &mlen, 2);
956 mlen = (unsigned short)
957 extract_unsigned_integer ((gdb_byte *) &mlen, 2, byte_order);
958
959 /* If the block includes the first part of the desired
960 range, return as much it has; GDB will re-request the
961 remainder, which might be in a different block of this
962 trace frame. */
963 if (maddr <= offset && offset < (maddr + mlen))
964 {
965 amt = (maddr + mlen) - offset;
966 if (amt > len)
967 amt = len;
968
969 if (maddr != offset)
970 lseek (trace_fd, offset - maddr, SEEK_CUR);
971 tfile_read (readbuf, amt);
972 *xfered_len = amt;
973 return TARGET_XFER_OK;
974 }
975
976 if (offset < maddr && maddr < (offset + len))
977 if (low_addr_available == 0 || low_addr_available > maddr)
978 low_addr_available = maddr;
979
980 /* Skip over this block. */
981 pos += (8 + 2 + mlen);
982 }
983
984 /* Requested memory is unavailable in the context of traceframes,
985 and this address falls within a read-only section, fallback
986 to reading from executable, up to LOW_ADDR_AVAILABLE. */
987 if (offset < low_addr_available)
988 len = std::min (len, low_addr_available - offset);
989 res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
990
991 if (res == TARGET_XFER_OK)
992 return TARGET_XFER_OK;
993 else
994 {
995 /* No use trying further, we know some memory starting
996 at MEMADDR isn't available. */
997 *xfered_len = len;
999 }
1000 }
1001 else
1002 {
1003 /* Fallback to reading from read-only sections. */
1004 return section_table_read_available_memory (readbuf, offset, len,
1005 xfered_len);
1006 }
1007}
1008
1009/* Iterate through the blocks of a trace frame, looking for a 'V'
1010 block with a matching tsv number. */
1011
1012bool
1014{
1015 int pos;
1016 bool found = false;
1017
1018 /* Iterate over blocks in current frame and find the last 'V'
1019 block in which tsv number is TSVNUM. In one trace frame, there
1020 may be multiple 'V' blocks created for a given trace variable,
1021 and the last matched 'V' block contains the updated value. */
1022 pos = 0;
1023 while ((pos = traceframe_find_block_type ('V', pos)) >= 0)
1024 {
1025 int vnum;
1026
1027 tfile_read ((gdb_byte *) &vnum, 4);
1028 vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
1030 (target_gdbarch ()));
1031 if (tsvnum == vnum)
1032 {
1033 tfile_read ((gdb_byte *) val, 8);
1034 *val = extract_signed_integer ((gdb_byte *) val, 8,
1036 (target_gdbarch ()));
1037 found = true;
1038 }
1039 pos += (4 + 8);
1040 }
1041
1042 return found;
1043}
1044
1045/* Callback for traceframe_walk_blocks. Builds a traceframe_info
1046 object for the tfile target's current traceframe. */
1047
1048static bool
1050{
1051 switch (blocktype)
1052 {
1053 case 'M':
1054 {
1055 ULONGEST maddr;
1056 unsigned short mlen;
1057
1058 tfile_read ((gdb_byte *) &maddr, 8);
1059 maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
1061 (target_gdbarch ()));
1062 tfile_read ((gdb_byte *) &mlen, 2);
1063 mlen = (unsigned short)
1064 extract_unsigned_integer ((gdb_byte *) &mlen,
1066 (target_gdbarch ()));
1067
1068 info->memory.emplace_back (maddr, mlen);
1069 break;
1070 }
1071 case 'V':
1072 {
1073 int vnum;
1074
1075 tfile_read ((gdb_byte *) &vnum, 4);
1076 info->tvars.push_back (vnum);
1077 }
1078 case 'R':
1079 case 'S':
1080 {
1081 break;
1082 }
1083 default:
1084 warning (_("Unhandled trace block type (%d) '%c ' "
1085 "while building trace frame info."),
1086 blocktype, blocktype);
1087 break;
1088 }
1089
1090 return false;
1091}
1092
1095{
1097
1098 traceframe_walk_blocks ([&] (char blocktype)
1099 {
1100 return build_traceframe_info (blocktype, info.get ());
1101 }, 0);
1102
1103 return info;
1104}
1105
1106/* Handles tdesc lines from tfile by appending the payload to
1107 a global trace_tdesc variable. */
1108
1109static void
1110tfile_append_tdesc_line (const char *line)
1111{
1112 trace_tdesc += line;
1113 trace_tdesc += "\n";
1114}
1115
1117void
void * xmalloc(YYSIZE_T)
void xfree(void *)
struct gdbarch * target_gdbarch(void)
struct tracepoint * get_tracepoint_by_number_on_target(int num)
struct tracepoint * get_tracepoint(int num)
@ bp_fast_tracepoint
Definition breakpoint.h:185
CORE_ADDR address
Definition breakpoint.h:437
int unpush_target(struct target_ops *t)
Definition inferior.c:96
void push_target(struct target_ops *t)
Definition inferior.h:406
gdbarch * arch() const
Definition regcache.c:231
void raw_supply(int regnum, const void *buf) override
Definition regcache.c:1062
enum register_status get_register_status(int regnum) const override
Definition regcache.c:304
bool get_trace_state_variable_value(int tsv, LONGEST *val) override
void fetch_registers(struct regcache *, int) override
const target_info & info() const override
int trace_find(enum trace_find_type type, int num, CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) override
traceframe_info_up traceframe_info() override
void get_tracepoint_status(tracepoint *tp, struct uploaded_tp *utp) override
void close() override
enum target_xfer_status xfer_partial(enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) override
void files_info() override
void filename_completer(struct cmd_list_element *ignore, completion_tracker &tracker, const char *text, const char *word)
Definition completer.c:204
#define SEEK_SET
Definition defs.h:101
#define O_BINARY
Definition defs.h:114
#define SEEK_CUR
Definition defs.h:104
static LONGEST extract_signed_integer(gdb::array_view< const gdb_byte > buf, enum bfd_endian byte_order)
Definition defs.h:465
static ULONGEST extract_unsigned_integer(gdb::array_view< const gdb_byte > buf, enum bfd_endian byte_order)
Definition defs.h:480
enum target_xfer_status section_table_read_available_memory(gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
Definition exec.c:779
enum target_xfer_status exec_read_partial_read_only(gdb_byte *readbuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
Definition exec.c:696
ssize_t read(int fd, void *buf, size_t count)
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition gdbarch.c:1396
int gdbarch_num_regs(struct gdbarch *gdbarch)
Definition gdbarch.c:1930
struct thread_info * add_thread_silent(process_stratum_target *targ, ptid_t ptid)
Definition thread.c:296
void switch_to_thread(struct thread_info *thr)
Definition thread.c:1360
void switch_to_no_thread()
Definition thread.c:1345
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t err
Definition gnu-nat.c:1789
mach_port_t kern_return_t mach_port_t mach_msg_type_name_t msgportsPoly mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition gnu-nat.c:1861
unsigned dummy
Definition go32-nat.c:8
size_t size
Definition go32-nat.c:239
void post_create_inferior(int from_tty)
Definition infcmd.c:232
void inferior_appeared(struct inferior *inf, int pid)
Definition inferior.c:363
struct inferior * current_inferior(void)
Definition inferior.c:55
void exit_inferior(struct inferior *inf)
Definition inferior.c:307
block_type
Definition mdebugread.c:237
info(Component c)
Definition gdbarch.py:41
int register_size(struct gdbarch *gdbarch, int regnum)
Definition regcache.c:170
int remote_register_number_and_offset(struct gdbarch *gdbarch, int regnum, int *pnum, int *poffset)
Definition remote.c:1761
bool has_locations() const
Definition breakpoint.h:661
bp_location & first_loc()
Definition breakpoint.h:683
struct trace_file_writer base
const struct trace_file_write_ops * ops
Definition tracefile.h:113
int disconnected_tracing
Definition tracepoint.h:136
int running_known
Definition tracepoint.h:99
char * stop_desc
Definition tracepoint.h:115
int traceframes_created
Definition tracepoint.h:123
LONGEST stop_time
Definition tracepoint.h:157
LONGEST start_time
Definition tracepoint.h:156
int stopping_tracepoint
Definition tracepoint.h:109
int circular_buffer
Definition tracepoint.h:141
char * user_name
Definition tracepoint.h:146
int traceframe_count
Definition tracepoint.h:119
const char * filename
Definition tracepoint.h:96
enum trace_stop_reason stop_reason
Definition tracepoint.h:104
int number_on_target
std::vector< gdb::unique_xmalloc_ptr< char[]> > cmd_strings
Definition tracepoint.h:195
gdb::unique_xmalloc_ptr< char[]> cond_string
Definition tracepoint.h:192
enum bptype type
Definition tracepoint.h:173
std::vector< gdb::unique_xmalloc_ptr< char[]> > step_actions
Definition tracepoint.h:186
ULONGEST traceframe_usage
Definition tracepoint.h:201
std::vector< gdb::unique_xmalloc_ptr< char[]> > actions
Definition tracepoint.h:185
ULONGEST addr
Definition tracepoint.h:174
gdb::unique_xmalloc_ptr< char[]> at_string
Definition tracepoint.h:189
gdb::unique_xmalloc_ptr< char[]> cond
Definition tracepoint.h:181
const char * name
Definition tracepoint.h:210
LONGEST initial_value
Definition tracepoint.h:212
void target_find_description(void)
void add_target(const target_info &t, target_open_ftype *func, completer_ftype *completer)
Definition target.c:868
void target_preopen(int from_tty)
Definition target.c:2495
int target_save_trace_data(const char *filename)
Definition target.c:699
target_xfer_status
Definition target.h:219
@ TARGET_XFER_E_IO
Definition target.h:232
@ TARGET_XFER_EOF
Definition target.h:224
@ TARGET_XFER_OK
Definition target.h:221
@ TARGET_XFER_UNAVAILABLE
Definition target.h:227
target_object
Definition target.h:143
@ TARGET_OBJECT_AVAILABLE_FEATURES
Definition target.h:174
@ TARGET_OBJECT_MEMORY
Definition target.h:147
#define TFILE_PID
struct trace_file_writer * tfile_trace_file_writer_new(void)
#define O_LARGEFILE
static int tfile_target_save(struct trace_file_writer *self, const char *filename)
static int traceframe_walk_blocks(gdb::function_view< bool(char)> callback, int pos)
static void tfile_write_header(struct trace_file_writer *self)
static void tfile_read(gdb_byte *readbuf, int size)
static off_t trace_frames_offset
static void tfile_write_definition_end(struct trace_file_writer *self)
#define TRACE_HEADER_SIZE
static gdb::unique_xmalloc_ptr< char > trace_filename
static void tfile_write_regblock_type(struct trace_file_writer *self, int size)
static void tfile_target_open(const char *arg, int from_tty)
int trace_regblock_size
static void tfile_interp_line(const char *line, struct uploaded_tp **utpp, struct uploaded_tsv **utsvp)
static int cur_data_size
static CORE_ADDR tfile_get_traceframe_address(off_t tframe_offset)
static void tfile_write_status(struct trace_file_writer *self, struct trace_status *ts)
static void tfile_append_tdesc_line(const char *line)
static void tfile_write_uploaded_tp(struct trace_file_writer *self, struct uploaded_tp *utp)
static int traceframe_find_block_type(char type_wanted, int pos)
static void tfile_write_raw_data(struct trace_file_writer *self, gdb_byte *buf, LONGEST len)
static void tfile_write_tdesc(struct trace_file_writer *self)
static void tfile_end(struct trace_file_writer *self)
static void tfile_write_uploaded_tsv(struct trace_file_writer *self, struct uploaded_tsv *utsv)
static const target_info tfile_target_info
static enum target_xfer_status tfile_xfer_partial_features(const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
static std::string trace_tdesc
#define MAX_TRACE_UPLOAD
static off_t cur_offset
static const struct trace_file_write_ops tfile_write_ops
static void tfile_dtor(struct trace_file_writer *self)
static int trace_fd
static void tfile_start(struct trace_file_writer *self, const char *filename)
void _initialize_tracefile_tfile()
static tfile_target tfile_ops
static bool build_traceframe_info(char blocktype, struct traceframe_info *info)
void tracefile_fetch_registers(struct regcache *regcache, int regno)
Definition tracefile.c:380
struct trace_status * current_trace_status(void)
Definition tracepoint.c:175
const char * stop_reason_names[]
Definition tracepoint.c:164
void parse_trace_status(const char *line, struct trace_status *ts)
int get_traceframe_number(void)
void parse_tsv_definition(const char *line, struct uploaded_tsv **utsvp)
void trace_reset_local_state(void)
void merge_uploaded_tracepoints(struct uploaded_tp **uploaded_tps)
int encode_source_string(int tpnum, ULONGEST addr, const char *srctype, const char *src, char *buf, int buf_size)
void parse_tracepoint_definition(const char *line, struct uploaded_tp **utpp)
void merge_uploaded_trace_state_variables(struct uploaded_tsv **uploaded_tsvs)
std::unique_ptr< traceframe_info > traceframe_info_up
Definition tracepoint.h:40
@ tracepoint_error
Definition tracepoint.h:89
@ trace_stop_command
Definition tracepoint.h:85
@ trace_stop_reason_unknown
Definition tracepoint.h:83
trace_find_type
Definition tracepoint.h:406
@ tfind_outside
Definition tracepoint.h:411
@ tfind_pc
Definition tracepoint.h:408
@ tfind_number
Definition tracepoint.h:407
@ tfind_range
Definition tracepoint.h:410
@ tfind_tp
Definition tracepoint.h:409
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886
gdb::optional< std::string > target_fetch_description_xml(struct target_ops *ops)
Definition xml-tdesc.c:725