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
63 Throws an error if there is no thread or no trace. This function never
66 static struct thread_info
*
67 require_btrace_thread (void)
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 /* Update the branch trace for the current thread and return a pointer to its
89 branch trace information struct.
91 Throws an error if there is no thread or no trace. This function never
94 static struct btrace_thread_info
*
97 struct thread_info
*tp
;
99 tp
= require_btrace_thread ();
104 /* Enable branch tracing for one thread. Warn on errors. */
107 record_btrace_enable_warn (struct thread_info
*tp
)
109 volatile struct gdb_exception error
;
111 TRY_CATCH (error
, RETURN_MASK_ERROR
)
114 if (error
.message
!= NULL
)
115 warning ("%s", error
.message
);
118 /* Callback function to disable branch tracing for one thread. */
121 record_btrace_disable_callback (void *arg
)
123 struct thread_info
*tp
;
130 /* Enable automatic tracing of new threads. */
133 record_btrace_auto_enable (void)
135 DEBUG ("attach thread observer");
137 record_btrace_thread_observer
138 = observer_attach_new_thread (record_btrace_enable_warn
);
141 /* Disable automatic tracing of new threads. */
144 record_btrace_auto_disable (void)
146 /* The observer may have been detached, already. */
147 if (record_btrace_thread_observer
== NULL
)
150 DEBUG ("detach thread observer");
152 observer_detach_new_thread (record_btrace_thread_observer
);
153 record_btrace_thread_observer
= NULL
;
156 /* The to_open method of target record-btrace. */
159 record_btrace_open (char *args
, int from_tty
)
161 struct cleanup
*disable_chain
;
162 struct thread_info
*tp
;
168 if (!target_has_execution
)
169 error (_("The program is not being run."));
171 if (!target_supports_btrace ())
172 error (_("Target does not support branch tracing."));
174 gdb_assert (record_btrace_thread_observer
== NULL
);
176 disable_chain
= make_cleanup (null_cleanup
, NULL
);
178 if (args
== NULL
|| *args
== 0 || number_is_in_list (args
, tp
->num
))
182 make_cleanup (record_btrace_disable_callback
, tp
);
185 record_btrace_auto_enable ();
187 push_target (&record_btrace_ops
);
189 observer_notify_record_changed (current_inferior (), 1);
191 discard_cleanups (disable_chain
);
194 /* The to_stop_recording method of target record-btrace. */
197 record_btrace_stop_recording (void)
199 struct thread_info
*tp
;
201 DEBUG ("stop recording");
203 record_btrace_auto_disable ();
206 if (tp
->btrace
.target
!= NULL
)
210 /* The to_close method of target record-btrace. */
213 record_btrace_close (void)
215 /* Make sure automatic recording gets disabled even if we did not stop
216 recording before closing the record-btrace target. */
217 record_btrace_auto_disable ();
219 /* We already stopped recording. */
222 /* The to_info_record method of target record-btrace. */
225 record_btrace_info (void)
227 struct btrace_thread_info
*btinfo
;
228 struct thread_info
*tp
;
229 unsigned int insns
, calls
;
233 tp
= find_thread_ptid (inferior_ptid
);
235 error (_("No thread."));
242 btinfo
= &tp
->btrace
;
243 if (btinfo
->begin
!= NULL
)
245 struct btrace_call_iterator call
;
246 struct btrace_insn_iterator insn
;
248 btrace_call_end (&call
, btinfo
);
249 btrace_call_prev (&call
, 1);
250 calls
= btrace_call_number (&call
);
252 btrace_insn_end (&insn
, btinfo
);
253 btrace_insn_prev (&insn
, 1);
254 insns
= btrace_insn_number (&insn
);
257 printf_unfiltered (_("Recorded %u instructions in %u functions for thread "
258 "%d (%s).\n"), insns
, calls
, tp
->num
,
259 target_pid_to_str (tp
->ptid
));
261 if (btrace_is_replaying (tp
))
262 printf_unfiltered (_("Replay in progress. At instruction %u.\n"),
263 btrace_insn_number (btinfo
->replay
));
266 /* Print an unsigned int. */
269 ui_out_field_uint (struct ui_out
*uiout
, const char *fld
, unsigned int val
)
271 ui_out_field_fmt (uiout
, fld
, "%u", val
);
274 /* Disassemble a section of the recorded instruction trace. */
277 btrace_insn_history (struct ui_out
*uiout
,
278 const struct btrace_insn_iterator
*begin
,
279 const struct btrace_insn_iterator
*end
, int flags
)
281 struct gdbarch
*gdbarch
;
282 struct btrace_insn_iterator it
;
284 DEBUG ("itrace (0x%x): [%u; %u)", flags
, btrace_insn_number (begin
),
285 btrace_insn_number (end
));
287 gdbarch
= target_gdbarch ();
289 for (it
= *begin
; btrace_insn_cmp (&it
, end
) != 0; btrace_insn_next (&it
, 1))
291 const struct btrace_insn
*insn
;
293 insn
= btrace_insn_get (&it
);
295 /* Print the instruction index. */
296 ui_out_field_uint (uiout
, "index", btrace_insn_number (&it
));
297 ui_out_text (uiout
, "\t");
299 /* Disassembly with '/m' flag may not produce the expected result.
301 gdb_disassembly (gdbarch
, uiout
, NULL
, flags
, 1, insn
->pc
, insn
->pc
+ 1);
305 /* The to_insn_history method of target record-btrace. */
308 record_btrace_insn_history (int size
, int flags
)
310 struct btrace_thread_info
*btinfo
;
311 struct btrace_insn_history
*history
;
312 struct btrace_insn_iterator begin
, end
;
313 struct cleanup
*uiout_cleanup
;
314 struct ui_out
*uiout
;
315 unsigned int context
, covered
;
317 uiout
= current_uiout
;
318 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
320 context
= abs (size
);
322 error (_("Bad record instruction-history-size."));
324 btinfo
= require_btrace ();
325 history
= btinfo
->insn_history
;
328 struct btrace_insn_iterator
*replay
;
330 DEBUG ("insn-history (0x%x): %d", flags
, size
);
332 /* If we're replaying, we start at the replay position. Otherwise, we
333 start at the tail of the trace. */
334 replay
= btinfo
->replay
;
338 btrace_insn_end (&begin
, btinfo
);
340 /* We start from here and expand in the requested direction. Then we
341 expand in the other direction, as well, to fill up any remaining
346 /* We want the current position covered, as well. */
347 covered
= btrace_insn_next (&end
, 1);
348 covered
+= btrace_insn_prev (&begin
, context
- covered
);
349 covered
+= btrace_insn_next (&end
, context
- covered
);
353 covered
= btrace_insn_next (&end
, context
);
354 covered
+= btrace_insn_prev (&begin
, context
- covered
);
359 begin
= history
->begin
;
362 DEBUG ("insn-history (0x%x): %d, prev: [%u; %u)", flags
, size
,
363 btrace_insn_number (&begin
), btrace_insn_number (&end
));
368 covered
= btrace_insn_prev (&begin
, context
);
373 covered
= btrace_insn_next (&end
, context
);
378 btrace_insn_history (uiout
, &begin
, &end
, flags
);
382 printf_unfiltered (_("At the start of the branch trace record.\n"));
384 printf_unfiltered (_("At the end of the branch trace record.\n"));
387 btrace_set_insn_history (btinfo
, &begin
, &end
);
388 do_cleanups (uiout_cleanup
);
391 /* The to_insn_history_range method of target record-btrace. */
394 record_btrace_insn_history_range (ULONGEST from
, ULONGEST to
, int flags
)
396 struct btrace_thread_info
*btinfo
;
397 struct btrace_insn_history
*history
;
398 struct btrace_insn_iterator begin
, end
;
399 struct cleanup
*uiout_cleanup
;
400 struct ui_out
*uiout
;
401 unsigned int low
, high
;
404 uiout
= current_uiout
;
405 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
410 DEBUG ("insn-history (0x%x): [%u; %u)", flags
, low
, high
);
412 /* Check for wrap-arounds. */
413 if (low
!= from
|| high
!= to
)
414 error (_("Bad range."));
417 error (_("Bad range."));
419 btinfo
= require_btrace ();
421 found
= btrace_find_insn_by_number (&begin
, btinfo
, low
);
423 error (_("Range out of bounds."));
425 found
= btrace_find_insn_by_number (&end
, btinfo
, high
);
428 /* Silently truncate the range. */
429 btrace_insn_end (&end
, btinfo
);
433 /* We want both begin and end to be inclusive. */
434 btrace_insn_next (&end
, 1);
437 btrace_insn_history (uiout
, &begin
, &end
, flags
);
438 btrace_set_insn_history (btinfo
, &begin
, &end
);
440 do_cleanups (uiout_cleanup
);
443 /* The to_insn_history_from method of target record-btrace. */
446 record_btrace_insn_history_from (ULONGEST from
, int size
, int flags
)
448 ULONGEST begin
, end
, context
;
450 context
= abs (size
);
452 error (_("Bad record instruction-history-size."));
461 begin
= from
- context
+ 1;
466 end
= from
+ context
- 1;
468 /* Check for wrap-around. */
473 record_btrace_insn_history_range (begin
, end
, flags
);
476 /* Print the instruction number range for a function call history line. */
479 btrace_call_history_insn_range (struct ui_out
*uiout
,
480 const struct btrace_function
*bfun
)
482 unsigned int begin
, end
, size
;
484 size
= VEC_length (btrace_insn_s
, bfun
->insn
);
485 gdb_assert (size
> 0);
487 begin
= bfun
->insn_offset
;
488 end
= begin
+ size
- 1;
490 ui_out_field_uint (uiout
, "insn begin", begin
);
491 ui_out_text (uiout
, ",");
492 ui_out_field_uint (uiout
, "insn end", end
);
495 /* Print the source line information for a function call history line. */
498 btrace_call_history_src_line (struct ui_out
*uiout
,
499 const struct btrace_function
*bfun
)
508 ui_out_field_string (uiout
, "file",
509 symtab_to_filename_for_display (sym
->symtab
));
511 begin
= bfun
->lbegin
;
517 ui_out_text (uiout
, ":");
518 ui_out_field_int (uiout
, "min line", begin
);
523 ui_out_text (uiout
, ",");
524 ui_out_field_int (uiout
, "max line", end
);
527 /* Disassemble a section of the recorded function trace. */
530 btrace_call_history (struct ui_out
*uiout
,
531 const struct btrace_thread_info
*btinfo
,
532 const struct btrace_call_iterator
*begin
,
533 const struct btrace_call_iterator
*end
,
534 enum record_print_flag flags
)
536 struct btrace_call_iterator it
;
538 DEBUG ("ftrace (0x%x): [%u; %u)", flags
, btrace_call_number (begin
),
539 btrace_call_number (end
));
541 for (it
= *begin
; btrace_call_cmp (&it
, end
) < 0; btrace_call_next (&it
, 1))
543 const struct btrace_function
*bfun
;
544 struct minimal_symbol
*msym
;
547 bfun
= btrace_call_get (&it
);
551 /* Print the function index. */
552 ui_out_field_uint (uiout
, "index", bfun
->number
);
553 ui_out_text (uiout
, "\t");
555 if ((flags
& RECORD_PRINT_INDENT_CALLS
) != 0)
557 int level
= bfun
->level
+ btinfo
->level
, i
;
559 for (i
= 0; i
< level
; ++i
)
560 ui_out_text (uiout
, " ");
564 ui_out_field_string (uiout
, "function", SYMBOL_PRINT_NAME (sym
));
565 else if (msym
!= NULL
)
566 ui_out_field_string (uiout
, "function", SYMBOL_PRINT_NAME (msym
));
567 else if (!ui_out_is_mi_like_p (uiout
))
568 ui_out_field_string (uiout
, "function", "??");
570 if ((flags
& RECORD_PRINT_INSN_RANGE
) != 0)
572 ui_out_text (uiout
, _("\tinst "));
573 btrace_call_history_insn_range (uiout
, bfun
);
576 if ((flags
& RECORD_PRINT_SRC_LINE
) != 0)
578 ui_out_text (uiout
, _("\tat "));
579 btrace_call_history_src_line (uiout
, bfun
);
582 ui_out_text (uiout
, "\n");
586 /* The to_call_history method of target record-btrace. */
589 record_btrace_call_history (int size
, int flags
)
591 struct btrace_thread_info
*btinfo
;
592 struct btrace_call_history
*history
;
593 struct btrace_call_iterator begin
, end
;
594 struct cleanup
*uiout_cleanup
;
595 struct ui_out
*uiout
;
596 unsigned int context
, covered
;
598 uiout
= current_uiout
;
599 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
601 context
= abs (size
);
603 error (_("Bad record function-call-history-size."));
605 btinfo
= require_btrace ();
606 history
= btinfo
->call_history
;
609 struct btrace_insn_iterator
*replay
;
611 DEBUG ("call-history (0x%x): %d", flags
, size
);
613 /* If we're replaying, we start at the replay position. Otherwise, we
614 start at the tail of the trace. */
615 replay
= btinfo
->replay
;
618 begin
.function
= replay
->function
;
619 begin
.btinfo
= btinfo
;
622 btrace_call_end (&begin
, btinfo
);
624 /* We start from here and expand in the requested direction. Then we
625 expand in the other direction, as well, to fill up any remaining
630 /* We want the current position covered, as well. */
631 covered
= btrace_call_next (&end
, 1);
632 covered
+= btrace_call_prev (&begin
, context
- covered
);
633 covered
+= btrace_call_next (&end
, context
- covered
);
637 covered
= btrace_call_next (&end
, context
);
638 covered
+= btrace_call_prev (&begin
, context
- covered
);
643 begin
= history
->begin
;
646 DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags
, size
,
647 btrace_call_number (&begin
), btrace_call_number (&end
));
652 covered
= btrace_call_prev (&begin
, context
);
657 covered
= btrace_call_next (&end
, context
);
662 btrace_call_history (uiout
, btinfo
, &begin
, &end
, flags
);
666 printf_unfiltered (_("At the start of the branch trace record.\n"));
668 printf_unfiltered (_("At the end of the branch trace record.\n"));
671 btrace_set_call_history (btinfo
, &begin
, &end
);
672 do_cleanups (uiout_cleanup
);
675 /* The to_call_history_range method of target record-btrace. */
678 record_btrace_call_history_range (ULONGEST from
, ULONGEST to
, int flags
)
680 struct btrace_thread_info
*btinfo
;
681 struct btrace_call_history
*history
;
682 struct btrace_call_iterator begin
, end
;
683 struct cleanup
*uiout_cleanup
;
684 struct ui_out
*uiout
;
685 unsigned int low
, high
;
688 uiout
= current_uiout
;
689 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
694 DEBUG ("call-history (0x%x): [%u; %u)", flags
, low
, high
);
696 /* Check for wrap-arounds. */
697 if (low
!= from
|| high
!= to
)
698 error (_("Bad range."));
701 error (_("Bad range."));
703 btinfo
= require_btrace ();
705 found
= btrace_find_call_by_number (&begin
, btinfo
, low
);
707 error (_("Range out of bounds."));
709 found
= btrace_find_call_by_number (&end
, btinfo
, high
);
712 /* Silently truncate the range. */
713 btrace_call_end (&end
, btinfo
);
717 /* We want both begin and end to be inclusive. */
718 btrace_call_next (&end
, 1);
721 btrace_call_history (uiout
, btinfo
, &begin
, &end
, flags
);
722 btrace_set_call_history (btinfo
, &begin
, &end
);
724 do_cleanups (uiout_cleanup
);
727 /* The to_call_history_from method of target record-btrace. */
730 record_btrace_call_history_from (ULONGEST from
, int size
, int flags
)
732 ULONGEST begin
, end
, context
;
734 context
= abs (size
);
736 error (_("Bad record function-call-history-size."));
745 begin
= from
- context
+ 1;
750 end
= from
+ context
- 1;
752 /* Check for wrap-around. */
757 record_btrace_call_history_range (begin
, end
, flags
);
760 /* The to_record_is_replaying method of target record-btrace. */
763 record_btrace_is_replaying (void)
765 struct thread_info
*tp
;
768 if (btrace_is_replaying (tp
))
774 /* The to_xfer_partial method of target record-btrace. */
777 record_btrace_xfer_partial (struct target_ops
*ops
, enum target_object object
,
778 const char *annex
, gdb_byte
*readbuf
,
779 const gdb_byte
*writebuf
, ULONGEST offset
,
782 struct target_ops
*t
;
784 /* Filter out requests that don't make sense during replay. */
785 if (!record_btrace_allow_memory_access
&& record_btrace_is_replaying ())
789 case TARGET_OBJECT_MEMORY
:
791 struct target_section
*section
;
793 /* We do not allow writing memory in general. */
794 if (writebuf
!= NULL
)
795 return TARGET_XFER_E_UNAVAILABLE
;
797 /* We allow reading readonly memory. */
798 section
= target_section_by_addr (ops
, offset
);
801 /* Check if the section we found is readonly. */
802 if ((bfd_get_section_flags (section
->the_bfd_section
->owner
,
803 section
->the_bfd_section
)
804 & SEC_READONLY
) != 0)
806 /* Truncate the request to fit into this section. */
807 len
= min (len
, section
->endaddr
- offset
);
812 return TARGET_XFER_E_UNAVAILABLE
;
817 /* Forward the request. */
818 for (ops
= ops
->beneath
; ops
!= NULL
; ops
= ops
->beneath
)
819 if (ops
->to_xfer_partial
!= NULL
)
820 return ops
->to_xfer_partial (ops
, object
, annex
, readbuf
, writebuf
,
823 return TARGET_XFER_E_UNAVAILABLE
;
826 /* The to_insert_breakpoint method of target record-btrace. */
829 record_btrace_insert_breakpoint (struct target_ops
*ops
,
830 struct gdbarch
*gdbarch
,
831 struct bp_target_info
*bp_tgt
)
833 volatile struct gdb_exception except
;
836 /* Inserting breakpoints requires accessing memory. Allow it for the
837 duration of this function. */
838 old
= record_btrace_allow_memory_access
;
839 record_btrace_allow_memory_access
= 1;
842 TRY_CATCH (except
, RETURN_MASK_ALL
)
843 ret
= forward_target_insert_breakpoint (ops
->beneath
, gdbarch
, bp_tgt
);
845 record_btrace_allow_memory_access
= old
;
847 if (except
.reason
< 0)
848 throw_exception (except
);
853 /* The to_remove_breakpoint method of target record-btrace. */
856 record_btrace_remove_breakpoint (struct target_ops
*ops
,
857 struct gdbarch
*gdbarch
,
858 struct bp_target_info
*bp_tgt
)
860 volatile struct gdb_exception except
;
863 /* Removing breakpoints requires accessing memory. Allow it for the
864 duration of this function. */
865 old
= record_btrace_allow_memory_access
;
866 record_btrace_allow_memory_access
= 1;
869 TRY_CATCH (except
, RETURN_MASK_ALL
)
870 ret
= forward_target_remove_breakpoint (ops
->beneath
, gdbarch
, bp_tgt
);
872 record_btrace_allow_memory_access
= old
;
874 if (except
.reason
< 0)
875 throw_exception (except
);
880 /* The to_fetch_registers method of target record-btrace. */
883 record_btrace_fetch_registers (struct target_ops
*ops
,
884 struct regcache
*regcache
, int regno
)
886 struct btrace_insn_iterator
*replay
;
887 struct thread_info
*tp
;
889 tp
= find_thread_ptid (inferior_ptid
);
890 gdb_assert (tp
!= NULL
);
892 replay
= tp
->btrace
.replay
;
895 const struct btrace_insn
*insn
;
896 struct gdbarch
*gdbarch
;
899 gdbarch
= get_regcache_arch (regcache
);
900 pcreg
= gdbarch_pc_regnum (gdbarch
);
904 /* We can only provide the PC register. */
905 if (regno
>= 0 && regno
!= pcreg
)
908 insn
= btrace_insn_get (replay
);
909 gdb_assert (insn
!= NULL
);
911 regcache_raw_supply (regcache
, regno
, &insn
->pc
);
915 struct target_ops
*t
;
917 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
918 if (t
->to_fetch_registers
!= NULL
)
920 t
->to_fetch_registers (t
, regcache
, regno
);
926 /* The to_store_registers method of target record-btrace. */
929 record_btrace_store_registers (struct target_ops
*ops
,
930 struct regcache
*regcache
, int regno
)
932 struct target_ops
*t
;
934 if (record_btrace_is_replaying ())
935 error (_("This record target does not allow writing registers."));
937 gdb_assert (may_write_registers
!= 0);
939 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
940 if (t
->to_store_registers
!= NULL
)
942 t
->to_store_registers (t
, regcache
, regno
);
949 /* The to_prepare_to_store method of target record-btrace. */
952 record_btrace_prepare_to_store (struct target_ops
*ops
,
953 struct regcache
*regcache
)
955 struct target_ops
*t
;
957 if (record_btrace_is_replaying ())
960 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
961 if (t
->to_prepare_to_store
!= NULL
)
963 t
->to_prepare_to_store (t
, regcache
);
968 /* Implement stop_reason method for record_btrace_frame_unwind. */
970 static enum unwind_stop_reason
971 record_btrace_frame_unwind_stop_reason (struct frame_info
*this_frame
,
974 return UNWIND_UNAVAILABLE
;
977 /* Implement this_id method for record_btrace_frame_unwind. */
980 record_btrace_frame_this_id (struct frame_info
*this_frame
, void **this_cache
,
981 struct frame_id
*this_id
)
983 /* Leave there the outer_frame_id value. */
986 /* Implement prev_register method for record_btrace_frame_unwind. */
988 static struct value
*
989 record_btrace_frame_prev_register (struct frame_info
*this_frame
,
993 throw_error (NOT_AVAILABLE_ERROR
,
994 _("Registers are not available in btrace record history"));
997 /* Implement sniffer method for record_btrace_frame_unwind. */
1000 record_btrace_frame_sniffer (const struct frame_unwind
*self
,
1001 struct frame_info
*this_frame
,
1004 struct thread_info
*tp
;
1005 struct btrace_thread_info
*btinfo
;
1006 struct btrace_insn_iterator
*replay
;
1008 /* THIS_FRAME does not contain a reference to its thread. */
1009 tp
= find_thread_ptid (inferior_ptid
);
1010 gdb_assert (tp
!= NULL
);
1012 return btrace_is_replaying (tp
);
1015 /* btrace recording does not store previous memory content, neither the stack
1016 frames content. Any unwinding would return errorneous results as the stack
1017 contents no longer matches the changed PC value restored from history.
1018 Therefore this unwinder reports any possibly unwound registers as
1021 static const struct frame_unwind record_btrace_frame_unwind
=
1024 record_btrace_frame_unwind_stop_reason
,
1025 record_btrace_frame_this_id
,
1026 record_btrace_frame_prev_register
,
1028 record_btrace_frame_sniffer
1031 /* The to_resume method of target record-btrace. */
1034 record_btrace_resume (struct target_ops
*ops
, ptid_t ptid
, int step
,
1035 enum gdb_signal signal
)
1037 /* As long as we're not replaying, just forward the request. */
1038 if (!record_btrace_is_replaying ())
1040 for (ops
= ops
->beneath
; ops
!= NULL
; ops
= ops
->beneath
)
1041 if (ops
->to_resume
!= NULL
)
1042 return ops
->to_resume (ops
, ptid
, step
, signal
);
1044 error (_("Cannot find target for stepping."));
1047 error (_("You can't do this from here. Do 'record goto end', first."));
1050 /* The to_wait method of target record-btrace. */
1053 record_btrace_wait (struct target_ops
*ops
, ptid_t ptid
,
1054 struct target_waitstatus
*status
, int options
)
1056 /* As long as we're not replaying, just forward the request. */
1057 if (!record_btrace_is_replaying ())
1059 for (ops
= ops
->beneath
; ops
!= NULL
; ops
= ops
->beneath
)
1060 if (ops
->to_wait
!= NULL
)
1061 return ops
->to_wait (ops
, ptid
, status
, options
);
1063 error (_("Cannot find target for waiting."));
1066 error (_("You can't do this from here. Do 'record goto end', first."));
1069 /* The to_find_new_threads method of target record-btrace. */
1072 record_btrace_find_new_threads (struct target_ops
*ops
)
1074 /* Don't expect new threads if we're replaying. */
1075 if (record_btrace_is_replaying ())
1078 /* Forward the request. */
1079 for (ops
= ops
->beneath
; ops
!= NULL
; ops
= ops
->beneath
)
1080 if (ops
->to_find_new_threads
!= NULL
)
1082 ops
->to_find_new_threads (ops
);
1087 /* The to_thread_alive method of target record-btrace. */
1090 record_btrace_thread_alive (struct target_ops
*ops
, ptid_t ptid
)
1092 /* We don't add or remove threads during replay. */
1093 if (record_btrace_is_replaying ())
1094 return find_thread_ptid (ptid
) != NULL
;
1096 /* Forward the request. */
1097 for (ops
= ops
->beneath
; ops
!= NULL
; ops
= ops
->beneath
)
1098 if (ops
->to_thread_alive
!= NULL
)
1099 return ops
->to_thread_alive (ops
, ptid
);
1104 /* Set the replay branch trace instruction iterator. If IT is NULL, replay
1108 record_btrace_set_replay (struct thread_info
*tp
,
1109 const struct btrace_insn_iterator
*it
)
1111 struct btrace_thread_info
*btinfo
;
1113 btinfo
= &tp
->btrace
;
1115 if (it
== NULL
|| it
->function
== NULL
)
1117 if (btinfo
->replay
== NULL
)
1120 xfree (btinfo
->replay
);
1121 btinfo
->replay
= NULL
;
1125 if (btinfo
->replay
== NULL
)
1126 btinfo
->replay
= xmalloc (sizeof (*btinfo
->replay
));
1127 else if (btrace_insn_cmp (btinfo
->replay
, it
) == 0)
1130 *btinfo
->replay
= *it
;
1133 /* Clear the function call and instruction histories so we start anew
1134 from the new replay position. */
1135 xfree (btinfo
->insn_history
);
1136 xfree (btinfo
->call_history
);
1138 btinfo
->insn_history
= NULL
;
1139 btinfo
->call_history
= NULL
;
1141 registers_changed_ptid (tp
->ptid
);
1144 /* The to_goto_record_begin method of target record-btrace. */
1147 record_btrace_goto_begin (void)
1149 struct thread_info
*tp
;
1150 struct btrace_insn_iterator begin
;
1152 tp
= require_btrace_thread ();
1154 btrace_insn_begin (&begin
, &tp
->btrace
);
1155 record_btrace_set_replay (tp
, &begin
);
1157 print_stack_frame (get_selected_frame (NULL
), 1, SRC_AND_LOC
, 1);
1160 /* The to_goto_record_end method of target record-btrace. */
1163 record_btrace_goto_end (void)
1165 struct thread_info
*tp
;
1167 tp
= require_btrace_thread ();
1169 record_btrace_set_replay (tp
, NULL
);
1171 print_stack_frame (get_selected_frame (NULL
), 1, SRC_AND_LOC
, 1);
1174 /* The to_goto_record method of target record-btrace. */
1177 record_btrace_goto (ULONGEST insn
)
1179 struct thread_info
*tp
;
1180 struct btrace_insn_iterator it
;
1181 unsigned int number
;
1186 /* Check for wrap-arounds. */
1188 error (_("Instruction number out of range."));
1190 tp
= require_btrace_thread ();
1192 found
= btrace_find_insn_by_number (&it
, &tp
->btrace
, number
);
1194 error (_("No such instruction."));
1196 record_btrace_set_replay (tp
, &it
);
1198 print_stack_frame (get_selected_frame (NULL
), 1, SRC_AND_LOC
, 1);
1201 /* Initialize the record-btrace target ops. */
1204 init_record_btrace_ops (void)
1206 struct target_ops
*ops
;
1208 ops
= &record_btrace_ops
;
1209 ops
->to_shortname
= "record-btrace";
1210 ops
->to_longname
= "Branch tracing target";
1211 ops
->to_doc
= "Collect control-flow trace and provide the execution history.";
1212 ops
->to_open
= record_btrace_open
;
1213 ops
->to_close
= record_btrace_close
;
1214 ops
->to_detach
= record_detach
;
1215 ops
->to_disconnect
= record_disconnect
;
1216 ops
->to_mourn_inferior
= record_mourn_inferior
;
1217 ops
->to_kill
= record_kill
;
1218 ops
->to_create_inferior
= find_default_create_inferior
;
1219 ops
->to_stop_recording
= record_btrace_stop_recording
;
1220 ops
->to_info_record
= record_btrace_info
;
1221 ops
->to_insn_history
= record_btrace_insn_history
;
1222 ops
->to_insn_history_from
= record_btrace_insn_history_from
;
1223 ops
->to_insn_history_range
= record_btrace_insn_history_range
;
1224 ops
->to_call_history
= record_btrace_call_history
;
1225 ops
->to_call_history_from
= record_btrace_call_history_from
;
1226 ops
->to_call_history_range
= record_btrace_call_history_range
;
1227 ops
->to_record_is_replaying
= record_btrace_is_replaying
;
1228 ops
->to_xfer_partial
= record_btrace_xfer_partial
;
1229 ops
->to_remove_breakpoint
= record_btrace_remove_breakpoint
;
1230 ops
->to_insert_breakpoint
= record_btrace_insert_breakpoint
;
1231 ops
->to_fetch_registers
= record_btrace_fetch_registers
;
1232 ops
->to_store_registers
= record_btrace_store_registers
;
1233 ops
->to_prepare_to_store
= record_btrace_prepare_to_store
;
1234 ops
->to_get_unwinder
= &record_btrace_frame_unwind
;
1235 ops
->to_resume
= record_btrace_resume
;
1236 ops
->to_wait
= record_btrace_wait
;
1237 ops
->to_find_new_threads
= record_btrace_find_new_threads
;
1238 ops
->to_thread_alive
= record_btrace_thread_alive
;
1239 ops
->to_goto_record_begin
= record_btrace_goto_begin
;
1240 ops
->to_goto_record_end
= record_btrace_goto_end
;
1241 ops
->to_goto_record
= record_btrace_goto
;
1242 ops
->to_stratum
= record_stratum
;
1243 ops
->to_magic
= OPS_MAGIC
;
1246 /* Alias for "target record". */
1249 cmd_record_btrace_start (char *args
, int from_tty
)
1251 if (args
!= NULL
&& *args
!= 0)
1252 error (_("Invalid argument."));
1254 execute_command ("target record-btrace", from_tty
);
1257 void _initialize_record_btrace (void);
1259 /* Initialize btrace commands. */
1262 _initialize_record_btrace (void)
1264 add_cmd ("btrace", class_obscure
, cmd_record_btrace_start
,
1265 _("Start branch trace recording."),
1267 add_alias_cmd ("b", "btrace", class_obscure
, 1, &record_cmdlist
);
1269 init_record_btrace_ops ();
1270 add_target (&record_btrace_ops
);