]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2008-06-21 Michael Snyder <msnyder@specifix.com>
authorMichael Snyder <msnyder@vmware.com>
Sat, 21 Jun 2008 22:58:24 +0000 (22:58 +0000)
committerMichael Snyder <msnyder@vmware.com>
Sat, 21 Jun 2008 22:58:24 +0000 (22:58 +0000)
* 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
gdb/gdbserver/gdbfreeplay-back.c
gdb/gdbserver/gdbfreeplay-i386.c
gdb/gdbserver/gdbfreeplay.h

index deaf51e164d4931e4418f406116b3af414697171..e83af3cbd9250fd728bb83f496dc26f3ea838169 100644 (file)
@@ -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.
index b7535dbbae55fdcd5f28f4977cbba57e47933a4f..84e63cd0884a735ccb8d4a5376909a06f684c09d 100644 (file)
@@ -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",
index 319064f1680122ec7899ff771a8344a8156ea29e..ef4d96f8f8fa5e7ed44c5a557730cf38bdedd945 100644 (file)
@@ -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;
 }
index b6cbe662b588c59052fe5b0b5cb5e38787483069..e337cf2189516d7126f1148f9984fbf0d6aef129 100644 (file)
@@ -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);