diff --git a/gdb/record-full.c b/gdb/record-full.c index 3b49296..32c6558 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -1959,167 +1959,6 @@ record_execution_direction (void) return record_execution_dir; } -/* The "to_info_record" method. */ - -static void record_info (char *args, int from_tty) -{ - struct record_entry *p; - - if (current_target.to_stratum == record_stratum) - { - if (RECORD_IS_REPLAY) - printf_filtered (_("Replay mode:\n")); - else - printf_filtered (_("Record mode:\n")); - - /* Find entry for first actual instruction in the log. */ - for (p = record_first.next; - p != NULL && p->type != record_end; - p = p->next) - ; - - /* Do we have a log at all? */ - if (p != NULL && p->type == record_end) - { - /* Display instruction number for first instruction in the log. */ - printf_filtered (_("Lowest recorded instruction number is %s.\n"), - pulongest (p->u.end.insn_num)); - - /* If in replay mode, display where we are in the log. */ - if (RECORD_IS_REPLAY) - printf_filtered (_("Current instruction number is %s.\n"), - pulongest (record_list->u.end.insn_num)); - - /* Display instruction number for last instruction in the log. */ - printf_filtered (_("Highest recorded instruction number is %s.\n"), - pulongest (record_insn_count)); - - /* Display log count. */ - printf_filtered (_("Log contains %d instructions.\n"), - record_insn_num); - } - else - { - printf_filtered (_("No instructions have been logged.\n")); - } - } - else - { - printf_filtered (_("target record is not active.\n")); - } - - /* Display max log size. */ - printf_filtered (_("Max logged instructions is %d.\n"), - record_insn_max_num); -} - -/* record_goto_insn -- rewind the record log (forward or backward, - depending on DIR) to the given entry, changing the program state - correspondingly. */ - -static void -record_goto_insn (struct record_entry *entry, - enum exec_direction_kind dir) -{ - struct cleanup *set_cleanups = record_gdb_operation_disable_set (); - struct regcache *regcache = get_current_regcache (); - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - /* Assume everything is valid: we will hit the entry, - and we will not hit the end of the recording. */ - - if (dir == EXEC_FORWARD) - record_list = record_list->next; - - do - { - record_exec_insn (regcache, gdbarch, record_list); - if (dir == EXEC_REVERSE) - record_list = record_list->prev; - else - record_list = record_list->next; - } while (record_list != entry); - do_cleanups (set_cleanups); -} - -/* The "to_goto_record" method. */ - -static void record_goto (char *arg, int from_tty) -{ - struct record_entry *p = NULL; - ULONGEST target_insn = 0; - - if (arg == NULL || *arg == '\0') - error (_("Command requires an argument (insn number to go to).")); - - if (strncmp (arg, "start", strlen ("start")) == 0 - || strncmp (arg, "begin", strlen ("begin")) == 0) - { - /* Special case. Find first insn. */ - for (p = &record_first; p != NULL; p = p->next) - if (p->type == record_end) - break; - if (p) - target_insn = p->u.end.insn_num; - } - else if (strncmp (arg, "end", strlen ("end")) == 0) - { - /* Special case. Find last insn. */ - for (p = record_list; p->next != NULL; p = p->next) - ; - for (; p!= NULL; p = p->prev) - if (p->type == record_end) - break; - if (p) - target_insn = p->u.end.insn_num; - } - else - { - /* General case. Find designated insn. */ - target_insn = parse_and_eval_long (arg); - - for (p = &record_first; p != NULL; p = p->next) - if (p->type == record_end && p->u.end.insn_num == target_insn) - break; - } - - if (p == NULL) - error (_("Target insn '%s' not found."), arg); - else if (p == record_list) - error (_("Already at insn '%s'."), arg); - else if (p->u.end.insn_num > record_list->u.end.insn_num) - { - printf_filtered (_("Go forward to insn number %s\n"), - pulongest (target_insn)); - record_goto_insn (p, EXEC_FORWARD); - } - else - { - printf_filtered (_("Go backward to insn number %s\n"), - pulongest (target_insn)); - record_goto_insn (p, EXEC_REVERSE); - } - registers_changed (); - reinit_frame_cache (); - print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); -} - -/* The "to_delete_record" method of target record-full. */ - -static void -record_delete (char *args, int from_tty) -{ - if (RECORD_IS_REPLAY) - { - if (!from_tty || query (_("Delete the log from this point forward " - "and begin to record the running message " - "at current PC?"))) - record_list_release_following (record_list); - } - else - printf_unfiltered (_("Already at end of record list.\n")); -} - static void init_record_ops (void) { @@ -2387,6 +2226,33 @@ init_record_core_ops (void) record_core_ops.to_magic = OPS_MAGIC; } +/* Alias for "target record". */ + +static void +cmd_record_start (char *args, int from_tty) +{ + if (args != NULL && *args != 0) + error (_("Invalid argument.")); + + execute_command ("target record-full", from_tty); +} + +/* The "to_delete_record" method of target record-full. */ + +static void +record_delete (char *args, int from_tty) +{ + if (RECORD_IS_REPLAY) + { + if (!from_tty || query (_("Delete the log from this point forward " + "and begin to record the running message " + "at current PC?"))) + record_list_release_following (record_list); + } + else + printf_unfiltered (_("Already at end of record list.\n")); +} + /* Set upper limit of record log size. */ static void @@ -2403,6 +2269,60 @@ set_record_insn_max_num (char *args, int from_tty, struct cmd_list_element *c) } } +/* The "to_info_record" method. */ + +static void record_info (char *args, int from_tty) +{ + struct record_entry *p; + + if (current_target.to_stratum == record_stratum) + { + if (RECORD_IS_REPLAY) + printf_filtered (_("Replay mode:\n")); + else + printf_filtered (_("Record mode:\n")); + + /* Find entry for first actual instruction in the log. */ + for (p = record_first.next; + p != NULL && p->type != record_end; + p = p->next) + ; + + /* Do we have a log at all? */ + if (p != NULL && p->type == record_end) + { + /* Display instruction number for first instruction in the log. */ + printf_filtered (_("Lowest recorded instruction number is %s.\n"), + pulongest (p->u.end.insn_num)); + + /* If in replay mode, display where we are in the log. */ + if (RECORD_IS_REPLAY) + printf_filtered (_("Current instruction number is %s.\n"), + pulongest (record_list->u.end.insn_num)); + + /* Display instruction number for last instruction in the log. */ + printf_filtered (_("Highest recorded instruction number is %s.\n"), + pulongest (record_insn_count)); + + /* Display log count. */ + printf_filtered (_("Log contains %d instructions.\n"), + record_insn_num); + } + else + { + printf_filtered (_("No instructions have been logged.\n")); + } + } + else + { + printf_filtered (_("target record is not active.\n")); + } + + /* Display max log size. */ + printf_filtered (_("Max logged instructions is %d.\n"), + record_insn_max_num); +} + /* Record log save-file format Version 1 (never released) @@ -2664,27 +2584,6 @@ record_restore (void) print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); } -/* Restore the execution log from a file. We use a modified elf - corefile format, with an extra section for our data. */ - -static void -cmd_record_restore (char *args, int from_tty) -{ - core_file_command (args, from_tty); - record_open (args, from_tty); -} - -/* Alias for "target record". */ - -static void -cmd_record_start (char *args, int from_tty) -{ - if (args != NULL && *args != 0) - error (_("Invalid argument.")); - - execute_command ("target record-full", from_tty); -} - /* bfdcore_write -- write bytes into a core file section. */ static inline void @@ -2700,6 +2599,16 @@ bfdcore_write (bfd *obfd, asection *osec, void *buf, int len, int *offset) bfd_errmsg (bfd_get_error ())); } +/* Restore the execution log from a file. We use a modified elf + corefile format, with an extra section for our data. */ + +static void +cmd_record_restore (char *args, int from_tty) +{ + core_file_command (args, from_tty); + record_open (args, from_tty); +} + static void record_save_cleanups (void *data) { @@ -2915,6 +2824,97 @@ record_save (char *recfilename, int from_tty) recfilename); } +/* record_goto_insn -- rewind the record log (forward or backward, + depending on DIR) to the given entry, changing the program state + correspondingly. */ + +static void +record_goto_insn (struct record_entry *entry, + enum exec_direction_kind dir) +{ + struct cleanup *set_cleanups = record_gdb_operation_disable_set (); + struct regcache *regcache = get_current_regcache (); + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + /* Assume everything is valid: we will hit the entry, + and we will not hit the end of the recording. */ + + if (dir == EXEC_FORWARD) + record_list = record_list->next; + + do + { + record_exec_insn (regcache, gdbarch, record_list); + if (dir == EXEC_REVERSE) + record_list = record_list->prev; + else + record_list = record_list->next; + } while (record_list != entry); + do_cleanups (set_cleanups); +} + +/* The "to_goto_record" method. */ + +static void record_goto (char *arg, int from_tty) +{ + struct record_entry *p = NULL; + ULONGEST target_insn = 0; + + if (arg == NULL || *arg == '\0') + error (_("Command requires an argument (insn number to go to).")); + + if (strncmp (arg, "start", strlen ("start")) == 0 + || strncmp (arg, "begin", strlen ("begin")) == 0) + { + /* Special case. Find first insn. */ + for (p = &record_first; p != NULL; p = p->next) + if (p->type == record_end) + break; + if (p) + target_insn = p->u.end.insn_num; + } + else if (strncmp (arg, "end", strlen ("end")) == 0) + { + /* Special case. Find last insn. */ + for (p = record_list; p->next != NULL; p = p->next) + ; + for (; p!= NULL; p = p->prev) + if (p->type == record_end) + break; + if (p) + target_insn = p->u.end.insn_num; + } + else + { + /* General case. Find designated insn. */ + target_insn = parse_and_eval_long (arg); + + for (p = &record_first; p != NULL; p = p->next) + if (p->type == record_end && p->u.end.insn_num == target_insn) + break; + } + + if (p == NULL) + error (_("Target insn '%s' not found."), arg); + else if (p == record_list) + error (_("Already at insn '%s'."), arg); + else if (p->u.end.insn_num > record_list->u.end.insn_num) + { + printf_filtered (_("Go forward to insn number %s\n"), + pulongest (target_insn)); + record_goto_insn (p, EXEC_FORWARD); + } + else + { + printf_filtered (_("Go backward to insn number %s\n"), + pulongest (target_insn)); + record_goto_insn (p, EXEC_REVERSE); + } + registers_changed (); + reinit_frame_cache (); + print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); +} + /* The "set record full" command. */ static void