This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit+7.5] Fix /proc access regression on older Linux kernels


Hello,

this patch fixes an unfortunate regression introduced by my patch series to
support /proc file access for remote targets.  As a side-effect of these
patches, GDB (or gdbserver) will now actually use a "pread" system call
on /proc files.

This works fine on recent Linux kernels.  However, on certain older kernels
(e.g. the 2.6.18 in RHEL 5), pread on some /proc files, in particular on
/proc/.../maps, will always fail with an errno of ESPIPE.  This means that
current GDB on such systems will fail to properly execute any command that
requires /proc access, in particular "info proc" and "gcore".

The fix is to detect a failing pread call and fall back to doing an lseek
and read, as would be done anyway on systems without pread.  This works
fine on those /proc files even on old Linux kernels.

Tested on spu-elf, powerpc(64)-linux, and arm-linux-gnuabi in both
native and remote testing.

Committed to mainline and 7.5.

Bye,
Ulrich


ChangeLog:

	* inf-child.c (inf_child_fileio_pwrite): If pwrite fails, fall back
	to attempting lseek/write.
	(inf_child_fileio_pread): Likewise for pread.

gdbserver/ChangeLog:

	* hostio.c (handle_pread): If pread fails, fall back to attempting
	lseek/read.
	(handle_pwrite): Likewise for pwrite.

Index: gdb/inf-child.c
===================================================================
RCS file: /cvs/src/src/gdb/inf-child.c,v
retrieving revision 1.34
diff -u -p -r1.34 inf-child.c
--- gdb/inf-child.c	24 May 2012 16:39:09 -0000	1.34
+++ gdb/inf-child.c	2 Aug 2012 13:28:32 -0000
@@ -265,10 +265,15 @@ inf_child_fileio_pwrite (int fd, const g
 #ifdef HAVE_PWRITE
   ret = pwrite (fd, write_buf, len, (long) offset);
 #else
-  ret = lseek (fd, (long) offset, SEEK_SET);
-  if (ret != -1)
-    ret = write (fd, write_buf, len);
+  ret = -1;
 #endif
+  /* If we have no pwrite or it failed for this file, use lseek/write.  */
+  if (ret == -1)
+    {
+      ret = lseek (fd, (long) offset, SEEK_SET);
+      if (ret != -1)
+	ret = write (fd, write_buf, len);
+    }
 
   if (ret == -1)
     *target_errno = inf_child_errno_to_fileio_error (errno);
@@ -288,10 +293,15 @@ inf_child_fileio_pread (int fd, gdb_byte
 #ifdef HAVE_PREAD
   ret = pread (fd, read_buf, len, (long) offset);
 #else
-  ret = lseek (fd, (long) offset, SEEK_SET);
-  if (ret != -1)
-    ret = read (fd, read_buf, len);
+  ret = -1;
 #endif
+  /* If we have no pread or it failed for this file, use lseek/read.  */
+  if (ret == -1)
+    {
+      ret = lseek (fd, (long) offset, SEEK_SET);
+      if (ret != -1)
+	ret = read (fd, read_buf, len);
+    }
 
   if (ret == -1)
     *target_errno = inf_child_errno_to_fileio_error (errno);
Index: gdb/gdbserver/hostio.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/hostio.c,v
retrieving revision 1.18
diff -u -p -r1.18 hostio.c
--- gdb/gdbserver/hostio.c	9 Feb 2012 17:29:34 -0000	1.18
+++ gdb/gdbserver/hostio.c	2 Aug 2012 13:28:32 -0000
@@ -328,10 +328,15 @@ handle_pread (char *own_buf, int *new_pa
 #ifdef HAVE_PREAD
   ret = pread (fd, data, len, offset);
 #else
-  ret = lseek (fd, offset, SEEK_SET);
-  if (ret != -1)
-    ret = read (fd, data, len);
+  ret = -1;
 #endif
+  /* If we have no pread or it failed for this file, use lseek/read.  */
+  if (ret == -1)
+    {
+      ret = lseek (fd, offset, SEEK_SET);
+      if (ret != -1)
+	ret = read (fd, data, len);
+    }
 
   if (ret == -1)
     {
@@ -376,10 +381,15 @@ handle_pwrite (char *own_buf, int packet
 #ifdef HAVE_PWRITE
   ret = pwrite (fd, data, len, offset);
 #else
-  ret = lseek (fd, offset, SEEK_SET);
-  if (ret != -1)
-    ret = write (fd, data, len);
+  ret = -1;
 #endif
+  /* If we have no pwrite or it failed for this file, use lseek/write.  */
+  if (ret == -1)
+    {
+      ret = lseek (fd, offset, SEEK_SET);
+      if (ret != -1)
+	ret = write (fd, data, len);
+    }
 
   if (ret == -1)
     {
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]