From 4540c267a37186fb669d7044cee438a62fbb651c Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Wed, 3 May 2006 00:27:27 +0000 Subject: 2006-05-02 Michael Snyder * Target interface for reverse execution. * target.h (enum target_waitkind): Add new wait event, TARGET_WAITKIND_NO_HISTORY. (enum exec_direction_kind): New enum. (struct target_ops): New methods to_set_execdir, to_get_execdir. * target.c (target_get_execdir): New generic method. (target_set_execdir): Ditto. * remote.c (remote_get_execdir, remote_set_execdir): New methods. (remote_vcont_resume): Jump out if attempting reverse execution. (remote_resume): Check for reverse exec direction, and send appropriate command to target. (remote_wait): Check target response for NO_HISTORY status. Also check for empty reply (target doesn't understand "bs" or "bc). (_initialize_remote): Add new methods to remote target vector. --- gdb/ChangeLog | 17 +++++++++++++++ gdb/remote.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- gdb/target.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ gdb/target.h | 25 ++++++++++++++++++++- 4 files changed, 163 insertions(+), 6 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b2dd5f4..81fa9f7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2006-05-02 Michael Snyder + + * Target interface for reverse execution. + * target.h (enum target_waitkind): + Add new wait event, TARGET_WAITKIND_NO_HISTORY. + (enum exec_direction_kind): New enum. + (struct target_ops): New methods to_set_execdir, to_get_execdir. + * target.c (target_get_execdir): New generic method. + (target_set_execdir): Ditto. + * remote.c (remote_get_execdir, remote_set_execdir): New methods. + (remote_vcont_resume): Jump out if attempting reverse execution. + (remote_resume): Check for reverse exec direction, and send + appropriate command to target. + (remote_wait): Check target response for NO_HISTORY status. + Also check for empty reply (target doesn't understand "bs" or "bc). + (_initialize_remote): Add new methods to remote target vector. + 2006-04-30 Mark Kettenis * breakpoint.c (insert_single_step_breakpoint): Make a failure to diff --git a/gdb/remote.c b/gdb/remote.c index d1ffdb5..5c78747 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -2327,6 +2327,10 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) char *buf = NULL, *outbuf; struct cleanup *old_cleanup; + /* vCont does not currently support reverse execution. */ + if (target_get_execdir () == EXEC_REVERSE) + return 0; + if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN) remote_vcont_probe (rs); @@ -2419,7 +2423,15 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal) else set_thread (pid, 0); /* Run this thread. */ - if (siggnal != TARGET_SIGNAL_0) + if (target_get_execdir () == EXEC_REVERSE) + { + /* We don't pass signals to the target in reverse exec mode. */ + if (info_verbose && siggnal != TARGET_SIGNAL_0) + warning (_(" - Can't pass signal %d to target in reverse: ignored.\n"), + siggnal); + strcpy (buf, step ? "bs" : "bc"); + } + else if (siggnal != TARGET_SIGNAL_0) { buf[0] = step ? 'S' : 'C'; buf[1] = tohex (((int) siggnal >> 4) & 0xf); @@ -2693,6 +2705,12 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) switch (buf[0]) { case 'E': /* Error of some sort. */ + if (buf[1] == '0' && buf[2] == '6' + && target_get_execdir () == EXEC_REVERSE) + { + status->kind = TARGET_WAITKIND_NO_HISTORY; + goto got_status; + } warning (_("Remote failure reply: %s"), buf); continue; case 'F': /* File-I/O request. */ @@ -2823,10 +2841,10 @@ Packet: '%s'\n"), remote_console_output (buf + 1); continue; case '\0': + /* Zero length reply may mean that we tried 'S' or 'C' and + the remote system doesn't support it. */ if (last_sent_signal != TARGET_SIGNAL_0) { - /* Zero length reply means that we tried 'S' or 'C' and - the remote system doesn't support it. */ target_terminal_ours_for_output (); printf_filtered ("Can't send signals to this remote system. %s not sent.\n", @@ -2838,10 +2856,16 @@ Packet: '%s'\n"), putpkt ((char *) buf); continue; } + /* Or, it may mean that we tried "bs" or "bc" and + the remote system doesn't support that. */ + else if (target_get_execdir () == EXEC_REVERSE) + { + error (_("Target does not support reverse execution.")); + } /* else fallthrough */ default: - warning (_("Invalid remote reply: %s"), buf); - continue; + error (_("Invalid remote reply: %s"), buf); + break; /* Lint. */ } } got_status: @@ -5218,6 +5242,40 @@ remote_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) return 0; } +/* Reverse execution. + FIXME: set up as a capability. */ +static enum exec_direction_kind remote_execdir = EXEC_FORWARD; + +static enum exec_direction_kind +remote_get_execdir (void) +{ + if (remote_debug && info_verbose) + printf_filtered ("remote execdir is %s\n", + remote_execdir == EXEC_FORWARD ? "forward" : + remote_execdir == EXEC_REVERSE ? "reverse" : + "unknown"); + return remote_execdir; +} + +static enum exec_direction_kind +remote_set_execdir (enum exec_direction_kind dir) +{ + if (remote_debug && info_verbose) + printf_filtered ("Set remote execdir: %s\n", + dir == EXEC_FORWARD ? "forward" : + dir == EXEC_REVERSE ? "reverse" : + "bad direction"); + + /* FIXME: check target for capability. */ + if (dir == EXEC_FORWARD || dir == EXEC_REVERSE) + { + remote_execdir = dir; + return dir; + } + else + return EXEC_ERROR; +} + static void init_remote_ops (void) { @@ -5265,6 +5323,8 @@ Specify the serial device it is connected to\n\ remote_ops.to_has_registers = 1; remote_ops.to_has_execution = 1; remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ + remote_ops.to_get_execdir = remote_get_execdir; + remote_ops.to_set_execdir = remote_set_execdir; remote_ops.to_magic = OPS_MAGIC; } diff --git a/gdb/target.c b/gdb/target.c index 52e4527..c837609 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -457,6 +457,8 @@ update_current_target (void) INHERIT (to_find_memory_regions, t); INHERIT (to_make_corefile_notes, t); INHERIT (to_get_thread_local_address, t); + /* Do not inherit to_get_execdir. */ + /* Do not inherit to_set_execdir. */ INHERIT (to_magic, t); } #undef INHERIT @@ -1502,6 +1504,61 @@ target_async_mask (int mask) } /* Look through the list of possible targets for a target that can + support reverse execution. */ + +enum exec_direction_kind +target_get_execdir (void) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_get_execdir != NULL) + { + enum exec_direction_kind retval = t->to_get_execdir (); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "%s->to_get_execdir () = %s\n", + t->to_shortname, + retval == EXEC_FORWARD ? "Forward" : + retval == EXEC_REVERSE ? "Reverse" : + retval == EXEC_ERROR ? "Error" : + "*unknown*"); + return retval; + } + } + + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_get_execdir: unsupported\n"); + return EXEC_ERROR; +} + +enum exec_direction_kind +target_set_execdir (enum exec_direction_kind setdir) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_set_execdir != NULL) + { + enum exec_direction_kind retval = t->to_set_execdir (setdir); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "%s->to_set_execdir () = %s\n", + t->to_shortname, + retval == EXEC_FORWARD ? "Forward" : + retval == EXEC_REVERSE ? "Reverse" : + retval == EXEC_ERROR ? "Error" : + "*unknown*"); + return retval; + } + } + + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_set_execdir: unsupported\n"); + return EXEC_ERROR; +} + +/* Look through the list of possible targets for a target that can follow forks. */ int diff --git a/gdb/target.h b/gdb/target.h index 7decfd7..8a9f7fe 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -130,7 +130,11 @@ enum target_waitkind inferior, rather than being stuck in the remote_async_wait() function. This way the event loop is responsive to other events, like for instance the user typing. */ - TARGET_WAITKIND_IGNORE + TARGET_WAITKIND_IGNORE, + + /* The target has run out of history information, + and cannot run backward any further. */ + TARGET_WAITKIND_NO_HISTORY }; struct target_waitstatus @@ -149,6 +153,14 @@ struct target_waitstatus value; }; +/* Reverse execution. */ +enum exec_direction_kind + { + EXEC_FORWARD, + EXEC_REVERSE, + EXEC_ERROR + }; + /* Possible types of events that the inferior handler will have to deal with. */ enum inferior_event_type @@ -424,6 +436,11 @@ struct target_ops gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len); + /* Set execution direction (forward/reverse). */ + enum exec_direction_kind (*to_set_execdir) (enum exec_direction_kind); + /* Get execution direction (forward/reverse). */ + enum exec_direction_kind (*to_get_execdir) (void); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -1070,6 +1087,12 @@ extern int target_stopped_data_address_p (struct target_ops *); #define target_stopped_data_address_p(CURRENT_TARGET) (1) #endif +/* Forward/reverse execution direction. These will only be + implemented by a target that supports reverse execution. */ + +extern enum exec_direction_kind target_get_execdir (void); +extern enum exec_direction_kind target_set_execdir (enum exec_direction_kind); + /* This will only be defined by a target that supports catching vfork events, such as HP-UX. -- cgit v1.1