This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] Reverse debugging, part 1 rev. 2
- From: Michael Snyder <msnyder at redhat dot com>
- To: GDB Patches <gdb-patches at sources dot redhat dot com>, drow at false dot org
- Date: Fri, 28 Apr 2006 18:00:10 -0700
- Subject: [RFA] Reverse debugging, part 1 rev. 2
A revised patch, implementing earlier suggestions.
Still haven't added a probe, but I thought I'd seek comments anyway.
2006-03-31 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.
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.82
diff -p -r1.82 target.h
*** target.h 18 Apr 2006 19:20:06 -0000 1.82
--- target.h 29 Apr 2006 00:52:37 -0000
*************** enum target_waitkind
*** 130,136 ****
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
};
struct target_waitstatus
--- 130,140 ----
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,
!
! /* The target has run out of history information,
! and cannot run backward any further. */
! TARGET_WAITKIND_NO_HISTORY
};
struct target_waitstatus
*************** struct target_waitstatus
*** 149,154 ****
--- 153,166 ----
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
*************** struct target_ops
*** 424,429 ****
--- 436,446 ----
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?
*/
*************** extern int target_stopped_data_address_p
*** 1070,1075 ****
--- 1087,1098 ----
#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.
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.118
diff -p -r1.118 target.c
*** target.c 18 Apr 2006 19:20:06 -0000 1.118
--- target.c 29 Apr 2006 00:52:37 -0000
*************** update_current_target (void)
*** 457,462 ****
--- 457,464 ----
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
*************** target_async_mask (int mask)
*** 1502,1507 ****
--- 1504,1564 ----
}
/* 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
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.209
diff -p -r1.209 remote.c
*** remote.c 26 Apr 2006 18:45:32 -0000 1.209
--- remote.c 29 Apr 2006 00:52:38 -0000
*************** remote_vcont_resume (ptid_t ptid, int st
*** 2327,2332 ****
--- 2327,2336 ----
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);
*************** remote_resume (ptid_t ptid, int step, en
*** 2419,2425 ****
else
set_thread (pid, 0); /* Run this thread. */
! if (siggnal != TARGET_SIGNAL_0)
{
buf[0] = step ? 'S' : 'C';
buf[1] = tohex (((int) siggnal >> 4) & 0xf);
--- 2423,2437 ----
else
set_thread (pid, 0); /* Run this thread. */
! 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);
*************** remote_wait (ptid_t ptid, struct target_
*** 2693,2698 ****
--- 2705,2716 ----
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. */
*************** Packet: '%s'\n"),
*** 2823,2832 ****
remote_console_output (buf + 1);
continue;
case '\0':
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",
--- 2841,2850 ----
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)
{
target_terminal_ours_for_output ();
printf_filtered
("Can't send signals to this remote system. %s not sent.\n",
*************** Packet: '%s'\n"),
*** 2838,2847 ****
putpkt ((char *) buf);
continue;
}
/* else fallthrough */
default:
! warning (_("Invalid remote reply: %s"), buf);
! continue;
}
}
got_status:
--- 2856,2871 ----
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:
! error (_("Invalid remote reply: %s"), buf);
! break; /* Lint. */
}
}
got_status:
*************** remote_get_thread_local_address (ptid_t
*** 5218,5223 ****
--- 5242,5281 ----
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)
{
*************** Specify the serial device it is connecte
*** 5265,5270 ****
--- 5323,5330 ----
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;
}