Write entire buffer in gdbserver write_prim

We had a customer bug report which was eventually tracked down to
gdbserver not fully sending a target description to gdb.  (This
presented as a timeout on the gdb side.)

The customer was using the WINAPI code, which does this:

  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)

In this setup, I think it's possible to have a partial write.
However, gdbserver does not account for this possibility, despite the
fact that write_prim documents this.

This patch attempts to fix the problem by always writing the full
buffer in write_prim.  In this case the customer fixed their bug in a
different way, so we haven't actually tested this in the wild.

v2: Return bool from write_prim.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
This commit is contained in:
Tom Tromey
2025-10-16 08:58:38 -06:00
parent 9452b2fb46
commit cdb5949407

View File

@@ -598,17 +598,25 @@ read_ptid (const char *buf, const char **obuf)
return ptid_t (pid, tid); return ptid_t (pid, tid);
} }
/* Write COUNT bytes in BUF to the client. /* Write COUNT bytes in BUF to the client. Returns true if all bytes
The result is the number of bytes written or -1 if error. were written, false (with errno set) if not. */
This may return less than COUNT. */
static int static bool
write_prim (const void *buf, int count) write_prim (const char *buf, int count)
{ {
if (remote_connection_is_stdio ()) while (count > 0)
return write (fileno (stdout), buf, count); {
else int written;
return write (remote_desc, buf, count); if (remote_connection_is_stdio ())
written = write (fileno (stdout), buf, count);
else
written = write (remote_desc, buf, count);
if (written < 0)
return false;
buf += written;
count -= written;
}
return true;
} }
/* Read COUNT bytes from the client and store in BUF. /* Read COUNT bytes from the client and store in BUF.
@@ -664,7 +672,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
do do
{ {
if (write_prim (buf2, p - buf2) != p - buf2) if (!write_prim (buf2, p - buf2))
{ {
perror ("putpkt(write)"); perror ("putpkt(write)");
free (buf2); free (buf2);
@@ -980,7 +988,7 @@ getpkt (char *buf)
fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf); (c1 << 4) + c2, csum, buf);
if (write_prim ("-", 1) != 1) if (!write_prim ("-", 1))
return -1; return -1;
} }
@@ -988,7 +996,7 @@ getpkt (char *buf)
{ {
remote_debug_printf ("getpkt (\"%s\"); [sending ack]", buf); remote_debug_printf ("getpkt (\"%s\"); [sending ack]", buf);
if (write_prim ("+", 1) != 1) if (!write_prim ("+", 1))
return -1; return -1;
remote_debug_printf ("[sent ack]"); remote_debug_printf ("[sent ack]");