X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdb_bfd.c;h=4d4b0a53593a3560b742a27f7ad51d1dff5e109f;hb=cf2a3e990524cb794c75e0493169736dee6a660c;hp=40e1c4dc3a6b60cef2772c27c6a3f5f1f2b9970b;hpb=d6b289409bc58646f2a8ca2744e78fbee349497e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c index 40e1c4dc3a..4d4b0a5359 100644 --- a/gdb/gdb_bfd.c +++ b/gdb/gdb_bfd.c @@ -1,7 +1,6 @@ /* 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. @@ -21,10 +20,12 @@ #include "defs.h" #include "gdb_bfd.h" #include "gdb_assert.h" -#include "gdb_string.h" +#include #include "ui-out.h" #include "gdbcmd.h" #include "hashtab.h" +#include "filestuff.h" +#include "vec.h" #ifdef HAVE_ZLIB_H #include #endif @@ -35,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. */ @@ -57,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,8 +70,36 @@ 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; }; +#define GDB_BFD_DATA_ACCESSOR(ABFD) \ + ((struct gdb_bfd_data *) bfd_usrdata (ABFD)) + +DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR) + /* A hash table storing all the BFDs maintained in the cache. */ static htab_t gdb_bfd_cache; @@ -141,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); @@ -179,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; } @@ -246,11 +262,17 @@ gdb_bfd_ref (struct bfd *abfd) return; } + /* Ask BFD to decompress sections in bfd_get_full_section_contents. */ + abfd->flags |= BFD_DECOMPRESS; + gdata = bfd_zalloc (abfd, sizeof (struct gdb_bfd_data)); gdata->refc = 1; gdata->mtime = bfd_get_mtime (abfd); + gdata->archive_bfd = NULL; bfd_usrdata (abfd) = gdata; + bfd_alloc_data (abfd); + /* This is the first we've seen it, so add it to the hash table. */ slot = htab_find_slot (all_bfds, abfd, INSERT); gdb_assert (slot && !*slot); @@ -262,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; - void **slot; + bfd *archive_bfd, *included_bfd; if (abfd == NULL) return; @@ -276,6 +299,7 @@ gdb_bfd_unref (struct bfd *abfd) if (gdata->refc > 0) return; + archive_bfd = gdata->archive_bfd; search.filename = bfd_get_filename (abfd); if (gdb_bfd_cache && search.filename) @@ -291,11 +315,20 @@ 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. */ htab_remove_elt (all_bfds, abfd); gdb_bfd_close_or_warn (abfd); + + gdb_bfd_unref (archive_bfd); } /* A helper function that returns the section data descriptor @@ -318,108 +351,14 @@ get_section_descriptor (asection *section) return result; } -/* Decompress a section that was compressed using zlib. Store the - decompressed buffer, and its size, in DESCRIPTOR. */ - -static void -zlib_decompress_section (asection *sectp, - struct gdb_bfd_section_data *descriptor) -{ - bfd *abfd = sectp->owner; -#ifndef HAVE_ZLIB_H - error (_("Support for zlib-compressed data (from '%s', section '%s') " - "is disabled in this copy of GDB"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp)); -#else - bfd_size_type compressed_size = bfd_get_section_size (sectp); - gdb_byte *compressed_buffer = xmalloc (compressed_size); - struct cleanup *cleanup = make_cleanup (xfree, compressed_buffer); - struct cleanup *inner_cleanup; - bfd_size_type uncompressed_size; - gdb_byte *uncompressed_buffer; - z_stream strm; - int rc; - int header_size = 12; - struct dwarf2_per_bfd_section *section_data; - - if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 - || bfd_bread (compressed_buffer, - compressed_size, abfd) != compressed_size) - error (_("can't read data from '%s', section '%s'"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp)); - - /* Read the zlib header. In this case, it should be "ZLIB" followed - by the uncompressed section size, 8 bytes in big-endian order. */ - if (compressed_size < header_size - || strncmp (compressed_buffer, "ZLIB", 4) != 0) - error (_("corrupt ZLIB header from '%s', section '%s'"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp)); - uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8; - uncompressed_size += compressed_buffer[11]; - - /* It is possible the section consists of several compressed - buffers concatenated together, so we uncompress in a loop. */ - strm.zalloc = NULL; - strm.zfree = NULL; - strm.opaque = NULL; - strm.avail_in = compressed_size - header_size; - strm.next_in = (Bytef*) compressed_buffer + header_size; - strm.avail_out = uncompressed_size; - uncompressed_buffer = xmalloc (uncompressed_size); - inner_cleanup = make_cleanup (xfree, uncompressed_buffer); - rc = inflateInit (&strm); - while (strm.avail_in > 0) - { - if (rc != Z_OK) - error (_("setting up uncompression in '%s', section '%s': %d"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp), - rc); - strm.next_out = ((Bytef*) uncompressed_buffer - + (uncompressed_size - strm.avail_out)); - rc = inflate (&strm, Z_FINISH); - if (rc != Z_STREAM_END) - error (_("zlib error uncompressing from '%s', section '%s': %d"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp), - rc); - rc = inflateReset (&strm); - } - rc = inflateEnd (&strm); - if (rc != Z_OK - || strm.avail_out != 0) - error (_("concluding uncompression in '%s', section '%s': %d"), - bfd_get_filename (abfd), - bfd_get_section_name (abfd, sectp), - rc); - - discard_cleanups (inner_cleanup); - do_cleanups (cleanup); - - /* Attach the data to the BFD section. */ - descriptor->data = uncompressed_buffer; - descriptor->size = uncompressed_size; -#endif -} - /* See gdb_bfd.h. */ const gdb_byte * gdb_bfd_map_section (asection *sectp, bfd_size_type *size) { bfd *abfd; - gdb_byte *buf, *retbuf; - unsigned char header[4]; struct gdb_bfd_section_data *descriptor; + bfd_byte *data; gdb_assert ((sectp->flags & SEC_RELOC) == 0); gdb_assert (size != NULL); @@ -432,67 +371,53 @@ gdb_bfd_map_section (asection *sectp, bfd_size_type *size) if (descriptor->data != NULL) goto done; - /* Check if the file has a 4-byte header indicating compression. */ - if (bfd_get_section_size (sectp) > sizeof (header) - && bfd_seek (abfd, sectp->filepos, SEEK_SET) == 0 - && bfd_bread (header, sizeof (header), abfd) == sizeof (header)) - { - /* Upon decompression, update the buffer and its size. */ - if (strncmp (header, "ZLIB", sizeof (header)) == 0) - { - zlib_decompress_section (sectp, descriptor); - goto done; - } - } - #ifdef HAVE_MMAP - { - /* The page size, used when mmapping. */ - static int pagesize; - - if (pagesize == 0) - pagesize = getpagesize (); + if (!bfd_is_section_compressed (abfd, sectp)) + { + /* The page size, used when mmapping. */ + static int pagesize; - /* Only try to mmap sections which are large enough: we don't want - to waste space due to fragmentation. */ + if (pagesize == 0) + pagesize = getpagesize (); - if (bfd_get_section_size (sectp) > 4 * pagesize) - { - descriptor->size = bfd_get_section_size (sectp); - descriptor->data = bfd_mmap (abfd, 0, descriptor->size, PROT_READ, - MAP_PRIVATE, sectp->filepos, - &descriptor->map_addr, - &descriptor->map_len); + /* Only try to mmap sections which are large enough: we don't want + to waste space due to fragmentation. */ - if ((caddr_t)descriptor->data != MAP_FAILED) - { + if (bfd_get_section_size (sectp) > 4 * pagesize) + { + descriptor->size = bfd_get_section_size (sectp); + descriptor->data = bfd_mmap (abfd, 0, descriptor->size, PROT_READ, + MAP_PRIVATE, sectp->filepos, + &descriptor->map_addr, + &descriptor->map_len); + + if ((caddr_t)descriptor->data != MAP_FAILED) + { #if HAVE_POSIX_MADVISE - posix_madvise (descriptor->map_addr, descriptor->map_len, - POSIX_MADV_WILLNEED); + posix_madvise (descriptor->map_addr, descriptor->map_len, + POSIX_MADV_WILLNEED); #endif - goto done; - } + goto done; + } - /* On failure, clear out the section data and try again. */ - memset (descriptor, 0, sizeof (*descriptor)); - } - } + /* On failure, clear out the section data and try again. */ + memset (descriptor, 0, sizeof (*descriptor)); + } + } #endif /* HAVE_MMAP */ - /* If we get here, we are a normal, not-compressed section. */ + /* Handle compressed sections, or ordinary uncompressed sections in + the no-mmap case. */ descriptor->size = bfd_get_section_size (sectp); - descriptor->data = xmalloc (descriptor->size); + descriptor->data = NULL; - if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 - || bfd_bread (descriptor->data, bfd_get_section_size (sectp), - abfd) != bfd_get_section_size (sectp)) - { - xfree (descriptor->data); - descriptor->data = NULL; - error (_("Can't read data for section '%s'"), - bfd_get_filename (abfd)); - } + data = NULL; + if (!bfd_get_full_section_contents (abfd, sectp, &data)) + error (_("Can't read data for section '%s' in file '%s'"), + bfd_get_section_name (abfd, sectp), + bfd_get_filename (abfd)); + descriptor->data = data; done: gdb_assert (descriptor->data != NULL); @@ -500,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; +} + /* See gdb_bfd.h. */ @@ -511,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; } @@ -527,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; } @@ -543,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; } @@ -574,44 +542,122 @@ 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; } /* 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) - { - gdb_bfd_ref (result); - /* No need to stash the filename here. */ - } + gdb_bfd_mark_parent (result, archive); return result; } /* 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; +} + + + +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; }