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 /* Print a record-btrace debug message. Use do ... while (0) to avoid
45 ambiguities when used in if statements. */
47 #define DEBUG(msg, args...) \
50 if (record_debug != 0) \
51 fprintf_unfiltered (gdb_stdlog, \
52 "[record-btrace] " msg "\n", ##args); \
57 /* Update the branch trace for the current thread and return a pointer to its
58 branch trace information struct.
60 Throws an error if there is no thread or no trace. This function never
63 static struct btrace_thread_info
*
66 struct thread_info
*tp
;
67 struct btrace_thread_info
*btinfo
;
71 tp
= find_thread_ptid (inferior_ptid
);
73 error (_("No thread."));
79 if (btinfo
->begin
== NULL
)
80 error (_("No trace."));
85 /* Enable branch tracing for one thread. Warn on errors. */
88 record_btrace_enable_warn (struct thread_info
*tp
)
90 volatile struct gdb_exception error
;
92 TRY_CATCH (error
, RETURN_MASK_ERROR
)
95 if (error
.message
!= NULL
)
96 warning ("%s", error
.message
);
99 /* Callback function to disable branch tracing for one thread. */
102 record_btrace_disable_callback (void *arg
)
104 struct thread_info
*tp
;
111 /* Enable automatic tracing of new threads. */
114 record_btrace_auto_enable (void)
116 DEBUG ("attach thread observer");
118 record_btrace_thread_observer
119 = observer_attach_new_thread (record_btrace_enable_warn
);
122 /* Disable automatic tracing of new threads. */
125 record_btrace_auto_disable (void)
127 /* The observer may have been detached, already. */
128 if (record_btrace_thread_observer
== NULL
)
131 DEBUG ("detach thread observer");
133 observer_detach_new_thread (record_btrace_thread_observer
);
134 record_btrace_thread_observer
= NULL
;
137 /* The to_open method of target record-btrace. */
140 record_btrace_open (char *args
, int from_tty
)
142 struct cleanup
*disable_chain
;
143 struct thread_info
*tp
;
149 if (!target_has_execution
)
150 error (_("The program is not being run."));
152 if (!target_supports_btrace ())
153 error (_("Target does not support branch tracing."));
155 gdb_assert (record_btrace_thread_observer
== NULL
);
157 disable_chain
= make_cleanup (null_cleanup
, NULL
);
159 if (args
== NULL
|| *args
== 0 || number_is_in_list (args
, tp
->num
))
163 make_cleanup (record_btrace_disable_callback
, tp
);
166 record_btrace_auto_enable ();
168 push_target (&record_btrace_ops
);
170 observer_notify_record_changed (current_inferior (), 1);
172 discard_cleanups (disable_chain
);
175 /* The to_stop_recording method of target record-btrace. */
178 record_btrace_stop_recording (void)
180 struct thread_info
*tp
;
182 DEBUG ("stop recording");
184 record_btrace_auto_disable ();
187 if (tp
->btrace
.target
!= NULL
)
191 /* The to_close method of target record-btrace. */
194 record_btrace_close (void)
196 /* Make sure automatic recording gets disabled even if we did not stop
197 recording before closing the record-btrace target. */
198 record_btrace_auto_disable ();
200 /* We already stopped recording. */
203 /* The to_info_record method of target record-btrace. */
206 record_btrace_info (void)
208 struct btrace_thread_info
*btinfo
;
209 struct thread_info
*tp
;
210 unsigned int insns
, calls
;
214 tp
= find_thread_ptid (inferior_ptid
);
216 error (_("No thread."));
223 btinfo
= &tp
->btrace
;
224 if (btinfo
->begin
!= NULL
)
226 struct btrace_call_iterator call
;
227 struct btrace_insn_iterator insn
;
229 btrace_call_end (&call
, btinfo
);
230 btrace_call_prev (&call
, 1);
231 calls
= btrace_call_number (&call
);
233 btrace_insn_end (&insn
, btinfo
);
234 btrace_insn_prev (&insn
, 1);
235 insns
= btrace_insn_number (&insn
);
238 printf_unfiltered (_("Recorded %u instructions in %u functions for thread "
239 "%d (%s).\n"), insns
, calls
, tp
->num
,
240 target_pid_to_str (tp
->ptid
));
242 if (btrace_is_replaying (tp
))
243 printf_unfiltered (_("Replay in progress. At instruction %u.\n"),
244 btrace_insn_number (btinfo
->replay
));
247 /* Print an unsigned int. */
250 ui_out_field_uint (struct ui_out
*uiout
, const char *fld
, unsigned int val
)
252 ui_out_field_fmt (uiout
, fld
, "%u", val
);
255 /* Disassemble a section of the recorded instruction trace. */
258 btrace_insn_history (struct ui_out
*uiout
,
259 const struct btrace_insn_iterator
*begin
,
260 const struct btrace_insn_iterator
*end
, int flags
)
262 struct gdbarch
*gdbarch
;
263 struct btrace_insn_iterator it
;
265 DEBUG ("itrace (0x%x): [%u; %u)", flags
, btrace_insn_number (begin
),
266 btrace_insn_number (end
));
268 gdbarch
= target_gdbarch ();
270 for (it
= *begin
; btrace_insn_cmp (&it
, end
) != 0; btrace_insn_next (&it
, 1))
272 const struct btrace_insn
*insn
;
274 insn
= btrace_insn_get (&it
);
276 /* Print the instruction index. */
277 ui_out_field_uint (uiout
, "index", btrace_insn_number (&it
));
278 ui_out_text (uiout
, "\t");
280 /* Disassembly with '/m' flag may not produce the expected result.
282 gdb_disassembly (gdbarch
, uiout
, NULL
, flags
, 1, insn
->pc
, insn
->pc
+ 1);
286 /* The to_insn_history method of target record-btrace. */
289 record_btrace_insn_history (int size
, int flags
)
291 struct btrace_thread_info
*btinfo
;
292 struct btrace_insn_history
*history
;
293 struct btrace_insn_iterator begin
, end
;
294 struct cleanup
*uiout_cleanup
;
295 struct ui_out
*uiout
;
296 unsigned int context
, covered
;
298 uiout
= current_uiout
;
299 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
301 context
= abs (size
);
303 error (_("Bad record instruction-history-size."));
305 btinfo
= require_btrace ();
306 history
= btinfo
->insn_history
;
309 struct btrace_insn_iterator
*replay
;
311 DEBUG ("insn-history (0x%x): %d", flags
, size
);
313 /* If we're replaying, we start at the replay position. Otherwise, we
314 start at the tail of the trace. */
315 replay
= btinfo
->replay
;
319 btrace_insn_end (&begin
, btinfo
);
321 /* We start from here and expand in the requested direction. Then we
322 expand in the other direction, as well, to fill up any remaining
327 /* We want the current position covered, as well. */
328 covered
= btrace_insn_next (&end
, 1);
329 covered
+= btrace_insn_prev (&begin
, context
- covered
);
330 covered
+= btrace_insn_next (&end
, context
- covered
);
334 covered
= btrace_insn_next (&end
, context
);
335 covered
+= btrace_insn_prev (&begin
, context
- covered
);
340 begin
= history
->begin
;
343 DEBUG ("insn-history (0x%x): %d, prev: [%u; %u)", flags
, size
,
344 btrace_insn_number (&begin
), btrace_insn_number (&end
));
349 covered
= btrace_insn_prev (&begin
, context
);
354 covered
= btrace_insn_next (&end
, context
);
359 btrace_insn_history (uiout
, &begin
, &end
, flags
);
363 printf_unfiltered (_("At the start of the branch trace record.\n"));
365 printf_unfiltered (_("At the end of the branch trace record.\n"));
368 btrace_set_insn_history (btinfo
, &begin
, &end
);
369 do_cleanups (uiout_cleanup
);
372 /* The to_insn_history_range method of target record-btrace. */
375 record_btrace_insn_history_range (ULONGEST from
, ULONGEST to
, int flags
)
377 struct btrace_thread_info
*btinfo
;
378 struct btrace_insn_history
*history
;
379 struct btrace_insn_iterator begin
, end
;
380 struct cleanup
*uiout_cleanup
;
381 struct ui_out
*uiout
;
382 unsigned int low
, high
;
385 uiout
= current_uiout
;
386 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
391 DEBUG ("insn-history (0x%x): [%u; %u)", flags
, low
, high
);
393 /* Check for wrap-arounds. */
394 if (low
!= from
|| high
!= to
)
395 error (_("Bad range."));
398 error (_("Bad range."));
400 btinfo
= require_btrace ();
402 found
= btrace_find_insn_by_number (&begin
, btinfo
, low
);
404 error (_("Range out of bounds."));
406 found
= btrace_find_insn_by_number (&end
, btinfo
, high
);
409 /* Silently truncate the range. */
410 btrace_insn_end (&end
, btinfo
);
414 /* We want both begin and end to be inclusive. */
415 btrace_insn_next (&end
, 1);
418 btrace_insn_history (uiout
, &begin
, &end
, flags
);
419 btrace_set_insn_history (btinfo
, &begin
, &end
);
421 do_cleanups (uiout_cleanup
);
424 /* The to_insn_history_from method of target record-btrace. */
427 record_btrace_insn_history_from (ULONGEST from
, int size
, int flags
)
429 ULONGEST begin
, end
, context
;
431 context
= abs (size
);
433 error (_("Bad record instruction-history-size."));
442 begin
= from
- context
+ 1;
447 end
= from
+ context
- 1;
449 /* Check for wrap-around. */
454 record_btrace_insn_history_range (begin
, end
, flags
);
457 /* Print the instruction number range for a function call history line. */
460 btrace_call_history_insn_range (struct ui_out
*uiout
,
461 const struct btrace_function
*bfun
)
463 unsigned int begin
, end
, size
;
465 size
= VEC_length (btrace_insn_s
, bfun
->insn
);
466 gdb_assert (size
> 0);
468 begin
= bfun
->insn_offset
;
469 end
= begin
+ size
- 1;
471 ui_out_field_uint (uiout
, "insn begin", begin
);
472 ui_out_text (uiout
, ",");
473 ui_out_field_uint (uiout
, "insn end", end
);
476 /* Print the source line information for a function call history line. */
479 btrace_call_history_src_line (struct ui_out
*uiout
,
480 const struct btrace_function
*bfun
)
489 ui_out_field_string (uiout
, "file",
490 symtab_to_filename_for_display (sym
->symtab
));
492 begin
= bfun
->lbegin
;
498 ui_out_text (uiout
, ":");
499 ui_out_field_int (uiout
, "min line", begin
);
504 ui_out_text (uiout
, ",");
505 ui_out_field_int (uiout
, "max line", end
);
508 /* Disassemble a section of the recorded function trace. */
511 btrace_call_history (struct ui_out
*uiout
,
512 const struct btrace_thread_info
*btinfo
,
513 const struct btrace_call_iterator
*begin
,
514 const struct btrace_call_iterator
*end
,
515 enum record_print_flag flags
)
517 struct btrace_call_iterator it
;
519 DEBUG ("ftrace (0x%x): [%u; %u)", flags
, btrace_call_number (begin
),
520 btrace_call_number (end
));
522 for (it
= *begin
; btrace_call_cmp (&it
, end
) < 0; btrace_call_next (&it
, 1))
524 const struct btrace_function
*bfun
;
525 struct minimal_symbol
*msym
;
528 bfun
= btrace_call_get (&it
);
532 /* Print the function index. */
533 ui_out_field_uint (uiout
, "index", bfun
->number
);
534 ui_out_text (uiout
, "\t");
536 if ((flags
& RECORD_PRINT_INDENT_CALLS
) != 0)
538 int level
= bfun
->level
+ btinfo
->level
, i
;
540 for (i
= 0; i
< level
; ++i
)
541 ui_out_text (uiout
, " ");
545 ui_out_field_string (uiout
, "function", SYMBOL_PRINT_NAME (sym
));
546 else if (msym
!= NULL
)
547 ui_out_field_string (uiout
, "function", SYMBOL_PRINT_NAME (msym
));
548 else if (!ui_out_is_mi_like_p (uiout
))
549 ui_out_field_string (uiout
, "function", "??");
551 if ((flags
& RECORD_PRINT_INSN_RANGE
) != 0)
553 ui_out_text (uiout
, _("\tinst "));
554 btrace_call_history_insn_range (uiout
, bfun
);
557 if ((flags
& RECORD_PRINT_SRC_LINE
) != 0)
559 ui_out_text (uiout
, _("\tat "));
560 btrace_call_history_src_line (uiout
, bfun
);
563 ui_out_text (uiout
, "\n");
567 /* The to_call_history method of target record-btrace. */
570 record_btrace_call_history (int size
, int flags
)
572 struct btrace_thread_info
*btinfo
;
573 struct btrace_call_history
*history
;
574 struct btrace_call_iterator begin
, end
;
575 struct cleanup
*uiout_cleanup
;
576 struct ui_out
*uiout
;
577 unsigned int context
, covered
;
579 uiout
= current_uiout
;
580 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
582 context
= abs (size
);
584 error (_("Bad record function-call-history-size."));
586 btinfo
= require_btrace ();
587 history
= btinfo
->call_history
;
590 struct btrace_insn_iterator
*replay
;
592 DEBUG ("call-history (0x%x): %d", flags
, size
);
594 /* If we're replaying, we start at the replay position. Otherwise, we
595 start at the tail of the trace. */
596 replay
= btinfo
->replay
;
599 begin
.function
= replay
->function
;
600 begin
.btinfo
= btinfo
;
603 btrace_call_end (&begin
, btinfo
);
605 /* We start from here and expand in the requested direction. Then we
606 expand in the other direction, as well, to fill up any remaining
611 /* We want the current position covered, as well. */
612 covered
= btrace_call_next (&end
, 1);
613 covered
+= btrace_call_prev (&begin
, context
- covered
);
614 covered
+= btrace_call_next (&end
, context
- covered
);
618 covered
= btrace_call_next (&end
, context
);
619 covered
+= btrace_call_prev (&begin
, context
- covered
);
624 begin
= history
->begin
;
627 DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags
, size
,
628 btrace_call_number (&begin
), btrace_call_number (&end
));
633 covered
= btrace_call_prev (&begin
, context
);
638 covered
= btrace_call_next (&end
, context
);
643 btrace_call_history (uiout
, btinfo
, &begin
, &end
, flags
);
647 printf_unfiltered (_("At the start of the branch trace record.\n"));
649 printf_unfiltered (_("At the end of the branch trace record.\n"));
652 btrace_set_call_history (btinfo
, &begin
, &end
);
653 do_cleanups (uiout_cleanup
);
656 /* The to_call_history_range method of target record-btrace. */
659 record_btrace_call_history_range (ULONGEST from
, ULONGEST to
, int flags
)
661 struct btrace_thread_info
*btinfo
;
662 struct btrace_call_history
*history
;
663 struct btrace_call_iterator begin
, end
;
664 struct cleanup
*uiout_cleanup
;
665 struct ui_out
*uiout
;
666 unsigned int low
, high
;
669 uiout
= current_uiout
;
670 uiout_cleanup
= make_cleanup_ui_out_tuple_begin_end (uiout
,
675 DEBUG ("call-history (0x%x): [%u; %u)", flags
, low
, high
);
677 /* Check for wrap-arounds. */
678 if (low
!= from
|| high
!= to
)
679 error (_("Bad range."));
682 error (_("Bad range."));
684 btinfo
= require_btrace ();
686 found
= btrace_find_call_by_number (&begin
, btinfo
, low
);
688 error (_("Range out of bounds."));
690 found
= btrace_find_call_by_number (&end
, btinfo
, high
);
693 /* Silently truncate the range. */
694 btrace_call_end (&end
, btinfo
);
698 /* We want both begin and end to be inclusive. */
699 btrace_call_next (&end
, 1);
702 btrace_call_history (uiout
, btinfo
, &begin
, &end
, flags
);
703 btrace_set_call_history (btinfo
, &begin
, &end
);
705 do_cleanups (uiout_cleanup
);
708 /* The to_call_history_from method of target record-btrace. */
711 record_btrace_call_history_from (ULONGEST from
, int size
, int flags
)
713 ULONGEST begin
, end
, context
;
715 context
= abs (size
);
717 error (_("Bad record function-call-history-size."));
726 begin
= from
- context
+ 1;
731 end
= from
+ context
- 1;
733 /* Check for wrap-around. */
738 record_btrace_call_history_range (begin
, end
, flags
);
741 /* The to_record_is_replaying method of target record-btrace. */
744 record_btrace_is_replaying (void)
746 struct thread_info
*tp
;
749 if (btrace_is_replaying (tp
))
755 /* The to_fetch_registers method of target record-btrace. */
758 record_btrace_fetch_registers (struct target_ops
*ops
,
759 struct regcache
*regcache
, int regno
)
761 struct btrace_insn_iterator
*replay
;
762 struct thread_info
*tp
;
764 tp
= find_thread_ptid (inferior_ptid
);
765 gdb_assert (tp
!= NULL
);
767 replay
= tp
->btrace
.replay
;
770 const struct btrace_insn
*insn
;
771 struct gdbarch
*gdbarch
;
774 gdbarch
= get_regcache_arch (regcache
);
775 pcreg
= gdbarch_pc_regnum (gdbarch
);
779 /* We can only provide the PC register. */
780 if (regno
>= 0 && regno
!= pcreg
)
783 insn
= btrace_insn_get (replay
);
784 gdb_assert (insn
!= NULL
);
786 regcache_raw_supply (regcache
, regno
, &insn
->pc
);
790 struct target_ops
*t
;
792 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
793 if (t
->to_fetch_registers
!= NULL
)
795 t
->to_fetch_registers (t
, regcache
, regno
);
801 /* The to_store_registers method of target record-btrace. */
804 record_btrace_store_registers (struct target_ops
*ops
,
805 struct regcache
*regcache
, int regno
)
807 struct target_ops
*t
;
809 if (record_btrace_is_replaying ())
810 error (_("This record target does not allow writing registers."));
812 gdb_assert (may_write_registers
!= 0);
814 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
815 if (t
->to_store_registers
!= NULL
)
817 t
->to_store_registers (t
, regcache
, regno
);
824 /* The to_prepare_to_store method of target record-btrace. */
827 record_btrace_prepare_to_store (struct target_ops
*ops
,
828 struct regcache
*regcache
)
830 struct target_ops
*t
;
832 if (record_btrace_is_replaying ())
835 for (t
= ops
->beneath
; t
!= NULL
; t
= t
->beneath
)
836 if (t
->to_prepare_to_store
!= NULL
)
838 t
->to_prepare_to_store (t
, regcache
);
843 /* Implement stop_reason method for record_btrace_frame_unwind. */
845 static enum unwind_stop_reason
846 record_btrace_frame_unwind_stop_reason (struct frame_info
*this_frame
,
849 return UNWIND_UNAVAILABLE
;
852 /* Implement this_id method for record_btrace_frame_unwind. */
855 record_btrace_frame_this_id (struct frame_info
*this_frame
, void **this_cache
,
856 struct frame_id
*this_id
)
858 /* Leave there the outer_frame_id value. */
861 /* Implement prev_register method for record_btrace_frame_unwind. */
863 static struct value
*
864 record_btrace_frame_prev_register (struct frame_info
*this_frame
,
868 throw_error (NOT_AVAILABLE_ERROR
,
869 _("Registers are not available in btrace record history"));
872 /* Implement sniffer method for record_btrace_frame_unwind. */
875 record_btrace_frame_sniffer (const struct frame_unwind
*self
,
876 struct frame_info
*this_frame
,
879 struct thread_info
*tp
;
880 struct btrace_thread_info
*btinfo
;
881 struct btrace_insn_iterator
*replay
;
883 /* THIS_FRAME does not contain a reference to its thread. */
884 tp
= find_thread_ptid (inferior_ptid
);
885 gdb_assert (tp
!= NULL
);
887 return btrace_is_replaying (tp
);
890 /* btrace recording does not store previous memory content, neither the stack
891 frames content. Any unwinding would return errorneous results as the stack
892 contents no longer matches the changed PC value restored from history.
893 Therefore this unwinder reports any possibly unwound registers as
896 static const struct frame_unwind record_btrace_frame_unwind
=
899 record_btrace_frame_unwind_stop_reason
,
900 record_btrace_frame_this_id
,
901 record_btrace_frame_prev_register
,
903 record_btrace_frame_sniffer
905 /* Initialize the record-btrace target ops. */
908 init_record_btrace_ops (void)
910 struct target_ops
*ops
;
912 ops
= &record_btrace_ops
;
913 ops
->to_shortname
= "record-btrace";
914 ops
->to_longname
= "Branch tracing target";
915 ops
->to_doc
= "Collect control-flow trace and provide the execution history.";
916 ops
->to_open
= record_btrace_open
;
917 ops
->to_close
= record_btrace_close
;
918 ops
->to_detach
= record_detach
;
919 ops
->to_disconnect
= record_disconnect
;
920 ops
->to_mourn_inferior
= record_mourn_inferior
;
921 ops
->to_kill
= record_kill
;
922 ops
->to_create_inferior
= find_default_create_inferior
;
923 ops
->to_stop_recording
= record_btrace_stop_recording
;
924 ops
->to_info_record
= record_btrace_info
;
925 ops
->to_insn_history
= record_btrace_insn_history
;
926 ops
->to_insn_history_from
= record_btrace_insn_history_from
;
927 ops
->to_insn_history_range
= record_btrace_insn_history_range
;
928 ops
->to_call_history
= record_btrace_call_history
;
929 ops
->to_call_history_from
= record_btrace_call_history_from
;
930 ops
->to_call_history_range
= record_btrace_call_history_range
;
931 ops
->to_record_is_replaying
= record_btrace_is_replaying
;
932 ops
->to_fetch_registers
= record_btrace_fetch_registers
;
933 ops
->to_store_registers
= record_btrace_store_registers
;
934 ops
->to_prepare_to_store
= record_btrace_prepare_to_store
;
935 ops
->to_get_unwinder
= &record_btrace_frame_unwind
;
936 ops
->to_stratum
= record_stratum
;
937 ops
->to_magic
= OPS_MAGIC
;
940 /* Alias for "target record". */
943 cmd_record_btrace_start (char *args
, int from_tty
)
945 if (args
!= NULL
&& *args
!= 0)
946 error (_("Invalid argument."));
948 execute_command ("target record-btrace", from_tty
);
951 void _initialize_record_btrace (void);
953 /* Initialize btrace commands. */
956 _initialize_record_btrace (void)
958 add_cmd ("btrace", class_obscure
, cmd_record_btrace_start
,
959 _("Start branch trace recording."),
961 add_alias_cmd ("b", "btrace", class_obscure
, 1, &record_cmdlist
);
963 init_record_btrace_ops ();
964 add_target (&record_btrace_ops
);