From bdc4806851a901bc13d87c95ab9beaf9e80f8388 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Sat, 21 Jun 2008 22:58:24 +0000 Subject: 2008-06-21 Michael Snyder * gdbfreeplay-i386.c (target_compose_T_packet): Add default return. (target_compose_g_packet): New function. * gdbfreeplay.h (target_compose_g_packet): Export. * gdbfreeplay-back.c (handle_special_case): Give correct args for target_compose_T_packet. (fallbacks): Add handling for 'G', 'M', 'X', and 'g'. --- gdb/gdbserver/ChangeLog | 7 ++++ gdb/gdbserver/gdbfreeplay-back.c | 81 ++++++++++++++++++++++++++++++++++------ gdb/gdbserver/gdbfreeplay-i386.c | 71 +++++++++++++++++++++++++++++++++++ gdb/gdbserver/gdbfreeplay.h | 4 ++ 4 files changed, 151 insertions(+), 12 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index deaf51e..e83af3c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,5 +1,12 @@ 2008-06-21 Michael Snyder + * gdbfreeplay-i386.c (target_compose_T_packet): Add default return. + (target_compose_g_packet): New function. + * gdbfreeplay.h (target_compose_g_packet): Export. + * gdbfreeplay-back.c (handle_special_case): Give correct args + for target_compose_T_packet. + (fallbacks): Add handling for 'G', 'M', 'X', and 'g'. + * gdbfreeplay-front.c: New file. Extended gdbreplay. * gdbfreeplay-back.c: New file. * gdbfreeplay-i386.c: New file. diff --git a/gdb/gdbserver/gdbfreeplay-back.c b/gdb/gdbserver/gdbfreeplay-back.c index b7535db..84e63cd 100644 --- a/gdb/gdbserver/gdbfreeplay-back.c +++ b/gdb/gdbserver/gdbfreeplay-back.c @@ -4,10 +4,18 @@ * Backend for gdbfreeplay. */ +#include "config.h" #include -#include #include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H #include +#endif typedef struct STOPFRAME { /* frame_id -- a unique identifier per stop frame. */ @@ -49,7 +57,6 @@ scan_gdbreplay_file (FILE *infile) { /* Make a pass over the entire file -- cache the record positions. */ char *line, *p; - int next_id = 0; unsigned long nextpos; unsigned long GPC; @@ -77,10 +84,6 @@ scan_gdbreplay_file (FILE *infile) if (stopframe[last_cached_frame].pc == 0 || stopframe[last_cached_frame].pc == (unsigned long) -1) stopframe[last_cached_frame].pc = target_pc_from_g (infile); - - if (verbose) - fprintf (stdout, "Found 'g' packet at %u\n", - stopframe[last_cached_frame].gpos); } /* Reset PC after breakpoint? */ @@ -140,7 +143,7 @@ scan_gdbreplay_file (FILE *infile) stopframe[last_cached_frame].pc = target_pc_from_T (p); if (verbose) - fprintf (stdout, "Record event pos at %u\n", + fprintf (stdout, "Record event pos at %lu\n", stopframe [last_cached_frame].eventpos); } nextpos = ftell (infile); @@ -472,7 +475,7 @@ static void gdbwriteline (int fd, char *line) { char *end; - int len, ich; + int ich; char ch; if (line) @@ -519,7 +522,7 @@ 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]) << 8) + hex_to_int (p[3]); return sig; } return 0; @@ -666,7 +669,6 @@ handle_special_case (FILE *infile, int fd, char *request) /* Handle 's' (step) by advancing the cur_frame index. */ if (strstr (request, "$s#73") != NULL) { - step_label: if (cur_frame < last_cached_frame) cur_frame++; @@ -732,7 +734,9 @@ handle_special_case (FILE *infile, int fd, char *request) /* If it's a "$T", give the target a chance to re-compose it (possibly allowing for DECR_PC_AFTER_BREAK). */ if ((p = strstr (inbuf, "$T")) != NULL) - return add_checksum (target_compose_T_packet (p)); + return add_checksum (target_compose_T_packet (p, + stopframe[cur_frame].pc, + 1 /* breakpoint_p */)); /* If it's a "$S", just return it (FIXME?) */ else return &inbuf[0]; @@ -771,7 +775,9 @@ handle_special_case (FILE *infile, int fd, char *request) /* If it's a "$T", give the target a chance to re-compose it (possibly allowing for DECR_PC_AFTER_BREAK). */ if ((p = strstr (inbuf, "$T")) != NULL) - return add_checksum (target_compose_T_packet (p)); + return add_checksum (target_compose_T_packet (p, + stopframe[cur_frame].pc, + 1 /* breakpoint_p */)); /* If it's a "$S", just return it (FIXME?) */ else return &inbuf[0]; @@ -829,6 +835,8 @@ handle_special_case (FILE *infile, int fd, char *request) static char * fallbacks (FILE *infile, int fd, char *request) { + char *p; + /* Handle "Hc0" request. */ if (strstr (request, "$Hc0#db") != NULL) { @@ -858,6 +866,55 @@ fallbacks (FILE *infile, int fd, char *request) return EMPTY; /* Tell gdb we don't know that one. */ } + /* Handle 'G' request (if not handled upstream). + Just tell gdb "OK", and otherwise ignore it. + The debugger now has its own idea of what the registers are... */ + if (strstr (request, "$G") != NULL) + { + if (verbose) + fprintf (stdout, "fallbacks: absorbing G request.\n"); + return OK; + } + + /* Handle 'M' or 'X' request (if not handled upstream). + There are two ways to go here -- just say "OK", without + actually doing anything, or return an error. + + Going to try just saying "OK", for now... */ + if (strstr (request, "$M") != NULL || + strstr (request, "$X") != NULL) + { + if (verbose) + fprintf (stdout, "fallbacks: absorbing memory write request.\n"); + return OK; + } + + /* Handle 'g' request (if not handled upstream). + This is usually at a singlestep event. + We need to construct a 'g' packet for gdb from the 'T' packet. */ + if (strstr (request, "$g#67") != NULL) + { + /* Find the original event message for this stop event. */ + fseek (infile, stopframe[cur_frame].eventpos, SEEK_SET); + fgets (inbuf, sizeof (inbuf), infile); + /* If it's a "$T", give the target a chance to compose a g packet. + (possibly allowing for DECR_PC_AFTER_BREAK). */ + if ((p = strstr (inbuf, "$T")) != NULL) + { + if (verbose) + fprintf (stdout, "fallbacks: constructing 'g' packet.\n"); + return add_checksum (target_compose_g_packet (p)); + } + /* If it's an 'S' packet, there ain't much we can do + (FIXME unles we at least know the PC? */ + else + { + if (verbose) + fprintf (stdout, "fallbacks: punting on 'g' packet request.\n"); + return EMPTY; + } + } + /* Default for any other un-handled request -- return empty string. */ if (verbose) fprintf (stdout, "fallbacks: absorbing unknown request '%s'.\n", diff --git a/gdb/gdbserver/gdbfreeplay-i386.c b/gdb/gdbserver/gdbfreeplay-i386.c index 319064f..ef4d96f 100644 --- a/gdb/gdbserver/gdbfreeplay-i386.c +++ b/gdb/gdbserver/gdbfreeplay-i386.c @@ -331,4 +331,75 @@ target_compose_T_packet (char *origTpacket, /* Caller has to recompute checksum. */ return reply_buf; } + /* Bail... */ + return origTpacket; +} + +/* + * target_compose_g_packet + * + * Take the registers from the 'T' packet, and compose them into a + * 'g' packet response. Registers for which we have no values will + * be filled in with 'xxxx', in the manner of tracepoints. + * + * Returns: string, g packet reply. + */ + +#define IX86_TARGET_GBYTES 624 +static char gbuffer[IX86_TARGET_GBYTES + 1]; +#define IX86_BOGUS_NUMREGS (IX86_TARGET_GBYTES / 8) + +static unsigned long regval[IX86_BOGUS_NUMREGS]; +static int gotreg[IX86_BOGUS_NUMREGS]; + +char * +target_compose_g_packet (char *tpac) +{ + int i; + int regnum; + int signum; + + /* See which regs we can get from the T packet. Assume none... */ + for (i = 0; i < IX86_BOGUS_NUMREGS; i++) + gotreg[i] = 0; + + /* OK, scan off the prefix -- $T plus signal number. */ + if (*tpac++ == '$' && *tpac++ == 'T') + { + /* We won't actually use signum. */ + signum = (hex_to_int (*tpac++) << 4) + hex_to_int (*tpac++); + while (*tpac) + { + regnum = (hex_to_int (*tpac++) << 4) + hex_to_int (*tpac++); + if (*tpac++ == ':') + { + gotreg[regnum] = 1; + regval[regnum] = ix86_hex_to_unsigned_long (expand_rle (tpac)); + tpac = strchr (tpac, ';'); + } + else goto gpacket_fail; + + if (tpac && *tpac == ';') + tpac++; + else goto gpacket_fail; + + if (strncmp (tpac, "thread", 6) == 0) + break; + } + + /* Got values, now get to composin'. */ + strcpy (gbuffer, "$"); + for (i = 0; i < IX86_BOGUS_NUMREGS; i++) + if (gotreg[i]) + strcat (gbuffer, ix86_unsigned_long_to_hex (regval[i])); + else + strcat (gbuffer, "xxxxxxxx"); + + /* Return composed g packet reply. + Caller has responsibility of appending checksum. */ + return gbuffer; + } + gpacket_fail: + /* Fail. */ + return NULL; } diff --git a/gdb/gdbserver/gdbfreeplay.h b/gdb/gdbserver/gdbfreeplay.h index b6cbe66..e337cf2 100644 --- a/gdb/gdbserver/gdbfreeplay.h +++ b/gdb/gdbserver/gdbfreeplay.h @@ -15,6 +15,10 @@ extern void gdbfreeplay (int socket_fd); extern unsigned long target_pc_from_T (char *tpacket); extern unsigned long target_pc_from_G (char *gpacket); extern unsigned long target_pc_from_g (FILE *infile); +extern char *target_compose_T_packet (char *origTpacket, + unsigned long pc, + int breakpoint_p); +extern char *target_compose_g_packet (char *origTpacket); extern int hex_to_int (int ch); -- cgit v1.1