From: Michael Snyder Date: Sun, 22 Jun 2008 01:51:05 +0000 (+0000) Subject: 2008-06-21 Michael Snyder X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f1182023d1548eecd8556f176fac6d386cf81257;p=thirdparty%2Fbinutils-gdb.git 2008-06-21 Michael Snyder Add support for 'O' packet output. * remote-breakpoint.h (PLAY_O_PACKETS): New enum const. * gdbfreeplay-back.c (StopFrame): Discard gpos, replace with Opos. (scan_gdbreplay_file): Record Opos for frame if 'O' packet found. (frame_replay_O_packets): New function. (freeplay_find_event): Call frame_replay_O_packets. (handle_special_case): Pass PLAY_O_PACKETS to freeplay_find_event. Add temporary support for "monitor gdbfreeplay-echo" command (just for testing). --- diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index beb3d9151a3..a748f2858e0 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,15 @@ 2008-06-21 Michael Snyder + Add support for 'O' packet output. + * remote-breakpoint.h (PLAY_O_PACKETS): New enum const. + * gdbfreeplay-back.c (StopFrame): Discard gpos, replace with Opos. + (scan_gdbreplay_file): Record Opos for frame if 'O' packet found. + (frame_replay_O_packets): New function. + (freeplay_find_event): Call frame_replay_O_packets. + (handle_special_case): Pass PLAY_O_PACKETS to freeplay_find_event. + Add temporary support for "monitor gdbfreeplay-echo" command + (just for testing). + * gdbfreeplay-back.c: Clean up round, comments, remove #if 0 etc. * gdbfreeplay-i386.c: Ditto. diff --git a/gdb/gdbserver/gdbfreeplay-back.c b/gdb/gdbserver/gdbfreeplay-back.c index 5944ec5bab5..0cc65fe4dc2 100644 --- a/gdb/gdbserver/gdbfreeplay-back.c +++ b/gdb/gdbserver/gdbfreeplay-back.c @@ -27,7 +27,7 @@ typedef struct STOPFRAME { DECR_PC_AFTER_BREAK. */ unsigned long predecr_pc; unsigned long eventpos; - unsigned long gpos; + unsigned long Opos; } StopFrame; StopFrame *stopframe; @@ -77,9 +77,6 @@ scan_gdbreplay_file (FILE *infile) /* 'g' packet message? */ if (strstr (line, "$g#67") != NULL) { - /* Record position of 'g' packet (next line). */ - stopframe[last_cached_frame].gpos = ftell (infile); - /* See if we need to grab the PC from this packet. */ if (stopframe[last_cached_frame].pc == 0 || stopframe[last_cached_frame].pc == (unsigned long) -1) @@ -109,6 +106,15 @@ scan_gdbreplay_file (FILE *infile) } } + /* 'O' packet(s)? Watch out for "$OK", we don't want that. */ + else if ((p = strstr (line, "$O")) != NULL && + strstr (p, "$OK#9a") == NULL) + { + /* If we know these, we can feed them back to gdb + during 'continue'. */ + stopframe[last_cached_frame].Opos = nextpos; + } + /* Stop event message? */ else if ((p = strstr (line, "$T")) != NULL || (p = strstr (line, "$S")) != NULL) @@ -142,6 +148,9 @@ scan_gdbreplay_file (FILE *infile) /* Since we now have a known frame, default to using it. */ cur_frame = 0; stopframe[last_cached_frame].eventpos = nextpos + p - line; + /* The frame for this event will default to not having + any 'O' packets, until we recognize one. */ + stopframe[last_cached_frame].Opos = 0; if (p[1] == 'T') stopframe[last_cached_frame].pc = target_pc_from_T (p); @@ -505,12 +514,43 @@ stopframe_signal (FILE *infile, int id) (p = strstr (line, "$S")) != NULL) { /* Signal value is two ascii/hex bytes following "$S" or "$T". */ - sig = (hex_to_int (p[2]) << 8) + hex_to_int (p[3]); + sig = (hex_to_int (p[2]) << 4) + hex_to_int (p[3]); return sig; } return 0; } +/* + * freeplay_play_O_packets + * + * Send one or more 'O' packets back to gdb. + * Returns void. + */ + +static void +freeplay_play_O_packets (FILE *infile, int fd, unsigned long filepos) +{ + char *line, *p; + + fseek (infile, filepos, SEEK_SET); + + while ((line = fgets (inbuf, sizeof (inbuf), infile)) != NULL) + { + if ((p = strstr (line, "$O")) != NULL) + { + /* FIXME: do I need to send an ACK? */ + gdb_ack (fd); + gdbwriteline (fd, p); + } + /* When we reach the next stop event, we're done. */ + else if (strstr (line, "$T") != NULL || + strstr (line, "$S") != NULL) + { + return; /* done */ + } + } +} + /* * freeplay_find_event * @@ -522,7 +562,11 @@ stopframe_signal (FILE *infile, int id) */ static int -freeplay_find_event (FILE *infile, int start, enum direction_code direction) +freeplay_find_event (FILE *infile, + int gdb_fd, + int start, + enum direction_code direction, + enum direction_code play_O_packets) { int i; int signum; @@ -546,6 +590,8 @@ freeplay_find_event (FILE *infile, int start, enum direction_code direction) FIXME need some DECR_PC_AFTER_BREAK handling. */ return i; } + if (play_O_packets && stopframe[i].Opos != 0) + freeplay_play_O_packets (infile, gdb_fd, stopframe[i].Opos); } /* Found no reason to stop. */ return -1; @@ -609,9 +655,14 @@ handle_special_case (FILE *infile, int fd, char *request) { unsigned long addr; unsigned long len; - int next_event_frame; + int next_event_frame, c; char *p; + static char *monitor_verbose_off = "$qRcmd,766572626f7365206f6666#13"; + static char *monitor_verbose_on = "$qRcmd,766572626f7365206f6e#d6"; + static char *monitor_echo = "$qRcmd,67646266726565706c61792d6563686f"; + + /* Handle 'k' (kill) request by exiting. */ if (strstr (request, "$k#6b") != NULL) { @@ -636,19 +687,39 @@ handle_special_case (FILE *infile, int fd, char *request) } /* Handle "monitor verbose on". */ - if (strstr (request, "$qRcmd,766572626f7365206f6e#d6") != NULL) + if (strstr (request, monitor_verbose_on) != NULL) { verbose = 1; return OK; } /* Handle "monitor verbose off". */ - if (strstr (request, "$qRcmd,766572626f7365206f6666#13") != NULL) + if (strstr (request, monitor_verbose_off) != NULL) { verbose = 0; return OK; } + /* Handle "monitor gdbfreeplay-echo" + (just to get a handle on the 'O' message). */ + if ((p = strstr (request, monitor_echo)) != NULL) + { + /* OK, this will be an ascii-fied string. */ + p += strlen (monitor_echo); + /* Skip spaces */ + while (p[0] == '2' && p[1] == '0') + p += 2; /* skip a space */ + + while (p[0] && p[0] != '#') + { + c = hex_to_int (*p++) << 4; + c += hex_to_int (*p++); + fputc (c, stdout); + } + fprintf (stdout, "\n"); + return OK; + } + /* Handle 's' (step) by advancing the cur_frame index. */ if (strstr (request, "$s#73") != NULL) { @@ -688,7 +759,10 @@ handle_special_case (FILE *infile, int fd, char *request) /* Handle 'c' (continue) by searching the cache for a stop event. */ if (strstr (request, "$c#63") != NULL) { - next_event_frame = freeplay_find_event (infile, cur_frame, DIR_FORWARD); + next_event_frame = freeplay_find_event (infile, fd, + cur_frame, + DIR_FORWARD, + PLAY_O_PACKETS); if (next_event_frame != -1) { /* Got a stop event. Make it the current frame, and tell gdb. @@ -717,7 +791,10 @@ handle_special_case (FILE *infile, int fd, char *request) /* Handle 'bc' (revese continue) by searching the cache for a stop event. */ if (strstr (request, "$bc#c5") != NULL) { - next_event_frame = freeplay_find_event (infile, cur_frame, DIR_BACKWARD); + next_event_frame = freeplay_find_event (infile, fd, + cur_frame, + DIR_BACKWARD, + PLAY_O_PACKETS); if (next_event_frame != -1) { /* Got a stop event. Make it the current frame, and tell gdb. @@ -726,6 +803,12 @@ handle_special_case (FILE *infile, int fd, char *request) } else { + /* WTF? */ + gdb_ack (fd); + strcpy (inbuf, "$O5768617420746865206675636b3f"); + if (verbose) + fprintf (stdout, "WTF? %s\n", add_checksum (inbuf)); + gdbwriteline (fd, add_checksum (inbuf)); cur_frame = 0; } diff --git a/gdb/gdbserver/remote-breakpoint.h b/gdb/gdbserver/remote-breakpoint.h index 1ee1b5c44dd..d98a659b6e0 100644 --- a/gdb/gdbserver/remote-breakpoint.h +++ b/gdb/gdbserver/remote-breakpoint.h @@ -26,7 +26,8 @@ enum successcode { enum direction_code { DIR_FORWARD = 0, - DIR_BACKWARD + DIR_BACKWARD, + PLAY_O_PACKETS }; extern enum successcode remote_remove_breakpoint (enum breakpoint_type,