PR symtab/16426
[deliverable/binutils-gdb.git] / gdb / gdb_bfd.c
index ae561d39f6fe298c78ad925ee53f1bdb5ce4c1ca..4d4b0a53593a3560b742a27f7ad51d1dff5e109f 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions for BFD wrappers used by GDB.
 
-   Copyright (C) 2011-2013 Free Software Foundation, Inc.
+   Copyright (C) 2011-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "defs.h"
 #include "gdb_bfd.h"
 #include "gdb_assert.h"
-#include "gdb_string.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
@@ -34,6 +36,9 @@
 #endif
 #endif
 
+typedef bfd *bfdp;
+DEF_VEC_P (bfdp);
+
 /* An object of this type is stored in the section's user data when
    mapping a section.  */
 
@@ -56,21 +61,6 @@ struct gdb_bfd_section_data
 
 static htab_t all_bfds;
 
-/* See gdb_bfd.h.  */
-
-void
-gdb_bfd_stash_filename (struct bfd *abfd)
-{
-  char *name = bfd_get_filename (abfd);
-  char *data;
-
-  data = bfd_alloc (abfd, strlen (name) + 1);
-  strcpy (data, name);
-
-  /* Unwarranted chumminess with BFD.  */
-  abfd->filename = data;
-}
-
 /* An object of this type is stored in each BFD's user data.  */
 
 struct gdb_bfd_data
@@ -81,10 +71,26 @@ struct gdb_bfd_data
   /* The mtime of the BFD at the point the cache entry was made.  */
   time_t mtime;
 
+  /* This is true if we have determined whether this BFD has any
+     sections requiring relocation.  */
+  unsigned int relocation_computed : 1;
+
+  /* This is true if any section needs relocation.  */
+  unsigned int needs_relocations : 1;
+
+  /* This is true if we have successfully computed the file's CRC.  */
+  unsigned int crc_computed : 1;
+
+  /* The file's CRC.  */
+  unsigned long crc;
+
   /* If the BFD comes from an archive, this points to the archive's
      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;
 };
@@ -152,7 +158,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
 
   if (fd == -1)
     {
-      fd = open (name, O_RDONLY | O_BINARY);
+      fd = gdb_open_cloexec (name, O_RDONLY | O_BINARY, 0);
       if (fd == -1)
        {
          bfd_set_error (bfd_error_system_call);
@@ -190,7 +196,6 @@ gdb_bfd_open (const char *name, const char *target, int fd)
   gdb_assert (!*slot);
   *slot = abfd;
 
-  gdb_bfd_stash_filename (abfd);
   gdb_bfd_ref (abfd);
   return abfd;
 }
@@ -279,9 +284,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;
@@ -309,6 +315,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.  */
 
@@ -345,7 +357,6 @@ const gdb_byte *
 gdb_bfd_map_section (asection *sectp, bfd_size_type *size)
 {
   bfd *abfd;
-  unsigned char header[4];
   struct gdb_bfd_section_data *descriptor;
   bfd_byte *data;
 
@@ -414,6 +425,58 @@ gdb_bfd_map_section (asection *sectp, bfd_size_type *size)
   return descriptor->data;
 }
 
+/* Return 32-bit CRC for ABFD.  If successful store it to *FILE_CRC_RETURN and
+   return 1.  Otherwise print a warning and return 0.  ABFD seek position is
+   not preserved.  */
+
+static int
+get_file_crc (bfd *abfd, unsigned long *file_crc_return)
+{
+  unsigned long file_crc = 0;
+
+  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+    {
+      warning (_("Problem reading \"%s\" for CRC: %s"),
+              bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+      return 0;
+    }
+
+  for (;;)
+    {
+      gdb_byte buffer[8 * 1024];
+      bfd_size_type count;
+
+      count = bfd_bread (buffer, sizeof (buffer), abfd);
+      if (count == (bfd_size_type) -1)
+       {
+         warning (_("Problem reading \"%s\" for CRC: %s"),
+                  bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+         return 0;
+       }
+      if (count == 0)
+       break;
+      file_crc = bfd_calc_gnu_debuglink_crc32 (file_crc, buffer, count);
+    }
+
+  *file_crc_return = file_crc;
+  return 1;
+}
+
+/* See gdb_bfd.h.  */
+
+int
+gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out)
+{
+  struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
+
+  if (!gdata->crc_computed)
+    gdata->crc_computed = get_file_crc (abfd, &gdata->crc);
+
+  if (gdata->crc_computed)
+    *crc_out = gdata->crc;
+  return gdata->crc_computed;
+}
+
 \f
 
 /* See gdb_bfd.h.  */
@@ -425,10 +488,7 @@ gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
   bfd *result = bfd_fopen (filename, target, mode, fd);
 
   if (result)
-    {
-      gdb_bfd_stash_filename (result);
-      gdb_bfd_ref (result);
-    }
+    gdb_bfd_ref (result);
 
   return result;
 }
@@ -441,10 +501,7 @@ gdb_bfd_openr (const char *filename, const char *target)
   bfd *result = bfd_openr (filename, target);
 
   if (result)
-    {
-      gdb_bfd_stash_filename (result);
-      gdb_bfd_ref (result);
-    }
+    gdb_bfd_ref (result);
 
   return result;
 }
@@ -457,10 +514,7 @@ gdb_bfd_openw (const char *filename, const char *target)
   bfd *result = bfd_openw (filename, target);
 
   if (result)
-    {
-      gdb_bfd_stash_filename (result);
-      gdb_bfd_ref (result);
-    }
+    gdb_bfd_ref (result);
 
   return result;
 }
@@ -488,10 +542,7 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
                                 pread_func, close_func, stat_func);
 
   if (result)
-    {
-      gdb_bfd_ref (result);
-      gdb_bfd_stash_filename (result);
-    }
+    gdb_bfd_ref (result);
 
   return result;
 }
@@ -532,18 +583,81 @@ 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)
 {
   bfd *result = bfd_fdopenr (filename, target, fd);
 
   if (result)
+    gdb_bfd_ref (result);
+
+  return result;
+}
+
+\f
+
+gdb_static_assert (ARRAY_SIZE (_bfd_std_section) == 4);
+
+/* See gdb_bfd.h.  */
+
+int
+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;
+  else if (section == bfd_und_section_ptr)
+    return bfd_count_sections (abfd) + 2;
+  else if (section == bfd_abs_section_ptr)
+    return bfd_count_sections (abfd) + 3;
+  else if (section == bfd_ind_section_ptr)
+    return bfd_count_sections (abfd) + 4;
+  return section->index;
+}
+
+/* See gdb_bfd.h.  */
+
+int
+gdb_bfd_count_sections (bfd *abfd)
+{
+  return bfd_count_sections (abfd) + 4;
+}
+
+/* See gdb_bfd.h.  */
+
+int
+gdb_bfd_requires_relocations (bfd *abfd)
+{
+  struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
+
+  if (gdata->relocation_computed == 0)
     {
-      gdb_bfd_ref (result);
-      gdb_bfd_stash_filename (result);
+      asection *sect;
+
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+       if ((sect->flags & SEC_RELOC) != 0)
+         {
+           gdata->needs_relocations = 1;
+           break;
+         }
+
+      gdata->relocation_computed = 1;
     }
 
-  return result;
+  return gdata->needs_relocations;
 }
 
 \f
This page took 0.028496 seconds and 4 git commands to generate.