Disable displaced stepping if trying it fails
[deliverable/binutils-gdb.git] / gdb / gdb_bfd.c
index 5230d213b35cd88566dab40ae8546128fce3d2d1..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 "gdb_assert.h"
-#include <string.h>
 #include "ui-out.h"
 #include "gdbcmd.h"
 #include "hashtab.h"
 #include "filestuff.h"
-#ifdef HAVE_ZLIB_H
-#include <zlib.h>
-#endif
+#include "vec.h"
 #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);
 
 /* An object of this type is stored in the section's user data when
    mapping a section.  */
@@ -84,6 +86,9 @@ struct gdb_bfd_data
      BFD.  Otherwise, this is NULL.  */
   bfd *archive_bfd;
 
+  /* Table of all the bfds this bfd has included.  */
+  VEC (bfdp) *included_bfds;
+
   /* The registry.  */
   REGISTRY_FIELDS;
 };
@@ -136,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)
 {
@@ -145,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);
@@ -277,9 +471,10 @@ gdb_bfd_ref (struct bfd *abfd)
 void
 gdb_bfd_unref (struct bfd *abfd)
 {
+  int ix;
   struct gdb_bfd_data *gdata;
   struct gdb_bfd_cache_search search;
-  bfd *archive_bfd;
+  bfd *archive_bfd, *included_bfd;
 
   if (abfd == NULL)
     return;
@@ -307,6 +502,12 @@ gdb_bfd_unref (struct bfd *abfd)
        htab_clear_slot (gdb_bfd_cache, slot);
     }
 
+  for (ix = 0;
+       VEC_iterate (bfdp, gdata->included_bfds, ix, included_bfd);
+       ++ix)
+    gdb_bfd_unref (included_bfd);
+  VEC_free (bfdp, gdata->included_bfds);
+
   bfd_free_data (abfd);
   bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
 
@@ -569,6 +770,18 @@ gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
 
 /* See gdb_bfd.h.  */
 
+void
+gdb_bfd_record_inclusion (bfd *includer, bfd *includee)
+{
+  struct gdb_bfd_data *gdata;
+
+  gdb_bfd_ref (includee);
+  gdata = bfd_usrdata (includer);
+  VEC_safe_push (bfdp, gdata->included_bfds, includee);
+}
+
+/* See gdb_bfd.h.  */
+
 bfd *
 gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
 {
@@ -592,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.027302 seconds and 4 git commands to generate.