summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/dwarf2read.c200
-rw-r--r--gdb/gdb_bfd.c252
-rw-r--r--gdb/gdb_bfd.h14
4 files changed, 294 insertions, 190 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a200927a62e..10dacd665cd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
2012-07-18 Tom Tromey <tromey@redhat.com>
+ * dwarf2read.c: Don't include zlib.h or sys/mman.h.
+ (pagesize): Remove.
+ (struct dwarf2_section_info) <map_addr, map_len>: Remove.
+ (zlib_decompress_section): Remove.
+ (dwarf2_read_section): Use gdb_bfd_map_section.
+ (munmap_section_buffer): Remove.
+ (free_dwo_file, dwarf2_per_objfile_free): Don't use
+ munmap_section_buffer.
+ * gdb_bfd.c: Include zlib.h, sys/mman.h.
+ (struct gdb_bfd_section_data): New.
+ (free_one_bfd_section): New function.
+ (gdb_bfd_close_or_warn): Use free_one_bfd_section.
+ (get_section_descriptor, zlib_decompress_section)
+ (gdb_bfd_map_section): New functions.
+ * gdb_bfd.h (gdb_bfd_map_section): Declare.
+
+2012-07-18 Tom Tromey <tromey@redhat.com>
+
* dwarf2read.c (try_open_dwo_file): use gdb_bfd_open.
2012-07-18 Tom Tromey <tromey@redhat.com>
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 023447f78ef..da23cc44122 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -70,15 +70,6 @@
#include "gdb_string.h"
#include "gdb_assert.h"
#include <sys/types.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
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
@@ -96,8 +87,6 @@ static int check_physname = 0;
/* When non-zero, do not reject deprecated .gdb_index sections. */
int use_deprecated_index_sections = 0;
-static int pagesize;
-
/* When set, the file that we're processing is known to have debugging
info for C++ namespaces. GCC 3.3.x did not produce this information,
but later versions do. */
@@ -111,10 +100,6 @@ struct dwarf2_section_info
asection *asection;
gdb_byte *buffer;
bfd_size_type size;
- /* Not NULL if the section was actually mmapped. */
- void *map_addr;
- /* Page aligned size of mmapped area. */
- bfd_size_type map_len;
/* True if we have tried to read this section. */
int readin;
};
@@ -1609,8 +1594,6 @@ static struct dwo_unit *lookup_dwo_type_unit
static void free_dwo_file_cleanup (void *);
-static void munmap_section_buffer (struct dwarf2_section_info *);
-
static void process_cu_includes (void);
#if WORDS_BIGENDIAN
@@ -1780,85 +1763,6 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
dwarf2_per_objfile->has_section_at_zero = 1;
}
-/* Decompress a section that was compressed using zlib. Store the
- decompressed buffer, and its size, in OUTBUF and OUTSIZE. */
-
-static void
-zlib_decompress_section (struct objfile *objfile, asection *sectp,
- gdb_byte **outbuf, bfd_size_type *outsize)
-{
- bfd *abfd = sectp->owner;
-#ifndef HAVE_ZLIB_H
- error (_("Support for zlib-compressed DWARF data (from '%s') "
- "is disabled in this copy of GDB"),
- bfd_get_filename (abfd));
-#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);
- bfd_size_type uncompressed_size;
- gdb_byte *uncompressed_buffer;
- z_stream strm;
- int rc;
- int header_size = 12;
-
- if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
- || bfd_bread (compressed_buffer,
- compressed_size, abfd) != compressed_size)
- error (_("Dwarf Error: Can't read DWARF data from '%s'"),
- bfd_get_filename (abfd));
-
- /* 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 (_("Dwarf Error: Corrupt DWARF ZLIB header from '%s'"),
- bfd_get_filename (abfd));
- 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 = obstack_alloc (&objfile->objfile_obstack,
- uncompressed_size);
- rc = inflateInit (&strm);
- while (strm.avail_in > 0)
- {
- if (rc != Z_OK)
- error (_("Dwarf Error: setting up DWARF uncompression in '%s': %d"),
- bfd_get_filename (abfd), rc);
- strm.next_out = ((Bytef*) uncompressed_buffer
- + (uncompressed_size - strm.avail_out));
- rc = inflate (&strm, Z_FINISH);
- if (rc != Z_STREAM_END)
- error (_("Dwarf Error: zlib error uncompressing from '%s': %d"),
- bfd_get_filename (abfd), rc);
- rc = inflateReset (&strm);
- }
- rc = inflateEnd (&strm);
- if (rc != Z_OK
- || strm.avail_out != 0)
- error (_("Dwarf Error: concluding DWARF uncompression in '%s': %d"),
- bfd_get_filename (abfd), rc);
-
- do_cleanups (cleanup);
- *outbuf = uncompressed_buffer;
- *outsize = uncompressed_size;
-#endif
-}
-
/* A helper function that decides whether a section is empty,
or not present. */
@@ -1885,56 +1789,27 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
if (info->readin)
return;
info->buffer = NULL;
- info->map_addr = NULL;
info->readin = 1;
if (dwarf2_section_empty_p (info))
return;
- /* Note that ABFD may not be from OBJFILE, e.g. a DWO section. */
abfd = sectp->owner;
- /* Check if the file has a 4-byte header indicating compression. */
- if (info->size > 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 (objfile, sectp, &info->buffer,
- &info->size);
- return;
- }
- }
-
-#ifdef HAVE_MMAP
- if (pagesize == 0)
- pagesize = getpagesize ();
-
- /* Only try to mmap sections which are large enough: we don't want to
- waste space due to fragmentation. Also, only try mmap for sections
- without relocations. */
-
- if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0)
+ /* If the section has relocations, we must read it ourselves.
+ Otherwise we attach it to the BFD. */
+ if ((sectp->flags & SEC_RELOC) == 0)
{
- info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ,
- MAP_PRIVATE, sectp->filepos,
- &info->map_addr, &info->map_len);
+ const gdb_byte *bytes = gdb_bfd_map_section (sectp, &info->size);
- if ((caddr_t)info->buffer != MAP_FAILED)
- {
-#if HAVE_POSIX_MADVISE
- posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED);
-#endif
- return;
- }
+ /* We have to cast away const here for historical reasons.
+ Fixing dwarf2read to be const-correct would be quite nice. */
+ info->buffer = (gdb_byte *) bytes;
+ return;
}
-#endif
- /* If we get here, we are a normal, not-compressed section. */
- info->buffer = buf
- = obstack_alloc (&objfile->objfile_obstack, info->size);
+ buf = obstack_alloc (&objfile->objfile_obstack, info->size);
+ info->buffer = buf;
/* When debugging .o files, we may need to apply relocations; see
http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html .
@@ -8324,19 +8199,6 @@ free_dwo_file (struct dwo_file *dwo_file, struct objfile *objfile)
gdb_assert (dwo_file->dwo_bfd != objfile->obfd);
gdb_bfd_unref (dwo_file->dwo_bfd);
- munmap_section_buffer (&dwo_file->sections.abbrev);
- munmap_section_buffer (&dwo_file->sections.info);
- munmap_section_buffer (&dwo_file->sections.line);
- munmap_section_buffer (&dwo_file->sections.loc);
- munmap_section_buffer (&dwo_file->sections.str);
- munmap_section_buffer (&dwo_file->sections.str_offsets);
-
- for (ix = 0;
- VEC_iterate (dwarf2_section_info_def, dwo_file->sections.types,
- ix, section);
- ++ix)
- munmap_section_buffer (section);
-
VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
}
@@ -18338,53 +18200,13 @@ show_dwarf2_cmd (char *args, int from_tty)
cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
}
-/* If section described by INFO was mmapped, munmap it now. */
-
-static void
-munmap_section_buffer (struct dwarf2_section_info *info)
-{
- if (info->map_addr != NULL)
- {
-#ifdef HAVE_MMAP
- int res;
-
- res = munmap (info->map_addr, info->map_len);
- gdb_assert (res == 0);
-#else
- /* Without HAVE_MMAP, we should never be here to begin with. */
- gdb_assert_not_reached ("no mmap support");
-#endif
- }
-}
-
-/* munmap debug sections for OBJFILE, if necessary. */
+/* Free data associated with OBJFILE, if necessary. */
static void
dwarf2_per_objfile_free (struct objfile *objfile, void *d)
{
struct dwarf2_per_objfile *data = d;
int ix;
- struct dwarf2_section_info *section;
-
- /* This is sorted according to the order they're defined in to make it easier
- to keep in sync. */
- munmap_section_buffer (&data->info);
- munmap_section_buffer (&data->abbrev);
- munmap_section_buffer (&data->line);
- munmap_section_buffer (&data->loc);
- munmap_section_buffer (&data->macinfo);
- munmap_section_buffer (&data->macro);
- munmap_section_buffer (&data->str);
- munmap_section_buffer (&data->ranges);
- munmap_section_buffer (&data->addr);
- munmap_section_buffer (&data->frame);
- munmap_section_buffer (&data->eh_frame);
- munmap_section_buffer (&data->gdb_index);
-
- for (ix = 0;
- VEC_iterate (dwarf2_section_info_def, data->types, ix, section);
- ++ix)
- munmap_section_buffer (section);
for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
VEC_free (dwarf2_per_cu_ptr,
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 5ad987887a8..10489ace8f2 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -23,6 +23,30 @@
#include "gdb_assert.h"
#include "gdb_string.h"
#include "hashtab.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
+
+/* An object of this type is stored in the section's user data when
+ mapping a section. */
+
+struct gdb_bfd_section_data
+{
+ /* Size of the data. */
+ bfd_size_type size;
+ /* If the data was mmapped, this is the length of the map. */
+ bfd_size_type map_len;
+ /* The data. If NULL, the section data has not been read. */
+ void *data;
+ /* If the data was mmapped, this is the map address. */
+ void *map_addr;
+};
/* See gdb_bfd.h. */
@@ -149,6 +173,30 @@ gdb_bfd_open (const char *name, const char *target, int fd)
return gdb_bfd_ref (abfd);
}
+/* A helper function that releases any section data attached to the
+ BFD. */
+
+static void
+free_one_bfd_section (bfd *abfd, asection *sectp, void *ignore)
+{
+ struct gdb_bfd_section_data *sect = bfd_get_section_userdata (abfd, sectp);
+
+ if (sect != NULL && sect->data != NULL)
+ {
+#ifdef HAVE_MMAP
+ if (sect->map_addr != NULL)
+ {
+ int res;
+
+ res = munmap (sect->map_addr, sect->map_len);
+ gdb_assert (res == 0);
+ }
+ else
+#endif
+ xfree (sect->data);
+ }
+}
+
/* Close ABFD, and warn if that fails. */
static int
@@ -157,6 +205,8 @@ gdb_bfd_close_or_warn (struct bfd *abfd)
int ret;
char *name = bfd_get_filename (abfd);
+ bfd_map_over_sections (abfd, free_one_bfd_section, NULL);
+
ret = bfd_close (abfd);
if (!ret)
@@ -229,3 +279,205 @@ gdb_bfd_unref (struct bfd *abfd)
gdb_bfd_close_or_warn (abfd);
}
+
+/* A helper function that returns the section data descriptor
+ associated with SECTION. If no such descriptor exists, a new one
+ is allocated and cleared. */
+
+static struct gdb_bfd_section_data *
+get_section_descriptor (asection *section)
+{
+ struct gdb_bfd_section_data *result;
+
+ result = bfd_get_section_userdata (section->owner, section);
+
+ if (result == NULL)
+ {
+ result = bfd_zalloc (section->owner, sizeof (*result));
+ bfd_set_section_userdata (section->owner, section, result);
+ }
+
+ 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 (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;
+
+ gdb_assert ((sectp->flags & SEC_RELOC) == 0);
+ gdb_assert (size != NULL);
+
+ abfd = sectp->owner;
+
+ descriptor = get_section_descriptor (sectp);
+
+ /* If the data was already read for this BFD, just reuse it. */
+ 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 ();
+
+ /* Only try to mmap sections which are large enough: we don't want
+ to waste space due to fragmentation. */
+
+ 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);
+#endif
+ goto done;
+ }
+
+ /* 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. */
+
+ descriptor->size = bfd_get_section_size (sectp);
+ descriptor->data = xmalloc (descriptor->size);
+
+ 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));
+ }
+
+ done:
+ gdb_assert (descriptor->data != NULL);
+ *size = descriptor->size;
+ return descriptor->data;
+}
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index 78d303b3a67..1dd82c319de 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -1,6 +1,6 @@
/* Definitions for BFD wrappers used by GDB.
- Copyright (C) 2011
+ Copyright (C) 2011, 2012
Free Software Foundation, Inc.
This file is part of GDB.
@@ -46,4 +46,16 @@ struct bfd *gdb_bfd_ref (struct bfd *abfd);
void gdb_bfd_unref (struct bfd *abfd);
+/* Try to read or map the contents of the section SECT. If
+ successful, the section data is returned and *SIZE is set to the
+ size of the section data; this may not be the same as the size
+ according to bfd_get_section_size if the section was compressed.
+ The returned section data is associated with the BFD and will be
+ destroyed when the BFD is destroyed. There is no other way to free
+ it; for temporary uses of section data, see
+ bfd_malloc_and_get_section. SECT may not have relocations. This
+ function will throw on error. */
+
+const gdb_byte *gdb_bfd_map_section (asection *section, bfd_size_type *size);
+
#endif /* GDB_BFD_H */