1 /* Branch trace support for GDB, the GNU debugger.
3 Copyright (C) 2013-2014 Free Software Foundation, Inc.
5 Contributed by Intel Corp. <markus.t.metzger@intel.com>
7 This file is part of GDB.
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.
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.
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/>. */
24 #include "gdbthread.h"
29 #include "exceptions.h"
30 #include "cli/cli-utils.h"
34 #include "filenames.h"
36 #include "frame-unwind.h"
38 /* The target_ops of record-btrace. */
39 static struct target_ops record_btrace_ops;
41 /* A new thread observer enabling branch tracing for the new thread. */
42 static struct observer *record_btrace_thread_observer;
44 /* Temporarily allow memory accesses. */
45 static int record_btrace_allow_memory_access;
47 /* Print a record-btrace debug message. Use do ... while (0) to avoid
48 ambiguities when used in if statements. */
50 #define DEBUG(msg, args...) \
53 if (record_debug != 0) \
54 fprintf_unfiltered (gdb_stdlog, \
55 "[record-btrace] " msg "\n", ##args); \
60 /* Update the branch trace for the current thread and return a pointer to its
61 branch trace information struct.
63 Throws an error if there is no thread or no trace. This function never
66 static struct btrace_thread_info *
69 struct thread_info *tp;
70 struct btrace_thread_info *btinfo;
74 tp = find_thread_ptid (inferior_ptid);
76 error (_("No thread."));
82 if (btinfo->begin == NULL)
83 error (_("No trace."));
88 /* Enable branch tracing for one thread. Warn on errors. */
91 record_btrace_enable_warn (struct thread_info *tp)
93 volatile struct gdb_exception error;
95 TRY_CATCH (error, RETURN_MASK_ERROR)
98 if (error.message != NULL)
99 warning ("%s", error.message);
102 /* Callback function to disable branch tracing for one thread. */
105 record_btrace_disable_callback (void *arg)
107 struct thread_info *tp;
114 /* Enable automatic tracing of new threads. */
117 record_btrace_auto_enable (void)
119 DEBUG ("attach thread observer");
121 record_btrace_thread_observer
122 = observer_attach_new_thread (record_btrace_enable_warn);
125 /* Disable automatic tracing of new threads. */
128 record_btrace_auto_disable (void)
130 /* The observer may have been detached, already. */
131 if (record_btrace_thread_observer == NULL)
134 DEBUG ("detach thread observer");
136 observer_detach_new_thread (record_btrace_thread_observer);
137 record_btrace_thread_observer = NULL;
140 /* The to_open method of target record-btrace. */
143 record_btrace_open (char *args, int from_tty)
145 struct cleanup *disable_chain;
146 struct thread_info *tp;
152 if (!target_has_execution)
153 error (_("The program is not being run."));
155 if (!target_supports_btrace ())
156 error (_("Target does not support branch tracing."));
158 gdb_assert (record_btrace_thread_observer == NULL);
160 disable_chain = make_cleanup (null_cleanup, NULL);
162 if (args == NULL || *args == 0 || number_is_in_list (args, tp->num))
166 make_cleanup (record_btrace_disable_callback, tp);
169 record_btrace_auto_enable ();
171 push_target (&record_btrace_ops);
173 observer_notify_record_changed (current_inferior (), 1);
175 discard_cleanups (disable_chain);
178 /* The to_stop_recording method of target record-btrace. */
181 record_btrace_stop_recording (void)
183 struct thread_info *tp;
185 DEBUG ("stop recording");
187 record_btrace_auto_disable ();
190 if (tp->btrace.target != NULL)
194 /* The to_close method of target record-btrace. */
197 record_btrace_close (void)
199 /* Make sure automatic recording gets disabled even if we did not stop
200 recording before closing the record-btrace target. */
201 record_btrace_auto_disable ();
203 /* We already stopped recording. */
206 /* The to_info_record method of target record-btrace. */
209 record_btrace_info (void)
211 struct btrace_thread_info *btinfo;
212 struct thread_info *tp;
213 unsigned int insns, calls;
217 tp = find_thread_ptid (inferior_ptid);
219 error (_("No thread."));
226 btinfo = &tp->btrace;
227 if (btinfo->begin != NULL)
229 struct btrace_call_iterator call;
230 struct btrace_insn_iterator insn;
232 btrace_call_end (&call, btinfo);
233 btrace_call_prev (&call, 1);
234 calls = btrace_call_number (&call);
236 btrace_insn_end (&insn, btinfo);
237 btrace_insn_prev (&insn, 1);
238 insns = btrace_insn_number (&insn);
241 printf_unfiltered (_("Recorded %u instructions in %u functions for thread "
242 "%d (%s).\n"), insns, calls, tp->num,
243 target_pid_to_str (tp->ptid));
245 if (btrace_is_replaying (tp))
246 printf_unfiltered (_("Replay in progress. At instruction %u.\n"),
247 btrace_insn_number (btinfo->replay));
250 /* Print an unsigned int. */
253 ui_out_field_uint (struct ui_out *uiout, const char *fld, unsigned int val)
255 ui_out_field_fmt (uiout, fld, "%u", val);
258 /* Disassemble a section of the recorded instruction trace. */
261 btrace_insn_history (struct ui_out *uiout,
262 const struct btrace_insn_iterator *begin,
263 const struct btrace_insn_iterator *end, int flags)
265 struct gdbarch *gdbarch;
266 struct btrace_insn_iterator it;
268 DEBUG ("itrace (0x%x): [%u; %u)", flags, btrace_insn_number (begin),
269 btrace_insn_number (end));
271 gdbarch = target_gdbarch ();
273 for (it = *begin; btrace_insn_cmp (&it, end) != 0; btrace_insn_next (&it, 1))
275 const struct btrace_insn *insn;
277 insn = btrace_insn_get (&it);
279 /* Print the instruction index. */
280 ui_out_field_uint (uiout, "index", btrace_insn_number (&it));
281 ui_out_text (uiout, "\t");
283 /* Disassembly with '/m' flag may not produce the expected result.
285 gdb_disassembly (gdbarch, uiout, NULL, flags, 1, insn->pc, insn->pc + 1);
289 /* The to_insn_history method of target record-btrace. */
292 record_btrace_insn_history (int size, int flags)
294 struct btrace_thread_info *btinfo;
295 struct btrace_insn_history *history;
296 struct btrace_insn_iterator begin, end;
297 struct cleanup *uiout_cleanup;
298 struct ui_out *uiout;
299 unsigned int context, covered;
301 uiout = current_uiout;
302 uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
304 context = abs (size);
306 error (_("Bad record instruction-history-size."));
308 btinfo = require_btrace ();
309 history = btinfo->insn_history;
312 struct btrace_insn_iterator *replay;
314 DEBUG ("insn-history (0x%x): %d", flags, size);
316 /* If we're replaying, we start at the replay position. Otherwise, we
317 start at the tail of the trace. */
318 replay = btinfo->replay;
322 btrace_insn_end (&begin, btinfo);
324 /* We start from here and expand in the requested direction. Then we
325 expand in the other direction, as well, to fill up any remaining
330 /* We want the current position covered, as well. */
331 covered = btrace_insn_next (&end, 1);
332 covered += btrace_insn_prev (&begin, context - covered);
333 covered += btrace_insn_next (&end, context - covered);
337 covered = btrace_insn_next (&end, context);
338 covered += btrace_insn_prev (&begin, context - covered);
343 begin = history->begin;
346 DEBUG ("insn-history (0x%x): %d, prev: [%u; %u)", flags, size,
347 btrace_insn_number (&begin), btrace_insn_number (&end));
352 covered = btrace_insn_prev (&begin, context);
357 covered = btrace_insn_next (&end, context);
362 btrace_insn_history (uiout, &begin, &end, flags);
366 printf_unfiltered (_("At the start of the branch trace record.\n"));
368 printf_unfiltered (_("At the end of the branch trace record.\n"));
371 btrace_set_insn_history (btinfo, &begin, &end);
372 do_cleanups (uiout_cleanup);
375 /* The to_insn_history_range method of target record-btrace. */
378 record_btrace_insn_history_range (ULONGEST from, ULONGEST to, int flags)
380 struct btrace_thread_info *btinfo;
381 struct btrace_insn_history *history;
382 struct btrace_insn_iterator begin, end;
383 struct cleanup *uiout_cleanup;
384 struct ui_out *uiout;
385 unsigned int low, high;
388 uiout = current_uiout;
389 uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
394 DEBUG ("insn-history (0x%x): [%u; %u)", flags, low, high);
396 /* Check for wrap-arounds. */
397 if (low != from || high != to)
398 error (_("Bad range."));
401 error (_("Bad range."));
403 btinfo = require_btrace ();
405 found = btrace_find_insn_by_number (&begin, btinfo, low);
407 error (_("Range out of bounds."));
409 found = btrace_find_insn_by_number (&end, btinfo, high);
412 /* Silently truncate the range. */
413 btrace_insn_end (&end, btinfo);
417 /* We want both begin and end to be inclusive. */
418 btrace_insn_next (&end, 1);
421 btrace_insn_history (uiout, &begin, &end, flags);
422 btrace_set_insn_history (btinfo, &begin, &end);
424 do_cleanups (uiout_cleanup);
427 /* The to_insn_history_from method of target record-btrace. */
430 record_btrace_insn_history_from (ULONGEST from, int size, int flags)
432 ULONGEST begin, end, context;
434 context = abs (size);
436 error (_("Bad record instruction-history-size."));
445 begin = from - context + 1;
450 end = from + context - 1;
452 /* Check for wrap-around. */
457 record_btrace_insn_history_range (begin, end, flags);
460 /* Print the instruction number range for a function call history line. */
463 btrace_call_history_insn_range (struct ui_out *uiout,
464 const struct btrace_function *bfun)
466 unsigned int begin, end, size;
468 size = VEC_length (btrace_insn_s, bfun->insn);
469 gdb_assert (size > 0);
471 begin = bfun->insn_offset;
472 end = begin + size - 1;
474 ui_out_field_uint (uiout, "insn begin", begin);
475 ui_out_text (uiout, ",");
476 ui_out_field_uint (uiout, "insn end", end);
479 /* Print the source line information for a function call history line. */
482 btrace_call_history_src_line (struct ui_out *uiout,
483 const struct btrace_function *bfun)
492 ui_out_field_string (uiout, "file",
493 symtab_to_filename_for_display (sym->symtab));
495 begin = bfun->lbegin;
501 ui_out_text (uiout, ":");
502 ui_out_field_int (uiout, "min line", begin);
507 ui_out_text (uiout, ",");
508 ui_out_field_int (uiout, "max line", end);
511 /* Disassemble a section of the recorded function trace. */
514 btrace_call_history (struct ui_out *uiout,
515 const struct btrace_thread_info *btinfo,
516 const struct btrace_call_iterator *begin,
517 const struct btrace_call_iterator *end,
518 enum record_print_flag flags)
520 struct btrace_call_iterator it;
522 DEBUG ("ftrace (0x%x): [%u; %u)", flags, btrace_call_number (begin),
523 btrace_call_number (end));
525 for (it = *begin; btrace_call_cmp (&it, end) < 0; btrace_call_next (&it, 1))
527 const struct btrace_function *bfun;
528 struct minimal_symbol *msym;
531 bfun = btrace_call_get (&it);
535 /* Print the function index. */
536 ui_out_field_uint (uiout, "index", bfun->number);
537 ui_out_text (uiout, "\t");
539 if ((flags & RECORD_PRINT_INDENT_CALLS) != 0)
541 int level = bfun->level + btinfo->level, i;
543 for (i = 0; i < level; ++i)
544 ui_out_text (uiout, " ");
548 ui_out_field_string (uiout, "function", SYMBOL_PRINT_NAME (sym));
549 else if (msym != NULL)
550 ui_out_field_string (uiout, "function", SYMBOL_PRINT_NAME (msym));
551 else if (!ui_out_is_mi_like_p (uiout))
552 ui_out_field_string (uiout, "function", "??");
554 if ((flags & RECORD_PRINT_INSN_RANGE) != 0)
556 ui_out_text (uiout, _("\tinst "));
557 btrace_call_history_insn_range (uiout, bfun);
560 if ((flags & RECORD_PRINT_SRC_LINE) != 0)
562 ui_out_text (uiout, _("\tat "));
563 btrace_call_history_src_line (uiout, bfun);
566 ui_out_text (uiout, "\n");
570 /* The to_call_history method of target record-btrace. */
573 record_btrace_call_history (int size, int flags)
575 struct btrace_thread_info *btinfo;
576 struct btrace_call_history *history;
577 struct btrace_call_iterator begin, end;
578 struct cleanup *uiout_cleanup;
579 struct ui_out *uiout;
580 unsigned int context, covered;
582 uiout = current_uiout;
583 uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
585 context = abs (size);
587 error (_("Bad record function-call-history-size."));
589 btinfo = require_btrace ();
590 history = btinfo->call_history;
593 struct btrace_insn_iterator *replay;
595 DEBUG ("call-history (0x%x): %d", flags, size);
597 /* If we're replaying, we start at the replay position. Otherwise, we
598 start at the tail of the trace. */
599 replay = btinfo->replay;
602 begin.function = replay->function;
603 begin.btinfo = btinfo;
606 btrace_call_end (&begin, btinfo);
608 /* We start from here and expand in the requested direction. Then we
609 expand in the other direction, as well, to fill up any remaining
614 /* We want the current position covered, as well. */
615 covered = btrace_call_next (&end, 1);
616 covered += btrace_call_prev (&begin, context - covered);
617 covered += btrace_call_next (&end, context - covered);
621 covered = btrace_call_next (&end, context);
622 covered += btrace_call_prev (&begin, context- covered);
627 begin = history->begin;
630 DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags, size,
631 btrace_call_number (&begin), btrace_call_number (&end));
636 covered = btrace_call_prev (&begin, context);
641 covered = btrace_call_next (&end, context);
646 btrace_call_history (uiout, btinfo, &begin, &end, flags);
650 printf_unfiltered (_("At the start of the branch trace record.\n"));
652 printf_unfiltered (_("At the end of the branch trace record.\n"));
655 btrace_set_call_history (btinfo, &begin, &end);
656 do_cleanups (uiout_cleanup);
659 /* The to_call_history_range method of target record-btrace. */
662 record_btrace_call_history_range (ULONGEST from, ULONGEST to, int flags)
664 struct btrace_thread_info *btinfo;
665 struct btrace_call_history *history;
666 struct btrace_call_iterator begin, end;
667 struct cleanup *uiout_cleanup;
668 struct ui_out *uiout;
669 unsigned int low, high;
672 uiout = current_uiout;
673 uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
678 DEBUG ("call-history (0x%x): [%u; %u)", flags, low, high);
680 /* Check for wrap-arounds. */
681 if (low != from || high != to)
682 error (_("Bad range."));
685 error (_("Bad range."));
687 btinfo = require_btrace ();
689 found = btrace_find_call_by_number (&begin, btinfo, low);
691 error (_("Range out of bounds."));
693 found = btrace_find_call_by_number (&end, btinfo, high);
696 /* Silently truncate the range. */
697 btrace_call_end (&end, btinfo);
701 /* We want both begin and end to be inclusive. */
702 btrace_call_next (&end, 1);
705 btrace_call_history (uiout, btinfo, &begin, &end, flags);
706 btrace_set_call_history (btinfo, &begin, &end);
708 do_cleanups (uiout_cleanup);
711 /* The to_call_history_from method of target record-btrace. */
714 record_btrace_call_history_from (ULONGEST from, int size, int flags)
716 ULONGEST begin, end, context;
718 context = abs (size);
720 error (_("Bad record function-call-history-size."));
729 begin = from - context + 1;
734 end = from + context - 1;
736 /* Check for wrap-around. */
741 record_btrace_call_history_range (begin, end, flags);
744 /* The to_record_is_replaying method of target record-btrace. */
747 record_btrace_is_replaying (void)
749 struct thread_info *tp;
752 if (btrace_is_replaying (tp))
758 /* The to_xfer_partial method of target record-btrace. */
761 record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
762 const char *annex, gdb_byte *readbuf,
763 const gdb_byte *writebuf, ULONGEST offset,
766 struct target_ops *t;
768 /* Filter out requests that don't make sense during replay. */
769 if (!record_btrace_allow_memory_access && record_btrace_is_replaying ())
773 case TARGET_OBJECT_MEMORY:
775 struct target_section *section;
777 /* We do not allow writing memory in general. */
778 if (writebuf != NULL)
779 return TARGET_XFER_E_UNAVAILABLE;
781 /* We allow reading readonly memory. */
782 section = target_section_by_addr (ops, offset);
785 /* Check if the section we found is readonly. */
786 if ((bfd_get_section_flags (section->the_bfd_section->owner,
787 section->the_bfd_section)
788 & SEC_READONLY) != 0)
790 /* Truncate the request to fit into this section. */
791 len = min (len, section->endaddr - offset);
796 return TARGET_XFER_E_UNAVAILABLE;
801 /* Forward the request. */
802 for (ops = ops->beneath; ops != NULL; ops = ops->beneath)
803 if (ops->to_xfer_partial != NULL)
804 return ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
807 return TARGET_XFER_E_UNAVAILABLE;
810 /* The to_insert_breakpoint method of target record-btrace. */
813 record_btrace_insert_breakpoint (struct target_ops *ops,
814 struct gdbarch *gdbarch,
815 struct bp_target_info *bp_tgt)
817 volatile struct gdb_exception except;
820 /* Inserting breakpoints requires accessing memory. Allow it for the
821 duration of this function. */
822 old = record_btrace_allow_memory_access;
823 record_btrace_allow_memory_access = 1;
826 TRY_CATCH (except, RETURN_MASK_ALL)
827 ret = forward_target_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
829 record_btrace_allow_memory_access = old;
831 if (except.reason < 0)
832 throw_exception (except);
837 /* The to_remove_breakpoint method of target record-btrace. */
840 record_btrace_remove_breakpoint (struct target_ops *ops,
841 struct gdbarch *gdbarch,
842 struct bp_target_info *bp_tgt)
844 volatile struct gdb_exception except;
847 /* Removing breakpoints requires accessing memory. Allow it for the
848 duration of this function. */
849 old = record_btrace_allow_memory_access;
850 record_btrace_allow_memory_access = 1;
853 TRY_CATCH (except, RETURN_MASK_ALL)
854 ret = forward_target_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
856 record_btrace_allow_memory_access = old;
858 if (except.reason < 0)
859 throw_exception (except);
864 /* The to_fetch_registers method of target record-btrace. */
867 record_btrace_fetch_registers (struct target_ops *ops,
868 struct regcache *regcache, int regno)
870 struct btrace_insn_iterator *replay;
871 struct thread_info *tp;
873 tp = find_thread_ptid (inferior_ptid);
874 gdb_assert (tp != NULL);
876 replay = tp->btrace.replay;
879 const struct btrace_insn *insn;
880 struct gdbarch *gdbarch;
883 gdbarch = get_regcache_arch (regcache);
884 pcreg = gdbarch_pc_regnum (gdbarch);
888 /* We can only provide the PC register. */
889 if (regno >= 0 && regno != pcreg)
892 insn = btrace_insn_get (replay);
893 gdb_assert (insn != NULL);
895 regcache_raw_supply (regcache, regno, &insn->pc);
899 struct target_ops *t;
901 for (t = ops->beneath; t != NULL; t = t->beneath)
902 if (t->to_fetch_registers != NULL)
904 t->to_fetch_registers (t, regcache, regno);
910 /* The to_store_registers method of target record-btrace. */
913 record_btrace_store_registers (struct target_ops *ops,
914 struct regcache *regcache, int regno)
916 struct target_ops *t;
918 if (record_btrace_is_replaying ())
919 error (_("This record target does not allow writing registers."));
921 gdb_assert (may_write_registers != 0);
923 for (t = ops->beneath; t != NULL; t = t->beneath)
924 if (t->to_store_registers != NULL)
926 t->to_store_registers (t, regcache, regno);
933 /* The to_prepare_to_store method of target record-btrace. */
936 record_btrace_prepare_to_store (struct target_ops *ops,
937 struct regcache *regcache)
939 struct target_ops *t;
941 if (record_btrace_is_replaying ())
944 for (t = ops->beneath; t != NULL; t = t->beneath)
945 if (t->to_prepare_to_store != NULL)
947 t->to_prepare_to_store (t, regcache);
952 /* Implement stop_reason method for record_btrace_frame_unwind. */
954 static enum unwind_stop_reason
955 record_btrace_frame_unwind_stop_reason (struct frame_info *this_frame,
958 return UNWIND_UNAVAILABLE;
961 /* Implement this_id method for record_btrace_frame_unwind. */
964 record_btrace_frame_this_id (struct frame_info *this_frame, void **this_cache,
965 struct frame_id *this_id)
967 /* Leave there the outer_frame_id value. */
970 /* Implement prev_register method for record_btrace_frame_unwind. */
972 static struct value *
973 record_btrace_frame_prev_register (struct frame_info *this_frame,
977 throw_error (NOT_AVAILABLE_ERROR,
978 _("Registers are not available in btrace record history"));
981 /* Implement sniffer method for record_btrace_frame_unwind. */
984 record_btrace_frame_sniffer (const struct frame_unwind *self,
985 struct frame_info *this_frame,
988 struct thread_info *tp;
989 struct btrace_thread_info *btinfo;
990 struct btrace_insn_iterator *replay;
992 /* THIS_FRAME does not contain a reference to its thread. */
993 tp = find_thread_ptid (inferior_ptid);
994 gdb_assert (tp != NULL);
996 return btrace_is_replaying (tp);
999 /* btrace recording does not store previous memory content, neither the stack
1000 frames content. Any unwinding would return errorneous results as the stack
1001 contents no longer matches the changed PC value restored from history.
1002 Therefore this unwinder reports any possibly unwound registers as
1005 static const struct frame_unwind record_btrace_frame_unwind =
1008 record_btrace_frame_unwind_stop_reason,
1009 record_btrace_frame_this_id,
1010 record_btrace_frame_prev_register,
1012 record_btrace_frame_sniffer
1015 /* The to_resume method of target record-btrace. */
1018 record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
1019 enum gdb_signal signal)
1021 /* As long as we're not replaying, just forward the request. */
1022 if (!record_btrace_is_replaying ())
1024 for (ops = ops->beneath; ops != NULL; ops = ops->beneath)
1025 if (ops->to_resume != NULL)
1026 return ops->to_resume (ops, ptid, step, signal);
1028 error (_("Cannot find target for stepping."));
1031 error (_("You can't do this from here. Do 'record goto end', first."));
1034 /* The to_wait method of target record-btrace. */
1037 record_btrace_wait (struct target_ops *ops, ptid_t ptid,
1038 struct target_waitstatus *status, int options)
1040 /* As long as we're not replaying, just forward the request. */
1041 if (!record_btrace_is_replaying ())
1043 for (ops = ops->beneath; ops != NULL; ops = ops->beneath)
1044 if (ops->to_wait != NULL)
1045 return ops->to_wait (ops, ptid, status, options);
1047 error (_("Cannot find target for waiting."));
1050 error (_("You can't do this from here. Do 'record goto end', first."));
1053 /* Initialize the record-btrace target ops. */
1056 init_record_btrace_ops (void)
1058 struct target_ops *ops;
1060 ops = &record_btrace_ops;
1061 ops->to_shortname = "record-btrace";
1062 ops->to_longname = "Branch tracing target";
1063 ops->to_doc = "Collect control-flow trace and provide the execution history.";
1064 ops->to_open = record_btrace_open;
1065 ops->to_close = record_btrace_close;
1066 ops->to_detach = record_detach;
1067 ops->to_disconnect = record_disconnect;
1068 ops->to_mourn_inferior = record_mourn_inferior;
1069 ops->to_kill = record_kill;
1070 ops->to_create_inferior = find_default_create_inferior;
1071 ops->to_stop_recording = record_btrace_stop_recording;
1072 ops->to_info_record = record_btrace_info;
1073 ops->to_insn_history = record_btrace_insn_history;
1074 ops->to_insn_history_from = record_btrace_insn_history_from;
1075 ops->to_insn_history_range = record_btrace_insn_history_range;
1076 ops->to_call_history = record_btrace_call_history;
1077 ops->to_call_history_from = record_btrace_call_history_from;
1078 ops->to_call_history_range = record_btrace_call_history_range;
1079 ops->to_record_is_replaying = record_btrace_is_replaying;
1080 ops->to_xfer_partial = record_btrace_xfer_partial;
1081 ops->to_remove_breakpoint = record_btrace_remove_breakpoint;
1082 ops->to_insert_breakpoint = record_btrace_insert_breakpoint;
1083 ops->to_fetch_registers = record_btrace_fetch_registers;
1084 ops->to_store_registers = record_btrace_store_registers;
1085 ops->to_prepare_to_store = record_btrace_prepare_to_store;
1086 ops->to_get_unwinder = &record_btrace_frame_unwind;
1087 ops->to_resume = record_btrace_resume;
1088 ops->to_wait = record_btrace_wait;
1089 ops->to_stratum = record_stratum;
1090 ops->to_magic = OPS_MAGIC;
1093 /* Alias for "target record". */
1096 cmd_record_btrace_start (char *args, int from_tty)
1098 if (args != NULL && *args != 0)
1099 error (_("Invalid argument."));
1101 execute_command ("target record-btrace", from_tty);
1104 void _initialize_record_btrace (void);
1106 /* Initialize btrace commands. */
1109 _initialize_record_btrace (void)
1111 add_cmd ("btrace", class_obscure, cmd_record_btrace_start,
1112 _("Start branch trace recording."),
1114 add_alias_cmd ("b", "btrace", class_obscure, 1, &record_cmdlist);
1116 init_record_btrace_ops ();
1117 add_target (&record_btrace_ops);