* 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-05-02 Michael Snyder <msnyder@redhat.com>
+
+ * 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 <kettenis@gnu.org>
* breakpoint.c (insert_single_step_breakpoint): Make a failure to
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);
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);
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. */
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",
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:
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)
{
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;
}
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
return saved_async_masked_status;
}
+/* 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. */
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
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
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?
*/
#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.