2012-01-20 Pedro Alves <palves@redhat.com>
authorUlrich Weigand <uweigand@de.ibm.com>
Fri, 20 Jan 2012 09:45:51 +0000 (09:45 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Fri, 20 Jan 2012 09:45:51 +0000 (09:45 +0000)
    Ulrich Weigand  <ulrich.weigand@linaro.org>

* 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.

gdb/ChangeLog
gdb/config.in
gdb/configure
gdb/configure.ac
gdb/inf-child.c
gdb/remote.c
gdb/target.c
gdb/target.h

index 6a94f5de3921fbcca5f96673bb39baec2bf089b6..65cfb170968d9550d3e2f8d45e4edea12bd7bd2f 100644 (file)
@@ -1,3 +1,45 @@
+2012-01-20  Pedro Alves  <palves@redhat.com>
+           Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+       * 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.
+
 2012-01-20  Pedro Alves  <palves@redhat.com>
            Ulrich Weigand  <ulrich.weigand@linaro.org>
 
index 45c2c73ff0af7f715e6ad72d7d7374ab0f08b64a..540234fbb2ae8a9389abd76727e21631558b020c 100644 (file)
 /* 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
 
 /* 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 2ced763c10a9ae353ddbb41d1aa4e27c67c6b9aa..5dd99fbc9fde3596b059808f7d31694b0f9e6517 100755 (executable)
@@ -12931,8 +12931,9 @@ $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
 
 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 66844ed614afc8453b1d70fa61a0e6c64498cbf7..aca96b8ce3448458d05f99c4219d6eba9da7d149 100644 (file)
@@ -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])
index c91a89b0c994fcb7d74ef063c8651ff6a91555be..0dda33151876d82e2d9e426cdf34b11171cd0c51 100644 (file)
 #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 2b46c43c0659a6fffb66ccce363e742b5bfe863e..89d491ee3be9f5b6f99d3ceea6c068d15d93440c 100644 (file)
@@ -10674,6 +10674,11 @@ Specify the serial device it is connected to\n\
   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 6af4620ddf709c5c45f279fe961b2460d30f11e7..595c2ced6c3a9fbf2bf9599803a956680db93e0f 100644 (file)
@@ -42,6 +42,7 @@
 #include "exec.h"
 #include "inline-frame.h"
 #include "tracepoint.h"
+#include "gdb/fileio.h"
 
 static void target_info (char *, int);
 
@@ -2344,7 +2345,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
                      const char *annex)
 {
   gdb_byte *buffer;
-  LONGEST transferred;
+  LONGEST i, transferred;
 
   transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
 
@@ -2355,10 +2356,16 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
     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;
 }
@@ -3159,6 +3166,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 425c877077cd8df7987b222857bcce3c60827646..4bbf4de88d19e8eb3af71e65797478a316b04a53 100644 (file)
@@ -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_ADDR start_addr,
                                  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() \