/* Definitions for BFD wrappers used by GDB.
- Copyright (C) 2011, 2012
- 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
#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. */
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
/* 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;
};
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);
gdb_assert (!*slot);
*slot = abfd;
- gdb_bfd_stash_filename (abfd);
gdb_bfd_ref (abfd);
return 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;
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. */
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;
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. */
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;
}
bfd *result = bfd_openr (filename, target);
if (result)
- {
- gdb_bfd_stash_filename (result);
- gdb_bfd_ref (result);
- }
+ gdb_bfd_ref (result);
return result;
}
bfd *result = bfd_openw (filename, target);
if (result)
- {
- gdb_bfd_stash_filename (result);
- gdb_bfd_ref (result);
- }
+ gdb_bfd_ref (result);
return result;
}
pread_func, close_func, stat_func);
if (result)
- {
- gdb_bfd_ref (result);
- gdb_bfd_stash_filename (result);
- }
+ gdb_bfd_ref (result);
return result;
}
/* See gdb_bfd.h. */
+void
+gdb_bfd_mark_parent (bfd *child, bfd *parent)
+{
+ struct gdb_bfd_data *gdata;
+
+ gdb_bfd_ref (child);
+ /* No need to stash the filename here, because we also keep a
+ reference on the parent archive. */
+
+ gdata = bfd_usrdata (child);
+ if (gdata->archive_bfd == NULL)
+ {
+ gdata->archive_bfd = parent;
+ gdb_bfd_ref (parent);
+ }
+ else
+ gdb_assert (gdata->archive_bfd == parent);
+}
+
+/* See gdb_bfd.h. */
+
bfd *
gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
{
bfd *result = bfd_openr_next_archived_file (archive, previous);
if (result)
- {
- struct gdb_bfd_data *gdata;
+ gdb_bfd_mark_parent (result, archive);
- gdb_bfd_ref (result);
- /* No need to stash the filename here, because we also keep a
- reference on the parent archive. */
+ return result;
+}
- gdata = bfd_usrdata (result);
- gdb_assert (gdata->archive_bfd == NULL || gdata->archive_bfd == archive);
- gdata->archive_bfd = archive;
- gdb_bfd_ref (archive);
- }
+/* See gdb_bfd.h. */
- return result;
+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 *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