Multi-target support
[deliverable/binutils-gdb.git] / gdb / record-btrace.c
CommitLineData
afedecd3
MM
1/* Branch trace support for GDB, the GNU debugger.
2
b811d2c2 3 Copyright (C) 2013-2020 Free Software Foundation, Inc.
afedecd3
MM
4
5 Contributed by Intel Corp. <markus.t.metzger@intel.com>
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22#include "defs.h"
23#include "record.h"
c0272db5 24#include "record-btrace.h"
afedecd3
MM
25#include "gdbthread.h"
26#include "target.h"
27#include "gdbcmd.h"
28#include "disasm.h"
76727919 29#include "observable.h"
afedecd3
MM
30#include "cli/cli-utils.h"
31#include "source.h"
32#include "ui-out.h"
33#include "symtab.h"
34#include "filenames.h"
1f3ef581 35#include "regcache.h"
cecac1ab 36#include "frame-unwind.h"
0b722aec 37#include "hashtab.h"
45741a9c 38#include "infrun.h"
70ad5bff
MM
39#include "event-loop.h"
40#include "inf-loop.h"
00431a78 41#include "inferior.h"
325fac50 42#include <algorithm>
0d12e84c 43#include "gdbarch.h"
e43b10e1 44#include "cli/cli-style.h"
afedecd3 45
d9f719f1
PA
46static const target_info record_btrace_target_info = {
47 "record-btrace",
48 N_("Branch tracing target"),
49 N_("Collect control-flow trace and provide the execution history.")
50};
51
afedecd3 52/* The target_ops of record-btrace. */
f6ac5f3d
PA
53
54class record_btrace_target final : public target_ops
55{
56public:
d9f719f1
PA
57 const target_info &info () const override
58 { return record_btrace_target_info; }
f6ac5f3d 59
66b4deae
PA
60 strata stratum () const override { return record_stratum; }
61
f6ac5f3d
PA
62 void close () override;
63 void async (int) override;
64
65 void detach (inferior *inf, int from_tty) override
66 { record_detach (this, inf, from_tty); }
67
68 void disconnect (const char *, int) override;
69
70 void mourn_inferior () override
71 { record_mourn_inferior (this); }
72
73 void kill () override
74 { record_kill (this); }
75
76 enum record_method record_method (ptid_t ptid) override;
77
78 void stop_recording () override;
79 void info_record () override;
80
81 void insn_history (int size, gdb_disassembly_flags flags) override;
82 void insn_history_from (ULONGEST from, int size,
83 gdb_disassembly_flags flags) override;
84 void insn_history_range (ULONGEST begin, ULONGEST end,
85 gdb_disassembly_flags flags) override;
86 void call_history (int size, record_print_flags flags) override;
87 void call_history_from (ULONGEST begin, int size, record_print_flags flags)
88 override;
89 void call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
90 override;
91
57810aa7
PA
92 bool record_is_replaying (ptid_t ptid) override;
93 bool record_will_replay (ptid_t ptid, int dir) override;
f6ac5f3d
PA
94 void record_stop_replaying () override;
95
96 enum target_xfer_status xfer_partial (enum target_object object,
97 const char *annex,
98 gdb_byte *readbuf,
99 const gdb_byte *writebuf,
100 ULONGEST offset, ULONGEST len,
101 ULONGEST *xfered_len) override;
102
103 int insert_breakpoint (struct gdbarch *,
104 struct bp_target_info *) override;
105 int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
106 enum remove_bp_reason) override;
107
108 void fetch_registers (struct regcache *, int) override;
109
110 void store_registers (struct regcache *, int) override;
111 void prepare_to_store (struct regcache *) override;
112
113 const struct frame_unwind *get_unwinder () override;
114
115 const struct frame_unwind *get_tailcall_unwinder () override;
116
117 void commit_resume () override;
118 void resume (ptid_t, int, enum gdb_signal) override;
119 ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
120
121 void stop (ptid_t) override;
122 void update_thread_list () override;
57810aa7 123 bool thread_alive (ptid_t ptid) override;
f6ac5f3d
PA
124 void goto_record_begin () override;
125 void goto_record_end () override;
126 void goto_record (ULONGEST insn) override;
127
57810aa7 128 bool can_execute_reverse () override;
f6ac5f3d 129
57810aa7
PA
130 bool stopped_by_sw_breakpoint () override;
131 bool supports_stopped_by_sw_breakpoint () override;
f6ac5f3d 132
57810aa7
PA
133 bool stopped_by_hw_breakpoint () override;
134 bool supports_stopped_by_hw_breakpoint () override;
f6ac5f3d
PA
135
136 enum exec_direction_kind execution_direction () override;
137 void prepare_to_generate_core () override;
138 void done_generating_core () override;
139};
140
141static record_btrace_target record_btrace_ops;
142
143/* Initialize the record-btrace target ops. */
afedecd3 144
76727919
TT
145/* Token associated with a new-thread observer enabling branch tracing
146 for the new thread. */
3dcfdc58 147static const gdb::observers::token record_btrace_thread_observer_token {};
afedecd3 148
67b5c0c1
MM
149/* Memory access types used in set/show record btrace replay-memory-access. */
150static const char replay_memory_access_read_only[] = "read-only";
151static const char replay_memory_access_read_write[] = "read-write";
152static const char *const replay_memory_access_types[] =
153{
154 replay_memory_access_read_only,
155 replay_memory_access_read_write,
156 NULL
157};
158
159/* The currently allowed replay memory access type. */
160static const char *replay_memory_access = replay_memory_access_read_only;
161
4a4495d6
MM
162/* The cpu state kinds. */
163enum record_btrace_cpu_state_kind
164{
165 CS_AUTO,
166 CS_NONE,
167 CS_CPU
168};
169
170/* The current cpu state. */
171static enum record_btrace_cpu_state_kind record_btrace_cpu_state = CS_AUTO;
172
173/* The current cpu for trace decode. */
174static struct btrace_cpu record_btrace_cpu;
175
67b5c0c1
MM
176/* Command lists for "set/show record btrace". */
177static struct cmd_list_element *set_record_btrace_cmdlist;
178static struct cmd_list_element *show_record_btrace_cmdlist;
633785ff 179
70ad5bff
MM
180/* The execution direction of the last resume we got. See record-full.c. */
181static enum exec_direction_kind record_btrace_resume_exec_dir = EXEC_FORWARD;
182
183/* The async event handler for reverse/replay execution. */
184static struct async_event_handler *record_btrace_async_inferior_event_handler;
185
aef92902
MM
186/* A flag indicating that we are currently generating a core file. */
187static int record_btrace_generating_corefile;
188
f4abbc16
MM
189/* The current branch trace configuration. */
190static struct btrace_config record_btrace_conf;
191
192/* Command list for "record btrace". */
193static struct cmd_list_element *record_btrace_cmdlist;
194
d33501a5
MM
195/* Command lists for "set/show record btrace bts". */
196static struct cmd_list_element *set_record_btrace_bts_cmdlist;
197static struct cmd_list_element *show_record_btrace_bts_cmdlist;
198
b20a6524
MM
199/* Command lists for "set/show record btrace pt". */
200static struct cmd_list_element *set_record_btrace_pt_cmdlist;
201static struct cmd_list_element *show_record_btrace_pt_cmdlist;
202
4a4495d6
MM
203/* Command list for "set record btrace cpu". */
204static struct cmd_list_element *set_record_btrace_cpu_cmdlist;
205
afedecd3
MM
206/* Print a record-btrace debug message. Use do ... while (0) to avoid
207 ambiguities when used in if statements. */
208
209#define DEBUG(msg, args...) \
210 do \
211 { \
212 if (record_debug != 0) \
213 fprintf_unfiltered (gdb_stdlog, \
214 "[record-btrace] " msg "\n", ##args); \
215 } \
216 while (0)
217
218
4a4495d6
MM
219/* Return the cpu configured by the user. Returns NULL if the cpu was
220 configured as auto. */
221const struct btrace_cpu *
222record_btrace_get_cpu (void)
223{
224 switch (record_btrace_cpu_state)
225 {
226 case CS_AUTO:
227 return nullptr;
228
229 case CS_NONE:
230 record_btrace_cpu.vendor = CV_UNKNOWN;
231 /* Fall through. */
232 case CS_CPU:
233 return &record_btrace_cpu;
234 }
235
236 error (_("Internal error: bad record btrace cpu state."));
237}
238
afedecd3 239/* Update the branch trace for the current thread and return a pointer to its
066ce621 240 thread_info.
afedecd3
MM
241
242 Throws an error if there is no thread or no trace. This function never
243 returns NULL. */
244
066ce621
MM
245static struct thread_info *
246require_btrace_thread (void)
afedecd3 247{
afedecd3
MM
248 DEBUG ("require");
249
00431a78 250 if (inferior_ptid == null_ptid)
afedecd3
MM
251 error (_("No thread."));
252
00431a78
PA
253 thread_info *tp = inferior_thread ();
254
cd4007e4
MM
255 validate_registers_access ();
256
4a4495d6 257 btrace_fetch (tp, record_btrace_get_cpu ());
afedecd3 258
6e07b1d2 259 if (btrace_is_empty (tp))
afedecd3
MM
260 error (_("No trace."));
261
066ce621
MM
262 return tp;
263}
264
265/* Update the branch trace for the current thread and return a pointer to its
266 branch trace information struct.
267
268 Throws an error if there is no thread or no trace. This function never
269 returns NULL. */
270
271static struct btrace_thread_info *
272require_btrace (void)
273{
274 struct thread_info *tp;
275
276 tp = require_btrace_thread ();
277
278 return &tp->btrace;
afedecd3
MM
279}
280
281/* Enable branch tracing for one thread. Warn on errors. */
282
283static void
284record_btrace_enable_warn (struct thread_info *tp)
285{
a70b8144 286 try
492d29ea
PA
287 {
288 btrace_enable (tp, &record_btrace_conf);
289 }
230d2906 290 catch (const gdb_exception_error &error)
492d29ea 291 {
3d6e9d23 292 warning ("%s", error.what ());
492d29ea 293 }
afedecd3
MM
294}
295
afedecd3
MM
296/* Enable automatic tracing of new threads. */
297
298static void
299record_btrace_auto_enable (void)
300{
301 DEBUG ("attach thread observer");
302
76727919
TT
303 gdb::observers::new_thread.attach (record_btrace_enable_warn,
304 record_btrace_thread_observer_token);
afedecd3
MM
305}
306
307/* Disable automatic tracing of new threads. */
308
309static void
310record_btrace_auto_disable (void)
311{
afedecd3
MM
312 DEBUG ("detach thread observer");
313
76727919 314 gdb::observers::new_thread.detach (record_btrace_thread_observer_token);
afedecd3
MM
315}
316
70ad5bff
MM
317/* The record-btrace async event handler function. */
318
319static void
320record_btrace_handle_async_inferior_event (gdb_client_data data)
321{
322 inferior_event_handler (INF_REG_EVENT, NULL);
323}
324
c0272db5
TW
325/* See record-btrace.h. */
326
327void
328record_btrace_push_target (void)
329{
330 const char *format;
331
332 record_btrace_auto_enable ();
333
334 push_target (&record_btrace_ops);
335
336 record_btrace_async_inferior_event_handler
337 = create_async_event_handler (record_btrace_handle_async_inferior_event,
338 NULL);
339 record_btrace_generating_corefile = 0;
340
341 format = btrace_format_short_string (record_btrace_conf.format);
76727919 342 gdb::observers::record_changed.notify (current_inferior (), 1, "btrace", format);
c0272db5
TW
343}
344
228f1508
SM
345/* Disable btrace on a set of threads on scope exit. */
346
347struct scoped_btrace_disable
348{
349 scoped_btrace_disable () = default;
350
351 DISABLE_COPY_AND_ASSIGN (scoped_btrace_disable);
352
353 ~scoped_btrace_disable ()
354 {
355 for (thread_info *tp : m_threads)
356 btrace_disable (tp);
357 }
358
359 void add_thread (thread_info *thread)
360 {
361 m_threads.push_front (thread);
362 }
363
364 void discard ()
365 {
366 m_threads.clear ();
367 }
368
369private:
370 std::forward_list<thread_info *> m_threads;
371};
372
d9f719f1 373/* Open target record-btrace. */
afedecd3 374
d9f719f1
PA
375static void
376record_btrace_target_open (const char *args, int from_tty)
afedecd3 377{
228f1508
SM
378 /* If we fail to enable btrace for one thread, disable it for the threads for
379 which it was successfully enabled. */
380 scoped_btrace_disable btrace_disable;
afedecd3
MM
381
382 DEBUG ("open");
383
8213266a 384 record_preopen ();
afedecd3
MM
385
386 if (!target_has_execution)
387 error (_("The program is not being run."));
388
08036331 389 for (thread_info *tp : all_non_exited_threads ())
5d5658a1 390 if (args == NULL || *args == 0 || number_is_in_list (args, tp->global_num))
afedecd3 391 {
f4abbc16 392 btrace_enable (tp, &record_btrace_conf);
afedecd3 393
228f1508 394 btrace_disable.add_thread (tp);
afedecd3
MM
395 }
396
c0272db5 397 record_btrace_push_target ();
afedecd3 398
228f1508 399 btrace_disable.discard ();
afedecd3
MM
400}
401
f6ac5f3d 402/* The stop_recording method of target record-btrace. */
afedecd3 403
f6ac5f3d
PA
404void
405record_btrace_target::stop_recording ()
afedecd3 406{
afedecd3
MM
407 DEBUG ("stop recording");
408
409 record_btrace_auto_disable ();
410
08036331 411 for (thread_info *tp : all_non_exited_threads ())
afedecd3
MM
412 if (tp->btrace.target != NULL)
413 btrace_disable (tp);
414}
415
f6ac5f3d 416/* The disconnect method of target record-btrace. */
c0272db5 417
f6ac5f3d
PA
418void
419record_btrace_target::disconnect (const char *args,
420 int from_tty)
c0272db5 421{
b6a8c27b 422 struct target_ops *beneath = this->beneath ();
c0272db5
TW
423
424 /* Do not stop recording, just clean up GDB side. */
f6ac5f3d 425 unpush_target (this);
c0272db5
TW
426
427 /* Forward disconnect. */
f6ac5f3d 428 beneath->disconnect (args, from_tty);
c0272db5
TW
429}
430
f6ac5f3d 431/* The close method of target record-btrace. */
afedecd3 432
f6ac5f3d
PA
433void
434record_btrace_target::close ()
afedecd3 435{
70ad5bff
MM
436 if (record_btrace_async_inferior_event_handler != NULL)
437 delete_async_event_handler (&record_btrace_async_inferior_event_handler);
438
99c819ee
MM
439 /* Make sure automatic recording gets disabled even if we did not stop
440 recording before closing the record-btrace target. */
441 record_btrace_auto_disable ();
442
568e808b
MM
443 /* We should have already stopped recording.
444 Tear down btrace in case we have not. */
08036331 445 for (thread_info *tp : all_non_exited_threads ())
568e808b 446 btrace_teardown (tp);
afedecd3
MM
447}
448
f6ac5f3d 449/* The async method of target record-btrace. */
b7d2e916 450
f6ac5f3d
PA
451void
452record_btrace_target::async (int enable)
b7d2e916 453{
6a3753b3 454 if (enable)
b7d2e916
PA
455 mark_async_event_handler (record_btrace_async_inferior_event_handler);
456 else
457 clear_async_event_handler (record_btrace_async_inferior_event_handler);
458
b6a8c27b 459 this->beneath ()->async (enable);
b7d2e916
PA
460}
461
d33501a5
MM
462/* Adjusts the size and returns a human readable size suffix. */
463
464static const char *
465record_btrace_adjust_size (unsigned int *size)
466{
467 unsigned int sz;
468
469 sz = *size;
470
471 if ((sz & ((1u << 30) - 1)) == 0)
472 {
473 *size = sz >> 30;
474 return "GB";
475 }
476 else if ((sz & ((1u << 20) - 1)) == 0)
477 {
478 *size = sz >> 20;
479 return "MB";
480 }
481 else if ((sz & ((1u << 10) - 1)) == 0)
482 {
483 *size = sz >> 10;
484 return "kB";
485 }
486 else
487 return "";
488}
489
490/* Print a BTS configuration. */
491
492static void
493record_btrace_print_bts_conf (const struct btrace_config_bts *conf)
494{
495 const char *suffix;
496 unsigned int size;
497
498 size = conf->size;
499 if (size > 0)
500 {
501 suffix = record_btrace_adjust_size (&size);
502 printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
503 }
504}
505
bc504a31 506/* Print an Intel Processor Trace configuration. */
b20a6524
MM
507
508static void
509record_btrace_print_pt_conf (const struct btrace_config_pt *conf)
510{
511 const char *suffix;
512 unsigned int size;
513
514 size = conf->size;
515 if (size > 0)
516 {
517 suffix = record_btrace_adjust_size (&size);
518 printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
519 }
520}
521
d33501a5
MM
522/* Print a branch tracing configuration. */
523
524static void
525record_btrace_print_conf (const struct btrace_config *conf)
526{
527 printf_unfiltered (_("Recording format: %s.\n"),
528 btrace_format_string (conf->format));
529
530 switch (conf->format)
531 {
532 case BTRACE_FORMAT_NONE:
533 return;
534
535 case BTRACE_FORMAT_BTS:
536 record_btrace_print_bts_conf (&conf->bts);
537 return;
b20a6524
MM
538
539 case BTRACE_FORMAT_PT:
540 record_btrace_print_pt_conf (&conf->pt);
541 return;
d33501a5
MM
542 }
543
544 internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
545}
546
f6ac5f3d 547/* The info_record method of target record-btrace. */
afedecd3 548
f6ac5f3d
PA
549void
550record_btrace_target::info_record ()
afedecd3
MM
551{
552 struct btrace_thread_info *btinfo;
f4abbc16 553 const struct btrace_config *conf;
afedecd3 554 struct thread_info *tp;
31fd9caa 555 unsigned int insns, calls, gaps;
afedecd3
MM
556
557 DEBUG ("info");
558
5b6d1e4f 559 if (inferior_ptid == null_ptid)
afedecd3
MM
560 error (_("No thread."));
561
5b6d1e4f
PA
562 tp = inferior_thread ();
563
cd4007e4
MM
564 validate_registers_access ();
565
f4abbc16
MM
566 btinfo = &tp->btrace;
567
f6ac5f3d 568 conf = ::btrace_conf (btinfo);
f4abbc16 569 if (conf != NULL)
d33501a5 570 record_btrace_print_conf (conf);
f4abbc16 571
4a4495d6 572 btrace_fetch (tp, record_btrace_get_cpu ());
afedecd3 573
23a7fe75
MM
574 insns = 0;
575 calls = 0;
31fd9caa 576 gaps = 0;
23a7fe75 577
6e07b1d2 578 if (!btrace_is_empty (tp))
23a7fe75
MM
579 {
580 struct btrace_call_iterator call;
581 struct btrace_insn_iterator insn;
582
583 btrace_call_end (&call, btinfo);
584 btrace_call_prev (&call, 1);
5de9129b 585 calls = btrace_call_number (&call);
23a7fe75
MM
586
587 btrace_insn_end (&insn, btinfo);
5de9129b 588 insns = btrace_insn_number (&insn);
31fd9caa 589
69090cee
TW
590 /* If the last instruction is not a gap, it is the current instruction
591 that is not actually part of the record. */
592 if (btrace_insn_get (&insn) != NULL)
593 insns -= 1;
31fd9caa
MM
594
595 gaps = btinfo->ngaps;
23a7fe75 596 }
afedecd3 597
31fd9caa 598 printf_unfiltered (_("Recorded %u instructions in %u functions (%u gaps) "
43792cf0 599 "for thread %s (%s).\n"), insns, calls, gaps,
a068643d
TT
600 print_thread_id (tp),
601 target_pid_to_str (tp->ptid).c_str ());
07bbe694
MM
602
603 if (btrace_is_replaying (tp))
604 printf_unfiltered (_("Replay in progress. At instruction %u.\n"),
605 btrace_insn_number (btinfo->replay));
afedecd3
MM
606}
607
31fd9caa
MM
608/* Print a decode error. */
609
610static void
611btrace_ui_out_decode_error (struct ui_out *uiout, int errcode,
612 enum btrace_format format)
613{
508352a9 614 const char *errstr = btrace_decode_error (format, errcode);
31fd9caa 615
112e8700 616 uiout->text (_("["));
508352a9
TW
617 /* ERRCODE > 0 indicates notifications on BTRACE_FORMAT_PT. */
618 if (!(format == BTRACE_FORMAT_PT && errcode > 0))
31fd9caa 619 {
112e8700 620 uiout->text (_("decode error ("));
381befee 621 uiout->field_signed ("errcode", errcode);
112e8700 622 uiout->text (_("): "));
31fd9caa 623 }
112e8700
SM
624 uiout->text (errstr);
625 uiout->text (_("]\n"));
31fd9caa
MM
626}
627
f94cc897
MM
628/* A range of source lines. */
629
630struct btrace_line_range
631{
632 /* The symtab this line is from. */
633 struct symtab *symtab;
634
635 /* The first line (inclusive). */
636 int begin;
637
638 /* The last line (exclusive). */
639 int end;
640};
641
642/* Construct a line range. */
643
644static struct btrace_line_range
645btrace_mk_line_range (struct symtab *symtab, int begin, int end)
646{
647 struct btrace_line_range range;
648
649 range.symtab = symtab;
650 range.begin = begin;
651 range.end = end;
652
653 return range;
654}
655
656/* Add a line to a line range. */
657
658static struct btrace_line_range
659btrace_line_range_add (struct btrace_line_range range, int line)
660{
661 if (range.end <= range.begin)
662 {
663 /* This is the first entry. */
664 range.begin = line;
665 range.end = line + 1;
666 }
667 else if (line < range.begin)
668 range.begin = line;
669 else if (range.end < line)
670 range.end = line;
671
672 return range;
673}
674
675/* Return non-zero if RANGE is empty, zero otherwise. */
676
677static int
678btrace_line_range_is_empty (struct btrace_line_range range)
679{
680 return range.end <= range.begin;
681}
682
683/* Return non-zero if LHS contains RHS, zero otherwise. */
684
685static int
686btrace_line_range_contains_range (struct btrace_line_range lhs,
687 struct btrace_line_range rhs)
688{
689 return ((lhs.symtab == rhs.symtab)
690 && (lhs.begin <= rhs.begin)
691 && (rhs.end <= lhs.end));
692}
693
694/* Find the line range associated with PC. */
695
696static struct btrace_line_range
697btrace_find_line_range (CORE_ADDR pc)
698{
699 struct btrace_line_range range;
700 struct linetable_entry *lines;
701 struct linetable *ltable;
702 struct symtab *symtab;
703 int nlines, i;
704
705 symtab = find_pc_line_symtab (pc);
706 if (symtab == NULL)
707 return btrace_mk_line_range (NULL, 0, 0);
708
709 ltable = SYMTAB_LINETABLE (symtab);
710 if (ltable == NULL)
711 return btrace_mk_line_range (symtab, 0, 0);
712
713 nlines = ltable->nitems;
714 lines = ltable->item;
715 if (nlines <= 0)
716 return btrace_mk_line_range (symtab, 0, 0);
717
718 range = btrace_mk_line_range (symtab, 0, 0);
719 for (i = 0; i < nlines - 1; i++)
720 {
721 if ((lines[i].pc == pc) && (lines[i].line != 0))
722 range = btrace_line_range_add (range, lines[i].line);
723 }
724
725 return range;
726}
727
728/* Print source lines in LINES to UIOUT.
729
730 UI_ITEM_CHAIN is a cleanup chain for the last source line and the
731 instructions corresponding to that source line. When printing a new source
732 line, we do the cleanups for the open chain and open a new cleanup chain for
733 the new source line. If the source line range in LINES is not empty, this
734 function will leave the cleanup chain for the last printed source line open
735 so instructions can be added to it. */
736
737static void
738btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout,
7ea78b59
SM
739 gdb::optional<ui_out_emit_tuple> *src_and_asm_tuple,
740 gdb::optional<ui_out_emit_list> *asm_list,
741 gdb_disassembly_flags flags)
f94cc897 742{
8d297bbf 743 print_source_lines_flags psl_flags;
f94cc897 744
f94cc897
MM
745 if (flags & DISASSEMBLY_FILENAME)
746 psl_flags |= PRINT_SOURCE_LINES_FILENAME;
747
7ea78b59 748 for (int line = lines.begin; line < lines.end; ++line)
f94cc897 749 {
7ea78b59 750 asm_list->reset ();
f94cc897 751
7ea78b59 752 src_and_asm_tuple->emplace (uiout, "src_and_asm_line");
f94cc897
MM
753
754 print_source_lines (lines.symtab, line, line + 1, psl_flags);
755
7ea78b59 756 asm_list->emplace (uiout, "line_asm_insn");
f94cc897
MM
757 }
758}
759
afedecd3
MM
760/* Disassemble a section of the recorded instruction trace. */
761
762static void
23a7fe75 763btrace_insn_history (struct ui_out *uiout,
31fd9caa 764 const struct btrace_thread_info *btinfo,
23a7fe75 765 const struct btrace_insn_iterator *begin,
9a24775b
PA
766 const struct btrace_insn_iterator *end,
767 gdb_disassembly_flags flags)
afedecd3 768{
9a24775b
PA
769 DEBUG ("itrace (0x%x): [%u; %u)", (unsigned) flags,
770 btrace_insn_number (begin), btrace_insn_number (end));
afedecd3 771
f94cc897
MM
772 flags |= DISASSEMBLY_SPECULATIVE;
773
7ea78b59
SM
774 struct gdbarch *gdbarch = target_gdbarch ();
775 btrace_line_range last_lines = btrace_mk_line_range (NULL, 0, 0);
f94cc897 776
7ea78b59 777 ui_out_emit_list list_emitter (uiout, "asm_insns");
f94cc897 778
7ea78b59
SM
779 gdb::optional<ui_out_emit_tuple> src_and_asm_tuple;
780 gdb::optional<ui_out_emit_list> asm_list;
afedecd3 781
046bebe1 782 gdb_pretty_print_disassembler disasm (gdbarch, uiout);
8b172ce7 783
7ea78b59
SM
784 for (btrace_insn_iterator it = *begin; btrace_insn_cmp (&it, end) != 0;
785 btrace_insn_next (&it, 1))
afedecd3 786 {
23a7fe75
MM
787 const struct btrace_insn *insn;
788
789 insn = btrace_insn_get (&it);
790
31fd9caa
MM
791 /* A NULL instruction indicates a gap in the trace. */
792 if (insn == NULL)
793 {
794 const struct btrace_config *conf;
795
796 conf = btrace_conf (btinfo);
afedecd3 797
31fd9caa
MM
798 /* We have trace so we must have a configuration. */
799 gdb_assert (conf != NULL);
800
69090cee
TW
801 uiout->field_fmt ("insn-number", "%u",
802 btrace_insn_number (&it));
803 uiout->text ("\t");
804
805 btrace_ui_out_decode_error (uiout, btrace_insn_get_error (&it),
31fd9caa
MM
806 conf->format);
807 }
808 else
809 {
f94cc897 810 struct disasm_insn dinsn;
da8c46d2 811
f94cc897 812 if ((flags & DISASSEMBLY_SOURCE) != 0)
da8c46d2 813 {
f94cc897
MM
814 struct btrace_line_range lines;
815
816 lines = btrace_find_line_range (insn->pc);
817 if (!btrace_line_range_is_empty (lines)
818 && !btrace_line_range_contains_range (last_lines, lines))
819 {
7ea78b59
SM
820 btrace_print_lines (lines, uiout, &src_and_asm_tuple, &asm_list,
821 flags);
f94cc897
MM
822 last_lines = lines;
823 }
7ea78b59 824 else if (!src_and_asm_tuple.has_value ())
f94cc897 825 {
7ea78b59
SM
826 gdb_assert (!asm_list.has_value ());
827
828 src_and_asm_tuple.emplace (uiout, "src_and_asm_line");
829
f94cc897 830 /* No source information. */
7ea78b59 831 asm_list.emplace (uiout, "line_asm_insn");
f94cc897
MM
832 }
833
7ea78b59
SM
834 gdb_assert (src_and_asm_tuple.has_value ());
835 gdb_assert (asm_list.has_value ());
da8c46d2 836 }
da8c46d2 837
f94cc897
MM
838 memset (&dinsn, 0, sizeof (dinsn));
839 dinsn.number = btrace_insn_number (&it);
840 dinsn.addr = insn->pc;
31fd9caa 841
da8c46d2 842 if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
f94cc897 843 dinsn.is_speculative = 1;
da8c46d2 844
046bebe1 845 disasm.pretty_print_insn (&dinsn, flags);
31fd9caa 846 }
afedecd3
MM
847 }
848}
849
f6ac5f3d 850/* The insn_history method of target record-btrace. */
afedecd3 851
f6ac5f3d
PA
852void
853record_btrace_target::insn_history (int size, gdb_disassembly_flags flags)
afedecd3
MM
854{
855 struct btrace_thread_info *btinfo;
23a7fe75
MM
856 struct btrace_insn_history *history;
857 struct btrace_insn_iterator begin, end;
afedecd3 858 struct ui_out *uiout;
23a7fe75 859 unsigned int context, covered;
afedecd3
MM
860
861 uiout = current_uiout;
2e783024 862 ui_out_emit_tuple tuple_emitter (uiout, "insn history");
afedecd3 863 context = abs (size);
afedecd3
MM
864 if (context == 0)
865 error (_("Bad record instruction-history-size."));
866
23a7fe75
MM
867 btinfo = require_btrace ();
868 history = btinfo->insn_history;
869 if (history == NULL)
afedecd3 870 {
07bbe694 871 struct btrace_insn_iterator *replay;
afedecd3 872
9a24775b 873 DEBUG ("insn-history (0x%x): %d", (unsigned) flags, size);
afedecd3 874
07bbe694
MM
875 /* If we're replaying, we start at the replay position. Otherwise, we
876 start at the tail of the trace. */
877 replay = btinfo->replay;
878 if (replay != NULL)
879 begin = *replay;
880 else
881 btrace_insn_end (&begin, btinfo);
882
883 /* We start from here and expand in the requested direction. Then we
884 expand in the other direction, as well, to fill up any remaining
885 context. */
886 end = begin;
887 if (size < 0)
888 {
889 /* We want the current position covered, as well. */
890 covered = btrace_insn_next (&end, 1);
891 covered += btrace_insn_prev (&begin, context - covered);
892 covered += btrace_insn_next (&end, context - covered);
893 }
894 else
895 {
896 covered = btrace_insn_next (&end, context);
897 covered += btrace_insn_prev (&begin, context - covered);
898 }
afedecd3
MM
899 }
900 else
901 {
23a7fe75
MM
902 begin = history->begin;
903 end = history->end;
afedecd3 904
9a24775b 905 DEBUG ("insn-history (0x%x): %d, prev: [%u; %u)", (unsigned) flags, size,
23a7fe75 906 btrace_insn_number (&begin), btrace_insn_number (&end));
afedecd3 907
23a7fe75
MM
908 if (size < 0)
909 {
910 end = begin;
911 covered = btrace_insn_prev (&begin, context);
912 }
913 else
914 {
915 begin = end;
916 covered = btrace_insn_next (&end, context);
917 }
afedecd3
MM
918 }
919
23a7fe75 920 if (covered > 0)
31fd9caa 921 btrace_insn_history (uiout, btinfo, &begin, &end, flags);
23a7fe75
MM
922 else
923 {
924 if (size < 0)
925 printf_unfiltered (_("At the start of the branch trace record.\n"));
926 else
927 printf_unfiltered (_("At the end of the branch trace record.\n"));
928 }
afedecd3 929
23a7fe75 930 btrace_set_insn_history (btinfo, &begin, &end);
afedecd3
MM
931}
932
f6ac5f3d 933/* The insn_history_range method of target record-btrace. */
afedecd3 934
f6ac5f3d
PA
935void
936record_btrace_target::insn_history_range (ULONGEST from, ULONGEST to,
937 gdb_disassembly_flags flags)
afedecd3
MM
938{
939 struct btrace_thread_info *btinfo;
23a7fe75 940 struct btrace_insn_iterator begin, end;
afedecd3 941 struct ui_out *uiout;
23a7fe75
MM
942 unsigned int low, high;
943 int found;
afedecd3
MM
944
945 uiout = current_uiout;
2e783024 946 ui_out_emit_tuple tuple_emitter (uiout, "insn history");
23a7fe75
MM
947 low = from;
948 high = to;
afedecd3 949
9a24775b 950 DEBUG ("insn-history (0x%x): [%u; %u)", (unsigned) flags, low, high);
afedecd3
MM
951
952 /* Check for wrap-arounds. */
23a7fe75 953 if (low != from || high != to)
afedecd3
MM
954 error (_("Bad range."));
955
0688d04e 956 if (high < low)
afedecd3
MM
957 error (_("Bad range."));
958
23a7fe75 959 btinfo = require_btrace ();
afedecd3 960
23a7fe75
MM
961 found = btrace_find_insn_by_number (&begin, btinfo, low);
962 if (found == 0)
963 error (_("Range out of bounds."));
afedecd3 964
23a7fe75
MM
965 found = btrace_find_insn_by_number (&end, btinfo, high);
966 if (found == 0)
0688d04e
MM
967 {
968 /* Silently truncate the range. */
969 btrace_insn_end (&end, btinfo);
970 }
971 else
972 {
973 /* We want both begin and end to be inclusive. */
974 btrace_insn_next (&end, 1);
975 }
afedecd3 976
31fd9caa 977 btrace_insn_history (uiout, btinfo, &begin, &end, flags);
23a7fe75 978 btrace_set_insn_history (btinfo, &begin, &end);
afedecd3
MM
979}
980
f6ac5f3d 981/* The insn_history_from method of target record-btrace. */
afedecd3 982
f6ac5f3d
PA
983void
984record_btrace_target::insn_history_from (ULONGEST from, int size,
985 gdb_disassembly_flags flags)
afedecd3
MM
986{
987 ULONGEST begin, end, context;
988
989 context = abs (size);
0688d04e
MM
990 if (context == 0)
991 error (_("Bad record instruction-history-size."));
afedecd3
MM
992
993 if (size < 0)
994 {
995 end = from;
996
997 if (from < context)
998 begin = 0;
999 else
0688d04e 1000 begin = from - context + 1;
afedecd3
MM
1001 }
1002 else
1003 {
1004 begin = from;
0688d04e 1005 end = from + context - 1;
afedecd3
MM
1006
1007 /* Check for wrap-around. */
1008 if (end < begin)
1009 end = ULONGEST_MAX;
1010 }
1011
f6ac5f3d 1012 insn_history_range (begin, end, flags);
afedecd3
MM
1013}
1014
1015/* Print the instruction number range for a function call history line. */
1016
1017static void
23a7fe75
MM
1018btrace_call_history_insn_range (struct ui_out *uiout,
1019 const struct btrace_function *bfun)
afedecd3 1020{
7acbe133
MM
1021 unsigned int begin, end, size;
1022
0860c437 1023 size = bfun->insn.size ();
7acbe133 1024 gdb_assert (size > 0);
afedecd3 1025
23a7fe75 1026 begin = bfun->insn_offset;
7acbe133 1027 end = begin + size - 1;
afedecd3 1028
1f77b012 1029 uiout->field_unsigned ("insn begin", begin);
112e8700 1030 uiout->text (",");
1f77b012 1031 uiout->field_unsigned ("insn end", end);
afedecd3
MM
1032}
1033
ce0dfbea
MM
1034/* Compute the lowest and highest source line for the instructions in BFUN
1035 and return them in PBEGIN and PEND.
1036 Ignore instructions that can't be mapped to BFUN, e.g. instructions that
1037 result from inlining or macro expansion. */
1038
1039static void
1040btrace_compute_src_line_range (const struct btrace_function *bfun,
1041 int *pbegin, int *pend)
1042{
ce0dfbea
MM
1043 struct symtab *symtab;
1044 struct symbol *sym;
ce0dfbea
MM
1045 int begin, end;
1046
1047 begin = INT_MAX;
1048 end = INT_MIN;
1049
1050 sym = bfun->sym;
1051 if (sym == NULL)
1052 goto out;
1053
1054 symtab = symbol_symtab (sym);
1055
0860c437 1056 for (const btrace_insn &insn : bfun->insn)
ce0dfbea
MM
1057 {
1058 struct symtab_and_line sal;
1059
0860c437 1060 sal = find_pc_line (insn.pc, 0);
ce0dfbea
MM
1061 if (sal.symtab != symtab || sal.line == 0)
1062 continue;
1063
325fac50
PA
1064 begin = std::min (begin, sal.line);
1065 end = std::max (end, sal.line);
ce0dfbea
MM
1066 }
1067
1068 out:
1069 *pbegin = begin;
1070 *pend = end;
1071}
1072
afedecd3
MM
1073/* Print the source line information for a function call history line. */
1074
1075static void
23a7fe75
MM
1076btrace_call_history_src_line (struct ui_out *uiout,
1077 const struct btrace_function *bfun)
afedecd3
MM
1078{
1079 struct symbol *sym;
23a7fe75 1080 int begin, end;
afedecd3
MM
1081
1082 sym = bfun->sym;
1083 if (sym == NULL)
1084 return;
1085
112e8700 1086 uiout->field_string ("file",
cbe56571 1087 symtab_to_filename_for_display (symbol_symtab (sym)),
e43b10e1 1088 file_name_style.style ());
afedecd3 1089
ce0dfbea 1090 btrace_compute_src_line_range (bfun, &begin, &end);
23a7fe75 1091 if (end < begin)
afedecd3
MM
1092 return;
1093
112e8700 1094 uiout->text (":");
381befee 1095 uiout->field_signed ("min line", begin);
afedecd3 1096
23a7fe75 1097 if (end == begin)
afedecd3
MM
1098 return;
1099
112e8700 1100 uiout->text (",");
381befee 1101 uiout->field_signed ("max line", end);
afedecd3
MM
1102}
1103
0b722aec
MM
1104/* Get the name of a branch trace function. */
1105
1106static const char *
1107btrace_get_bfun_name (const struct btrace_function *bfun)
1108{
1109 struct minimal_symbol *msym;
1110 struct symbol *sym;
1111
1112 if (bfun == NULL)
1113 return "??";
1114
1115 msym = bfun->msym;
1116 sym = bfun->sym;
1117
1118 if (sym != NULL)
987012b8 1119 return sym->print_name ();
0b722aec 1120 else if (msym != NULL)
c9d95fa3 1121 return msym->print_name ();
0b722aec
MM
1122 else
1123 return "??";
1124}
1125
afedecd3
MM
1126/* Disassemble a section of the recorded function trace. */
1127
1128static void
23a7fe75 1129btrace_call_history (struct ui_out *uiout,
8710b709 1130 const struct btrace_thread_info *btinfo,
23a7fe75
MM
1131 const struct btrace_call_iterator *begin,
1132 const struct btrace_call_iterator *end,
8d297bbf 1133 int int_flags)
afedecd3 1134{
23a7fe75 1135 struct btrace_call_iterator it;
8d297bbf 1136 record_print_flags flags = (enum record_print_flag) int_flags;
afedecd3 1137
8d297bbf 1138 DEBUG ("ftrace (0x%x): [%u; %u)", int_flags, btrace_call_number (begin),
23a7fe75 1139 btrace_call_number (end));
afedecd3 1140
23a7fe75 1141 for (it = *begin; btrace_call_cmp (&it, end) < 0; btrace_call_next (&it, 1))
afedecd3 1142 {
23a7fe75
MM
1143 const struct btrace_function *bfun;
1144 struct minimal_symbol *msym;
1145 struct symbol *sym;
1146
1147 bfun = btrace_call_get (&it);
23a7fe75 1148 sym = bfun->sym;
0b722aec 1149 msym = bfun->msym;
23a7fe75 1150
afedecd3 1151 /* Print the function index. */
1f77b012 1152 uiout->field_unsigned ("index", bfun->number);
112e8700 1153 uiout->text ("\t");
afedecd3 1154
31fd9caa
MM
1155 /* Indicate gaps in the trace. */
1156 if (bfun->errcode != 0)
1157 {
1158 const struct btrace_config *conf;
1159
1160 conf = btrace_conf (btinfo);
1161
1162 /* We have trace so we must have a configuration. */
1163 gdb_assert (conf != NULL);
1164
1165 btrace_ui_out_decode_error (uiout, bfun->errcode, conf->format);
1166
1167 continue;
1168 }
1169
8710b709
MM
1170 if ((flags & RECORD_PRINT_INDENT_CALLS) != 0)
1171 {
1172 int level = bfun->level + btinfo->level, i;
1173
1174 for (i = 0; i < level; ++i)
112e8700 1175 uiout->text (" ");
8710b709
MM
1176 }
1177
1178 if (sym != NULL)
987012b8 1179 uiout->field_string ("function", sym->print_name (),
e43b10e1 1180 function_name_style.style ());
8710b709 1181 else if (msym != NULL)
c9d95fa3 1182 uiout->field_string ("function", msym->print_name (),
e43b10e1 1183 function_name_style.style ());
112e8700 1184 else if (!uiout->is_mi_like_p ())
cbe56571 1185 uiout->field_string ("function", "??",
e43b10e1 1186 function_name_style.style ());
8710b709 1187
1e038f67 1188 if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
afedecd3 1189 {
112e8700 1190 uiout->text (_("\tinst "));
23a7fe75 1191 btrace_call_history_insn_range (uiout, bfun);
afedecd3
MM
1192 }
1193
1e038f67 1194 if ((flags & RECORD_PRINT_SRC_LINE) != 0)
afedecd3 1195 {
112e8700 1196 uiout->text (_("\tat "));
23a7fe75 1197 btrace_call_history_src_line (uiout, bfun);
afedecd3
MM
1198 }
1199
112e8700 1200 uiout->text ("\n");
afedecd3
MM
1201 }
1202}
1203
f6ac5f3d 1204/* The call_history method of target record-btrace. */
afedecd3 1205
f6ac5f3d
PA
1206void
1207record_btrace_target::call_history (int size, record_print_flags flags)
afedecd3
MM
1208{
1209 struct btrace_thread_info *btinfo;
23a7fe75
MM
1210 struct btrace_call_history *history;
1211 struct btrace_call_iterator begin, end;
afedecd3 1212 struct ui_out *uiout;
23a7fe75 1213 unsigned int context, covered;
afedecd3
MM
1214
1215 uiout = current_uiout;
2e783024 1216 ui_out_emit_tuple tuple_emitter (uiout, "insn history");
afedecd3 1217 context = abs (size);
afedecd3
MM
1218 if (context == 0)
1219 error (_("Bad record function-call-history-size."));
1220
23a7fe75
MM
1221 btinfo = require_btrace ();
1222 history = btinfo->call_history;
1223 if (history == NULL)
afedecd3 1224 {
07bbe694 1225 struct btrace_insn_iterator *replay;
afedecd3 1226
0cb7c7b0 1227 DEBUG ("call-history (0x%x): %d", (int) flags, size);
afedecd3 1228
07bbe694
MM
1229 /* If we're replaying, we start at the replay position. Otherwise, we
1230 start at the tail of the trace. */
1231 replay = btinfo->replay;
1232 if (replay != NULL)
1233 {
07bbe694 1234 begin.btinfo = btinfo;
a0f1b963 1235 begin.index = replay->call_index;
07bbe694
MM
1236 }
1237 else
1238 btrace_call_end (&begin, btinfo);
1239
1240 /* We start from here and expand in the requested direction. Then we
1241 expand in the other direction, as well, to fill up any remaining
1242 context. */
1243 end = begin;
1244 if (size < 0)
1245 {
1246 /* We want the current position covered, as well. */
1247 covered = btrace_call_next (&end, 1);
1248 covered += btrace_call_prev (&begin, context - covered);
1249 covered += btrace_call_next (&end, context - covered);
1250 }
1251 else
1252 {
1253 covered = btrace_call_next (&end, context);
1254 covered += btrace_call_prev (&begin, context- covered);
1255 }
afedecd3
MM
1256 }
1257 else
1258 {
23a7fe75
MM
1259 begin = history->begin;
1260 end = history->end;
afedecd3 1261
0cb7c7b0 1262 DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", (int) flags, size,
23a7fe75 1263 btrace_call_number (&begin), btrace_call_number (&end));
afedecd3 1264
23a7fe75
MM
1265 if (size < 0)
1266 {
1267 end = begin;
1268 covered = btrace_call_prev (&begin, context);
1269 }
1270 else
1271 {
1272 begin = end;
1273 covered = btrace_call_next (&end, context);
1274 }
afedecd3
MM
1275 }
1276
23a7fe75 1277 if (covered > 0)
8710b709 1278 btrace_call_history (uiout, btinfo, &begin, &end, flags);
23a7fe75
MM
1279 else
1280 {
1281 if (size < 0)
1282 printf_unfiltered (_("At the start of the branch trace record.\n"));
1283 else
1284 printf_unfiltered (_("At the end of the branch trace record.\n"));
1285 }
afedecd3 1286
23a7fe75 1287 btrace_set_call_history (btinfo, &begin, &end);
afedecd3
MM
1288}
1289
f6ac5f3d 1290/* The call_history_range method of target record-btrace. */
afedecd3 1291
f6ac5f3d
PA
1292void
1293record_btrace_target::call_history_range (ULONGEST from, ULONGEST to,
1294 record_print_flags flags)
afedecd3
MM
1295{
1296 struct btrace_thread_info *btinfo;
23a7fe75 1297 struct btrace_call_iterator begin, end;
afedecd3 1298 struct ui_out *uiout;
23a7fe75
MM
1299 unsigned int low, high;
1300 int found;
afedecd3
MM
1301
1302 uiout = current_uiout;
2e783024 1303 ui_out_emit_tuple tuple_emitter (uiout, "func history");
23a7fe75
MM
1304 low = from;
1305 high = to;
afedecd3 1306
0cb7c7b0 1307 DEBUG ("call-history (0x%x): [%u; %u)", (int) flags, low, high);
afedecd3
MM
1308
1309 /* Check for wrap-arounds. */
23a7fe75 1310 if (low != from || high != to)
afedecd3
MM
1311 error (_("Bad range."));
1312
0688d04e 1313 if (high < low)
afedecd3
MM
1314 error (_("Bad range."));
1315
23a7fe75 1316 btinfo = require_btrace ();
afedecd3 1317
23a7fe75
MM
1318 found = btrace_find_call_by_number (&begin, btinfo, low);
1319 if (found == 0)
1320 error (_("Range out of bounds."));
afedecd3 1321
23a7fe75
MM
1322 found = btrace_find_call_by_number (&end, btinfo, high);
1323 if (found == 0)
0688d04e
MM
1324 {
1325 /* Silently truncate the range. */
1326 btrace_call_end (&end, btinfo);
1327 }
1328 else
1329 {
1330 /* We want both begin and end to be inclusive. */
1331 btrace_call_next (&end, 1);
1332 }
afedecd3 1333
8710b709 1334 btrace_call_history (uiout, btinfo, &begin, &end, flags);
23a7fe75 1335 btrace_set_call_history (btinfo, &begin, &end);
afedecd3
MM
1336}
1337
f6ac5f3d 1338/* The call_history_from method of target record-btrace. */
afedecd3 1339
f6ac5f3d
PA
1340void
1341record_btrace_target::call_history_from (ULONGEST from, int size,
1342 record_print_flags flags)
afedecd3
MM
1343{
1344 ULONGEST begin, end, context;
1345
1346 context = abs (size);
0688d04e
MM
1347 if (context == 0)
1348 error (_("Bad record function-call-history-size."));
afedecd3
MM
1349
1350 if (size < 0)
1351 {
1352 end = from;
1353
1354 if (from < context)
1355 begin = 0;
1356 else
0688d04e 1357 begin = from - context + 1;
afedecd3
MM
1358 }
1359 else
1360 {
1361 begin = from;
0688d04e 1362 end = from + context - 1;
afedecd3
MM
1363
1364 /* Check for wrap-around. */
1365 if (end < begin)
1366 end = ULONGEST_MAX;
1367 }
1368
f6ac5f3d 1369 call_history_range ( begin, end, flags);
afedecd3
MM
1370}
1371
f6ac5f3d 1372/* The record_method method of target record-btrace. */
b158a20f 1373
f6ac5f3d
PA
1374enum record_method
1375record_btrace_target::record_method (ptid_t ptid)
b158a20f 1376{
5b6d1e4f
PA
1377 process_stratum_target *proc_target = current_inferior ()->process_target ();
1378 thread_info *const tp = find_thread_ptid (proc_target, ptid);
b158a20f
TW
1379
1380 if (tp == NULL)
1381 error (_("No thread."));
1382
1383 if (tp->btrace.target == NULL)
1384 return RECORD_METHOD_NONE;
1385
1386 return RECORD_METHOD_BTRACE;
1387}
1388
f6ac5f3d 1389/* The record_is_replaying method of target record-btrace. */
07bbe694 1390
57810aa7 1391bool
f6ac5f3d 1392record_btrace_target::record_is_replaying (ptid_t ptid)
07bbe694 1393{
5b6d1e4f
PA
1394 process_stratum_target *proc_target = current_inferior ()->process_target ();
1395 for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
08036331 1396 if (btrace_is_replaying (tp))
57810aa7 1397 return true;
07bbe694 1398
57810aa7 1399 return false;
07bbe694
MM
1400}
1401
f6ac5f3d 1402/* The record_will_replay method of target record-btrace. */
7ff27e9b 1403
57810aa7 1404bool
f6ac5f3d 1405record_btrace_target::record_will_replay (ptid_t ptid, int dir)
7ff27e9b 1406{
f6ac5f3d 1407 return dir == EXEC_REVERSE || record_is_replaying (ptid);
7ff27e9b
MM
1408}
1409
f6ac5f3d 1410/* The xfer_partial method of target record-btrace. */
633785ff 1411
f6ac5f3d
PA
1412enum target_xfer_status
1413record_btrace_target::xfer_partial (enum target_object object,
1414 const char *annex, gdb_byte *readbuf,
1415 const gdb_byte *writebuf, ULONGEST offset,
1416 ULONGEST len, ULONGEST *xfered_len)
633785ff 1417{
633785ff 1418 /* Filter out requests that don't make sense during replay. */
67b5c0c1 1419 if (replay_memory_access == replay_memory_access_read_only
aef92902 1420 && !record_btrace_generating_corefile
f6ac5f3d 1421 && record_is_replaying (inferior_ptid))
633785ff
MM
1422 {
1423 switch (object)
1424 {
1425 case TARGET_OBJECT_MEMORY:
1426 {
1427 struct target_section *section;
1428
1429 /* We do not allow writing memory in general. */
1430 if (writebuf != NULL)
9b409511
YQ
1431 {
1432 *xfered_len = len;
bc113b4e 1433 return TARGET_XFER_UNAVAILABLE;
9b409511 1434 }
633785ff
MM
1435
1436 /* We allow reading readonly memory. */
f6ac5f3d 1437 section = target_section_by_addr (this, offset);
633785ff
MM
1438 if (section != NULL)
1439 {
1440 /* Check if the section we found is readonly. */
fd361982 1441 if ((bfd_section_flags (section->the_bfd_section)
633785ff
MM
1442 & SEC_READONLY) != 0)
1443 {
1444 /* Truncate the request to fit into this section. */
325fac50 1445 len = std::min (len, section->endaddr - offset);
633785ff
MM
1446 break;
1447 }
1448 }
1449
9b409511 1450 *xfered_len = len;
bc113b4e 1451 return TARGET_XFER_UNAVAILABLE;
633785ff
MM
1452 }
1453 }
1454 }
1455
1456 /* Forward the request. */
b6a8c27b
PA
1457 return this->beneath ()->xfer_partial (object, annex, readbuf, writebuf,
1458 offset, len, xfered_len);
633785ff
MM
1459}
1460
f6ac5f3d 1461/* The insert_breakpoint method of target record-btrace. */
633785ff 1462
f6ac5f3d
PA
1463int
1464record_btrace_target::insert_breakpoint (struct gdbarch *gdbarch,
1465 struct bp_target_info *bp_tgt)
633785ff 1466{
67b5c0c1
MM
1467 const char *old;
1468 int ret;
633785ff
MM
1469
1470 /* Inserting breakpoints requires accessing memory. Allow it for the
1471 duration of this function. */
67b5c0c1
MM
1472 old = replay_memory_access;
1473 replay_memory_access = replay_memory_access_read_write;
633785ff
MM
1474
1475 ret = 0;
a70b8144 1476 try
492d29ea 1477 {
b6a8c27b 1478 ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt);
492d29ea 1479 }
230d2906 1480 catch (const gdb_exception &except)
492d29ea 1481 {
6c63c96a 1482 replay_memory_access = old;
eedc3f4f 1483 throw;
492d29ea 1484 }
6c63c96a 1485 replay_memory_access = old;
633785ff
MM
1486
1487 return ret;
1488}
1489
f6ac5f3d 1490/* The remove_breakpoint method of target record-btrace. */
633785ff 1491
f6ac5f3d
PA
1492int
1493record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
1494 struct bp_target_info *bp_tgt,
1495 enum remove_bp_reason reason)
633785ff 1496{
67b5c0c1
MM
1497 const char *old;
1498 int ret;
633785ff
MM
1499
1500 /* Removing breakpoints requires accessing memory. Allow it for the
1501 duration of this function. */
67b5c0c1
MM
1502 old = replay_memory_access;
1503 replay_memory_access = replay_memory_access_read_write;
633785ff
MM
1504
1505 ret = 0;
a70b8144 1506 try
492d29ea 1507 {
b6a8c27b 1508 ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt, reason);
492d29ea 1509 }
230d2906 1510 catch (const gdb_exception &except)
492d29ea 1511 {
6c63c96a 1512 replay_memory_access = old;
eedc3f4f 1513 throw;
492d29ea 1514 }
6c63c96a 1515 replay_memory_access = old;
633785ff
MM
1516
1517 return ret;
1518}
1519
f6ac5f3d 1520/* The fetch_registers method of target record-btrace. */
1f3ef581 1521
f6ac5f3d
PA
1522void
1523record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
1f3ef581 1524{
5b6d1e4f 1525 thread_info *tp = find_thread_ptid (regcache->target (), regcache->ptid ());
1f3ef581
MM
1526 gdb_assert (tp != NULL);
1527
5b6d1e4f 1528 btrace_insn_iterator *replay = tp->btrace.replay;
aef92902 1529 if (replay != NULL && !record_btrace_generating_corefile)
1f3ef581
MM
1530 {
1531 const struct btrace_insn *insn;
1532 struct gdbarch *gdbarch;
1533 int pcreg;
1534
ac7936df 1535 gdbarch = regcache->arch ();
1f3ef581
MM
1536 pcreg = gdbarch_pc_regnum (gdbarch);
1537 if (pcreg < 0)
1538 return;
1539
1540 /* We can only provide the PC register. */
1541 if (regno >= 0 && regno != pcreg)
1542 return;
1543
1544 insn = btrace_insn_get (replay);
1545 gdb_assert (insn != NULL);
1546
73e1c03f 1547 regcache->raw_supply (regno, &insn->pc);
1f3ef581
MM
1548 }
1549 else
b6a8c27b 1550 this->beneath ()->fetch_registers (regcache, regno);
1f3ef581
MM
1551}
1552
f6ac5f3d 1553/* The store_registers method of target record-btrace. */
1f3ef581 1554
f6ac5f3d
PA
1555void
1556record_btrace_target::store_registers (struct regcache *regcache, int regno)
1f3ef581 1557{
a52eab48 1558 if (!record_btrace_generating_corefile
222312d3 1559 && record_is_replaying (regcache->ptid ()))
4d10e986 1560 error (_("Cannot write registers while replaying."));
1f3ef581 1561
491144b5 1562 gdb_assert (may_write_registers);
1f3ef581 1563
b6a8c27b 1564 this->beneath ()->store_registers (regcache, regno);
1f3ef581
MM
1565}
1566
f6ac5f3d 1567/* The prepare_to_store method of target record-btrace. */
1f3ef581 1568
f6ac5f3d
PA
1569void
1570record_btrace_target::prepare_to_store (struct regcache *regcache)
1f3ef581 1571{
a52eab48 1572 if (!record_btrace_generating_corefile
222312d3 1573 && record_is_replaying (regcache->ptid ()))
1f3ef581
MM
1574 return;
1575
b6a8c27b 1576 this->beneath ()->prepare_to_store (regcache);
1f3ef581
MM
1577}
1578
0b722aec
MM
1579/* The branch trace frame cache. */
1580
1581struct btrace_frame_cache
1582{
1583 /* The thread. */
1584 struct thread_info *tp;
1585
1586 /* The frame info. */
1587 struct frame_info *frame;
1588
1589 /* The branch trace function segment. */
1590 const struct btrace_function *bfun;
1591};
1592
1593/* A struct btrace_frame_cache hash table indexed by NEXT. */
1594
1595static htab_t bfcache;
1596
1597/* hash_f for htab_create_alloc of bfcache. */
1598
1599static hashval_t
1600bfcache_hash (const void *arg)
1601{
19ba03f4
SM
1602 const struct btrace_frame_cache *cache
1603 = (const struct btrace_frame_cache *) arg;
0b722aec
MM
1604
1605 return htab_hash_pointer (cache->frame);
1606}
1607
1608/* eq_f for htab_create_alloc of bfcache. */
1609
1610static int
1611bfcache_eq (const void *arg1, const void *arg2)
1612{
19ba03f4
SM
1613 const struct btrace_frame_cache *cache1
1614 = (const struct btrace_frame_cache *) arg1;
1615 const struct btrace_frame_cache *cache2
1616 = (const struct btrace_frame_cache *) arg2;
0b722aec
MM
1617
1618 return cache1->frame == cache2->frame;
1619}
1620
1621/* Create a new btrace frame cache. */
1622
1623static struct btrace_frame_cache *
1624bfcache_new (struct frame_info *frame)
1625{
1626 struct btrace_frame_cache *cache;
1627 void **slot;
1628
1629 cache = FRAME_OBSTACK_ZALLOC (struct btrace_frame_cache);
1630 cache->frame = frame;
1631
1632 slot = htab_find_slot (bfcache, cache, INSERT);
1633 gdb_assert (*slot == NULL);
1634 *slot = cache;
1635
1636 return cache;
1637}
1638
1639/* Extract the branch trace function from a branch trace frame. */
1640
1641static const struct btrace_function *
1642btrace_get_frame_function (struct frame_info *frame)
1643{
1644 const struct btrace_frame_cache *cache;
0b722aec
MM
1645 struct btrace_frame_cache pattern;
1646 void **slot;
1647
1648 pattern.frame = frame;
1649
1650 slot = htab_find_slot (bfcache, &pattern, NO_INSERT);
1651 if (slot == NULL)
1652 return NULL;
1653
19ba03f4 1654 cache = (const struct btrace_frame_cache *) *slot;
0b722aec
MM
1655 return cache->bfun;
1656}
1657
cecac1ab
MM
1658/* Implement stop_reason method for record_btrace_frame_unwind. */
1659
1660static enum unwind_stop_reason
1661record_btrace_frame_unwind_stop_reason (struct frame_info *this_frame,
1662 void **this_cache)
1663{
0b722aec
MM
1664 const struct btrace_frame_cache *cache;
1665 const struct btrace_function *bfun;
1666
19ba03f4 1667 cache = (const struct btrace_frame_cache *) *this_cache;
0b722aec
MM
1668 bfun = cache->bfun;
1669 gdb_assert (bfun != NULL);
1670
42bfe59e 1671 if (bfun->up == 0)
0b722aec
MM
1672 return UNWIND_UNAVAILABLE;
1673
1674 return UNWIND_NO_REASON;
cecac1ab
MM
1675}
1676
1677/* Implement this_id method for record_btrace_frame_unwind. */
1678
1679static void
1680record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
1681 struct frame_id *this_id)
1682{
0b722aec
MM
1683 const struct btrace_frame_cache *cache;
1684 const struct btrace_function *bfun;
4aeb0dfc 1685 struct btrace_call_iterator it;
0b722aec
MM
1686 CORE_ADDR code, special;
1687
19ba03f4 1688 cache = (const struct btrace_frame_cache *) *this_cache;
0b722aec
MM
1689
1690 bfun = cache->bfun;
1691 gdb_assert (bfun != NULL);
1692
4aeb0dfc
TW
1693 while (btrace_find_call_by_number (&it, &cache->tp->btrace, bfun->prev) != 0)
1694 bfun = btrace_call_get (&it);
0b722aec
MM
1695
1696 code = get_frame_func (this_frame);
1697 special = bfun->number;
1698
1699 *this_id = frame_id_build_unavailable_stack_special (code, special);
1700
1701 DEBUG ("[frame] %s id: (!stack, pc=%s, special=%s)",
1702 btrace_get_bfun_name (cache->bfun),
1703 core_addr_to_string_nz (this_id->code_addr),
1704 core_addr_to_string_nz (this_id->special_addr));
cecac1ab
MM
1705}
1706
1707/* Implement prev_register method for record_btrace_frame_unwind. */
1708
1709static struct value *
1710record_btrace_frame_prev_register (struct frame_info *this_frame,
1711 void **this_cache,
1712 int regnum)
1713{
0b722aec
MM
1714 const struct btrace_frame_cache *cache;
1715 const struct btrace_function *bfun, *caller;
42bfe59e 1716 struct btrace_call_iterator it;
0b722aec
MM
1717 struct gdbarch *gdbarch;
1718 CORE_ADDR pc;
1719 int pcreg;
1720
1721 gdbarch = get_frame_arch (this_frame);
1722 pcreg = gdbarch_pc_regnum (gdbarch);
1723 if (pcreg < 0 || regnum != pcreg)
1724 throw_error (NOT_AVAILABLE_ERROR,
1725 _("Registers are not available in btrace record history"));
1726
19ba03f4 1727 cache = (const struct btrace_frame_cache *) *this_cache;
0b722aec
MM
1728 bfun = cache->bfun;
1729 gdb_assert (bfun != NULL);
1730
42bfe59e 1731 if (btrace_find_call_by_number (&it, &cache->tp->btrace, bfun->up) == 0)
0b722aec
MM
1732 throw_error (NOT_AVAILABLE_ERROR,
1733 _("No caller in btrace record history"));
1734
42bfe59e
TW
1735 caller = btrace_call_get (&it);
1736
0b722aec 1737 if ((bfun->flags & BFUN_UP_LINKS_TO_RET) != 0)
0860c437 1738 pc = caller->insn.front ().pc;
0b722aec
MM
1739 else
1740 {
0860c437 1741 pc = caller->insn.back ().pc;
0b722aec
MM
1742 pc += gdb_insn_length (gdbarch, pc);
1743 }
1744
1745 DEBUG ("[frame] unwound PC in %s on level %d: %s",
1746 btrace_get_bfun_name (bfun), bfun->level,
1747 core_addr_to_string_nz (pc));
1748
1749 return frame_unwind_got_address (this_frame, regnum, pc);
cecac1ab
MM
1750}
1751
1752/* Implement sniffer method for record_btrace_frame_unwind. */
1753
1754static int
1755record_btrace_frame_sniffer (const struct frame_unwind *self,
1756 struct frame_info *this_frame,
1757 void **this_cache)
1758{
0b722aec
MM
1759 const struct btrace_function *bfun;
1760 struct btrace_frame_cache *cache;
cecac1ab 1761 struct thread_info *tp;
0b722aec 1762 struct frame_info *next;
cecac1ab
MM
1763
1764 /* THIS_FRAME does not contain a reference to its thread. */
00431a78 1765 tp = inferior_thread ();
cecac1ab 1766
0b722aec
MM
1767 bfun = NULL;
1768 next = get_next_frame (this_frame);
1769 if (next == NULL)
1770 {
1771 const struct btrace_insn_iterator *replay;
1772
1773 replay = tp->btrace.replay;
1774 if (replay != NULL)
08c3f6d2 1775 bfun = &replay->btinfo->functions[replay->call_index];
0b722aec
MM
1776 }
1777 else
1778 {
1779 const struct btrace_function *callee;
42bfe59e 1780 struct btrace_call_iterator it;
0b722aec
MM
1781
1782 callee = btrace_get_frame_function (next);
42bfe59e
TW
1783 if (callee == NULL || (callee->flags & BFUN_UP_LINKS_TO_TAILCALL) != 0)
1784 return 0;
1785
1786 if (btrace_find_call_by_number (&it, &tp->btrace, callee->up) == 0)
1787 return 0;
1788
1789 bfun = btrace_call_get (&it);
0b722aec
MM
1790 }
1791
1792 if (bfun == NULL)
1793 return 0;
1794
1795 DEBUG ("[frame] sniffed frame for %s on level %d",
1796 btrace_get_bfun_name (bfun), bfun->level);
1797
1798 /* This is our frame. Initialize the frame cache. */
1799 cache = bfcache_new (this_frame);
1800 cache->tp = tp;
1801 cache->bfun = bfun;
1802
1803 *this_cache = cache;
1804 return 1;
1805}
1806
1807/* Implement sniffer method for record_btrace_tailcall_frame_unwind. */
1808
1809static int
1810record_btrace_tailcall_frame_sniffer (const struct frame_unwind *self,
1811 struct frame_info *this_frame,
1812 void **this_cache)
1813{
1814 const struct btrace_function *bfun, *callee;
1815 struct btrace_frame_cache *cache;
42bfe59e 1816 struct btrace_call_iterator it;
0b722aec 1817 struct frame_info *next;
42bfe59e 1818 struct thread_info *tinfo;
0b722aec
MM
1819
1820 next = get_next_frame (this_frame);
1821 if (next == NULL)
1822 return 0;
1823
1824 callee = btrace_get_frame_function (next);
1825 if (callee == NULL)
1826 return 0;
1827
1828 if ((callee->flags & BFUN_UP_LINKS_TO_TAILCALL) == 0)
1829 return 0;
1830
00431a78 1831 tinfo = inferior_thread ();
42bfe59e 1832 if (btrace_find_call_by_number (&it, &tinfo->btrace, callee->up) == 0)
0b722aec
MM
1833 return 0;
1834
42bfe59e
TW
1835 bfun = btrace_call_get (&it);
1836
0b722aec
MM
1837 DEBUG ("[frame] sniffed tailcall frame for %s on level %d",
1838 btrace_get_bfun_name (bfun), bfun->level);
1839
1840 /* This is our frame. Initialize the frame cache. */
1841 cache = bfcache_new (this_frame);
42bfe59e 1842 cache->tp = tinfo;
0b722aec
MM
1843 cache->bfun = bfun;
1844
1845 *this_cache = cache;
1846 return 1;
1847}
1848
1849static void
1850record_btrace_frame_dealloc_cache (struct frame_info *self, void *this_cache)
1851{
1852 struct btrace_frame_cache *cache;
1853 void **slot;
1854
19ba03f4 1855 cache = (struct btrace_frame_cache *) this_cache;
0b722aec
MM
1856
1857 slot = htab_find_slot (bfcache, cache, NO_INSERT);
1858 gdb_assert (slot != NULL);
1859
1860 htab_remove_elt (bfcache, cache);
cecac1ab
MM
1861}
1862
1863/* btrace recording does not store previous memory content, neither the stack
30baf67b 1864 frames content. Any unwinding would return erroneous results as the stack
cecac1ab
MM
1865 contents no longer matches the changed PC value restored from history.
1866 Therefore this unwinder reports any possibly unwound registers as
1867 <unavailable>. */
1868
0b722aec 1869const struct frame_unwind record_btrace_frame_unwind =
cecac1ab
MM
1870{
1871 NORMAL_FRAME,
1872 record_btrace_frame_unwind_stop_reason,
1873 record_btrace_frame_this_id,
1874 record_btrace_frame_prev_register,
1875 NULL,
0b722aec
MM
1876 record_btrace_frame_sniffer,
1877 record_btrace_frame_dealloc_cache
1878};
1879
1880const struct frame_unwind record_btrace_tailcall_frame_unwind =
1881{
1882 TAILCALL_FRAME,
1883 record_btrace_frame_unwind_stop_reason,
1884 record_btrace_frame_this_id,
1885 record_btrace_frame_prev_register,
1886 NULL,
1887 record_btrace_tailcall_frame_sniffer,
1888 record_btrace_frame_dealloc_cache
cecac1ab 1889};
b2f4cfde 1890
f6ac5f3d 1891/* Implement the get_unwinder method. */
ac01945b 1892
f6ac5f3d
PA
1893const struct frame_unwind *
1894record_btrace_target::get_unwinder ()
ac01945b
TT
1895{
1896 return &record_btrace_frame_unwind;
1897}
1898
f6ac5f3d 1899/* Implement the get_tailcall_unwinder method. */
ac01945b 1900
f6ac5f3d
PA
1901const struct frame_unwind *
1902record_btrace_target::get_tailcall_unwinder ()
ac01945b
TT
1903{
1904 return &record_btrace_tailcall_frame_unwind;
1905}
1906
987e68b1
MM
1907/* Return a human-readable string for FLAG. */
1908
1909static const char *
1910btrace_thread_flag_to_str (enum btrace_thread_flag flag)
1911{
1912 switch (flag)
1913 {
1914 case BTHR_STEP:
1915 return "step";
1916
1917 case BTHR_RSTEP:
1918 return "reverse-step";
1919
1920 case BTHR_CONT:
1921 return "cont";
1922
1923 case BTHR_RCONT:
1924 return "reverse-cont";
1925
1926 case BTHR_STOP:
1927 return "stop";
1928 }
1929
1930 return "<invalid>";
1931}
1932
52834460
MM
1933/* Indicate that TP should be resumed according to FLAG. */
1934
1935static void
1936record_btrace_resume_thread (struct thread_info *tp,
1937 enum btrace_thread_flag flag)
1938{
1939 struct btrace_thread_info *btinfo;
1940
43792cf0 1941 DEBUG ("resuming thread %s (%s): %x (%s)", print_thread_id (tp),
a068643d
TT
1942 target_pid_to_str (tp->ptid).c_str (), flag,
1943 btrace_thread_flag_to_str (flag));
52834460
MM
1944
1945 btinfo = &tp->btrace;
1946
52834460 1947 /* Fetch the latest branch trace. */
4a4495d6 1948 btrace_fetch (tp, record_btrace_get_cpu ());
52834460 1949
0ca912df
MM
1950 /* A resume request overwrites a preceding resume or stop request. */
1951 btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
52834460
MM
1952 btinfo->flags |= flag;
1953}
1954
ec71cc2f
MM
1955/* Get the current frame for TP. */
1956
79b8d3b0
TT
1957static struct frame_id
1958get_thread_current_frame_id (struct thread_info *tp)
ec71cc2f 1959{
79b8d3b0 1960 struct frame_id id;
ec71cc2f
MM
1961 int executing;
1962
00431a78
PA
1963 /* Set current thread, which is implicitly used by
1964 get_current_frame. */
1965 scoped_restore_current_thread restore_thread;
1966
1967 switch_to_thread (tp);
ec71cc2f 1968
5b6d1e4f
PA
1969 process_stratum_target *proc_target = tp->inf->process_target ();
1970
ec71cc2f
MM
1971 /* Clear the executing flag to allow changes to the current frame.
1972 We are not actually running, yet. We just started a reverse execution
1973 command or a record goto command.
1974 For the latter, EXECUTING is false and this has no effect.
f6ac5f3d 1975 For the former, EXECUTING is true and we're in wait, about to
ec71cc2f 1976 move the thread. Since we need to recompute the stack, we temporarily
85102364 1977 set EXECUTING to false. */
00431a78 1978 executing = tp->executing;
5b6d1e4f 1979 set_executing (proc_target, inferior_ptid, false);
ec71cc2f 1980
79b8d3b0 1981 id = null_frame_id;
a70b8144 1982 try
ec71cc2f 1983 {
79b8d3b0 1984 id = get_frame_id (get_current_frame ());
ec71cc2f 1985 }
230d2906 1986 catch (const gdb_exception &except)
ec71cc2f
MM
1987 {
1988 /* Restore the previous execution state. */
5b6d1e4f 1989 set_executing (proc_target, inferior_ptid, executing);
ec71cc2f 1990
eedc3f4f 1991 throw;
ec71cc2f 1992 }
ec71cc2f
MM
1993
1994 /* Restore the previous execution state. */
5b6d1e4f 1995 set_executing (proc_target, inferior_ptid, executing);
ec71cc2f 1996
79b8d3b0 1997 return id;
ec71cc2f
MM
1998}
1999
52834460
MM
2000/* Start replaying a thread. */
2001
2002static struct btrace_insn_iterator *
2003record_btrace_start_replaying (struct thread_info *tp)
2004{
52834460
MM
2005 struct btrace_insn_iterator *replay;
2006 struct btrace_thread_info *btinfo;
52834460
MM
2007
2008 btinfo = &tp->btrace;
2009 replay = NULL;
2010
2011 /* We can't start replaying without trace. */
b54b03bd 2012 if (btinfo->functions.empty ())
52834460
MM
2013 return NULL;
2014
52834460
MM
2015 /* GDB stores the current frame_id when stepping in order to detects steps
2016 into subroutines.
2017 Since frames are computed differently when we're replaying, we need to
2018 recompute those stored frames and fix them up so we can still detect
2019 subroutines after we started replaying. */
a70b8144 2020 try
52834460 2021 {
52834460
MM
2022 struct frame_id frame_id;
2023 int upd_step_frame_id, upd_step_stack_frame_id;
2024
2025 /* The current frame without replaying - computed via normal unwind. */
79b8d3b0 2026 frame_id = get_thread_current_frame_id (tp);
52834460
MM
2027
2028 /* Check if we need to update any stepping-related frame id's. */
2029 upd_step_frame_id = frame_id_eq (frame_id,
2030 tp->control.step_frame_id);
2031 upd_step_stack_frame_id = frame_id_eq (frame_id,
2032 tp->control.step_stack_frame_id);
2033
2034 /* We start replaying at the end of the branch trace. This corresponds
2035 to the current instruction. */
8d749320 2036 replay = XNEW (struct btrace_insn_iterator);
52834460
MM
2037 btrace_insn_end (replay, btinfo);
2038
31fd9caa
MM
2039 /* Skip gaps at the end of the trace. */
2040 while (btrace_insn_get (replay) == NULL)
2041 {
2042 unsigned int steps;
2043
2044 steps = btrace_insn_prev (replay, 1);
2045 if (steps == 0)
2046 error (_("No trace."));
2047 }
2048
52834460
MM
2049 /* We're not replaying, yet. */
2050 gdb_assert (btinfo->replay == NULL);
2051 btinfo->replay = replay;
2052
2053 /* Make sure we're not using any stale registers. */
00431a78 2054 registers_changed_thread (tp);
52834460
MM
2055
2056 /* The current frame with replaying - computed via btrace unwind. */
79b8d3b0 2057 frame_id = get_thread_current_frame_id (tp);
52834460
MM
2058
2059 /* Replace stepping related frames where necessary. */
2060 if (upd_step_frame_id)
2061 tp->control.step_frame_id = frame_id;
2062 if (upd_step_stack_frame_id)
2063 tp->control.step_stack_frame_id = frame_id;
2064 }
230d2906 2065 catch (const gdb_exception &except)
52834460
MM
2066 {
2067 xfree (btinfo->replay);
2068 btinfo->replay = NULL;
2069
00431a78 2070 registers_changed_thread (tp);
52834460 2071
eedc3f4f 2072 throw;
52834460
MM
2073 }
2074
2075 return replay;
2076}
2077
2078/* Stop replaying a thread. */
2079
2080static void
2081record_btrace_stop_replaying (struct thread_info *tp)
2082{
2083 struct btrace_thread_info *btinfo;
2084
2085 btinfo = &tp->btrace;
2086
2087 xfree (btinfo->replay);
2088 btinfo->replay = NULL;
2089
2090 /* Make sure we're not leaving any stale registers. */
00431a78 2091 registers_changed_thread (tp);
52834460
MM
2092}
2093
e3cfc1c7
MM
2094/* Stop replaying TP if it is at the end of its execution history. */
2095
2096static void
2097record_btrace_stop_replaying_at_end (struct thread_info *tp)
2098{
2099 struct btrace_insn_iterator *replay, end;
2100 struct btrace_thread_info *btinfo;
2101
2102 btinfo = &tp->btrace;
2103 replay = btinfo->replay;
2104
2105 if (replay == NULL)
2106 return;
2107
2108 btrace_insn_end (&end, btinfo);
2109
2110 if (btrace_insn_cmp (replay, &end) == 0)
2111 record_btrace_stop_replaying (tp);
2112}
2113
f6ac5f3d 2114/* The resume method of target record-btrace. */
b2f4cfde 2115
f6ac5f3d
PA
2116void
2117record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
b2f4cfde 2118{
d2939ba2 2119 enum btrace_thread_flag flag, cflag;
52834460 2120
a068643d 2121 DEBUG ("resume %s: %s%s", target_pid_to_str (ptid).c_str (),
f6ac5f3d 2122 ::execution_direction == EXEC_REVERSE ? "reverse-" : "",
987e68b1 2123 step ? "step" : "cont");
52834460 2124
0ca912df
MM
2125 /* Store the execution direction of the last resume.
2126
f6ac5f3d 2127 If there is more than one resume call, we have to rely on infrun
0ca912df 2128 to not change the execution direction in-between. */
f6ac5f3d 2129 record_btrace_resume_exec_dir = ::execution_direction;
70ad5bff 2130
0ca912df 2131 /* As long as we're not replaying, just forward the request.
52834460 2132
0ca912df
MM
2133 For non-stop targets this means that no thread is replaying. In order to
2134 make progress, we may need to explicitly move replaying threads to the end
2135 of their execution history. */
f6ac5f3d
PA
2136 if ((::execution_direction != EXEC_REVERSE)
2137 && !record_is_replaying (minus_one_ptid))
b2f4cfde 2138 {
b6a8c27b 2139 this->beneath ()->resume (ptid, step, signal);
04c4fe8c 2140 return;
b2f4cfde
MM
2141 }
2142
52834460 2143 /* Compute the btrace thread flag for the requested move. */
f6ac5f3d 2144 if (::execution_direction == EXEC_REVERSE)
d2939ba2
MM
2145 {
2146 flag = step == 0 ? BTHR_RCONT : BTHR_RSTEP;
2147 cflag = BTHR_RCONT;
2148 }
52834460 2149 else
d2939ba2
MM
2150 {
2151 flag = step == 0 ? BTHR_CONT : BTHR_STEP;
2152 cflag = BTHR_CONT;
2153 }
52834460 2154
52834460 2155 /* We just indicate the resume intent here. The actual stepping happens in
d2939ba2
MM
2156 record_btrace_wait below.
2157
2158 For all-stop targets, we only step INFERIOR_PTID and continue others. */
5b6d1e4f
PA
2159
2160 process_stratum_target *proc_target = current_inferior ()->process_target ();
2161
d2939ba2
MM
2162 if (!target_is_non_stop_p ())
2163 {
26a57c92 2164 gdb_assert (inferior_ptid.matches (ptid));
d2939ba2 2165
5b6d1e4f 2166 for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
08036331
PA
2167 {
2168 if (tp->ptid.matches (inferior_ptid))
2169 record_btrace_resume_thread (tp, flag);
2170 else
2171 record_btrace_resume_thread (tp, cflag);
2172 }
d2939ba2
MM
2173 }
2174 else
2175 {
5b6d1e4f 2176 for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
08036331 2177 record_btrace_resume_thread (tp, flag);
d2939ba2 2178 }
70ad5bff
MM
2179
2180 /* Async support. */
2181 if (target_can_async_p ())
2182 {
6a3753b3 2183 target_async (1);
70ad5bff
MM
2184 mark_async_event_handler (record_btrace_async_inferior_event_handler);
2185 }
52834460
MM
2186}
2187
f6ac5f3d 2188/* The commit_resume method of target record-btrace. */
85ad3aaf 2189
f6ac5f3d
PA
2190void
2191record_btrace_target::commit_resume ()
85ad3aaf 2192{
f6ac5f3d
PA
2193 if ((::execution_direction != EXEC_REVERSE)
2194 && !record_is_replaying (minus_one_ptid))
b6a8c27b 2195 beneath ()->commit_resume ();
85ad3aaf
PA
2196}
2197
987e68b1
MM
2198/* Cancel resuming TP. */
2199
2200static void
2201record_btrace_cancel_resume (struct thread_info *tp)
2202{
2203 enum btrace_thread_flag flags;
2204
2205 flags = tp->btrace.flags & (BTHR_MOVE | BTHR_STOP);
2206 if (flags == 0)
2207 return;
2208
43792cf0
PA
2209 DEBUG ("cancel resume thread %s (%s): %x (%s)",
2210 print_thread_id (tp),
a068643d 2211 target_pid_to_str (tp->ptid).c_str (), flags,
987e68b1
MM
2212 btrace_thread_flag_to_str (flags));
2213
2214 tp->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
e3cfc1c7 2215 record_btrace_stop_replaying_at_end (tp);
52834460
MM
2216}
2217
2218/* Return a target_waitstatus indicating that we ran out of history. */
2219
2220static struct target_waitstatus
2221btrace_step_no_history (void)
2222{
2223 struct target_waitstatus status;
2224
2225 status.kind = TARGET_WAITKIND_NO_HISTORY;
2226
2227 return status;
2228}
2229
2230/* Return a target_waitstatus indicating that a step finished. */
2231
2232static struct target_waitstatus
2233btrace_step_stopped (void)
2234{
2235 struct target_waitstatus status;
2236
2237 status.kind = TARGET_WAITKIND_STOPPED;
2238 status.value.sig = GDB_SIGNAL_TRAP;
2239
2240 return status;
2241}
2242
6e4879f0
MM
2243/* Return a target_waitstatus indicating that a thread was stopped as
2244 requested. */
2245
2246static struct target_waitstatus
2247btrace_step_stopped_on_request (void)
2248{
2249 struct target_waitstatus status;
2250
2251 status.kind = TARGET_WAITKIND_STOPPED;
2252 status.value.sig = GDB_SIGNAL_0;
2253
2254 return status;
2255}
2256
d825d248
MM
2257/* Return a target_waitstatus indicating a spurious stop. */
2258
2259static struct target_waitstatus
2260btrace_step_spurious (void)
2261{
2262 struct target_waitstatus status;
2263
2264 status.kind = TARGET_WAITKIND_SPURIOUS;
2265
2266 return status;
2267}
2268
e3cfc1c7
MM
2269/* Return a target_waitstatus indicating that the thread was not resumed. */
2270
2271static struct target_waitstatus
2272btrace_step_no_resumed (void)
2273{
2274 struct target_waitstatus status;
2275
2276 status.kind = TARGET_WAITKIND_NO_RESUMED;
2277
2278 return status;
2279}
2280
2281/* Return a target_waitstatus indicating that we should wait again. */
2282
2283static struct target_waitstatus
2284btrace_step_again (void)
2285{
2286 struct target_waitstatus status;
2287
2288 status.kind = TARGET_WAITKIND_IGNORE;
2289
2290 return status;
2291}
2292
52834460
MM
2293/* Clear the record histories. */
2294
2295static void
2296record_btrace_clear_histories (struct btrace_thread_info *btinfo)
2297{
2298 xfree (btinfo->insn_history);
2299 xfree (btinfo->call_history);
2300
2301 btinfo->insn_history = NULL;
2302 btinfo->call_history = NULL;
2303}
2304
3c615f99
MM
2305/* Check whether TP's current replay position is at a breakpoint. */
2306
2307static int
2308record_btrace_replay_at_breakpoint (struct thread_info *tp)
2309{
2310 struct btrace_insn_iterator *replay;
2311 struct btrace_thread_info *btinfo;
2312 const struct btrace_insn *insn;
3c615f99
MM
2313
2314 btinfo = &tp->btrace;
2315 replay = btinfo->replay;
2316
2317 if (replay == NULL)
2318 return 0;
2319
2320 insn = btrace_insn_get (replay);
2321 if (insn == NULL)
2322 return 0;
2323
00431a78 2324 return record_check_stopped_by_breakpoint (tp->inf->aspace, insn->pc,
3c615f99
MM
2325 &btinfo->stop_reason);
2326}
2327
d825d248 2328/* Step one instruction in forward direction. */
52834460
MM
2329
2330static struct target_waitstatus
d825d248 2331record_btrace_single_step_forward (struct thread_info *tp)
52834460 2332{
b61ce85c 2333 struct btrace_insn_iterator *replay, end, start;
52834460 2334 struct btrace_thread_info *btinfo;
52834460 2335
d825d248
MM
2336 btinfo = &tp->btrace;
2337 replay = btinfo->replay;
2338
2339 /* We're done if we're not replaying. */
2340 if (replay == NULL)
2341 return btrace_step_no_history ();
2342
011c71b6
MM
2343 /* Check if we're stepping a breakpoint. */
2344 if (record_btrace_replay_at_breakpoint (tp))
2345 return btrace_step_stopped ();
2346
b61ce85c
MM
2347 /* Skip gaps during replay. If we end up at a gap (at the end of the trace),
2348 jump back to the instruction at which we started. */
2349 start = *replay;
d825d248
MM
2350 do
2351 {
2352 unsigned int steps;
2353
e3cfc1c7
MM
2354 /* We will bail out here if we continue stepping after reaching the end
2355 of the execution history. */
d825d248
MM
2356 steps = btrace_insn_next (replay, 1);
2357 if (steps == 0)
b61ce85c
MM
2358 {
2359 *replay = start;
2360 return btrace_step_no_history ();
2361 }
d825d248
MM
2362 }
2363 while (btrace_insn_get (replay) == NULL);
2364
2365 /* Determine the end of the instruction trace. */
2366 btrace_insn_end (&end, btinfo);
2367
e3cfc1c7
MM
2368 /* The execution trace contains (and ends with) the current instruction.
2369 This instruction has not been executed, yet, so the trace really ends
2370 one instruction earlier. */
d825d248 2371 if (btrace_insn_cmp (replay, &end) == 0)
e3cfc1c7 2372 return btrace_step_no_history ();
d825d248
MM
2373
2374 return btrace_step_spurious ();
2375}
2376
2377/* Step one instruction in backward direction. */
2378
2379static struct target_waitstatus
2380record_btrace_single_step_backward (struct thread_info *tp)
2381{
b61ce85c 2382 struct btrace_insn_iterator *replay, start;
d825d248 2383 struct btrace_thread_info *btinfo;
e59fa00f 2384
52834460
MM
2385 btinfo = &tp->btrace;
2386 replay = btinfo->replay;
2387
d825d248
MM
2388 /* Start replaying if we're not already doing so. */
2389 if (replay == NULL)
2390 replay = record_btrace_start_replaying (tp);
2391
2392 /* If we can't step any further, we reached the end of the history.
b61ce85c
MM
2393 Skip gaps during replay. If we end up at a gap (at the beginning of
2394 the trace), jump back to the instruction at which we started. */
2395 start = *replay;
d825d248
MM
2396 do
2397 {
2398 unsigned int steps;
2399
2400 steps = btrace_insn_prev (replay, 1);
2401 if (steps == 0)
b61ce85c
MM
2402 {
2403 *replay = start;
2404 return btrace_step_no_history ();
2405 }
d825d248
MM
2406 }
2407 while (btrace_insn_get (replay) == NULL);
2408
011c71b6
MM
2409 /* Check if we're stepping a breakpoint.
2410
2411 For reverse-stepping, this check is after the step. There is logic in
2412 infrun.c that handles reverse-stepping separately. See, for example,
2413 proceed and adjust_pc_after_break.
2414
2415 This code assumes that for reverse-stepping, PC points to the last
2416 de-executed instruction, whereas for forward-stepping PC points to the
2417 next to-be-executed instruction. */
2418 if (record_btrace_replay_at_breakpoint (tp))
2419 return btrace_step_stopped ();
2420
d825d248
MM
2421 return btrace_step_spurious ();
2422}
2423
2424/* Step a single thread. */
2425
2426static struct target_waitstatus
2427record_btrace_step_thread (struct thread_info *tp)
2428{
2429 struct btrace_thread_info *btinfo;
2430 struct target_waitstatus status;
2431 enum btrace_thread_flag flags;
2432
2433 btinfo = &tp->btrace;
2434
6e4879f0
MM
2435 flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP);
2436 btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
52834460 2437
43792cf0 2438 DEBUG ("stepping thread %s (%s): %x (%s)", print_thread_id (tp),
a068643d 2439 target_pid_to_str (tp->ptid).c_str (), flags,
987e68b1 2440 btrace_thread_flag_to_str (flags));
52834460 2441
6e4879f0
MM
2442 /* We can't step without an execution history. */
2443 if ((flags & BTHR_MOVE) != 0 && btrace_is_empty (tp))
2444 return btrace_step_no_history ();
2445
52834460
MM
2446 switch (flags)
2447 {
2448 default:
2449 internal_error (__FILE__, __LINE__, _("invalid stepping type."));
2450
6e4879f0
MM
2451 case BTHR_STOP:
2452 return btrace_step_stopped_on_request ();
2453
52834460 2454 case BTHR_STEP:
d825d248
MM
2455 status = record_btrace_single_step_forward (tp);
2456 if (status.kind != TARGET_WAITKIND_SPURIOUS)
e3cfc1c7 2457 break;
52834460
MM
2458
2459 return btrace_step_stopped ();
2460
2461 case BTHR_RSTEP:
d825d248
MM
2462 status = record_btrace_single_step_backward (tp);
2463 if (status.kind != TARGET_WAITKIND_SPURIOUS)
e3cfc1c7 2464 break;
52834460
MM
2465
2466 return btrace_step_stopped ();
2467
2468 case BTHR_CONT:
e3cfc1c7
MM
2469 status = record_btrace_single_step_forward (tp);
2470 if (status.kind != TARGET_WAITKIND_SPURIOUS)
2471 break;
52834460 2472
e3cfc1c7
MM
2473 btinfo->flags |= flags;
2474 return btrace_step_again ();
52834460
MM
2475
2476 case BTHR_RCONT:
e3cfc1c7
MM
2477 status = record_btrace_single_step_backward (tp);
2478 if (status.kind != TARGET_WAITKIND_SPURIOUS)
2479 break;
52834460 2480
e3cfc1c7
MM
2481 btinfo->flags |= flags;
2482 return btrace_step_again ();
2483 }
d825d248 2484
f6ac5f3d 2485 /* We keep threads moving at the end of their execution history. The wait
e3cfc1c7
MM
2486 method will stop the thread for whom the event is reported. */
2487 if (status.kind == TARGET_WAITKIND_NO_HISTORY)
2488 btinfo->flags |= flags;
52834460 2489
e3cfc1c7 2490 return status;
b2f4cfde
MM
2491}
2492
a6b5be76
MM
2493/* Announce further events if necessary. */
2494
2495static void
53127008
SM
2496record_btrace_maybe_mark_async_event
2497 (const std::vector<thread_info *> &moving,
2498 const std::vector<thread_info *> &no_history)
a6b5be76 2499{
53127008
SM
2500 bool more_moving = !moving.empty ();
2501 bool more_no_history = !no_history.empty ();;
a6b5be76
MM
2502
2503 if (!more_moving && !more_no_history)
2504 return;
2505
2506 if (more_moving)
2507 DEBUG ("movers pending");
2508
2509 if (more_no_history)
2510 DEBUG ("no-history pending");
2511
2512 mark_async_event_handler (record_btrace_async_inferior_event_handler);
2513}
2514
f6ac5f3d 2515/* The wait method of target record-btrace. */
b2f4cfde 2516
f6ac5f3d
PA
2517ptid_t
2518record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
2519 int options)
b2f4cfde 2520{
53127008
SM
2521 std::vector<thread_info *> moving;
2522 std::vector<thread_info *> no_history;
52834460 2523
a068643d 2524 DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid).c_str (), options);
52834460 2525
b2f4cfde 2526 /* As long as we're not replaying, just forward the request. */
f6ac5f3d
PA
2527 if ((::execution_direction != EXEC_REVERSE)
2528 && !record_is_replaying (minus_one_ptid))
b2f4cfde 2529 {
b6a8c27b 2530 return this->beneath ()->wait (ptid, status, options);
b2f4cfde
MM
2531 }
2532
e3cfc1c7 2533 /* Keep a work list of moving threads. */
5b6d1e4f
PA
2534 process_stratum_target *proc_target = current_inferior ()->process_target ();
2535 for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
08036331
PA
2536 if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
2537 moving.push_back (tp);
e3cfc1c7 2538
53127008 2539 if (moving.empty ())
52834460 2540 {
e3cfc1c7 2541 *status = btrace_step_no_resumed ();
52834460 2542
a068643d 2543 DEBUG ("wait ended by %s: %s", target_pid_to_str (null_ptid).c_str (),
23fdd69e 2544 target_waitstatus_to_string (status).c_str ());
e3cfc1c7 2545
e3cfc1c7 2546 return null_ptid;
52834460
MM
2547 }
2548
e3cfc1c7
MM
2549 /* Step moving threads one by one, one step each, until either one thread
2550 reports an event or we run out of threads to step.
2551
2552 When stepping more than one thread, chances are that some threads reach
2553 the end of their execution history earlier than others. If we reported
2554 this immediately, all-stop on top of non-stop would stop all threads and
2555 resume the same threads next time. And we would report the same thread
2556 having reached the end of its execution history again.
2557
2558 In the worst case, this would starve the other threads. But even if other
2559 threads would be allowed to make progress, this would result in far too
2560 many intermediate stops.
2561
2562 We therefore delay the reporting of "no execution history" until we have
2563 nothing else to report. By this time, all threads should have moved to
2564 either the beginning or the end of their execution history. There will
2565 be a single user-visible stop. */
53127008
SM
2566 struct thread_info *eventing = NULL;
2567 while ((eventing == NULL) && !moving.empty ())
e3cfc1c7 2568 {
53127008 2569 for (unsigned int ix = 0; eventing == NULL && ix < moving.size ();)
e3cfc1c7 2570 {
53127008
SM
2571 thread_info *tp = moving[ix];
2572
e3cfc1c7
MM
2573 *status = record_btrace_step_thread (tp);
2574
2575 switch (status->kind)
2576 {
2577 case TARGET_WAITKIND_IGNORE:
2578 ix++;
2579 break;
2580
2581 case TARGET_WAITKIND_NO_HISTORY:
53127008 2582 no_history.push_back (ordered_remove (moving, ix));
e3cfc1c7
MM
2583 break;
2584
2585 default:
53127008 2586 eventing = unordered_remove (moving, ix);
e3cfc1c7
MM
2587 break;
2588 }
2589 }
2590 }
2591
2592 if (eventing == NULL)
2593 {
2594 /* We started with at least one moving thread. This thread must have
2595 either stopped or reached the end of its execution history.
2596
2597 In the former case, EVENTING must not be NULL.
2598 In the latter case, NO_HISTORY must not be empty. */
53127008 2599 gdb_assert (!no_history.empty ());
e3cfc1c7
MM
2600
2601 /* We kept threads moving at the end of their execution history. Stop
2602 EVENTING now that we are going to report its stop. */
53127008 2603 eventing = unordered_remove (no_history, 0);
e3cfc1c7
MM
2604 eventing->btrace.flags &= ~BTHR_MOVE;
2605
2606 *status = btrace_step_no_history ();
2607 }
2608
2609 gdb_assert (eventing != NULL);
2610
2611 /* We kept threads replaying at the end of their execution history. Stop
2612 replaying EVENTING now that we are going to report its stop. */
2613 record_btrace_stop_replaying_at_end (eventing);
52834460
MM
2614
2615 /* Stop all other threads. */
5953356c 2616 if (!target_is_non_stop_p ())
53127008 2617 {
08036331 2618 for (thread_info *tp : all_non_exited_threads ())
53127008
SM
2619 record_btrace_cancel_resume (tp);
2620 }
52834460 2621
a6b5be76
MM
2622 /* In async mode, we need to announce further events. */
2623 if (target_is_async_p ())
2624 record_btrace_maybe_mark_async_event (moving, no_history);
2625
52834460 2626 /* Start record histories anew from the current position. */
e3cfc1c7 2627 record_btrace_clear_histories (&eventing->btrace);
52834460
MM
2628
2629 /* We moved the replay position but did not update registers. */
00431a78 2630 registers_changed_thread (eventing);
e3cfc1c7 2631
43792cf0
PA
2632 DEBUG ("wait ended by thread %s (%s): %s",
2633 print_thread_id (eventing),
a068643d 2634 target_pid_to_str (eventing->ptid).c_str (),
23fdd69e 2635 target_waitstatus_to_string (status).c_str ());
52834460 2636
e3cfc1c7 2637 return eventing->ptid;
52834460
MM
2638}
2639
f6ac5f3d 2640/* The stop method of target record-btrace. */
6e4879f0 2641
f6ac5f3d
PA
2642void
2643record_btrace_target::stop (ptid_t ptid)
6e4879f0 2644{
a068643d 2645 DEBUG ("stop %s", target_pid_to_str (ptid).c_str ());
6e4879f0
MM
2646
2647 /* As long as we're not replaying, just forward the request. */
f6ac5f3d
PA
2648 if ((::execution_direction != EXEC_REVERSE)
2649 && !record_is_replaying (minus_one_ptid))
6e4879f0 2650 {
b6a8c27b 2651 this->beneath ()->stop (ptid);
6e4879f0
MM
2652 }
2653 else
2654 {
5b6d1e4f
PA
2655 process_stratum_target *proc_target
2656 = current_inferior ()->process_target ();
2657
2658 for (thread_info *tp : all_non_exited_threads (proc_target, ptid))
08036331
PA
2659 {
2660 tp->btrace.flags &= ~BTHR_MOVE;
2661 tp->btrace.flags |= BTHR_STOP;
2662 }
6e4879f0
MM
2663 }
2664 }
2665
f6ac5f3d 2666/* The can_execute_reverse method of target record-btrace. */
52834460 2667
57810aa7 2668bool
f6ac5f3d 2669record_btrace_target::can_execute_reverse ()
52834460 2670{
57810aa7 2671 return true;
52834460
MM
2672}
2673
f6ac5f3d 2674/* The stopped_by_sw_breakpoint method of target record-btrace. */
52834460 2675
57810aa7 2676bool
f6ac5f3d 2677record_btrace_target::stopped_by_sw_breakpoint ()
52834460 2678{
f6ac5f3d 2679 if (record_is_replaying (minus_one_ptid))
9e8915c6
PA
2680 {
2681 struct thread_info *tp = inferior_thread ();
2682
2683 return tp->btrace.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
2684 }
2685
b6a8c27b 2686 return this->beneath ()->stopped_by_sw_breakpoint ();
9e8915c6
PA
2687}
2688
f6ac5f3d 2689/* The supports_stopped_by_sw_breakpoint method of target
9e8915c6
PA
2690 record-btrace. */
2691
57810aa7 2692bool
f6ac5f3d 2693record_btrace_target::supports_stopped_by_sw_breakpoint ()
9e8915c6 2694{
f6ac5f3d 2695 if (record_is_replaying (minus_one_ptid))
57810aa7 2696 return true;
9e8915c6 2697
b6a8c27b 2698 return this->beneath ()->supports_stopped_by_sw_breakpoint ();
9e8915c6
PA
2699}
2700
f6ac5f3d 2701/* The stopped_by_sw_breakpoint method of target record-btrace. */
9e8915c6 2702
57810aa7 2703bool
f6ac5f3d 2704record_btrace_target::stopped_by_hw_breakpoint ()
9e8915c6 2705{
f6ac5f3d 2706 if (record_is_replaying (minus_one_ptid))
9e8915c6
PA
2707 {
2708 struct thread_info *tp = inferior_thread ();
2709
2710 return tp->btrace.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
2711 }
2712
b6a8c27b 2713 return this->beneath ()->stopped_by_hw_breakpoint ();
9e8915c6
PA
2714}
2715
f6ac5f3d 2716/* The supports_stopped_by_hw_breakpoint method of target
9e8915c6
PA
2717 record-btrace. */
2718
57810aa7 2719bool
f6ac5f3d 2720record_btrace_target::supports_stopped_by_hw_breakpoint ()
9e8915c6 2721{
f6ac5f3d 2722 if (record_is_replaying (minus_one_ptid))
57810aa7 2723 return true;
52834460 2724
b6a8c27b 2725 return this->beneath ()->supports_stopped_by_hw_breakpoint ();
b2f4cfde
MM
2726}
2727
f6ac5f3d 2728/* The update_thread_list method of target record-btrace. */
e2887aa3 2729
f6ac5f3d
PA
2730void
2731record_btrace_target::update_thread_list ()
e2887aa3 2732{
e8032dde 2733 /* We don't add or remove threads during replay. */
f6ac5f3d 2734 if (record_is_replaying (minus_one_ptid))
e2887aa3
MM
2735 return;
2736
2737 /* Forward the request. */
b6a8c27b 2738 this->beneath ()->update_thread_list ();
e2887aa3
MM
2739}
2740
f6ac5f3d 2741/* The thread_alive method of target record-btrace. */
e2887aa3 2742
57810aa7 2743bool
f6ac5f3d 2744record_btrace_target::thread_alive (ptid_t ptid)
e2887aa3
MM
2745{
2746 /* We don't add or remove threads during replay. */
f6ac5f3d 2747 if (record_is_replaying (minus_one_ptid))
00431a78 2748 return true;
e2887aa3
MM
2749
2750 /* Forward the request. */
b6a8c27b 2751 return this->beneath ()->thread_alive (ptid);
e2887aa3
MM
2752}
2753
066ce621
MM
2754/* Set the replay branch trace instruction iterator. If IT is NULL, replay
2755 is stopped. */
2756
2757static void
2758record_btrace_set_replay (struct thread_info *tp,
2759 const struct btrace_insn_iterator *it)
2760{
2761 struct btrace_thread_info *btinfo;
2762
2763 btinfo = &tp->btrace;
2764
a0f1b963 2765 if (it == NULL)
52834460 2766 record_btrace_stop_replaying (tp);
066ce621
MM
2767 else
2768 {
2769 if (btinfo->replay == NULL)
52834460 2770 record_btrace_start_replaying (tp);
066ce621
MM
2771 else if (btrace_insn_cmp (btinfo->replay, it) == 0)
2772 return;
2773
2774 *btinfo->replay = *it;
00431a78 2775 registers_changed_thread (tp);
066ce621
MM
2776 }
2777
52834460
MM
2778 /* Start anew from the new replay position. */
2779 record_btrace_clear_histories (btinfo);
485668e5 2780
f2ffa92b
PA
2781 inferior_thread ()->suspend.stop_pc
2782 = regcache_read_pc (get_current_regcache ());
485668e5 2783 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
066ce621
MM
2784}
2785
f6ac5f3d 2786/* The goto_record_begin method of target record-btrace. */
066ce621 2787
f6ac5f3d
PA
2788void
2789record_btrace_target::goto_record_begin ()
066ce621
MM
2790{
2791 struct thread_info *tp;
2792 struct btrace_insn_iterator begin;
2793
2794 tp = require_btrace_thread ();
2795
2796 btrace_insn_begin (&begin, &tp->btrace);
b61ce85c
MM
2797
2798 /* Skip gaps at the beginning of the trace. */
2799 while (btrace_insn_get (&begin) == NULL)
2800 {
2801 unsigned int steps;
2802
2803 steps = btrace_insn_next (&begin, 1);
2804 if (steps == 0)
2805 error (_("No trace."));
2806 }
2807
066ce621 2808 record_btrace_set_replay (tp, &begin);
066ce621
MM
2809}
2810
f6ac5f3d 2811/* The goto_record_end method of target record-btrace. */
066ce621 2812
f6ac5f3d
PA
2813void
2814record_btrace_target::goto_record_end ()
066ce621
MM
2815{
2816 struct thread_info *tp;
2817
2818 tp = require_btrace_thread ();
2819
2820 record_btrace_set_replay (tp, NULL);
066ce621
MM
2821}
2822
f6ac5f3d 2823/* The goto_record method of target record-btrace. */
066ce621 2824
f6ac5f3d
PA
2825void
2826record_btrace_target::goto_record (ULONGEST insn)
066ce621
MM
2827{
2828 struct thread_info *tp;
2829 struct btrace_insn_iterator it;
2830 unsigned int number;
2831 int found;
2832
2833 number = insn;
2834
2835 /* Check for wrap-arounds. */
2836 if (number != insn)
2837 error (_("Instruction number out of range."));
2838
2839 tp = require_btrace_thread ();
2840
2841 found = btrace_find_insn_by_number (&it, &tp->btrace, number);
69090cee
TW
2842
2843 /* Check if the instruction could not be found or is a gap. */
2844 if (found == 0 || btrace_insn_get (&it) == NULL)
066ce621
MM
2845 error (_("No such instruction."));
2846
2847 record_btrace_set_replay (tp, &it);
066ce621
MM
2848}
2849
f6ac5f3d 2850/* The record_stop_replaying method of target record-btrace. */
797094dd 2851
f6ac5f3d
PA
2852void
2853record_btrace_target::record_stop_replaying ()
797094dd 2854{
08036331 2855 for (thread_info *tp : all_non_exited_threads ())
797094dd
MM
2856 record_btrace_stop_replaying (tp);
2857}
2858
f6ac5f3d 2859/* The execution_direction target method. */
70ad5bff 2860
f6ac5f3d
PA
2861enum exec_direction_kind
2862record_btrace_target::execution_direction ()
70ad5bff
MM
2863{
2864 return record_btrace_resume_exec_dir;
2865}
2866
f6ac5f3d 2867/* The prepare_to_generate_core target method. */
aef92902 2868
f6ac5f3d
PA
2869void
2870record_btrace_target::prepare_to_generate_core ()
aef92902
MM
2871{
2872 record_btrace_generating_corefile = 1;
2873}
2874
f6ac5f3d 2875/* The done_generating_core target method. */
aef92902 2876
f6ac5f3d
PA
2877void
2878record_btrace_target::done_generating_core ()
aef92902
MM
2879{
2880 record_btrace_generating_corefile = 0;
2881}
2882
f4abbc16
MM
2883/* Start recording in BTS format. */
2884
2885static void
cdb34d4a 2886cmd_record_btrace_bts_start (const char *args, int from_tty)
f4abbc16 2887{
f4abbc16
MM
2888 if (args != NULL && *args != 0)
2889 error (_("Invalid argument."));
2890
2891 record_btrace_conf.format = BTRACE_FORMAT_BTS;
2892
a70b8144 2893 try
492d29ea 2894 {
95a6b0a1 2895 execute_command ("target record-btrace", from_tty);
492d29ea 2896 }
230d2906 2897 catch (const gdb_exception &exception)
f4abbc16
MM
2898 {
2899 record_btrace_conf.format = BTRACE_FORMAT_NONE;
eedc3f4f 2900 throw;
f4abbc16
MM
2901 }
2902}
2903
bc504a31 2904/* Start recording in Intel Processor Trace format. */
afedecd3
MM
2905
2906static void
cdb34d4a 2907cmd_record_btrace_pt_start (const char *args, int from_tty)
afedecd3
MM
2908{
2909 if (args != NULL && *args != 0)
2910 error (_("Invalid argument."));
2911
b20a6524 2912 record_btrace_conf.format = BTRACE_FORMAT_PT;
f4abbc16 2913
a70b8144 2914 try
492d29ea 2915 {
95a6b0a1 2916 execute_command ("target record-btrace", from_tty);
492d29ea 2917 }
230d2906 2918 catch (const gdb_exception &exception)
492d29ea
PA
2919 {
2920 record_btrace_conf.format = BTRACE_FORMAT_NONE;
eedc3f4f 2921 throw;
492d29ea 2922 }
afedecd3
MM
2923}
2924
b20a6524
MM
2925/* Alias for "target record". */
2926
2927static void
981a3fb3 2928cmd_record_btrace_start (const char *args, int from_tty)
b20a6524
MM
2929{
2930 if (args != NULL && *args != 0)
2931 error (_("Invalid argument."));
2932
2933 record_btrace_conf.format = BTRACE_FORMAT_PT;
2934
a70b8144 2935 try
b20a6524 2936 {
95a6b0a1 2937 execute_command ("target record-btrace", from_tty);
b20a6524 2938 }
230d2906 2939 catch (const gdb_exception &exception)
b20a6524
MM
2940 {
2941 record_btrace_conf.format = BTRACE_FORMAT_BTS;
2942
a70b8144 2943 try
b20a6524 2944 {
95a6b0a1 2945 execute_command ("target record-btrace", from_tty);
b20a6524 2946 }
230d2906 2947 catch (const gdb_exception &ex)
b20a6524
MM
2948 {
2949 record_btrace_conf.format = BTRACE_FORMAT_NONE;
eedc3f4f 2950 throw;
b20a6524 2951 }
b20a6524 2952 }
b20a6524
MM
2953}
2954
67b5c0c1
MM
2955/* The "set record btrace" command. */
2956
2957static void
981a3fb3 2958cmd_set_record_btrace (const char *args, int from_tty)
67b5c0c1 2959{
b85310e1
MM
2960 printf_unfiltered (_("\"set record btrace\" must be followed "
2961 "by an appropriate subcommand.\n"));
2962 help_list (set_record_btrace_cmdlist, "set record btrace ",
2963 all_commands, gdb_stdout);
67b5c0c1
MM
2964}
2965
2966/* The "show record btrace" command. */
2967
2968static void
981a3fb3 2969cmd_show_record_btrace (const char *args, int from_tty)
67b5c0c1
MM
2970{
2971 cmd_show_list (show_record_btrace_cmdlist, from_tty, "");
2972}
2973
2974/* The "show record btrace replay-memory-access" command. */
2975
2976static void
2977cmd_show_replay_memory_access (struct ui_file *file, int from_tty,
2978 struct cmd_list_element *c, const char *value)
2979{
2980 fprintf_filtered (gdb_stdout, _("Replay memory access is %s.\n"),
2981 replay_memory_access);
2982}
2983
4a4495d6
MM
2984/* The "set record btrace cpu none" command. */
2985
2986static void
2987cmd_set_record_btrace_cpu_none (const char *args, int from_tty)
2988{
2989 if (args != nullptr && *args != 0)
2990 error (_("Trailing junk: '%s'."), args);
2991
2992 record_btrace_cpu_state = CS_NONE;
2993}
2994
2995/* The "set record btrace cpu auto" command. */
2996
2997static void
2998cmd_set_record_btrace_cpu_auto (const char *args, int from_tty)
2999{
3000 if (args != nullptr && *args != 0)
3001 error (_("Trailing junk: '%s'."), args);
3002
3003 record_btrace_cpu_state = CS_AUTO;
3004}
3005
3006/* The "set record btrace cpu" command. */
3007
3008static void
3009cmd_set_record_btrace_cpu (const char *args, int from_tty)
3010{
3011 if (args == nullptr)
3012 args = "";
3013
3014 /* We use a hard-coded vendor string for now. */
3015 unsigned int family, model, stepping;
3016 int l1, l2, matches = sscanf (args, "intel: %u/%u%n/%u%n", &family,
3017 &model, &l1, &stepping, &l2);
3018 if (matches == 3)
3019 {
3020 if (strlen (args) != l2)
3021 error (_("Trailing junk: '%s'."), args + l2);
3022 }
3023 else if (matches == 2)
3024 {
3025 if (strlen (args) != l1)
3026 error (_("Trailing junk: '%s'."), args + l1);
3027
3028 stepping = 0;
3029 }
3030 else
3031 error (_("Bad format. See \"help set record btrace cpu\"."));
3032
3033 if (USHRT_MAX < family)
3034 error (_("Cpu family too big."));
3035
3036 if (UCHAR_MAX < model)
3037 error (_("Cpu model too big."));
3038
3039 if (UCHAR_MAX < stepping)
3040 error (_("Cpu stepping too big."));
3041
3042 record_btrace_cpu.vendor = CV_INTEL;
3043 record_btrace_cpu.family = family;
3044 record_btrace_cpu.model = model;
3045 record_btrace_cpu.stepping = stepping;
3046
3047 record_btrace_cpu_state = CS_CPU;
3048}
3049
3050/* The "show record btrace cpu" command. */
3051
3052static void
3053cmd_show_record_btrace_cpu (const char *args, int from_tty)
3054{
4a4495d6
MM
3055 if (args != nullptr && *args != 0)
3056 error (_("Trailing junk: '%s'."), args);
3057
3058 switch (record_btrace_cpu_state)
3059 {
3060 case CS_AUTO:
3061 printf_unfiltered (_("btrace cpu is 'auto'.\n"));
3062 return;
3063
3064 case CS_NONE:
3065 printf_unfiltered (_("btrace cpu is 'none'.\n"));
3066 return;
3067
3068 case CS_CPU:
3069 switch (record_btrace_cpu.vendor)
3070 {
3071 case CV_INTEL:
3072 if (record_btrace_cpu.stepping == 0)
3073 printf_unfiltered (_("btrace cpu is 'intel: %u/%u'.\n"),
3074 record_btrace_cpu.family,
3075 record_btrace_cpu.model);
3076 else
3077 printf_unfiltered (_("btrace cpu is 'intel: %u/%u/%u'.\n"),
3078 record_btrace_cpu.family,
3079 record_btrace_cpu.model,
3080 record_btrace_cpu.stepping);
3081 return;
3082 }
3083 }
3084
3085 error (_("Internal error: bad cpu state."));
3086}
3087
3088/* The "s record btrace bts" command. */
d33501a5
MM
3089
3090static void
981a3fb3 3091cmd_set_record_btrace_bts (const char *args, int from_tty)
d33501a5
MM
3092{
3093 printf_unfiltered (_("\"set record btrace bts\" must be followed "
b20a6524 3094 "by an appropriate subcommand.\n"));
d33501a5
MM
3095 help_list (set_record_btrace_bts_cmdlist, "set record btrace bts ",
3096 all_commands, gdb_stdout);
3097}
3098
3099/* The "show record btrace bts" command. */
3100
3101static void
981a3fb3 3102cmd_show_record_btrace_bts (const char *args, int from_tty)
d33501a5
MM
3103{
3104 cmd_show_list (show_record_btrace_bts_cmdlist, from_tty, "");
3105}
3106
b20a6524
MM
3107/* The "set record btrace pt" command. */
3108
3109static void
981a3fb3 3110cmd_set_record_btrace_pt (const char *args, int from_tty)
b20a6524
MM
3111{
3112 printf_unfiltered (_("\"set record btrace pt\" must be followed "
3113 "by an appropriate subcommand.\n"));
3114 help_list (set_record_btrace_pt_cmdlist, "set record btrace pt ",
3115 all_commands, gdb_stdout);
3116}
3117
3118/* The "show record btrace pt" command. */
3119
3120static void
981a3fb3 3121cmd_show_record_btrace_pt (const char *args, int from_tty)
b20a6524
MM
3122{
3123 cmd_show_list (show_record_btrace_pt_cmdlist, from_tty, "");
3124}
3125
3126/* The "record bts buffer-size" show value function. */
3127
3128static void
3129show_record_bts_buffer_size_value (struct ui_file *file, int from_tty,
3130 struct cmd_list_element *c,
3131 const char *value)
3132{
3133 fprintf_filtered (file, _("The record/replay bts buffer size is %s.\n"),
3134 value);
3135}
3136
3137/* The "record pt buffer-size" show value function. */
3138
3139static void
3140show_record_pt_buffer_size_value (struct ui_file *file, int from_tty,
3141 struct cmd_list_element *c,
3142 const char *value)
3143{
3144 fprintf_filtered (file, _("The record/replay pt buffer size is %s.\n"),
3145 value);
3146}
3147
afedecd3
MM
3148/* Initialize btrace commands. */
3149
3150void
3151_initialize_record_btrace (void)
3152{
f4abbc16
MM
3153 add_prefix_cmd ("btrace", class_obscure, cmd_record_btrace_start,
3154 _("Start branch trace recording."), &record_btrace_cmdlist,
3155 "record btrace ", 0, &record_cmdlist);
afedecd3
MM
3156 add_alias_cmd ("b", "btrace", class_obscure, 1, &record_cmdlist);
3157
f4abbc16
MM
3158 add_cmd ("bts", class_obscure, cmd_record_btrace_bts_start,
3159 _("\
3160Start branch trace recording in Branch Trace Store (BTS) format.\n\n\
3161The processor stores a from/to record for each branch into a cyclic buffer.\n\
3162This format may not be available on all processors."),
3163 &record_btrace_cmdlist);
3164 add_alias_cmd ("bts", "btrace bts", class_obscure, 1, &record_cmdlist);
3165
b20a6524
MM
3166 add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start,
3167 _("\
bc504a31 3168Start branch trace recording in Intel Processor Trace format.\n\n\
b20a6524
MM
3169This format may not be available on all processors."),
3170 &record_btrace_cmdlist);
3171 add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
3172
67b5c0c1 3173 add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
590042fc 3174 _("Set record options."), &set_record_btrace_cmdlist,
67b5c0c1
MM
3175 "set record btrace ", 0, &set_record_cmdlist);
3176
3177 add_prefix_cmd ("btrace", class_support, cmd_show_record_btrace,
590042fc 3178 _("Show record options."), &show_record_btrace_cmdlist,
67b5c0c1
MM
3179 "show record btrace ", 0, &show_record_cmdlist);
3180
3181 add_setshow_enum_cmd ("replay-memory-access", no_class,
3182 replay_memory_access_types, &replay_memory_access, _("\
3183Set what memory accesses are allowed during replay."), _("\
3184Show what memory accesses are allowed during replay."),
3185 _("Default is READ-ONLY.\n\n\
3186The btrace record target does not trace data.\n\
3187The memory therefore corresponds to the live target and not \
3188to the current replay position.\n\n\
3189When READ-ONLY, allow accesses to read-only memory during replay.\n\
3190When READ-WRITE, allow accesses to read-only and read-write memory during \
3191replay."),
3192 NULL, cmd_show_replay_memory_access,
3193 &set_record_btrace_cmdlist,
3194 &show_record_btrace_cmdlist);
3195
4a4495d6
MM
3196 add_prefix_cmd ("cpu", class_support, cmd_set_record_btrace_cpu,
3197 _("\
3198Set the cpu to be used for trace decode.\n\n\
55063ddb
TT
3199The format is \"VENDOR:IDENTIFIER\" or \"none\" or \"auto\" (default).\n\
3200For vendor \"intel\" the format is \"FAMILY/MODEL[/STEPPING]\".\n\n\
4a4495d6
MM
3201When decoding branch trace, enable errata workarounds for the specified cpu.\n\
3202The default is \"auto\", which uses the cpu on which the trace was recorded.\n\
3203When GDB does not support that cpu, this option can be used to enable\n\
3204workarounds for a similar cpu that GDB supports.\n\n\
3205When set to \"none\", errata workarounds are disabled."),
3206 &set_record_btrace_cpu_cmdlist,
590042fc 3207 "set record btrace cpu ", 1,
4a4495d6
MM
3208 &set_record_btrace_cmdlist);
3209
3210 add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
3211Automatically determine the cpu to be used for trace decode."),
3212 &set_record_btrace_cpu_cmdlist);
3213
3214 add_cmd ("none", class_support, cmd_set_record_btrace_cpu_none, _("\
3215Do not enable errata workarounds for trace decode."),
3216 &set_record_btrace_cpu_cmdlist);
3217
3218 add_cmd ("cpu", class_support, cmd_show_record_btrace_cpu, _("\
3219Show the cpu to be used for trace decode."),
3220 &show_record_btrace_cmdlist);
3221
d33501a5 3222 add_prefix_cmd ("bts", class_support, cmd_set_record_btrace_bts,
590042fc 3223 _("Set record btrace bts options."),
d33501a5
MM
3224 &set_record_btrace_bts_cmdlist,
3225 "set record btrace bts ", 0, &set_record_btrace_cmdlist);
3226
3227 add_prefix_cmd ("bts", class_support, cmd_show_record_btrace_bts,
590042fc 3228 _("Show record btrace bts options."),
d33501a5
MM
3229 &show_record_btrace_bts_cmdlist,
3230 "show record btrace bts ", 0, &show_record_btrace_cmdlist);
3231
3232 add_setshow_uinteger_cmd ("buffer-size", no_class,
3233 &record_btrace_conf.bts.size,
3234 _("Set the record/replay bts buffer size."),
3235 _("Show the record/replay bts buffer size."), _("\
3236When starting recording request a trace buffer of this size. \
3237The actual buffer size may differ from the requested size. \
3238Use \"info record\" to see the actual buffer size.\n\n\
3239Bigger buffers allow longer recording but also take more time to process \
3240the recorded execution trace.\n\n\
b20a6524
MM
3241The trace buffer size may not be changed while recording."), NULL,
3242 show_record_bts_buffer_size_value,
d33501a5
MM
3243 &set_record_btrace_bts_cmdlist,
3244 &show_record_btrace_bts_cmdlist);
3245
b20a6524 3246 add_prefix_cmd ("pt", class_support, cmd_set_record_btrace_pt,
590042fc 3247 _("Set record btrace pt options."),
b20a6524
MM
3248 &set_record_btrace_pt_cmdlist,
3249 "set record btrace pt ", 0, &set_record_btrace_cmdlist);
3250
3251 add_prefix_cmd ("pt", class_support, cmd_show_record_btrace_pt,
590042fc 3252 _("Show record btrace pt options."),
b20a6524
MM
3253 &show_record_btrace_pt_cmdlist,
3254 "show record btrace pt ", 0, &show_record_btrace_cmdlist);
3255
3256 add_setshow_uinteger_cmd ("buffer-size", no_class,
3257 &record_btrace_conf.pt.size,
3258 _("Set the record/replay pt buffer size."),
3259 _("Show the record/replay pt buffer size."), _("\
3260Bigger buffers allow longer recording but also take more time to process \
3261the recorded execution.\n\
3262The actual buffer size may differ from the requested size. Use \"info record\" \
3263to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
3264 &set_record_btrace_pt_cmdlist,
3265 &show_record_btrace_pt_cmdlist);
3266
d9f719f1 3267 add_target (record_btrace_target_info, record_btrace_target_open);
0b722aec
MM
3268
3269 bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,
3270 xcalloc, xfree);
d33501a5
MM
3271
3272 record_btrace_conf.bts.size = 64 * 1024;
b20a6524 3273 record_btrace_conf.pt.size = 16 * 1024;
afedecd3 3274}
This page took 0.905431 seconds and 4 git commands to generate.