sim: trace: add set of system helpers
[deliverable/binutils-gdb.git] / gdb / gdb_bfd.c
index fdde3e7be42757a9ad6b6fabc5b8989e61bcf9d0..1781d80853723713a0b544928ae8edd4828214ca 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for BFD wrappers used by GDB.
 
-   Copyright (C) 2011-2014 Free Software Foundation, Inc.
+   Copyright (C) 2011-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include "defs.h"
 #include "gdb_bfd.h"
-#include <string.h>
 #include "ui-out.h"
 #include "gdbcmd.h"
 #include "hashtab.h"
 #include "filestuff.h"
 #include "vec.h"
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
 #ifndef MAP_FAILED
 #define MAP_FAILED ((void *) -1)
 #endif
 #endif
+#include "target.h"
+#include "gdb/fileio.h"
+#include "inferior.h"
 
 typedef bfd *bfdp;
 DEF_VEC_P (bfdp);
@@ -142,6 +141,178 @@ 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 *inferior)
+{
+  const char *filename = bfd_get_filename (abfd);
+  int fd, target_errno;
+  int *stream;
+
+  gdb_assert (is_target_filename (filename));
+
+  fd = target_fileio_open ((struct inferior *) inferior,
+                          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)
 {
@@ -151,6 +322,23 @@ 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);
+
+         return gdb_bfd_openr_iovec (name, target,
+                                     gdb_bfd_iovec_fileio_open,
+                                     current_inferior (),
+                                     gdb_bfd_iovec_fileio_pread,
+                                     gdb_bfd_iovec_fileio_close,
+                                     gdb_bfd_iovec_fileio_fstat);
+       }
+
+      name += strlen (TARGET_SYSROOT_PREFIX);
+    }
+
   if (gdb_bfd_cache == NULL)
     gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL,
                                       xcalloc, xfree);
@@ -617,13 +805,13 @@ gdb_bfd_section_index (bfd *abfd, asection *section)
   if (section == NULL)
     return -1;
   else if (section == bfd_com_section_ptr)
-    return bfd_count_sections (abfd) + 1;
+    return bfd_count_sections (abfd);
   else if (section == bfd_und_section_ptr)
-    return bfd_count_sections (abfd) + 2;
+    return bfd_count_sections (abfd) + 1;
   else if (section == bfd_abs_section_ptr)
-    return bfd_count_sections (abfd) + 3;
+    return bfd_count_sections (abfd) + 2;
   else if (section == bfd_ind_section_ptr)
-    return bfd_count_sections (abfd) + 4;
+    return bfd_count_sections (abfd) + 3;
   return section->index;
 }
 
This page took 0.026588 seconds and 4 git commands to generate.