* 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.
This commit is contained in:
Tom Tromey 2012-07-18 19:57:21 +00:00
parent bb39779773
commit 4bf44c1cf1
4 changed files with 295 additions and 191 deletions

View File

@ -1,3 +1,21 @@
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> 2012-07-18 Tom Tromey <tromey@redhat.com>
* dwarf2read.c (try_open_dwo_file): use gdb_bfd_open. * dwarf2read.c (try_open_dwo_file): use gdb_bfd_open.

View File

@ -70,15 +70,6 @@
#include "gdb_string.h" #include "gdb_string.h"
#include "gdb_assert.h" #include "gdb_assert.h"
#include <sys/types.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; typedef struct symbol *symbolp;
DEF_VEC_P (symbolp); DEF_VEC_P (symbolp);
@ -96,8 +87,6 @@ static int check_physname = 0;
/* When non-zero, do not reject deprecated .gdb_index sections. */ /* When non-zero, do not reject deprecated .gdb_index sections. */
int use_deprecated_index_sections = 0; int use_deprecated_index_sections = 0;
static int pagesize;
/* When set, the file that we're processing is known to have debugging /* 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, info for C++ namespaces. GCC 3.3.x did not produce this information,
but later versions do. */ but later versions do. */
@ -111,10 +100,6 @@ struct dwarf2_section_info
asection *asection; asection *asection;
gdb_byte *buffer; gdb_byte *buffer;
bfd_size_type size; 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. */ /* True if we have tried to read this section. */
int readin; int readin;
}; };
@ -1609,8 +1594,6 @@ static struct dwo_unit *lookup_dwo_type_unit
static void free_dwo_file_cleanup (void *); static void free_dwo_file_cleanup (void *);
static void munmap_section_buffer (struct dwarf2_section_info *);
static void process_cu_includes (void); static void process_cu_includes (void);
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
@ -1780,85 +1763,6 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
dwarf2_per_objfile->has_section_at_zero = 1; 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, /* A helper function that decides whether a section is empty,
or not present. */ or not present. */
@ -1885,56 +1789,27 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
if (info->readin) if (info->readin)
return; return;
info->buffer = NULL; info->buffer = NULL;
info->map_addr = NULL;
info->readin = 1; info->readin = 1;
if (dwarf2_section_empty_p (info)) if (dwarf2_section_empty_p (info))
return; return;
/* Note that ABFD may not be from OBJFILE, e.g. a DWO section. */
abfd = sectp->owner; abfd = sectp->owner;
/* Check if the file has a 4-byte header indicating compression. */ /* If the section has relocations, we must read it ourselves.
if (info->size > sizeof (header) Otherwise we attach it to the BFD. */
&& bfd_seek (abfd, sectp->filepos, SEEK_SET) == 0 if ((sectp->flags & SEC_RELOC) == 0)
&& bfd_bread (header, sizeof (header), abfd) == sizeof (header))
{ {
/* Upon decompression, update the buffer and its size. */ const gdb_byte *bytes = gdb_bfd_map_section (sectp, &info->size);
if (strncmp (header, "ZLIB", sizeof (header)) == 0)
{ /* We have to cast away const here for historical reasons.
zlib_decompress_section (objfile, sectp, &info->buffer, Fixing dwarf2read to be const-correct would be quite nice. */
&info->size); info->buffer = (gdb_byte *) bytes;
return; return;
}
} }
#ifdef HAVE_MMAP buf = obstack_alloc (&objfile->objfile_obstack, info->size);
if (pagesize == 0) info->buffer = buf;
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)
{
info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ,
MAP_PRIVATE, sectp->filepos,
&info->map_addr, &info->map_len);
if ((caddr_t)info->buffer != MAP_FAILED)
{
#if HAVE_POSIX_MADVISE
posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED);
#endif
return;
}
}
#endif
/* If we get here, we are a normal, not-compressed section. */
info->buffer = buf
= obstack_alloc (&objfile->objfile_obstack, info->size);
/* When debugging .o files, we may need to apply relocations; see /* When debugging .o files, we may need to apply relocations; see
http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . 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_assert (dwo_file->dwo_bfd != objfile->obfd);
gdb_bfd_unref (dwo_file->dwo_bfd); 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); 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, ""); cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
} }
/* If section described by INFO was mmapped, munmap it now. */ /* Free data associated with OBJFILE, if necessary. */
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. */
static void static void
dwarf2_per_objfile_free (struct objfile *objfile, void *d) dwarf2_per_objfile_free (struct objfile *objfile, void *d)
{ {
struct dwarf2_per_objfile *data = d; struct dwarf2_per_objfile *data = d;
int ix; 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) for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
VEC_free (dwarf2_per_cu_ptr, VEC_free (dwarf2_per_cu_ptr,

View File

@ -23,6 +23,30 @@
#include "gdb_assert.h" #include "gdb_assert.h"
#include "gdb_string.h" #include "gdb_string.h"
#include "hashtab.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. */ /* See gdb_bfd.h. */
@ -149,6 +173,30 @@ gdb_bfd_open (const char *name, const char *target, int fd)
return gdb_bfd_ref (abfd); 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. */ /* Close ABFD, and warn if that fails. */
static int static int
@ -157,6 +205,8 @@ gdb_bfd_close_or_warn (struct bfd *abfd)
int ret; int ret;
char *name = bfd_get_filename (abfd); char *name = bfd_get_filename (abfd);
bfd_map_over_sections (abfd, free_one_bfd_section, NULL);
ret = bfd_close (abfd); ret = bfd_close (abfd);
if (!ret) if (!ret)
@ -229,3 +279,205 @@ gdb_bfd_unref (struct bfd *abfd)
gdb_bfd_close_or_warn (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;
}

View File

@ -1,6 +1,6 @@
/* Definitions for BFD wrappers used by GDB. /* Definitions for BFD wrappers used by GDB.
Copyright (C) 2011 Copyright (C) 2011, 2012
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GDB. 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); 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 */ #endif /* GDB_BFD_H */