summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@specifix.com>2008-06-21 22:58:24 +0000
committerMichael Snyder <msnyder@specifix.com>2008-06-21 22:58:24 +0000
commit6af85239d820d806294f267605ba487a39e1a913 (patch)
tree2e8e5fab09bb40d2e85b660297ccaf352fc255c1
parent2bb10258330b2ecbd620050f719cdfe1eea33f8f (diff)
downloadgdb-6af85239d820d806294f267605ba487a39e1a913.tar.gz
2008-06-21 Michael Snyder <msnyder@specifix.com>
* 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'.
-rw-r--r--gdb/gdbserver/ChangeLog7
-rw-r--r--gdb/gdbserver/gdbfreeplay-back.c81
-rw-r--r--gdb/gdbserver/gdbfreeplay-i386.c71
-rw-r--r--gdb/gdbserver/gdbfreeplay.h4
4 files changed, 151 insertions, 12 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index deaf51e164d..e83af3cbd92 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,12 @@
2008-06-21 Michael Snyder <msnyder@specifix.com>
+ * 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 b7535dbbae5..84e63cd0884 100644
--- a/gdb/gdbserver/gdbfreeplay-back.c
+++ b/gdb/gdbserver/gdbfreeplay-back.c
@@ -4,10 +4,18 @@
* Backend for gdbfreeplay.
*/
+#include "config.h"
#include <stdio.h>
-#include <stdlib.h>
#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#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 319064f1680..ef4d96f8f8f 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 b6cbe662b58..e337cf21895 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);