More updated translations
[binutils-gdb.git] / gdb / record.c
blob97a4e46441bad19acb8f7528d8b917e4b3fb1710
1 /* Process record and replay target for GDB, the GNU debugger.
3 Copyright (C) 2008-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "cli/cli-cmds.h"
21 #include "completer.h"
22 #include "record.h"
23 #include "observable.h"
24 #include "inferior.h"
25 #include "gdbsupport/common-utils.h"
26 #include "cli/cli-utils.h"
27 #include "disasm.h"
28 #include "interps.h"
29 #include "top.h"
31 #include <ctype.h>
33 /* This is the debug switch for process record. */
34 unsigned int record_debug = 0;
36 /* The number of instructions to print in "record instruction-history". */
37 static unsigned int record_insn_history_size = 10;
39 /* The variable registered as control variable in the "record
40 instruction-history" command. Necessary for extra input
41 validation. */
42 static unsigned int record_insn_history_size_setshow_var;
44 /* The number of functions to print in "record function-call-history". */
45 static unsigned int record_call_history_size = 10;
47 /* The variable registered as control variable in the "record
48 call-history" command. Necessary for extra input validation. */
49 static unsigned int record_call_history_size_setshow_var;
51 struct cmd_list_element *record_cmdlist = NULL;
52 static struct cmd_list_element *record_goto_cmdlist = NULL;
53 struct cmd_list_element *set_record_cmdlist = NULL;
54 struct cmd_list_element *show_record_cmdlist = NULL;
55 struct cmd_list_element *info_record_cmdlist = NULL;
57 #define DEBUG(msg, args...) \
58 if (record_debug) \
59 gdb_printf (gdb_stdlog, "record: " msg "\n", ##args)
61 /* See record.h. */
63 struct target_ops *
64 find_record_target (void)
66 return find_target_at (record_stratum);
69 /* Check that recording is active. Throw an error, if it isn't. */
71 static struct target_ops *
72 require_record_target (void)
74 struct target_ops *t;
76 t = find_record_target ();
77 if (t == NULL)
78 error (_("No recording is currently active.\n"
79 "Use the \"record full\" or \"record btrace\" command first."));
81 return t;
84 /* See record.h. */
86 void
87 record_preopen (void)
89 /* Check if a record target is already running. */
90 if (find_record_target () != NULL)
91 error (_("The process is already being recorded. Use \"record stop\" to "
92 "stop recording first."));
95 /* See record.h. */
97 void
98 record_start (const char *method, const char *format, int from_tty)
100 if (method == NULL)
102 if (format == NULL)
103 execute_command_to_string ("record", from_tty, false);
104 else
105 error (_("Invalid format."));
107 else if (strcmp (method, "full") == 0)
109 if (format == NULL)
110 execute_command_to_string ("record full", from_tty, false);
111 else
112 error (_("Invalid format."));
114 else if (strcmp (method, "btrace") == 0)
116 if (format == NULL)
117 execute_command_to_string ("record btrace", from_tty, false);
118 else if (strcmp (format, "bts") == 0)
119 execute_command_to_string ("record btrace bts", from_tty, false);
120 else if (strcmp (format, "pt") == 0)
121 execute_command_to_string ("record btrace pt", from_tty, false);
122 else
123 error (_("Invalid format."));
125 else
126 error (_("Invalid method."));
129 /* See record.h. */
131 void
132 record_stop (int from_tty)
134 execute_command_to_string ("record stop", from_tty, false);
137 /* See record.h. */
140 record_read_memory (struct gdbarch *gdbarch,
141 CORE_ADDR memaddr, gdb_byte *myaddr,
142 ssize_t len)
144 int ret = target_read_memory (memaddr, myaddr, len);
146 if (ret != 0)
147 DEBUG ("error reading memory at addr %s len = %ld.\n",
148 paddress (gdbarch, memaddr), (long) len);
150 return ret;
153 /* Stop recording. */
155 static void
156 record_stop (struct target_ops *t)
158 DEBUG ("stop %s", t->shortname ());
160 t->stop_recording ();
163 /* Unpush the record target. */
165 static void
166 record_unpush (struct target_ops *t)
168 DEBUG ("unpush %s", t->shortname ());
170 current_inferior ()->unpush_target (t);
173 /* See record.h. */
175 void
176 record_disconnect (struct target_ops *t, const char *args, int from_tty)
178 gdb_assert (t->stratum () == record_stratum);
180 DEBUG ("disconnect %s", t->shortname ());
182 record_stop (t);
183 record_unpush (t);
185 target_disconnect (args, from_tty);
188 /* See record.h. */
190 void
191 record_detach (struct target_ops *t, inferior *inf, int from_tty)
193 gdb_assert (t->stratum () == record_stratum);
195 DEBUG ("detach %s", t->shortname ());
197 record_stop (t);
198 record_unpush (t);
200 target_detach (inf, from_tty);
203 /* See record.h. */
205 void
206 record_mourn_inferior (struct target_ops *t)
208 gdb_assert (t->stratum () == record_stratum);
210 DEBUG ("mourn inferior %s", t->shortname ());
212 /* It is safer to not stop recording. Resources will be freed when
213 threads are discarded. */
214 record_unpush (t);
216 target_mourn_inferior (inferior_ptid);
219 /* See record.h. */
221 void
222 record_kill (struct target_ops *t)
224 gdb_assert (t->stratum () == record_stratum);
226 DEBUG ("kill %s", t->shortname ());
228 /* It is safer to not stop recording. Resources will be freed when
229 threads are discarded. */
230 record_unpush (t);
232 target_kill ();
235 /* See record.h. */
238 record_check_stopped_by_breakpoint (const address_space *aspace,
239 CORE_ADDR pc,
240 enum target_stop_reason *reason)
242 if (breakpoint_inserted_here_p (aspace, pc))
244 if (hardware_breakpoint_inserted_here_p (aspace, pc))
245 *reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
246 else
247 *reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
248 return 1;
251 return 0;
254 /* Implement "show record debug" command. */
256 static void
257 show_record_debug (struct ui_file *file, int from_tty,
258 struct cmd_list_element *c, const char *value)
260 gdb_printf (file, _("Debugging of process record target is %s.\n"),
261 value);
264 /* Alias for "target record-full". */
266 static void
267 cmd_record_start (const char *args, int from_tty)
269 /* As 'record' is a prefix command then if the user types 'record blah'
270 GDB will search for the 'blah' sub-command and either run that instead
271 of calling this function, or throw an error if 'blah' doesn't exist.
272 As a result, we only get here if no args are given. */
273 gdb_assert (args == nullptr);
274 execute_command ("target record-full", from_tty);
277 /* Truncate the record log from the present point
278 of replay until the end. */
280 static void
281 cmd_record_delete (const char *args, int from_tty)
283 require_record_target ();
285 if (!target_record_is_replaying (inferior_ptid))
287 gdb_printf (_("Already at end of record list.\n"));
288 return;
291 if (!target_supports_delete_record ())
293 gdb_printf (_("The current record target does not support "
294 "this operation.\n"));
295 return;
298 if (!from_tty || query (_("Delete the log from this point forward "
299 "and begin to record the running message "
300 "at current PC?")))
301 target_delete_record ();
304 /* Implement the "stoprecord" or "record stop" command. */
306 static void
307 cmd_record_stop (const char *args, int from_tty)
309 struct target_ops *t;
311 t = require_record_target ();
313 record_stop (t);
314 record_unpush (t);
316 gdb_printf (_("Process record is stopped and all execution "
317 "logs are deleted.\n"));
319 interps_notify_record_changed (current_inferior (), 0, NULL, NULL);
323 /* The "info record" command. */
325 static void
326 info_record_command (const char *args, int from_tty)
328 struct target_ops *t;
330 t = find_record_target ();
331 if (t == NULL)
333 gdb_printf (_("No recording is currently active.\n"));
334 return;
337 gdb_printf (_("Active record target: %s\n"), t->shortname ());
338 t->info_record ();
341 /* The "record save" command. */
343 static void
344 cmd_record_save (const char *args, int from_tty)
346 const char *recfilename;
347 char recfilename_buffer[40];
349 require_record_target ();
351 if (args != NULL && *args != 0)
352 recfilename = args;
353 else
355 /* Default recfile name is "gdb_record.PID". */
356 xsnprintf (recfilename_buffer, sizeof (recfilename_buffer),
357 "gdb_record.%d", inferior_ptid.pid ());
358 recfilename = recfilename_buffer;
361 target_save_record (recfilename);
364 /* See record.h. */
366 void
367 record_goto (const char *arg)
369 ULONGEST insn;
371 if (arg == NULL || *arg == '\0')
372 error (_("Command requires an argument (insn number to go to)."));
374 insn = parse_and_eval_long (arg);
376 require_record_target ();
377 target_goto_record (insn);
380 /* "record goto" command. Argument is an instruction number,
381 as given by "info record".
383 Rewinds the recording (forward or backward) to the given instruction. */
385 static void
386 cmd_record_goto (const char *arg, int from_tty)
388 record_goto (arg);
391 /* The "record goto begin" command. */
393 static void
394 cmd_record_goto_begin (const char *arg, int from_tty)
396 if (arg != NULL && *arg != '\0')
397 error (_("Junk after argument: %s."), arg);
399 require_record_target ();
400 target_goto_record_begin ();
403 /* The "record goto end" command. */
405 static void
406 cmd_record_goto_end (const char *arg, int from_tty)
408 if (arg != NULL && *arg != '\0')
409 error (_("Junk after argument: %s."), arg);
411 require_record_target ();
412 target_goto_record_end ();
415 /* Read an instruction number from an argument string. */
417 static ULONGEST
418 get_insn_number (const char **arg)
420 ULONGEST number;
421 const char *begin, *end, *pos;
423 begin = *arg;
424 pos = skip_spaces (begin);
426 if (!isdigit (*pos))
427 error (_("Expected positive number, got: %s."), pos);
429 number = strtoulst (pos, &end, 10);
431 *arg += (end - begin);
433 return number;
436 /* Read a context size from an argument string. */
438 static int
439 get_context_size (const char **arg)
441 const char *pos;
442 char *end;
444 pos = skip_spaces (*arg);
446 if (!isdigit (*pos))
447 error (_("Expected positive number, got: %s."), pos);
449 long result = strtol (pos, &end, 10);
450 *arg = end;
451 return result;
454 /* Complain about junk at the end of an argument string. */
456 static void
457 no_chunk (const char *arg)
459 if (*arg != 0)
460 error (_("Junk after argument: %s."), arg);
463 /* Read instruction-history modifiers from an argument string. */
465 static gdb_disassembly_flags
466 get_insn_history_modifiers (const char **arg)
468 gdb_disassembly_flags modifiers;
469 const char *args;
471 modifiers = 0;
472 args = *arg;
474 if (args == NULL)
475 return modifiers;
477 while (*args == '/')
479 ++args;
481 if (*args == '\0')
482 error (_("Missing modifier."));
484 for (; *args; ++args)
486 if (isspace (*args))
487 break;
489 if (*args == '/')
490 continue;
492 switch (*args)
494 case 'a':
495 modifiers |= DISASSEMBLY_OMIT_AUX_INSN;
496 break;
497 case 'm':
498 case 's':
499 modifiers |= DISASSEMBLY_SOURCE;
500 modifiers |= DISASSEMBLY_FILENAME;
501 break;
502 case 'r':
503 modifiers |= DISASSEMBLY_RAW_INSN;
504 break;
505 case 'b':
506 modifiers |= DISASSEMBLY_RAW_BYTES;
507 break;
508 case 'f':
509 modifiers |= DISASSEMBLY_OMIT_FNAME;
510 break;
511 case 'p':
512 modifiers |= DISASSEMBLY_OMIT_PC;
513 break;
514 default:
515 error (_("Invalid modifier: %c."), *args);
519 args = skip_spaces (args);
522 /* Update the argument string. */
523 *arg = args;
525 return modifiers;
528 /* The "set record instruction-history-size / set record
529 function-call-history-size" commands are unsigned, with UINT_MAX
530 meaning unlimited. The target interfaces works with signed int
531 though, to indicate direction, so map "unlimited" to INT_MAX, which
532 is about the same as unlimited in practice. If the user does have
533 a log that huge, she can fetch it in chunks across several requests,
534 but she'll likely have other problems first... */
536 static int
537 command_size_to_target_size (unsigned int size)
539 gdb_assert (size <= INT_MAX || size == UINT_MAX);
541 if (size == UINT_MAX)
542 return INT_MAX;
543 else
544 return size;
547 /* The "record instruction-history" command. */
549 static void
550 cmd_record_insn_history (const char *arg, int from_tty)
552 require_record_target ();
554 gdb_disassembly_flags flags = get_insn_history_modifiers (&arg);
556 int size = command_size_to_target_size (record_insn_history_size);
558 if (arg == NULL || *arg == 0 || strcmp (arg, "+") == 0)
559 target_insn_history (size, flags);
560 else if (strcmp (arg, "-") == 0)
561 target_insn_history (-size, flags);
562 else
564 ULONGEST begin, end;
566 begin = get_insn_number (&arg);
568 if (*arg == ',')
570 arg = skip_spaces (++arg);
572 if (*arg == '+')
574 arg += 1;
575 size = get_context_size (&arg);
577 no_chunk (arg);
579 target_insn_history_from (begin, size, flags);
581 else if (*arg == '-')
583 arg += 1;
584 size = get_context_size (&arg);
586 no_chunk (arg);
588 target_insn_history_from (begin, -size, flags);
590 else
592 end = get_insn_number (&arg);
594 no_chunk (arg);
596 target_insn_history_range (begin, end, flags);
599 else
601 no_chunk (arg);
603 target_insn_history_from (begin, size, flags);
606 dont_repeat ();
610 /* Read function-call-history modifiers from an argument string. */
612 static record_print_flags
613 get_call_history_modifiers (const char **arg)
615 record_print_flags modifiers = 0;
616 const char *args = *arg;
618 if (args == NULL)
619 return modifiers;
621 while (*args == '/')
623 ++args;
625 if (*args == '\0')
626 error (_("Missing modifier."));
628 for (; *args; ++args)
630 if (isspace (*args))
631 break;
633 if (*args == '/')
634 continue;
636 switch (*args)
638 case 'l':
639 modifiers |= RECORD_PRINT_SRC_LINE;
640 break;
641 case 'i':
642 modifiers |= RECORD_PRINT_INSN_RANGE;
643 break;
644 case 'c':
645 modifiers |= RECORD_PRINT_INDENT_CALLS;
646 break;
647 case 'a':
648 modifiers |= RECORD_DONT_PRINT_AUX;
649 break;
650 default:
651 error (_("Invalid modifier: %c."), *args);
655 args = skip_spaces (args);
658 /* Update the argument string. */
659 *arg = args;
661 return modifiers;
664 /* The "record function-call-history" command. */
666 static void
667 cmd_record_call_history (const char *arg, int from_tty)
669 require_record_target ();
671 record_print_flags flags = get_call_history_modifiers (&arg);
673 int size = command_size_to_target_size (record_call_history_size);
675 if (arg == NULL || *arg == 0 || strcmp (arg, "+") == 0)
676 target_call_history (size, flags);
677 else if (strcmp (arg, "-") == 0)
678 target_call_history (-size, flags);
679 else
681 ULONGEST begin, end;
683 begin = get_insn_number (&arg);
685 if (*arg == ',')
687 arg = skip_spaces (++arg);
689 if (*arg == '+')
691 arg += 1;
692 size = get_context_size (&arg);
694 no_chunk (arg);
696 target_call_history_from (begin, size, flags);
698 else if (*arg == '-')
700 arg += 1;
701 size = get_context_size (&arg);
703 no_chunk (arg);
705 target_call_history_from (begin, -size, flags);
707 else
709 end = get_insn_number (&arg);
711 no_chunk (arg);
713 target_call_history_range (begin, end, flags);
716 else
718 no_chunk (arg);
720 target_call_history_from (begin, size, flags);
723 dont_repeat ();
727 /* Helper for "set record instruction-history-size" and "set record
728 function-call-history-size" input validation. COMMAND_VAR is the
729 variable registered in the command as control variable. *SETTING
730 is the real setting the command allows changing. */
732 static void
733 validate_history_size (unsigned int *command_var, unsigned int *setting)
735 if (*command_var != UINT_MAX && *command_var > INT_MAX)
737 unsigned int new_value = *command_var;
739 /* Restore previous value. */
740 *command_var = *setting;
741 error (_("integer %u out of range"), new_value);
744 /* Commit new value. */
745 *setting = *command_var;
748 /* Called by do_setshow_command. We only want values in the
749 [0..INT_MAX] range, while the command's machinery accepts
750 [0..UINT_MAX]. See command_size_to_target_size. */
752 static void
753 set_record_insn_history_size (const char *args, int from_tty,
754 struct cmd_list_element *c)
756 validate_history_size (&record_insn_history_size_setshow_var,
757 &record_insn_history_size);
760 /* Called by do_setshow_command. We only want values in the
761 [0..INT_MAX] range, while the command's machinery accepts
762 [0..UINT_MAX]. See command_size_to_target_size. */
764 static void
765 set_record_call_history_size (const char *args, int from_tty,
766 struct cmd_list_element *c)
768 validate_history_size (&record_call_history_size_setshow_var,
769 &record_call_history_size);
772 void _initialize_record ();
773 void
774 _initialize_record ()
776 struct cmd_list_element *c;
778 add_setshow_zuinteger_cmd ("record", no_class, &record_debug,
779 _("Set debugging of record/replay feature."),
780 _("Show debugging of record/replay feature."),
781 _("When enabled, debugging output for "
782 "record/replay feature is displayed."),
783 NULL, show_record_debug, &setdebuglist,
784 &showdebuglist);
786 add_setshow_uinteger_cmd ("instruction-history-size", no_class,
787 &record_insn_history_size_setshow_var, _("\
788 Set number of instructions to print in \"record instruction-history\"."), _("\
789 Show number of instructions to print in \"record instruction-history\"."), _("\
790 A size of \"unlimited\" means unlimited instructions. The default is 10."),
791 set_record_insn_history_size, NULL,
792 &set_record_cmdlist, &show_record_cmdlist);
794 add_setshow_uinteger_cmd ("function-call-history-size", no_class,
795 &record_call_history_size_setshow_var, _("\
796 Set number of function to print in \"record function-call-history\"."), _("\
797 Show number of functions to print in \"record function-call-history\"."), _("\
798 A size of \"unlimited\" means unlimited lines. The default is 10."),
799 set_record_call_history_size, NULL,
800 &set_record_cmdlist, &show_record_cmdlist);
802 cmd_list_element *record_cmd
803 = add_prefix_cmd ("record", class_obscure, cmd_record_start,
804 _("Start recording."),
805 &record_cmdlist, 0, &cmdlist);
806 add_com_alias ("rec", record_cmd, class_obscure, 1);
808 set_show_commands setshow_record_cmds
809 = add_setshow_prefix_cmd ("record", class_support,
810 _("Set record options."),
811 _("Show record options."),
812 &set_record_cmdlist, &show_record_cmdlist,
813 &setlist, &showlist);
816 add_alias_cmd ("rec", setshow_record_cmds.set, class_obscure, 1, &setlist);
817 add_alias_cmd ("rec", setshow_record_cmds.show, class_obscure, 1, &showlist);
819 cmd_list_element *info_record_cmd
820 = add_prefix_cmd ("record", class_support, info_record_command,
821 _("Info record options."), &info_record_cmdlist,
822 0, &infolist);
823 add_alias_cmd ("rec", info_record_cmd, class_obscure, 1, &infolist);
825 c = add_cmd ("save", class_obscure, cmd_record_save,
826 _("Save the execution log to a file.\n\
827 Usage: record save [FILENAME]\n\
828 Default filename is 'gdb_record.PROCESS_ID'."),
829 &record_cmdlist);
830 set_cmd_completer (c, deprecated_filename_completer);
832 cmd_list_element *record_delete_cmd
833 = add_cmd ("delete", class_obscure, cmd_record_delete,
834 _("Delete the rest of execution log and start recording it \
835 anew."),
836 &record_cmdlist);
837 add_alias_cmd ("d", record_delete_cmd, class_obscure, 1, &record_cmdlist);
838 add_alias_cmd ("del", record_delete_cmd, class_obscure, 1, &record_cmdlist);
840 cmd_list_element *record_stop_cmd
841 = add_cmd ("stop", class_obscure, cmd_record_stop,
842 _("Stop the record/replay target."),
843 &record_cmdlist);
844 add_alias_cmd ("s", record_stop_cmd, class_obscure, 1, &record_cmdlist);
846 add_prefix_cmd ("goto", class_obscure, cmd_record_goto, _("\
847 Restore the program to its state at instruction number N.\n\
848 Argument is instruction number, as shown by 'info record'."),
849 &record_goto_cmdlist, 1, &record_cmdlist);
851 cmd_list_element *record_goto_begin_cmd
852 = add_cmd ("begin", class_obscure, cmd_record_goto_begin,
853 _("Go to the beginning of the execution log."),
854 &record_goto_cmdlist);
855 add_alias_cmd ("start", record_goto_begin_cmd, class_obscure, 1,
856 &record_goto_cmdlist);
858 add_cmd ("end", class_obscure, cmd_record_goto_end,
859 _("Go to the end of the execution log."),
860 &record_goto_cmdlist);
862 add_cmd ("instruction-history", class_obscure, cmd_record_insn_history, _("\
863 Print disassembled instructions stored in the execution log.\n\
864 With a /m or /s modifier, source lines are included (if available).\n\
865 With a /r modifier, raw instructions in hex are included.\n\
866 With a /f modifier, function names are omitted.\n\
867 With a /p modifier, current position markers are omitted.\n\
868 With a /a modifier, omits output of auxiliary data, which is enabled\n\
869 by default.\n\
870 With no argument, disassembles ten more instructions after the previous\n\
871 disassembly.\n\
872 \"record instruction-history -\" disassembles ten instructions before a\n\
873 previous disassembly.\n\
874 One argument specifies an instruction number as shown by 'info record', and\n\
875 ten instructions are disassembled after that instruction.\n\
876 Two arguments with comma between them specify starting and ending instruction\n\
877 numbers to disassemble.\n\
878 If the second argument is preceded by '+' or '-', it specifies the distance\n\
879 from the first argument.\n\
880 The number of instructions to disassemble can be defined with\n\
881 \"set record instruction-history-size\"."),
882 &record_cmdlist);
884 add_cmd ("function-call-history", class_obscure, cmd_record_call_history, _("\
885 Prints the execution history at function granularity.\n\
886 It prints one line for each sequence of instructions that belong to the same\n\
887 function.\n\
888 Without modifiers, it prints the function name.\n\
889 With a /l modifier, the source file and line number range is included.\n\
890 With a /i modifier, the instruction number range is included.\n\
891 With a /c modifier, the output is indented based on the call stack depth.\n\
892 With a /a modifier, omits output of auxiliary data, which is enabled \
893 by default.\n\
894 With no argument, prints ten more lines after the previous ten-line print.\n\
895 \"record function-call-history -\" prints ten lines before a previous ten-line\n\
896 print.\n\
897 One argument specifies a function number as shown by 'info record', and\n\
898 ten lines are printed after that function.\n\
899 Two arguments with comma between them specify a range of functions to print.\n\
900 If the second argument is preceded by '+' or '-', it specifies the distance\n\
901 from the first argument.\n\
902 The number of functions to print can be defined with\n\
903 \"set record function-call-history-size\"."),
904 &record_cmdlist);
906 /* Sync command control variables. */
907 record_insn_history_size_setshow_var = record_insn_history_size;
908 record_call_history_size_setshow_var = record_call_history_size;