Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Abhay Kandpal <abhay@linux.ibm.com>
To: gdb-patches@sourceware.org
Cc: aburgess@redhat.com, Ulrich.Weigand@de.ibm.com, eliz@gnu.org,
	cel@linux.ibm.com, abhay.k@ibm.com,
	Abhay Kandpal <abhay@linux.ibm.com>
Subject: [PATCH v4 2/2] gdb: add stat64 and fstat64 to the F-packet file-i/o protocol
Date: Thu, 29 Oct 2026 04:21:24 -0500	[thread overview]
Message-ID: <20261029092124.233055-3-abhay@linux.ibm.com> (raw)
In-Reply-To: <20261029092124.233055-1-abhay@linux.ibm.com>

The previous patch widened the stat fields returned by the vFile
packets, using a qSupported feature to keep old and new GDB and
gdbserver compatible.  The F-packet file-i/o protocol has the same
problem: the Fstat and Ffstat calls write struct fio_stat into target
memory, in which st_dev, st_ino, st_nlink, st_rdev and the three
timestamps are 4 bytes, so those values are truncated on a 64-bit
host.

The F-packet calls cannot use qSupported, since the buffer is read
directly by the target.  But each request names the call it wants, so
add two new calls, Fstat64 and Ffstat64, which are identical to Fstat
and Ffstat except that they write struct fio_stat_wide.  Existing
targets keep using Fstat and Ffstat and see no change.  A GDB which
does not know the new calls already replies with ENOSYS, so a target
can try Fstat64 and fall back to Fstat.

The stat and fstat handlers become remote_fileio_do_stat and
remote_fileio_do_fstat, with a flag selecting the layout, and share a
new remote_fileio_write_stat helper.  The stat handler has always
reported st_dev as zero; that is now done on the struct stat before
packing, which gives the same result in either layout.

The console case in the fstat handler stored 1 into fst_dev, but that
was then overwritten when the struct was packed, so the target always
saw zero.  Drop the dead store; behaviour is unchanged.

Tested on powerpc64le-linux, on an xfs filesystem with inode numbers
above 2^32, using a fake remote stub which issues File-I/O requests
and checks the buffer GDB writes into target memory.  Fstat64 and
Ffstat64 return the full inode number; Fstat and Ffstat return the
same truncated values as before.  An unpatched GDB answers Fstat64
and Ffstat64 with ENOSYS.  gdb.server/fileio-packets.exp continues
to pass.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34567
Suggested-by: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
---
 gdb/NEWS            |  9 ++++++
 gdb/doc/gdb.texinfo | 52 ++++++++++++++++++++++++++++++--
 gdb/remote-fileio.c | 73 +++++++++++++++++++++++++++++++++++++--------
 gdbsupport/fileio.h | 14 ++++-----
 4 files changed, 126 insertions(+), 22 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 47425535661..5815a8c2261 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -83,6 +83,15 @@ info locals
   The new "-shadowed on|off" option overrides the "set print shadowed"
   setting for a single invocation of the command.
 
+* New remote packets
+
+Fstat64, Ffstat64
+  New File-I/O calls, identical to Fstat and Ffstat except that they
+  fill in the wider struct stat64 layout, in which st_dev, st_ino,
+  st_nlink, st_rdev and the three timestamps are 8 bytes rather than
+  4.  A GDB without these calls replies with ENOSYS, so a target can
+  fall back to Fstat and Ffstat.
+
 * Changed remote packets
 
 stat64 in qSupported
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4d606377987..2b28d64af01 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -48136,6 +48136,7 @@ is stopped at the user's request.
 * rename::
 * unlink::
 * stat/fstat::
+* stat64/fstat64::
 * gettimeofday::
 * isatty::
 * system::
@@ -48581,6 +48582,49 @@ The call was interrupted by the user.
 
 @end table
 
+The buffer uses the narrow @code{struct stat} layout, in which some
+members may be truncated on a 64-bit host.  @xref{stat64/fstat64}, for
+calls which use a wider layout.
+
+@node stat64/fstat64
+@unnumberedsubsubsec stat64/fstat64
+@cindex fstat64, file-i/o system call
+@cindex stat64, file-i/o system call
+
+@table @asis
+@item Synopsis:
+@smallexample
+int stat64(const char *pathname, struct stat64 *buf);
+int fstat64(int fd, struct stat64 *buf);
+@end smallexample
+
+@item Request:
+@samp{Fstat64,@var{pathnameptr}/@var{len},@var{bufptr}}@*
+@samp{Ffstat64,@var{fd},@var{bufptr}}
+
+These calls are identical to @samp{Fstat} and @samp{Ffstat}
+(@pxref{stat/fstat}), except that the buffer at @var{bufptr} is
+filled in using the wider @code{struct stat64} layout
+(@pxref{struct stat64}), which can hold the values found on a 64-bit
+host without truncation.
+
+A version of @value{GDBN} which does not support these calls replies
+with an @code{ENOSYS} error.  The target can then fall back to
+@samp{Fstat} or @samp{Ffstat}.
+
+@item Return value:
+On success, zero is returned.  On error, -1 is returned.
+
+@item Errors:
+As for @samp{Fstat} and @samp{Ffstat}, and in addition:
+
+@table @code
+@item ENOSYS
+@value{GDBN} does not support this call.
+@end table
+
+@end table
+
 @node gettimeofday
 @unnumberedsubsubsec gettimeofday
 @cindex gettimeofday, file-i/o system call
@@ -48837,7 +48881,9 @@ get truncated on the target.
 
 When the @samp{stat64} feature has been negotiated, the buffer returned
 by the @samp{vFile:fstat}, @samp{vFile:stat} and @samp{vFile:lstat}
-packets uses the following representation instead:
+packets uses the following representation instead.  The
+@samp{Fstat64} and @samp{Ffstat64} File-I/O calls
+(@pxref{stat64/fstat64}) always use it.
 
 @smallexample
 struct stat64 @{
@@ -48863,8 +48909,8 @@ as in the narrow form (@pxref{struct stat}), but @code{st_dev},
 are wide enough to hold the values found on a 64-bit host without
 truncation.
 
-This representation is only used by the @samp{vFile} packets; the
-File-I/O protocol always uses the narrow form (@pxref{struct stat}).
+The @samp{Fstat} and @samp{Ffstat} File-I/O calls always use the narrow
+form (@pxref{struct stat}).
 
 @node struct timeval
 @unnumberedsubsubsec struct timeval
diff --git a/gdb/remote-fileio.c b/gdb/remote-fileio.c
index a65db27d04e..c24c3c2ab9f 100644
--- a/gdb/remote-fileio.c
+++ b/gdb/remote-fileio.c
@@ -791,14 +791,39 @@ remote_fileio_func_unlink (remote_target *remote, char *buf)
     remote_fileio_return_success (remote, ret);
 }
 
+/* Write ST into target memory at ADDR, using the struct fio_stat
+   layout or, if WIDE, the struct fio_stat_wide layout.  Return 0 on
+   success, or an errno value.  */
+
+static int
+remote_fileio_write_stat (CORE_ADDR addr, struct stat *st, bool wide)
+{
+  if (wide)
+    {
+      struct fio_stat_wide fst;
+
+      host_to_fileio_stat_wide (st, &fst);
+      return target_write_memory (addr, (gdb_byte *) &fst, sizeof fst);
+    }
+  else
+    {
+      struct fio_stat fst;
+
+      host_to_fileio_stat (st, &fst);
+      return target_write_memory (addr, (gdb_byte *) &fst, sizeof fst);
+    }
+}
+
+/* Handle the stat and stat64 calls.  WIDE selects the struct
+   fio_stat_wide layout.  */
+
 static void
-remote_fileio_func_stat (remote_target *remote, char *buf)
+remote_fileio_do_stat (remote_target *remote, char *buf, bool wide)
 {
   CORE_ADDR statptr, nameptr;
   int ret, namelength;
   LONGEST lnum;
   struct stat st;
-  struct fio_stat fst;
 
   /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
   if (remote_fileio_extract_ptr_w_len (&buf, &nameptr, &namelength))
@@ -839,10 +864,9 @@ remote_fileio_func_stat (remote_target *remote, char *buf)
     }
   if (statptr)
     {
-      host_to_fileio_stat (&st, &fst);
-      host_to_fileio_uint (0, fst.fst_dev);
-
-      errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst);
+      /* The stat call has always reported st_dev as zero.  */
+      st.st_dev = 0;
+      errno = remote_fileio_write_stat (statptr, &st, wide);
       if (errno != 0)
 	{
 	  remote_fileio_return_errno (remote, -1);
@@ -853,14 +877,28 @@ remote_fileio_func_stat (remote_target *remote, char *buf)
 }
 
 static void
-remote_fileio_func_fstat (remote_target *remote, char *buf)
+remote_fileio_func_stat (remote_target *remote, char *buf)
+{
+  remote_fileio_do_stat (remote, buf, false);
+}
+
+static void
+remote_fileio_func_stat64 (remote_target *remote, char *buf)
+{
+  remote_fileio_do_stat (remote, buf, true);
+}
+
+/* Handle the fstat and fstat64 calls.  WIDE selects the struct
+   fio_stat_wide layout.  */
+
+static void
+remote_fileio_do_fstat (remote_target *remote, char *buf, bool wide)
 {
   CORE_ADDR ptrval;
   int fd, ret;
   long target_fd;
   LONGEST lnum;
   struct stat st;
-  struct fio_stat fst;
   struct timeval tv;
 
   /* 1. Parameter: file descriptor */
@@ -885,7 +923,6 @@ remote_fileio_func_fstat (remote_target *remote, char *buf)
 
   if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
     {
-      host_to_fileio_uint (1, fst.fst_dev);
       memset (&st, 0, sizeof (st));
       st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
       st.st_nlink = 1;
@@ -917,9 +954,7 @@ remote_fileio_func_fstat (remote_target *remote, char *buf)
     }
   if (ptrval)
     {
-      host_to_fileio_stat (&st, &fst);
-
-      errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst);
+      errno = remote_fileio_write_stat (ptrval, &st, wide);
       if (errno != 0)
 	{
 	  remote_fileio_return_errno (remote, -1);
@@ -929,6 +964,18 @@ remote_fileio_func_fstat (remote_target *remote, char *buf)
   remote_fileio_return_success (remote, ret);
 }
 
+static void
+remote_fileio_func_fstat (remote_target *remote, char *buf)
+{
+  remote_fileio_do_fstat (remote, buf, false);
+}
+
+static void
+remote_fileio_func_fstat64 (remote_target *remote, char *buf)
+{
+  remote_fileio_do_fstat (remote, buf, true);
+}
+
 static void
 remote_fileio_func_gettimeofday (remote_target *remote, char *buf)
 {
@@ -1062,6 +1109,8 @@ static struct {
   { "unlink", remote_fileio_func_unlink },
   { "stat", remote_fileio_func_stat },
   { "fstat", remote_fileio_func_fstat },
+  { "stat64", remote_fileio_func_stat64 },
+  { "fstat64", remote_fileio_func_fstat64 },
   { "gettimeofday", remote_fileio_func_gettimeofday },
   { "isatty", remote_fileio_func_isatty },
   { "system", remote_fileio_func_system },
diff --git a/gdbsupport/fileio.h b/gdbsupport/fileio.h
index 44b9bdcafc6..e158b45a9b4 100644
--- a/gdbsupport/fileio.h
+++ b/gdbsupport/fileio.h
@@ -121,10 +121,10 @@ using fio_long_t = char[FIO_LONG_LEN];
 using fio_ulong_t = char[FIO_ULONG_LEN];
 
 /* Struct stat as used in the protocol.  This is the format used by the
-   F-packet file-i/o protocol, and by the vFile stat packets when the
-   stat64 feature has not been negotiated.  Several fields are too narrow
-   to hold the corresponding struct stat member on a 64-bit host; see
-   struct fio_stat_wide.  */
+   F-packet file-i/o stat and fstat calls, and by the vFile stat packets
+   when the stat64 feature has not been negotiated.  Several fields are
+   too narrow to hold the corresponding struct stat member on a 64-bit
+   host; see struct fio_stat_wide.  */
 
 struct fio_stat
 {
@@ -145,9 +145,9 @@ struct fio_stat
 
 /* Struct stat as used in the wide form of the protocol.  The fields
    which cannot hold the corresponding struct stat member on a 64-bit
-   host are widened to 8 bytes.  This layout is only used by the vFile
-   stat packets, and only when the stat64 feature has been negotiated
-   with the peer.  */
+   host are widened to 8 bytes.  This layout is used by the vFile stat
+   packets when the stat64 feature has been negotiated with the peer,
+   and by the F-packet file-i/o stat64 and fstat64 calls.  */
 
 struct fio_stat_wide
 {
-- 
2.51.1


      parent reply	other threads:[~2026-10-29  9:22 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29  9:21 [PATCH v4 0/2] Widen the stat fields in the remote protocol Abhay Kandpal
2026-10-29  9:21 ` [PATCH v4 1/2] gdbserver: widen the stat fields returned by the vFile packets Abhay Kandpal
2026-10-29  9:21 ` Abhay Kandpal [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261029092124.233055-3-abhay@linux.ibm.com \
    --to=abhay@linux.ibm.com \
    --cc=Ulrich.Weigand@de.ibm.com \
    --cc=abhay.k@ibm.com \
    --cc=aburgess@redhat.com \
    --cc=cel@linux.ibm.com \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox