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]

[PATCH 3/9] Make gdb_bfd_open able to open BFDs using target fileio


This commit updates gdb_bfd_open to access files using target
fileio functions if the supplied path starts with "target:"
and if the local and target filesystems are not the same.
This allows users to specify "set sysroot target:" and have
GDB access files locally or from the remote as appropriate.

The new functions in gdb_bfd.c are copies of functions from
remote.c. This duplication is intentional and will be removed
by the next commit in this series.

gdb/ChangeLog:

	* gdb/gdb_bfd.h (TARGET_SYSROOT_PREFIX): New definition.
	(is_target_filename): New declaration.
	(gdb_bfd_has_target_filename): Likewise.
	(gdb_bfd_open): Update documentation comment.
	* gdb_bfd.c (target.h): New include.
	(gdb/fileio.h): Likewise.
	(is_target_filename): New function.
	(gdb_bfd_has_target_filename): Likewise.
	(fileio_errno_to_host): Likewise.
	(gdb_bfd_iovec_fileio_open): Likewise.
	(gdb_bfd_iovec_fileio_pread): Likewise.
	(gdb_bfd_iovec_fileio_close): Likewise.
	(gdb_bfd_iovec_fileio_fstat): Likewise.
	(gdb_bfd_open): Use target fileio to access paths prefixed
	with "target:" where necessary.
---
 gdb/ChangeLog |   18 +++++
 gdb/gdb_bfd.c |  203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdb_bfd.h |   29 +++++++-
 3 files changed, 246 insertions(+), 4 deletions(-)

diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 7543dae..43bd328 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -33,6 +33,8 @@
 #define MAP_FAILED ((void *) -1)
 #endif
 #endif
+#include "target.h"
+#include "gdb/fileio.h"
 
 typedef bfd *bfdp;
 DEF_VEC_P (bfdp);
@@ -141,6 +143,177 @@ eq_bfd (const void *a, const void *b)
 
 /* See gdb_bfd.h.  */
 
+int
+is_target_filename (const char *name)
+{
+  return startswith (name, TARGET_SYSROOT_PREFIX);
+}
+
+/* See gdb_bfd.h.  */
+
+int
+gdb_bfd_has_target_filename (struct bfd *abfd)
+{
+  return is_target_filename (bfd_get_filename (abfd));
+}
+
+
+/* Return the system error number corresponding to ERRNUM.  */
+
+static int
+fileio_errno_to_host (int errnum)
+{
+  switch (errnum)
+    {
+      case FILEIO_EPERM:
+        return EPERM;
+      case FILEIO_ENOENT:
+        return ENOENT;
+      case FILEIO_EINTR:
+        return EINTR;
+      case FILEIO_EIO:
+        return EIO;
+      case FILEIO_EBADF:
+        return EBADF;
+      case FILEIO_EACCES:
+        return EACCES;
+      case FILEIO_EFAULT:
+        return EFAULT;
+      case FILEIO_EBUSY:
+        return EBUSY;
+      case FILEIO_EEXIST:
+        return EEXIST;
+      case FILEIO_ENODEV:
+        return ENODEV;
+      case FILEIO_ENOTDIR:
+        return ENOTDIR;
+      case FILEIO_EISDIR:
+        return EISDIR;
+      case FILEIO_EINVAL:
+        return EINVAL;
+      case FILEIO_ENFILE:
+        return ENFILE;
+      case FILEIO_EMFILE:
+        return EMFILE;
+      case FILEIO_EFBIG:
+        return EFBIG;
+      case FILEIO_ENOSPC:
+        return ENOSPC;
+      case FILEIO_ESPIPE:
+        return ESPIPE;
+      case FILEIO_EROFS:
+        return EROFS;
+      case FILEIO_ENOSYS:
+        return ENOSYS;
+      case FILEIO_ENAMETOOLONG:
+        return ENAMETOOLONG;
+    }
+  return -1;
+}
+
+/* Wrapper for target_fileio_open suitable for passing as the
+   OPEN_FUNC argument to gdb_bfd_openr_iovec.  The supplied
+   OPEN_CLOSURE is unused.  */
+
+static void *
+gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
+{
+  const char *filename = bfd_get_filename (abfd);
+  int fd, target_errno;
+  int *stream;
+
+  gdb_assert (is_target_filename (filename));
+
+  fd = target_fileio_open (filename + strlen (TARGET_SYSROOT_PREFIX),
+			   FILEIO_O_RDONLY, 0,
+			   &target_errno);
+  if (fd == -1)
+    {
+      errno = fileio_errno_to_host (target_errno);
+      bfd_set_error (bfd_error_system_call);
+      return NULL;
+    }
+
+  stream = XCNEW (int);
+  *stream = fd;
+  return stream;
+}
+
+/* Wrapper for target_fileio_pread suitable for passing as the
+   PREAD_FUNC argument to gdb_bfd_openr_iovec.  */
+
+static file_ptr
+gdb_bfd_iovec_fileio_pread (struct bfd *abfd, void *stream, void *buf,
+			    file_ptr nbytes, file_ptr offset)
+{
+  int fd = *(int *) stream;
+  int target_errno;
+  file_ptr pos, bytes;
+
+  pos = 0;
+  while (nbytes > pos)
+    {
+      bytes = target_fileio_pread (fd, (gdb_byte *) buf + pos,
+				   nbytes - pos, offset + pos,
+				   &target_errno);
+      if (bytes == 0)
+        /* Success, but no bytes, means end-of-file.  */
+        break;
+      if (bytes == -1)
+	{
+	  errno = fileio_errno_to_host (target_errno);
+	  bfd_set_error (bfd_error_system_call);
+	  return -1;
+	}
+
+      pos += bytes;
+    }
+
+  return pos;
+}
+
+/* Wrapper for target_fileio_close suitable for passing as the
+   CLOSE_FUNC argument to gdb_bfd_openr_iovec.  */
+
+static int
+gdb_bfd_iovec_fileio_close (struct bfd *abfd, void *stream)
+{
+  int fd = *(int *) stream;
+  int target_errno;
+
+  xfree (stream);
+
+  /* Ignore errors on close.  These may happen with remote
+     targets if the connection has already been torn down.  */
+  target_fileio_close (fd, &target_errno);
+
+  /* Zero means success.  */
+  return 0;
+}
+
+/* Wrapper for target_fileio_fstat suitable for passing as the
+   STAT_FUNC argument to gdb_bfd_openr_iovec.  */
+
+static int
+gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
+			    struct stat *sb)
+{
+  int fd = *(int *) stream;
+  int target_errno;
+  int result;
+
+  result = target_fileio_fstat (fd, sb, &target_errno);
+  if (result == -1)
+    {
+      errno = fileio_errno_to_host (target_errno);
+      bfd_set_error (bfd_error_system_call);
+    }
+
+  return result;
+}
+
+/* See gdb_bfd.h.  */
+
 struct bfd *
 gdb_bfd_open (const char *name, const char *target, int fd)
 {
@@ -150,6 +323,36 @@ gdb_bfd_open (const char *name, const char *target, int fd)
   struct gdb_bfd_cache_search search;
   struct stat st;
 
+  if (is_target_filename (name))
+    {
+      if (!target_filesystem_is_local)
+	{
+	  gdb_assert (fd == -1);
+
+	  abfd = gdb_bfd_openr_iovec (name, target,
+				      gdb_bfd_iovec_fileio_open, NULL,
+				      gdb_bfd_iovec_fileio_pread,
+				      gdb_bfd_iovec_fileio_close,
+				      gdb_bfd_iovec_fileio_fstat);
+
+	  if (abfd != NULL || errno != ENOSYS)
+	    return abfd;
+
+	  /* gdb_bfd_iovec_fileio_open failed with ENOSYS.  This can
+	     happen, for example, with vgdb (Valgrind GDB), which
+	     presents itself as a remote target but works on the local
+	     filesystem: it does not implement remote get and users
+	     are not expected to set gdb_sysroot.  To handle this case
+	     we fall back to trying the local filesystem iff
+	     gdb_sysroot is exactly TARGET_SYSROOT_PREFIX.  */
+	  if (gdb_sysroot == NULL
+	      || strcmp (gdb_sysroot, TARGET_SYSROOT_PREFIX) != 0)
+	    return NULL;
+	}
+
+      name += strlen (TARGET_SYSROOT_PREFIX);
+    }
+
   if (gdb_bfd_cache == NULL)
     gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL,
 				       xcalloc, xfree);
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index 05b6870..8fbdf36 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -24,11 +24,32 @@
 
 DECLARE_REGISTRY (bfd);
 
+/* If supplied a path starting with this sequence, gdb_bfd_open will
+   open BFDs using target fileio operations.  */
+
+#define TARGET_SYSROOT_PREFIX "target:"
+
+/* Returns nonzero if NAME starts with TARGET_SYSROOT_PREFIX, zero
+   otherwise.  */
+
+int is_target_filename (const char *name);
+
+/* Returns nonzero if the filename associated with ABFD starts with
+   TARGET_SYSROOT_PREFIX, zero otherwise.  */
+
+int gdb_bfd_has_target_filename (struct bfd *abfd);
+
 /* Open a read-only (FOPEN_RB) BFD given arguments like bfd_fopen.
-   Returns NULL on error.  On success, returns a new reference to the
-   BFD, which must be freed with gdb_bfd_unref.  BFDs returned by this
-   call are shared among all callers opening the same file.  If FD is
-   not -1, then after this call it is owned by BFD.  */
+   If NAME starts with TARGET_SYSROOT_PREFIX then the BFD will be
+   opened using target fileio operations if necessary.  Returns NULL
+   on error.  On success, returns a new reference to the BFD, which
+   must be freed with gdb_bfd_unref.  BFDs returned by this call are
+   shared among all callers opening the same file.  If FD is not -1,
+   then after this call it is owned by BFD.  If the BFD was not
+   accessed using target fileio operations then the filename
+   associated with the BFD and accessible with bfd_get_filename will
+   not be exactly NAME but rather NAME with TARGET_SYSROOT_PREFIX
+   stripped.  */
 
 struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);
 
-- 
1.7.1


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