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