diff options
author | Michael Snyder <msnyder@specifix.com> | 2009-07-26 23:15:06 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@specifix.com> | 2009-07-26 23:15:06 +0000 |
commit | fba04a7abcc21476949b411e0e3d138595e32ecc (patch) | |
tree | 5e5973f075a0dca27ca49a87856a29e69625ab80 | |
parent | 2c5ca3379c26bc2ec115b566bb380b172f7e046f (diff) | |
download | gdb-fba04a7abcc21476949b411e0e3d138595e32ecc.tar.gz |
2009-07-26 Michael Snyder <msnyder@vmware.com>
In-flux state: target methods temporarily broken.
* checkpoint.c (checkpoint_insert): New function.
(checkpint_first): New function.
(checkpoint_next): New function.
(checkpoint_unlink): New function.
(checkpoint_find_id): New function.
(checkpoint_command): Manage list locally.
(delete_checkpoint_command): Ditto.
(info_checkpoints_command): Ditto.
(restart_command): Ditto
* checkpoint.h (checkpoint_insert, checkpoint_first,
checkpoint_next, checkpoint_unlink, checkpoint_find_id): Export.
* record.c (record_insert_checkpoint): New function.
(record_delete_checkpoint): New function.
(record_show_checkpoint_info): New function.
(record_goto_checkpoint): New function.
(record_restore_checkpoint): New function.
-rw-r--r-- | gdb/ChangeLog | 23 | ||||
-rw-r--r-- | gdb/checkpoint.c | 189 | ||||
-rw-r--r-- | gdb/checkpoint.h | 27 | ||||
-rw-r--r-- | gdb/record.c | 160 |
4 files changed, 395 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8b4a67bb44e..82093e63b30 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2009-07-26 Michael Snyder <msnyder@vmware.com> + + In-flux state: target methods temporarily broken. + + * checkpoint.c (checkpoint_insert): New function. + (checkpint_first): New function. + (checkpoint_next): New function. + (checkpoint_unlink): New function. + (checkpoint_find_id): New function. + (checkpoint_command): Manage list locally. + (delete_checkpoint_command): Ditto. + (info_checkpoints_command): Ditto. + (restart_command): Ditto + + * checkpoint.h (checkpoint_insert, checkpoint_first, + checkpoint_next, checkpoint_unlink, checkpoint_find_id): Export. + + * record.c (record_insert_checkpoint): New function. + (record_delete_checkpoint): New function. + (record_show_checkpoint_info): New function. + (record_goto_checkpoint): New function. + (record_restore_checkpoint): New function. + 2009-07-25 Michael Snyder <msnyder@vmware.com> * inf-child.c (inf_child_target): Initialize target_ops only once. diff --git a/gdb/checkpoint.c b/gdb/checkpoint.c index 96cce985fd6..f6f974ff14e 100644 --- a/gdb/checkpoint.c +++ b/gdb/checkpoint.c @@ -17,16 +17,103 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* XXX mvs put the actual commands here, and add them to gdb's - command lists only by request. - - TBD: actually manage the list here? +/* TBD: actually manage the list here? How would that interplay with forks as written now? */ #include "defs.h" #include "target.h" #include "gdbcmd.h" +#include "checkpoint.h" +#include "value.h" +#include "regcache.h" +#include "inferior.h" + +/* + * Checkpoint list management (exported). + */ + +static struct checkpoint_info *checkpoint_list, *checkpoint_iterator; +static int checkpoint_count; + +struct checkpoint_info * +checkpoint_insert (void *client_data) +{ + struct checkpoint_info *cp = XZALLOC (struct checkpoint_info); + + cp->checkpoint_id = ++checkpoint_count; + cp->client_data = client_data; + cp->next = checkpoint_list; + checkpoint_list = cp; + return cp; +} + +struct checkpoint_info * +checkpoint_first (void) +{ + if (checkpoint_list == NULL) + return NULL; + else + { + checkpoint_iterator = checkpoint_list; + return checkpoint_iterator; + } +} + +struct checkpoint_info * +checkpoint_next (void) +{ + if (checkpoint_iterator == NULL) + return NULL; + else if (checkpoint_iterator->next == NULL) + return NULL; + else + { + checkpoint_iterator = checkpoint_iterator->next; + return checkpoint_iterator; + } +} + +void +checkpoint_unlink (struct checkpoint_info *cp) +{ + if (cp == checkpoint_list) + checkpoint_list = cp->next; + else + { + struct checkpoint_info *prev; + + for (prev = checkpoint_first (); prev != NULL; + prev = checkpoint_next ()) + if (prev->next == cp) + break; + + if (prev == NULL) + internal_error (__FILE__, __LINE__, + _("checkpoint is not linked!")); + + prev->next = cp->next; + } + xfree (cp); +} + +struct checkpoint_info * +checkpoint_find_id (int id) +{ + struct checkpoint_info *cp; + + for (cp = checkpoint_first (); cp != NULL; cp = checkpoint_next ()) + if (cp->checkpoint_id == id) + return cp; + + return NULL; +} + +/* + * Checkpoint commands (private). + */ + +#if 0 /* First cut */ /* Set a checkpoint (call target_ops method). */ @@ -70,6 +157,100 @@ info_checkpoints_command (char *args, int from_tty) error (_("info checkpoints command not implemented for this target.")); } +#else +/* FIXME replace by target method. */ +extern void *record_insert_checkpoint (struct checkpoint_info *, int); +extern void record_delete_checkpoint (struct checkpoint_info *, int); +extern void record_show_checkpoint_info (struct checkpoint_info *, int); +extern void record_restore_checkpoint (struct checkpoint_info *, int); + + +static void +checkpoint_command (char *args, int from_tty) +{ + struct checkpoint_info *cp = checkpoint_insert (NULL); + + if (cp != NULL) + { + if (from_tty) + printf_filtered (_("Adding checkpoint #%d"), cp->checkpoint_id); + /* FIXME: here's the target method. */ + cp->client_data = record_insert_checkpoint (cp, from_tty); + if (from_tty) + puts_filtered (_("\n")); + } + else + error (_("insert checkpoint failed")); +} + +static void +delete_checkpoint_command (char *args, int from_tty) +{ + struct checkpoint_info *cp; + + if (!args || !*args) + error (_("Requires argument (checkpoint id to delete)")); + + /* FIXME: only accepts one argument, see breakpoint. */ + cp = checkpoint_find_id (parse_and_eval_long (args)); + if (cp == NULL) + error (_("Not found: checkpoint id %s"), args); + + /* FIXME: here's the target method. */ + record_delete_checkpoint (cp, from_tty); + checkpoint_unlink (cp); +} + +static void +info_checkpoints_command (char *args, int from_tty) +{ + struct checkpoint_info *cp = checkpoint_first (); + int requested = -1; + + if (cp == NULL) + { + printf_filtered ("No checkpoints.\n"); + return; + } + + if (args && *args) + requested = (int) parse_and_eval_long (args); + + do + { + /* Fixme: here's the target method. */ + if (requested == -1 || requested == cp->checkpoint_id) + record_show_checkpoint_info (cp, from_tty); + cp = checkpoint_next (); + } while (cp != NULL); +} + +static void +restart_command (char *args, int from_tty) +{ + extern void nullify_last_target_wait_ptid (); + struct checkpoint_info *cp; + + if (!args || !*args) + error (_("Requres argument (checkpoint id to restart)")); + + cp = checkpoint_find_id (parse_and_eval_long (args)); + if (cp == NULL) + error (_("Not found: checkpoint id %s"), args); + + /* FIXME: here's the target method. */ + record_restore_checkpoint (cp, from_tty); + + registers_changed (); + reinit_frame_cache (); + stop_pc = regcache_read_pc (get_current_regcache ()); + nullify_last_target_wait_ptid (); + if (from_tty) + print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); +} + +#endif + /* Initializer function checkpoint_init(). Note -- not called in the usual gdb module-initializer manner, diff --git a/gdb/checkpoint.h b/gdb/checkpoint.h index 7b994755662..7df7a48e618 100644 --- a/gdb/checkpoint.h +++ b/gdb/checkpoint.h @@ -20,6 +20,33 @@ #if !defined (CHECKPOINT_H) #define CHECKPOINT_H 1 +/* + * The data structure for the checkpoint list. + */ +struct checkpoint_info +{ + int checkpoint_id; + void *client_data; + struct checkpoint_info *next; +}; + +/* + * Public functions for managing the checkpoint list. + */ + +/* Insert a checkpoint into the list. */ +extern struct checkpoint_info *checkpoint_insert (void *client_data); + +/* Unlink a checkpoint from the list. */ +extern void checkpoint_unlink (struct checkpoint_info *cp); + +/* Find a checkpoint (by id) in the list. */ +extern struct checkpoint_info *checkpoint_find_id (int id); + +/* Traverse the checkpoint list. */ +extern struct checkpoint_info *checkpoint_first (void); +extern struct checkpoint_info *checkpoint_next (void); + extern void checkpoint_init (void); #endif /* CHECKPOINT_H */ diff --git a/gdb/record.c b/gdb/record.c index 85e75a09ca2..49adb5df7d7 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -24,6 +24,7 @@ #include "event-top.h" #include "exceptions.h" #include "record.h" +#include "checkpoint.h" #include <signal.h> @@ -1214,6 +1215,165 @@ info_record_command (char *args, int from_tty) cmd_show_list (info_record_cmdlist, from_tty, ""); } +/* + * Process Record checkpoint stuff + */ + +struct record_checkpoint_info +{ + struct record_entry *position; /* pointer into the record log */ + int insn_num; /* numbered position in log */ + CORE_ADDR pc; /* program counter of checkpoint */ +}; + +void * +record_insert_checkpoint (struct checkpoint_info *cp, int from_tty) +{ + struct record_checkpoint_info *rp; + rp = XZALLOC (struct record_checkpoint_info); + rp->position = record_list; + rp->insn_num = record_insn_num; + rp->pc = stop_pc; /* FIXME: should I use this? */ + if (from_tty && info_verbose) + { + printf_filtered (_(" at pos 0x%08x, count 0x%08x, pc 0x%08x"), + (unsigned int) rp->position, + (unsigned int) rp->insn_num, + (unsigned int) rp->pc); + } + return rp; +} + +void +record_delete_checkpoint (struct checkpoint_info *cp, int from_tty) +{ + xfree (cp->client_data); +} + +void +record_show_checkpoint_info (struct checkpoint_info *cp, int from_tty) +{ + struct record_checkpoint_info *re = cp->client_data; + + printf_filtered (_("\ +Checkpoint #%d at pos 0x%08x, count 0x%08x, pc 0x%08x\n"), + cp->checkpoint_id, + (unsigned int) re->position, + (unsigned int) re->insn_num, + (unsigned int) re->pc); +} + +static void +record_goto_checkpoint (struct record_entry *checkpoint, + 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 checkpoint, + and we will not hit the end of the recording. */ + + if (dir == EXEC_FORWARD) + record_list = record_list->next; + + do + { + /* Set ptid, register and memory according to record_list. */ + if (record_list->type == record_reg) + { + /* reg */ + gdb_byte reg[MAX_REGISTER_SIZE]; + if (record_debug > 1) + fprintf_unfiltered (gdb_stdlog, + "Process record: record_reg %s to " + "inferior num = %d.\n", + host_address_to_string (record_list), + record_list->u.reg.num); + regcache_cooked_read (regcache, record_list->u.reg.num, reg); + regcache_cooked_write (regcache, record_list->u.reg.num, + record_list->u.reg.val); + memcpy (record_list->u.reg.val, reg, MAX_REGISTER_SIZE); + } + else if (record_list->type == record_mem) + { + /* mem */ + gdb_byte *mem = alloca (record_list->u.mem.len); + if (record_debug > 1) + fprintf_unfiltered (gdb_stdlog, + "Process record: record_mem %s to " + "inferior addr = %s len = %d.\n", + host_address_to_string (record_list), + paddress (gdbarch, record_list->u.mem.addr), + record_list->u.mem.len); + + if (target_read_memory (record_list->u.mem.addr, + mem, record_list->u.mem.len)) + error (_("Process record: error reading memory at " + "addr = %s len = %d."), + paddress (gdbarch, record_list->u.mem.addr), + record_list->u.mem.len); + + if (target_write_memory (record_list->u.mem.addr, + record_list->u.mem.val, + record_list->u.mem.len)) + error (_("Process record: error writing memory at " + "addr = %s len = %d."), + paddress (gdbarch, record_list->u.mem.addr), + record_list->u.mem.len); + + memcpy (record_list->u.mem.val, mem, record_list->u.mem.len); + } + + if (dir == EXEC_REVERSE) + record_list = record_list->prev; + else + record_list = record_list->next; + } while (record_list != checkpoint); + do_cleanups (set_cleanups); +} + +void +record_restore_checkpoint (struct checkpoint_info *cp, int from_tty) +{ + int i = 0, checkpoint_index = 0, current_index = 0; + struct record_entry *p; + struct record_checkpoint_info *rp; + + rp = cp->client_data; + for (p = &record_first; p != NULL; p = p->next) + { + if (p == rp->position) + checkpoint_index = i; + if (p == record_list) + current_index = i; + i++; + } + if (from_tty && info_verbose) + { + printf_filtered ("Checkpoint is at index %d\n", checkpoint_index); + printf_filtered ("Cur point is at index %d\n", current_index); + printf_filtered ("Counted %d (officially %d)\n", i-1, record_insn_num); + } + + if (checkpoint_index == 0) + error (_("Checkpoint index not found.\n")); + else if (current_index == checkpoint_index) + error (_("Already at checkpoint.\n")); + else if (current_index > checkpoint_index) + { + if (from_tty) + printf_filtered ("Go backward to checkpoint.\n"); + record_goto_checkpoint (rp->position, EXEC_REVERSE); + } + else + { + if (from_tty) + printf_filtered ("Go forward to checkpoint.\n"); + record_goto_checkpoint (rp->position, EXEC_FORWARD); + } +} + void _initialize_record (void) { |