]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix gdbreplay checksum calculation
authorTom Tromey <tromey@adacore.com>
Mon, 9 Dec 2024 17:40:48 +0000 (10:40 -0700)
committerTom Tromey <tromey@adacore.com>
Wed, 11 Dec 2024 17:00:47 +0000 (10:00 -0700)
I needed to use gdbreplay today.  It didn't work quite right, and
using "set debug remote 1" showed that gdb was rejecting some
responses like:

  [remote] Sending packet: $vCont?#49
  [remote] Junk: #vCont?
  [remote] Junk: 8vCont?
  [remote] Junk: 3vCont?
  [remote] Received Ack

The checksum recalculation seems to have gone wrong.  Looking at the
code, it seems like 'where_csum' is calculated inconsistently: in the
main loop it is after the '#' but in the "== 0" case it is before the
'#'.

This patch fixes the problem and also avoids a string copy.

CC: Alexandra Hájková <ahajkova@redhat.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
gdbserver/gdbreplay.cc

index a9a55924ca9aeb746979023d633ce875a9b70d8d..951f50ea54ee502b3801eff800830b9a34339d4c 100644 (file)
@@ -405,11 +405,12 @@ expect (FILE *fp)
 /* Calculate checksum for the packet stored in buffer buf.  Store
    the checksum in a hexadecimal format in a checksum_hex variable.  */
 static void
-recalculate_csum (const std::string &buf, int cnt, unsigned char *checksum_hex)
+recalculate_csum (const std::string &buf, int off, unsigned char *checksum_hex)
 {
   unsigned char csum = 0;
 
-  for (int i = 0; i < cnt; i++)
+  int len = buf.length ();
+  for (int i = off; i < len; ++i)
     csum += buf[i];
 
   checksum_hex[0] = tohex ((csum >> 4) & 0xf);
@@ -435,9 +436,9 @@ play (FILE *fp)
     }
   while ((fromlog = logchar (fp, false)) != EOL)
     {
-      line.push_back (fromlog);
-      if (line[line.length ()] == '#')
+      if (fromlog == '#')
        where_csum = line.length ();
+      line.push_back (fromlog);
     }
 
   /* Packet starts with '+$' or '$', we don't want to calculate those
@@ -446,23 +447,13 @@ play (FILE *fp)
   if (line[0] == '+')
     offset = 2;
 
-  /* If '#' is missing at the end of the line, add it and adjust the line
-     length.  */
-  if (where_csum == 0)
-    {
-      where_csum = line.length ();
-      line.push_back ('#');
-    }
-  recalculate_csum (line.substr (offset), where_csum - offset, checksum);
-
-  /* Check if the checksum is missing and adjust the line length to be able
-     to fit the checksum.  */
-  if (where_csum + 1 >= line.length ())
-    line.resize (where_csum + 3);
+  if (where_csum > 0)
+    line.resize (where_csum);
+  recalculate_csum (line, offset, checksum);
 
-  /* Replace what is at the end of the packet with the checksum.  */
-  line[where_csum + 1] = checksum[0];
-  line[where_csum + 2] = checksum[1];
+  line.push_back ('#');
+  line.push_back (checksum[0]);
+  line.push_back (checksum[1]);
 
   if (write (remote_desc_out, line.data (), line.size ()) != line.size ())
     remote_error ("Error during write to gdb");