[rfc,v4,3/6] File I/O target operations

Message ID 201201201814.q0KIEAlS032145@d06av02.portsmouth.uk.ibm.com
State Accepted
Headers show

Commit Message

Ulrich Weigand Jan. 20, 2012, 6:14 p.m.
http://sourceware.org/ml/gdb-patches/2012-01/msg00688.html


ChangeLog:

	* configure.ac [AC_CHECK_FUNCS]: Check for pread and pwrite.
	* config.in, configure: Regenerate.

	* target.h (struct target_ops): Add to_fileio_open, to_fileio_pwrite,
	to_fileio_pread, to_fileio_close, to_fileio_unlink.
	(target_fileio_open): Add prototype.
	(target_fileio_pwrite): Likewise.
	(target_fileio_pread): Likewise.
	(target_fileio_close): Likewise.
	(target_fileio_unlink): Likewise.
	(target_fileio_read_alloc): Likewise.
	(target_fileio_read_stralloc): Likewise.

	* target.c: Include "gdb/fileio.h".
	(target_read_stralloc): Accept trailing, but not embedded NUL bytes.
	(default_fileio_target): New function.
	(target_fileio_open): Likewise.
	(target_fileio_pwrite): Likewise.
	(target_fileio_pread): Likewise.
	(target_fileio_close): Likewise.
	(target_fileio_unlink): Likewise.
	(target_fileio_close_cleanup): Likewise.
	(target_fileio_read_alloc_1): Likewise.
	(target_fileio_read_alloc): Likewise.
	(target_fileio_read_stralloc): Likewise.

	* inf-child.c: Include "gdb/fileio.h", <sys/types.h>, <sys/stat.h>,
	<fcntl.h>, and <unistd.h>.
	(inf_child_fileio_open_flags_to_host): New function.
	(inf_child_errno_to_fileio_error): Likewise.
	(inf_child_fileio_open): Likewise.
	(inf_child_fileio_pwrite): Likewise.
	(inf_child_fileio_pread): Likewise.
	(inf_child_fileio_close): Likewise.
	(inf_child_fileio_unlink): Likewise.
	(inf_child_target): Install to_fileio routines.

	* remote.c (init_remote_ops): Install to_fileio routines.

Patch

Index: gdb-head/gdb/inf-child.c
===================================================================
--- gdb-head.orig/gdb/inf-child.c	2012-01-19 10:35:59.000000000 +0100
+++ gdb-head/gdb/inf-child.c	2012-01-19 10:39:32.000000000 +0100
@@ -27,6 +27,12 @@ 
 #include "inferior.h"
 #include "gdb_string.h"
 #include "inf-child.h"
+#include "gdb/fileio.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
    for all registers.  */
@@ -108,6 +114,192 @@  inf_child_pid_to_exec_file (int pid)
   return NULL;
 }
 
+
+/* Target file operations.  */
+
+static int
+inf_child_fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
+{
+  int open_flags = 0;
+
+  if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
+    return -1;
+
+  if (fileio_open_flags & FILEIO_O_CREAT)
+    open_flags |= O_CREAT;
+  if (fileio_open_flags & FILEIO_O_EXCL)
+    open_flags |= O_EXCL;
+  if (fileio_open_flags & FILEIO_O_TRUNC)
+    open_flags |= O_TRUNC;
+  if (fileio_open_flags & FILEIO_O_APPEND)
+    open_flags |= O_APPEND;
+  if (fileio_open_flags & FILEIO_O_RDONLY)
+    open_flags |= O_RDONLY;
+  if (fileio_open_flags & FILEIO_O_WRONLY)
+    open_flags |= O_WRONLY;
+  if (fileio_open_flags & FILEIO_O_RDWR)
+    open_flags |= O_RDWR;
+/* On systems supporting binary and text mode, always open files in
+   binary mode. */
+#ifdef O_BINARY
+  open_flags |= O_BINARY;
+#endif
+
+  *open_flags_p = open_flags;
+  return 0;
+}
+
+static int
+inf_child_errno_to_fileio_error (int errnum)
+{
+  switch (errnum)
+    {
+      case EPERM:
+        return FILEIO_EPERM;
+      case ENOENT:
+        return FILEIO_ENOENT;
+      case EINTR:
+        return FILEIO_EINTR;
+      case EIO:
+        return FILEIO_EIO;
+      case EBADF:
+        return FILEIO_EBADF;
+      case EACCES:
+        return FILEIO_EACCES;
+      case EFAULT:
+        return FILEIO_EFAULT;
+      case EBUSY:
+        return FILEIO_EBUSY;
+      case EEXIST:
+        return FILEIO_EEXIST;
+      case ENODEV:
+        return FILEIO_ENODEV;
+      case ENOTDIR:
+        return FILEIO_ENOTDIR;
+      case EISDIR:
+        return FILEIO_EISDIR;
+      case EINVAL:
+        return FILEIO_EINVAL;
+      case ENFILE:
+        return FILEIO_ENFILE;
+      case EMFILE:
+        return FILEIO_EMFILE;
+      case EFBIG:
+        return FILEIO_EFBIG;
+      case ENOSPC:
+        return FILEIO_ENOSPC;
+      case ESPIPE:
+        return FILEIO_ESPIPE;
+      case EROFS:
+        return FILEIO_EROFS;
+      case ENOSYS:
+        return FILEIO_ENOSYS;
+      case ENAMETOOLONG:
+        return FILEIO_ENAMETOOLONG;
+    }
+  return FILEIO_EUNKNOWN;
+}
+
+/* Open FILENAME on the target, using FLAGS and MODE.  Return a
+   target file descriptor, or -1 if an error occurs (and set
+   *TARGET_ERRNO).  */
+static int
+inf_child_fileio_open (const char *filename, int flags, int mode,
+		       int *target_errno)
+{
+  int nat_flags;
+  int fd;
+
+  if (inf_child_fileio_open_flags_to_host (flags, &nat_flags) == -1)
+    {
+      *target_errno = FILEIO_EINVAL;
+      return -1;
+    }
+
+  /* We do not need to convert MODE, since the fileio protocol uses
+     the standard values.  */
+  fd = open (filename, nat_flags, mode);
+  if (fd == -1)
+    *target_errno = inf_child_errno_to_fileio_error (errno);
+
+  return fd;
+}
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the target.
+   Return the number of bytes written, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+static int
+inf_child_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+			 ULONGEST offset, int *target_errno)
+{
+  int ret;
+
+#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);
+#endif
+
+  if (ret == -1)
+    *target_errno = inf_child_errno_to_fileio_error (errno);
+
+  return ret;
+}
+
+/* Read up to LEN bytes FD on the target into READ_BUF.
+   Return the number of bytes read, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+static int
+inf_child_fileio_pread (int fd, gdb_byte *read_buf, int len,
+			ULONGEST offset, int *target_errno)
+{
+  int ret;
+
+#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);
+#endif
+
+  if (ret == -1)
+    *target_errno = inf_child_errno_to_fileio_error (errno);
+
+  return ret;
+}
+
+/* Close FD on the target.  Return 0, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+static int
+inf_child_fileio_close (int fd, int *target_errno)
+{
+  int ret;
+
+  ret = close (fd);
+  if (ret == -1)
+    *target_errno = inf_child_errno_to_fileio_error (errno);
+
+  return ret;
+}
+
+/* Unlink FILENAME on the target.  Return 0, or -1 if an error
+   occurs (and set *TARGET_ERRNO).  */
+static int
+inf_child_fileio_unlink (const char *filename, int *target_errno)
+{
+  int ret;
+
+  ret = unlink (filename);
+  if (ret == -1)
+    *target_errno = inf_child_errno_to_fileio_error (errno);
+
+  return ret;
+}
+
+
 struct target_ops *
 inf_child_target (void)
 {
@@ -139,6 +331,11 @@  inf_child_target (void)
   t->to_has_stack = default_child_has_stack;
   t->to_has_registers = default_child_has_registers;
   t->to_has_execution = default_child_has_execution;
+  t->to_fileio_open = inf_child_fileio_open;
+  t->to_fileio_pwrite = inf_child_fileio_pwrite;
+  t->to_fileio_pread = inf_child_fileio_pread;
+  t->to_fileio_close = inf_child_fileio_close;
+  t->to_fileio_unlink = inf_child_fileio_unlink;
   t->to_magic = OPS_MAGIC;
   return t;
 }
Index: gdb-head/gdb/remote.c
===================================================================
--- gdb-head.orig/gdb/remote.c	2012-01-19 10:39:30.000000000 +0100
+++ gdb-head/gdb/remote.c	2012-01-19 10:39:32.000000000 +0100
@@ -10674,6 +10674,11 @@  Specify the serial device it is connecte
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
   remote_ops.to_supports_disable_randomization
     = remote_supports_disable_randomization;
+  remote_ops.to_fileio_open = remote_hostio_open;
+  remote_ops.to_fileio_pwrite = remote_hostio_pwrite;
+  remote_ops.to_fileio_pread = remote_hostio_pread;
+  remote_ops.to_fileio_close = remote_hostio_close;
+  remote_ops.to_fileio_unlink = remote_hostio_unlink;
   remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint;
   remote_ops.to_supports_string_tracing = remote_supports_string_tracing;
   remote_ops.to_trace_init = remote_trace_init;
Index: gdb-head/gdb/target.c
===================================================================
--- gdb-head.orig/gdb/target.c	2012-01-19 10:35:58.000000000 +0100
+++ gdb-head/gdb/target.c	2012-01-19 10:39:32.000000000 +0100
@@ -42,6 +42,7 @@ 
 #include "exec.h"
 #include "inline-frame.h"
 #include "tracepoint.h"
+#include "gdb/fileio.h"
 
 static void target_info (char *, int);
 
@@ -2345,7 +2346,7 @@  target_read_stralloc (struct target_ops 
 		      const char *annex)
 {
   gdb_byte *buffer;
-  LONGEST transferred;
+  LONGEST i, transferred;
 
   transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
 
@@ -2356,10 +2357,16 @@  target_read_stralloc (struct target_ops 
     return xstrdup ("");
 
   buffer[transferred] = 0;
-  if (strlen (buffer) < transferred)
-    warning (_("target object %d, annex %s, "
-	       "contained unexpected null characters"),
-	     (int) object, annex ? annex : "(none)");
+
+  /* Check for embedded NUL bytes; but allow trailing NULs.  */
+  for (i = strlen (buffer); i < transferred; i++)
+    if (buffer[i] != 0)
+      {
+	warning (_("target object %d, annex %s, "
+		   "contained unexpected null characters"),
+		 (int) object, annex ? annex : "(none)");
+	break;
+      }
 
   return (char *) buffer;
 }
@@ -3160,6 +3167,277 @@  target_thread_address_space (ptid_t ptid
   return inf->aspace;
 }
 
+
+/* Target file operations.  */
+
+static struct target_ops *
+default_fileio_target (void)
+{
+  /* If we're already connected to something that can perform
+     file I/O, use it. Otherwise, try using the native target.  */
+  if (current_target.to_stratum >= process_stratum)
+    return current_target.beneath;
+  else
+    return find_default_run_target ("file I/O");
+}
+
+/* Open FILENAME on the target, using FLAGS and MODE.  Return a
+   target file descriptor, or -1 if an error occurs (and set
+   *TARGET_ERRNO).  */
+int
+target_fileio_open (const char *filename, int flags, int mode,
+		    int *target_errno)
+{
+  struct target_ops *t;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_open != NULL)
+	{
+	  int fd = t->to_fileio_open (filename, flags, mode, target_errno);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_open (%s,0x%x,0%o) = %d (%d)\n",
+				filename, flags, mode,
+				fd, fd != -1 ? 0 : *target_errno);
+	  return fd;
+	}
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the target.
+   Return the number of bytes written, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+int
+target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+		      ULONGEST offset, int *target_errno)
+{
+  struct target_ops *t;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_pwrite != NULL)
+	{
+	  int ret = t->to_fileio_pwrite (fd, write_buf, len, offset,
+					 target_errno);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_pwrite (%d,%p,%d,%s) "
+				"= %d (%d)\n",
+				fd, write_buf, len, pulongest (offset),
+				ret, ret != -1 ? 0 : *target_errno);
+	  return ret;
+	}
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+/* Read up to LEN bytes FD on the target into READ_BUF.
+   Return the number of bytes read, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+int
+target_fileio_pread (int fd, gdb_byte *read_buf, int len,
+		     ULONGEST offset, int *target_errno)
+{
+  struct target_ops *t;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_pread != NULL)
+	{
+	  int ret = t->to_fileio_pread (fd, read_buf, len, offset,
+					target_errno);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_pread (%d,%p,%d,%s) "
+				"= %d (%d)\n",
+				fd, read_buf, len, pulongest (offset),
+				ret, ret != -1 ? 0 : *target_errno);
+	  return ret;
+	}
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+/* Close FD on the target.  Return 0, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+int
+target_fileio_close (int fd, int *target_errno)
+{
+  struct target_ops *t;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_close != NULL)
+	{
+	  int ret = t->to_fileio_close (fd, target_errno);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_close (%d) = %d (%d)\n",
+				fd, ret, ret != -1 ? 0 : *target_errno);
+	  return ret;
+	}
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+/* Unlink FILENAME on the target.  Return 0, or -1 if an error
+   occurs (and set *TARGET_ERRNO).  */
+int
+target_fileio_unlink (const char *filename, int *target_errno)
+{
+  struct target_ops *t;
+
+  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+    {
+      if (t->to_fileio_unlink != NULL)
+	{
+	  int ret = t->to_fileio_unlink (filename, target_errno);
+
+	  if (targetdebug)
+	    fprintf_unfiltered (gdb_stdlog,
+				"target_fileio_unlink (%s) = %d (%d)\n",
+				filename, ret, ret != -1 ? 0 : *target_errno);
+	  return ret;
+	}
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+static void
+target_fileio_close_cleanup (void *opaque)
+{
+  int fd = *(int *) opaque;
+  int target_errno;
+
+  target_fileio_close (fd, &target_errno);
+}
+
+/* Read target file FILENAME.  Store the result in *BUF_P and
+   return the size of the transferred data.  PADDING additional bytes are
+   available in *BUF_P.  This is a helper function for
+   target_fileio_read_alloc; see the declaration of that function for more
+   information.  */
+
+static LONGEST
+target_fileio_read_alloc_1 (const char *filename,
+			    gdb_byte **buf_p, int padding)
+{
+  struct cleanup *close_cleanup;
+  size_t buf_alloc, buf_pos;
+  gdb_byte *buf;
+  LONGEST n;
+  int fd;
+  int target_errno;
+
+  fd = target_fileio_open (filename, FILEIO_O_RDONLY, 0700, &target_errno);
+  if (fd == -1)
+    return -1;
+
+  close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
+
+  /* Start by reading up to 4K at a time.  The target will throttle
+     this number down if necessary.  */
+  buf_alloc = 4096;
+  buf = xmalloc (buf_alloc);
+  buf_pos = 0;
+  while (1)
+    {
+      n = target_fileio_pread (fd, &buf[buf_pos],
+			       buf_alloc - buf_pos - padding, buf_pos,
+			       &target_errno);
+      if (n < 0)
+	{
+	  /* An error occurred.  */
+	  do_cleanups (close_cleanup);
+	  xfree (buf);
+	  return -1;
+	}
+      else if (n == 0)
+	{
+	  /* Read all there was.  */
+	  do_cleanups (close_cleanup);
+	  if (buf_pos == 0)
+	    xfree (buf);
+	  else
+	    *buf_p = buf;
+	  return buf_pos;
+	}
+
+      buf_pos += n;
+
+      /* If the buffer is filling up, expand it.  */
+      if (buf_alloc < buf_pos * 2)
+	{
+	  buf_alloc *= 2;
+	  buf = xrealloc (buf, buf_alloc);
+	}
+
+      QUIT;
+    }
+}
+
+/* Read target file FILENAME.  Store the result in *BUF_P and return
+   the size of the transferred data.  See the declaration in "target.h"
+   function for more information about the return value.  */
+
+LONGEST
+target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
+{
+  return target_fileio_read_alloc_1 (filename, buf_p, 0);
+}
+
+/* Read target file FILENAME.  The result is NUL-terminated and
+   returned as a string, allocated using xmalloc.  If an error occurs
+   or the transfer is unsupported, NULL is returned.  Empty objects
+   are returned as allocated but empty strings.  A warning is issued
+   if the result contains any embedded NUL bytes.  */
+
+char *
+target_fileio_read_stralloc (const char *filename)
+{
+  gdb_byte *buffer;
+  LONGEST i, transferred;
+
+  transferred = target_fileio_read_alloc_1 (filename, &buffer, 1);
+
+  if (transferred < 0)
+    return NULL;
+
+  if (transferred == 0)
+    return xstrdup ("");
+
+  buffer[transferred] = 0;
+
+  /* Check for embedded NUL bytes; but allow trailing NULs.  */
+  for (i = strlen (buffer); i < transferred; i++)
+    if (buffer[i] != 0)
+      {
+	warning (_("target file %s "
+		   "contained unexpected null characters"),
+		 filename);
+	break;
+      }
+
+  return (char *) buffer;
+}
+
+
 static int
 default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
 {
Index: gdb-head/gdb/target.h
===================================================================
--- gdb-head.orig/gdb/target.h	2012-01-19 10:35:58.000000000 +0100
+++ gdb-head/gdb/target.h	2012-01-19 10:39:32.000000000 +0100
@@ -681,6 +681,35 @@  struct target_ops
     struct address_space *(*to_thread_address_space) (struct target_ops *,
 						      ptid_t);
 
+    /* Target file operations.  */
+
+    /* Open FILENAME on the target, using FLAGS and MODE.  Return a
+       target file descriptor, or -1 if an error occurs (and set
+       *TARGET_ERRNO).  */
+    int (*to_fileio_open) (const char *filename, int flags, int mode,
+			   int *target_errno);
+
+    /* Write up to LEN bytes from WRITE_BUF to FD on the target.
+       Return the number of bytes written, or -1 if an error occurs
+       (and set *TARGET_ERRNO).  */
+    int (*to_fileio_pwrite) (int fd, const gdb_byte *write_buf, int len,
+			     ULONGEST offset, int *target_errno);
+
+    /* Read up to LEN bytes FD on the target into READ_BUF.
+       Return the number of bytes read, or -1 if an error occurs
+       (and set *TARGET_ERRNO).  */
+    int (*to_fileio_pread) (int fd, gdb_byte *read_buf, int len,
+			    ULONGEST offset, int *target_errno);
+
+    /* Close FD on the target.  Return 0, or -1 if an error occurs
+       (and set *TARGET_ERRNO).  */
+    int (*to_fileio_close) (int fd, int *target_errno);
+
+    /* Unlink FILENAME on the target.  Return 0, or -1 if an error
+       occurs (and set *TARGET_ERRNO).  */
+    int (*to_fileio_unlink) (const char *filename, int *target_errno);
+
+
     /* Tracepoint-related operations.  */
 
     /* Prepare the target for a tracing run.  */
@@ -1489,6 +1518,54 @@  extern int target_search_memory (CORE_AD
                                  ULONGEST pattern_len,
                                  CORE_ADDR *found_addrp);
 
+/* Target file operations.  */
+
+/* Open FILENAME on the target, using FLAGS and MODE.  Return a
+   target file descriptor, or -1 if an error occurs (and set
+   *TARGET_ERRNO).  */
+extern int target_fileio_open (const char *filename, int flags, int mode,
+			       int *target_errno);
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the target.
+   Return the number of bytes written, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+extern int target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+				 ULONGEST offset, int *target_errno);
+
+/* Read up to LEN bytes FD on the target into READ_BUF.
+   Return the number of bytes read, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+extern int target_fileio_pread (int fd, gdb_byte *read_buf, int len,
+				ULONGEST offset, int *target_errno);
+
+/* Close FD on the target.  Return 0, or -1 if an error occurs
+   (and set *TARGET_ERRNO).  */
+extern int target_fileio_close (int fd, int *target_errno);
+
+/* Unlink FILENAME on the target.  Return 0, or -1 if an error
+   occurs (and set *TARGET_ERRNO).  */
+extern int target_fileio_unlink (const char *filename, int *target_errno);
+
+/* Read target file FILENAME.  The return value will be -1 if the transfer
+   fails or is not supported; 0 if the object is empty; or the length
+   of the object otherwise.  If a positive value is returned, a
+   sufficiently large buffer will be allocated using xmalloc and
+   returned in *BUF_P containing the contents of the object.
+
+   This method should be used for objects sufficiently small to store
+   in a single xmalloc'd buffer, when no fixed bound on the object's
+   size is known in advance.  */
+extern LONGEST target_fileio_read_alloc (const char *filename,
+					 gdb_byte **buf_p);
+
+/* Read target file FILENAME.  The result is NUL-terminated and
+   returned as a string, allocated using xmalloc.  If an error occurs
+   or the transfer is unsupported, NULL is returned.  Empty objects
+   are returned as allocated but empty strings.  A warning is issued
+   if the result contains any embedded NUL bytes.  */
+extern char *target_fileio_read_stralloc (const char *filename);
+
+
 /* Tracepoint-related operations.  */
 
 #define target_trace_init() \
Index: gdb-head/gdb/config.in
===================================================================
--- gdb-head.orig/gdb/config.in	2012-01-19 10:38:28.000000000 +0100
+++ gdb-head/gdb/config.in	2012-01-19 10:39:32.000000000 +0100
@@ -324,6 +324,9 @@ 
 /* Define to 1 if you have the `posix_madvise' function. */
 #undef HAVE_POSIX_MADVISE
 
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
 /* Define to 1 if you have the `pread64' function. */
 #undef HAVE_PREAD64
 
@@ -381,6 +384,9 @@ 
 /* Define if sys/ptrace.h defines the PT_GETXMMREGS request. */
 #undef HAVE_PT_GETXMMREGS
 
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
 /* Define if Python interpreter is being linked in. */
 #undef HAVE_PYTHON
 
Index: gdb-head/gdb/configure
===================================================================
--- gdb-head.orig/gdb/configure	2012-01-19 10:38:28.000000000 +0100
+++ gdb-head/gdb/configure	2012-01-19 10:40:05.000000000 +0100
@@ -12931,8 +12931,9 @@  $as_echo "#define HAVE_WORKING_FORK 1" >
 
 fi
 
-for ac_func in canonicalize_file_name realpath getrusage getuid \
-		getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
+for ac_func in canonicalize_file_name realpath getrusage getuid getgid \
+		pipe poll pread pread64 pwrite resize_term \
+		sbrk setpgid setpgrp setsid \
 		sigaction sigprocmask sigsetmask socketpair syscall \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid lstat
Index: gdb-head/gdb/configure.ac
===================================================================
--- gdb-head.orig/gdb/configure.ac	2012-01-19 10:38:28.000000000 +0100
+++ gdb-head/gdb/configure.ac	2012-01-19 10:39:32.000000000 +0100
@@ -1063,8 +1063,9 @@  AC_C_BIGENDIAN
 AC_FUNC_ALLOCA
 AC_FUNC_MMAP
 AC_FUNC_VFORK
-AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \
-		getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
+AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid getgid \
+		pipe poll pread pread64 pwrite resize_term \
+		sbrk setpgid setpgrp setsid \
 		sigaction sigprocmask sigsetmask socketpair syscall \
 		ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
 		setrlimit getrlimit posix_madvise waitpid lstat])