diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2009-06-16 21:06:40 +0000 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2009-06-16 21:06:40 +0000 |
commit | dce234bc19cdb9db9663872e25ccb456facdfb4f (patch) | |
tree | 439823606840e2fdc077df6281bad3b02688f09e /gdb/dwarf2read.c | |
parent | 7eedccfa2afb7a44b513282cb138d85cde1f7f41 (diff) | |
download | gdb-dce234bc19cdb9db9663872e25ccb456facdfb4f.zip gdb-dce234bc19cdb9db9663872e25ccb456facdfb4f.tar.gz gdb-dce234bc19cdb9db9663872e25ccb456facdfb4f.tar.bz2 |
2009-06-16 Paul Pluzhnikov <ppluzhnikov@google.com>
* dwarf2read.c (dwarf_info_section, dwarf_abbrev_section)
(dwarf_line_section, dwarf_pubnames_section, dwarf_aranges_section)
(dwarf_loc_section, dwarf_macinfo_section, dwarf_str_section)
(dwarf_ranges_section, dwarf_frame_section)
(dwarf_eh_frame_section): Removed.
(dwarf2_resize_section): Likewise.
(dwarf2_read_section): Now static, use bfd_mmap() if possible.
(dwarf2_get_section_info): New function.
(munmap_section_buffer): Likewise.
(dwarf2_per_objfile_cleanup): Likewise.
(section_is_p): Signature change.
* dwarf2-frame.c (dwarf2_build_frame_info): Use
dwarf2_get_section_info instead of dwarf2_read_section.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 659 |
1 files changed, 331 insertions, 328 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 849b2af..89dcb45 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -55,20 +55,9 @@ #ifdef HAVE_ZLIB_H #include <zlib.h> #endif - -/* A note on memory usage for this file. - - At the present time, this code reads the debug info sections into - the objfile's objfile_obstack. A definite improvement for startup - time, on platforms which do not emit relocations for debug - sections, would be to use mmap instead. The object's complete - debug information is loaded into memory, partly to simplify - absolute DIE references. - - Whether using obstacks or mmap, the sections should remain loaded - until the objfile is released, and pointers into the section data - can be used for any other data associated to the objfile (symbol - names, type names, location expressions to name a few). */ +#ifdef HAVE_MMAP +#include <sys/mman.h> +#endif #if 0 /* .debug_info header for a compilation unit @@ -145,6 +134,8 @@ _STATEMENT_PROLOGUE; /* When non-zero, dump DIEs after they are read in. */ static int dwarf2_die_debug = 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. */ @@ -153,29 +144,27 @@ static int processing_has_namespace_info; static const struct objfile_data *dwarf2_objfile_data_key; +struct dwarf2_section_info +{ + asection *asection; + gdb_byte *buffer; + bfd_size_type size; + int was_mmapped; +}; + struct dwarf2_per_objfile { - /* Sizes of debugging sections. */ - unsigned int info_size; - unsigned int abbrev_size; - unsigned int line_size; - unsigned int pubnames_size; - unsigned int aranges_size; - unsigned int loc_size; - unsigned int macinfo_size; - unsigned int str_size; - unsigned int ranges_size; - unsigned int frame_size; - unsigned int eh_frame_size; - - /* Loaded data from the sections. */ - gdb_byte *info_buffer; - gdb_byte *abbrev_buffer; - gdb_byte *line_buffer; - gdb_byte *str_buffer; - gdb_byte *macinfo_buffer; - gdb_byte *ranges_buffer; - gdb_byte *loc_buffer; + struct dwarf2_section_info info; + struct dwarf2_section_info abbrev; + struct dwarf2_section_info line; + struct dwarf2_section_info pubnames; + struct dwarf2_section_info aranges; + struct dwarf2_section_info loc; + struct dwarf2_section_info macinfo; + struct dwarf2_section_info str; + struct dwarf2_section_info ranges; + struct dwarf2_section_info frame; + struct dwarf2_section_info eh_frame; /* A list of all the compilation units. This is used to locate the target compilation unit of a particular reference. */ @@ -195,18 +184,6 @@ struct dwarf2_per_objfile static struct dwarf2_per_objfile *dwarf2_per_objfile; -static asection *dwarf_info_section; -static asection *dwarf_abbrev_section; -static asection *dwarf_line_section; -static asection *dwarf_pubnames_section; -static asection *dwarf_aranges_section; -static asection *dwarf_loc_section; -static asection *dwarf_macinfo_section; -static asection *dwarf_str_section; -static asection *dwarf_ranges_section; -asection *dwarf_frame_section; -asection *dwarf_eh_frame_section; - /* names of the debugging sections */ /* Note that if the debugging section has been compressed, it might @@ -803,8 +780,6 @@ static void dwarf2_psymtab_to_symtab (struct partial_symtab *); static void psymtab_to_symtab_1 (struct partial_symtab *); -gdb_byte *dwarf2_read_section (struct objfile *, asection *); - static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu); static void dwarf2_free_abbrev_table (void *); @@ -1130,30 +1105,20 @@ dwarf2_has_info (struct objfile *objfile) set_objfile_data (objfile, dwarf2_objfile_data_key, data); dwarf2_per_objfile = data; - dwarf_info_section = 0; - dwarf_abbrev_section = 0; - dwarf_line_section = 0; - dwarf_str_section = 0; - dwarf_macinfo_section = 0; - dwarf_frame_section = 0; - dwarf_eh_frame_section = 0; - dwarf_ranges_section = 0; - dwarf_loc_section = 0; - bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL); - return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL); + return (data->info.asection != NULL && data->abbrev.asection != NULL); } /* When loading sections, we can either look for ".<name>", or for * ".z<name>", which indicates a compressed section. */ static int -section_is_p (asection *sectp, const char *name) +section_is_p (const char *section_name, const char *name) { - return ((sectp->name[0] == '.' - && strcmp (sectp->name + 1, name) == 0) - || (sectp->name[0] == '.' && sectp->name[1] == 'z' - && strcmp (sectp->name + 2, name) == 0)); + return (section_name[0] == '.' + && (strcmp (section_name + 1, name) == 0 + || (section_name[1] == 'z' + && strcmp (section_name + 2, name) == 0))); } /* This function is mapped across the sections and remembers the @@ -1163,140 +1128,266 @@ section_is_p (asection *sectp, const char *name) static void dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) { - if (section_is_p (sectp, INFO_SECTION)) + if (section_is_p (sectp->name, INFO_SECTION)) { - dwarf2_per_objfile->info_size = bfd_get_section_size (sectp); - dwarf_info_section = sectp; + dwarf2_per_objfile->info.asection = sectp; + dwarf2_per_objfile->info.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, ABBREV_SECTION)) + else if (section_is_p (sectp->name, ABBREV_SECTION)) { - dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp); - dwarf_abbrev_section = sectp; + dwarf2_per_objfile->abbrev.asection = sectp; + dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, LINE_SECTION)) + else if (section_is_p (sectp->name, LINE_SECTION)) { - dwarf2_per_objfile->line_size = bfd_get_section_size (sectp); - dwarf_line_section = sectp; + dwarf2_per_objfile->line.asection = sectp; + dwarf2_per_objfile->line.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, PUBNAMES_SECTION)) + else if (section_is_p (sectp->name, PUBNAMES_SECTION)) { - dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp); - dwarf_pubnames_section = sectp; + dwarf2_per_objfile->pubnames.asection = sectp; + dwarf2_per_objfile->pubnames.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, ARANGES_SECTION)) + else if (section_is_p (sectp->name, ARANGES_SECTION)) { - dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp); - dwarf_aranges_section = sectp; + dwarf2_per_objfile->aranges.asection = sectp; + dwarf2_per_objfile->aranges.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, LOC_SECTION)) + else if (section_is_p (sectp->name, LOC_SECTION)) { - dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp); - dwarf_loc_section = sectp; + dwarf2_per_objfile->loc.asection = sectp; + dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, MACINFO_SECTION)) + else if (section_is_p (sectp->name, MACINFO_SECTION)) { - dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp); - dwarf_macinfo_section = sectp; + dwarf2_per_objfile->macinfo.asection = sectp; + dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, STR_SECTION)) + else if (section_is_p (sectp->name, STR_SECTION)) { - dwarf2_per_objfile->str_size = bfd_get_section_size (sectp); - dwarf_str_section = sectp; + dwarf2_per_objfile->str.asection = sectp; + dwarf2_per_objfile->str.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, FRAME_SECTION)) + else if (section_is_p (sectp->name, FRAME_SECTION)) { - dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp); - dwarf_frame_section = sectp; + dwarf2_per_objfile->frame.asection = sectp; + dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp, EH_FRAME_SECTION)) + else if (section_is_p (sectp->name, EH_FRAME_SECTION)) { flagword aflag = bfd_get_section_flags (ignore_abfd, sectp); if (aflag & SEC_HAS_CONTENTS) { - dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp); - dwarf_eh_frame_section = sectp; + dwarf2_per_objfile->eh_frame.asection = sectp; + dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp); } } - else if (section_is_p (sectp, RANGES_SECTION)) + else if (section_is_p (sectp->name, RANGES_SECTION)) { - dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp); - dwarf_ranges_section = sectp; + dwarf2_per_objfile->ranges.asection = sectp; + dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp); } - + if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD) && bfd_section_vma (abfd, sectp) == 0) dwarf2_per_objfile->has_section_at_zero = 1; } -/* This function is called after decompressing a section, so - dwarf2_per_objfile can record its new, uncompressed size. */ +/* Decompress a section that was compressed using zlib. Store the + decompressed buffer, and its size, in OUTBUF and OUTSIZE. */ static void -dwarf2_resize_section (asection *sectp, bfd_size_type new_size) -{ - if (section_is_p (sectp, INFO_SECTION)) - dwarf2_per_objfile->info_size = new_size; - else if (section_is_p (sectp, ABBREV_SECTION)) - dwarf2_per_objfile->abbrev_size = new_size; - else if (section_is_p (sectp, LINE_SECTION)) - dwarf2_per_objfile->line_size = new_size; - else if (section_is_p (sectp, PUBNAMES_SECTION)) - dwarf2_per_objfile->pubnames_size = new_size; - else if (section_is_p (sectp, ARANGES_SECTION)) - dwarf2_per_objfile->aranges_size = new_size; - else if (section_is_p (sectp, LOC_SECTION)) - dwarf2_per_objfile->loc_size = new_size; - else if (section_is_p (sectp, MACINFO_SECTION)) - dwarf2_per_objfile->macinfo_size = new_size; - else if (section_is_p (sectp, STR_SECTION)) - dwarf2_per_objfile->str_size = new_size; - else if (section_is_p (sectp, FRAME_SECTION)) - dwarf2_per_objfile->frame_size = new_size; - else if (section_is_p (sectp, EH_FRAME_SECTION)) - dwarf2_per_objfile->eh_frame_size = new_size; - else if (section_is_p (sectp, RANGES_SECTION)) - dwarf2_per_objfile->ranges_size = new_size; - else - internal_error (__FILE__, __LINE__, - _("dwarf2_resize_section: missing section_is_p check: %s"), - sectp->name); +zlib_decompress_section (struct objfile *objfile, asection *sectp, + gdb_byte **outbuf, bfd_size_type *outsize) +{ + bfd *abfd = objfile->obfd; +#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); + 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); + + xfree (compressed_buffer); + *outbuf = uncompressed_buffer; + *outsize = uncompressed_size; +#endif } -/* Build a partial symbol table. */ +/* Read the contents of the section SECTP from object file specified by + OBJFILE, store info about the section into INFO. + If the section is compressed, uncompress it before returning. */ -void -dwarf2_build_psymtabs (struct objfile *objfile, int mainline) +static void +dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) { - /* We definitely need the .debug_info and .debug_abbrev sections */ + bfd *abfd = objfile->obfd; + asection *sectp = info->asection; + gdb_byte *buf, *retbuf; + unsigned char header[4]; - dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, dwarf_info_section); - dwarf2_per_objfile->abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_section); + info->buffer = NULL; + info->was_mmapped = 0; - if (dwarf_line_section) - dwarf2_per_objfile->line_buffer = dwarf2_read_section (objfile, dwarf_line_section); - else - dwarf2_per_objfile->line_buffer = NULL; + if (info->asection == NULL || info->size == 0) + return; - if (dwarf_str_section) - dwarf2_per_objfile->str_buffer = dwarf2_read_section (objfile, dwarf_str_section); - else - dwarf2_per_objfile->str_buffer = NULL; + /* 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; + } + } - if (dwarf_macinfo_section) - dwarf2_per_objfile->macinfo_buffer = dwarf2_read_section (objfile, - dwarf_macinfo_section); - else - dwarf2_per_objfile->macinfo_buffer = NULL; +#ifdef HAVE_MMAP + if (pagesize == 0) + pagesize = getpagesize (); - if (dwarf_ranges_section) - dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section); - else - dwarf2_per_objfile->ranges_buffer = NULL; + /* 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) + { + off_t pg_offset = sectp->filepos & ~(pagesize - 1); + size_t map_length = info->size + sectp->filepos - pg_offset; + caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ, + MAP_PRIVATE, pg_offset); + + if (retbuf != MAP_FAILED) + { + info->was_mmapped = 1; + info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; + 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 + http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . + We never compress sections in .o files, so we only need to + try this when the section is not compressed. */ + retbuf = symfile_relocate_debug_section (abfd, sectp, buf); + if (retbuf != NULL) + { + info->buffer = retbuf; + return; + } + + if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 + || bfd_bread (buf, info->size, abfd) != info->size) + error (_("Dwarf Error: Can't read DWARF data from '%s'"), + bfd_get_filename (abfd)); +} + +/* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and + SECTION_NAME. */ - if (dwarf_loc_section) - dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section); +void +dwarf2_get_section_info (struct objfile *objfile, const char *section_name, + asection **sectp, gdb_byte **bufp, + bfd_size_type *sizep) +{ + struct dwarf2_per_objfile *data + = objfile_data (objfile, dwarf2_objfile_data_key); + struct dwarf2_section_info *info; + if (section_is_p (section_name, EH_FRAME_SECTION)) + info = &data->eh_frame; + else if (section_is_p (section_name, FRAME_SECTION)) + info = &data->frame; else - dwarf2_per_objfile->loc_buffer = NULL; + gdb_assert (0); + + if (info->asection != NULL && info->size != 0 && info->buffer == NULL) + /* We haven't read this section in yet. Do it now. */ + dwarf2_read_section (objfile, info); + + *sectp = info->asection; + *bufp = info->buffer; + *sizep = info->size; +} + +/* Build a partial symbol table. */ + +void +dwarf2_build_psymtabs (struct objfile *objfile, int mainline) +{ + dwarf2_read_section (objfile, &dwarf2_per_objfile->info); + dwarf2_read_section (objfile, &dwarf2_per_objfile->abbrev); + dwarf2_read_section (objfile, &dwarf2_per_objfile->line); + dwarf2_read_section (objfile, &dwarf2_per_objfile->str); + dwarf2_read_section (objfile, &dwarf2_per_objfile->macinfo); + dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); + dwarf2_read_section (objfile, &dwarf2_per_objfile->loc); + dwarf2_read_section (objfile, &dwarf2_per_objfile->eh_frame); + dwarf2_read_section (objfile, &dwarf2_per_objfile->frame); if (mainline || (objfile->global_psymbols.size == 0 @@ -1337,7 +1428,7 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline) pubnames_buffer = dwarf2_read_section (objfile, dwarf_pubnames_section); pubnames_ptr = pubnames_buffer; - while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size) + while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames.size) { unsigned int bytes_read; @@ -1412,19 +1503,19 @@ partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, "(is %d, should be %d) [in module %s]"), header->version, 2, bfd_get_filename (abfd)); - if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size) + if (header->abbrev_offset >= dwarf2_per_objfile->abbrev.size) error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header " "(offset 0x%lx + 6) [in module %s]"), (long) header->abbrev_offset, - (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer), + (long) (beg_of_comp_unit - dwarf2_per_objfile->info.buffer), bfd_get_filename (abfd)); if (beg_of_comp_unit + header->length + header->initial_length_size - > dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size) + > dwarf2_per_objfile->info.buffer + dwarf2_per_objfile->info.size) error (_("Dwarf Error: bad length (0x%lx) in compilation unit header " "(offset 0x%lx + 0) [in module %s]"), (long) header->length, - (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer), + (long) (beg_of_comp_unit - dwarf2_per_objfile->info.buffer), bfd_get_filename (abfd)); return info_ptr; @@ -1506,7 +1597,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) struct cleanup *back_to; CORE_ADDR baseaddr; - info_ptr = dwarf2_per_objfile->info_buffer; + info_ptr = dwarf2_per_objfile->info.buffer; /* Any cached compilation units will be linked by the per-objfile read_in_chain. Make sure to free them when we're done. */ @@ -1530,8 +1621,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) For this loop condition, simply checking whether there's any data left at all should be sufficient. */ - while (info_ptr < (dwarf2_per_objfile->info_buffer - + dwarf2_per_objfile->info_size)) + while (info_ptr < (dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size)) { struct cleanup *back_to_inner; struct dwarf2_cu cu; @@ -1551,7 +1642,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd); /* Complete the cu_header */ - cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer; + cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info.buffer; cu.header.first_die_offset = info_ptr - beg_of_comp_unit; cu.list_in_scope = &file_symbols; @@ -1708,7 +1799,7 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) unsigned int bytes_read; struct cleanup *back_to; - info_ptr = dwarf2_per_objfile->info_buffer + this_cu->offset; + info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; beg_of_comp_unit = info_ptr; cu = xmalloc (sizeof (struct dwarf2_cu)); @@ -1720,7 +1811,7 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd); /* Complete the cu_header. */ - cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer; + cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info.buffer; cu->header.first_die_offset = info_ptr - beg_of_comp_unit; /* Read the abbrevs for this compilation unit into a table. */ @@ -1760,21 +1851,21 @@ create_all_comp_units (struct objfile *objfile) int n_allocated; int n_comp_units; struct dwarf2_per_cu_data **all_comp_units; - gdb_byte *info_ptr = dwarf2_per_objfile->info_buffer; + gdb_byte *info_ptr = dwarf2_per_objfile->info.buffer; n_comp_units = 0; n_allocated = 10; all_comp_units = xmalloc (n_allocated * sizeof (struct dwarf2_per_cu_data *)); - while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size) + while (info_ptr < dwarf2_per_objfile->info.buffer + dwarf2_per_objfile->info.size) { unsigned int length, initial_length_size; gdb_byte *beg_of_comp_unit; struct dwarf2_per_cu_data *this_cu; unsigned int offset; - offset = info_ptr - dwarf2_per_objfile->info_buffer; + offset = info_ptr - dwarf2_per_objfile->info.buffer; /* Read just enough information to find out where the next compilation unit is. */ @@ -2420,7 +2511,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, if (attr.form == DW_FORM_ref_addr) complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); else - return dwarf2_per_objfile->info_buffer + return dwarf2_per_objfile->info.buffer + dwarf2_get_ref_die_offset (&attr); } @@ -2706,7 +2797,7 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) /* Set local variables from the partial symbol table info. */ offset = per_cu->offset; - info_ptr = dwarf2_per_objfile->info_buffer + offset; + info_ptr = dwarf2_per_objfile->info.buffer + offset; cu = xmalloc (sizeof (struct dwarf2_cu)); memset (cu, 0, sizeof (struct dwarf2_cu)); @@ -3371,14 +3462,14 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, found_base = cu->base_known; base = cu->base_address; - if (offset >= dwarf2_per_objfile->ranges_size) + if (offset >= dwarf2_per_objfile->ranges.size) { complaint (&symfile_complaints, _("Offset %d out of bounds for DW_AT_ranges attribute"), offset); return 0; } - buffer = dwarf2_per_objfile->ranges_buffer + offset; + buffer = dwarf2_per_objfile->ranges.buffer + offset; /* Read in the largest possible address. */ marker = read_address (obfd, buffer, cu, &dummy); @@ -3653,7 +3744,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block, /* The value of the DW_AT_ranges attribute is the offset of the address range list in the .debug_ranges section. */ unsigned long offset = DW_UNSND (attr); - gdb_byte *buffer = dwarf2_per_objfile->ranges_buffer + offset; + gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset; /* For some target architectures, but not others, the read_address function sign-extends the addresses it returns. @@ -3672,7 +3763,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block, CORE_ADDR base = cu->base_address; int base_known = cu->base_known; - if (offset >= dwarf2_per_objfile->ranges_size) + if (offset >= dwarf2_per_objfile->ranges.size) { complaint (&symfile_complaints, _("Offset %lu out of bounds for DW_AT_ranges attribute"), @@ -5510,131 +5601,6 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, } } -/* 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 = objfile->obfd; -#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); - 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); - - xfree (compressed_buffer); - *outbuf = uncompressed_buffer; - *outsize = uncompressed_size; -#endif -} - - -/* Read the contents of the section at OFFSET and of size SIZE from the - object file specified by OBJFILE into the objfile_obstack and return it. - If the section is compressed, uncompress it before returning. */ - -gdb_byte * -dwarf2_read_section (struct objfile *objfile, asection *sectp) -{ - bfd *abfd = objfile->obfd; - gdb_byte *buf, *retbuf; - bfd_size_type size = bfd_get_section_size (sectp); - unsigned char header[4]; - - if (size == 0) - return NULL; - - /* Check if the file has a 4-byte header indicating compression. */ - if (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, &buf, &size); - dwarf2_resize_section (sectp, size); - return buf; - } - } - - /* If we get here, we are a normal, not-compressed section. */ - buf = obstack_alloc (&objfile->objfile_obstack, size); - /* When debugging .o files, we may need to apply relocations; see - http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . - We never compress sections in .o files, so we only need to - try this when the section is not compressed. */ - retbuf = symfile_relocate_debug_section (abfd, sectp, buf); - if (retbuf != NULL) - return retbuf; - - if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 - || bfd_bread (buf, size, abfd) != size) - error (_("Dwarf Error: Can't read DWARF data from '%s'"), - bfd_get_filename (abfd)); - - return buf; -} - /* In DWARF version 2, the description of the debugging information is stored in a separate .debug_abbrev section. Before we read any dies from a section we read in all abbreviations and install them @@ -5660,7 +5626,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu) memset (cu->dwarf2_abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *)); - abbrev_ptr = dwarf2_per_objfile->abbrev_buffer + cu_header->abbrev_offset; + abbrev_ptr = dwarf2_per_objfile->abbrev.buffer + cu_header->abbrev_offset; abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); abbrev_ptr += bytes_read; @@ -5732,8 +5698,8 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu) already read (which means we are about to read the abbreviations for the next compile unit) or if the end of the abbreviation table is reached. */ - if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev_buffer) - >= dwarf2_per_objfile->abbrev_size) + if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev.buffer) + >= dwarf2_per_objfile->abbrev.size) break; abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); abbrev_ptr += bytes_read; @@ -6051,7 +6017,7 @@ read_partial_die (struct partial_die_info *part_die, memset (part_die, 0, sizeof (struct partial_die_info)); - part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer; + part_die->offset = info_ptr - dwarf2_per_objfile->info.buffer; info_ptr += abbrev_len; @@ -6164,7 +6130,7 @@ read_partial_die (struct partial_die_info *part_die, if (attr.form == DW_FORM_ref_addr) complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); else - part_die->sibling = dwarf2_per_objfile->info_buffer + part_die->sibling = dwarf2_per_objfile->info.buffer + dwarf2_get_ref_die_offset (&attr); break; case DW_AT_stmt_list: @@ -6280,7 +6246,7 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu) dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu); back_to = make_cleanup (dwarf2_free_abbrev_table, per_cu->cu); } - info_ptr = (dwarf2_per_objfile->info_buffer + info_ptr = (dwarf2_per_objfile->info.buffer + per_cu->cu->header.offset + per_cu->cu->header.first_die_offset); abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu); @@ -6356,7 +6322,7 @@ read_full_die (struct die_info **diep, bfd *abfd, gdb_byte *info_ptr, struct abbrev_info *abbrev; struct die_info *die; - offset = info_ptr - dwarf2_per_objfile->info_buffer; + offset = info_ptr - dwarf2_per_objfile->info.buffer; abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; if (!abbrev_number) @@ -6792,22 +6758,22 @@ read_indirect_string (bfd *abfd, gdb_byte *buf, { LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); - if (dwarf2_per_objfile->str_buffer == NULL) + if (dwarf2_per_objfile->str.buffer == NULL) { error (_("DW_FORM_strp used without .debug_str section [in module %s]"), bfd_get_filename (abfd)); return NULL; } - if (str_offset >= dwarf2_per_objfile->str_size) + if (str_offset >= dwarf2_per_objfile->str.size) { error (_("DW_FORM_strp pointing outside of .debug_str section [in module %s]"), bfd_get_filename (abfd)); return NULL; } gdb_assert (HOST_CHAR_BIT == 8); - if (dwarf2_per_objfile->str_buffer[str_offset] == '\0') + if (dwarf2_per_objfile->str.buffer[str_offset] == '\0') return NULL; - return (char *) (dwarf2_per_objfile->str_buffer + str_offset); + return (char *) (dwarf2_per_objfile->str.buffer + str_offset); } static unsigned long @@ -7094,7 +7060,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, int i; char *cur_dir, *cur_file; - if (dwarf2_per_objfile->line_buffer == NULL) + if (dwarf2_per_objfile->line.buffer == NULL) { complaint (&symfile_complaints, _("missing .debug_line section")); return 0; @@ -7102,7 +7068,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, /* Make sure that at least there's room for the total_length field. That could be 12 bytes long, but we're just going to fudge that. */ - if (offset + 4 >= dwarf2_per_objfile->line_size) + if (offset + 4 >= dwarf2_per_objfile->line.size) { dwarf2_statement_list_fits_in_line_number_section_complaint (); return 0; @@ -7113,15 +7079,15 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, back_to = make_cleanup ((make_cleanup_ftype *) free_line_header, (void *) lh); - line_ptr = dwarf2_per_objfile->line_buffer + offset; + line_ptr = dwarf2_per_objfile->line.buffer + offset; /* Read in the header. */ lh->total_length = read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header, &bytes_read, &offset_size); line_ptr += bytes_read; - if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer - + dwarf2_per_objfile->line_size)) + if (line_ptr + lh->total_length > (dwarf2_per_objfile->line.buffer + + dwarf2_per_objfile->line.size)) { dwarf2_statement_list_fits_in_line_number_section_complaint (); return 0; @@ -7177,8 +7143,8 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, line_ptr += bytes_read; lh->statement_program_start = line_ptr; - if (line_ptr > (dwarf2_per_objfile->line_buffer - + dwarf2_per_objfile->line_size)) + if (line_ptr > (dwarf2_per_objfile->line.buffer + + dwarf2_per_objfile->line.size)) complaint (&symfile_complaints, _("line number info header doesn't fit in `.debug_line' section")); @@ -10163,7 +10129,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, enum dwarf_macinfo_record_type macinfo_type; int at_commandline; - if (dwarf2_per_objfile->macinfo_buffer == NULL) + if (dwarf2_per_objfile->macinfo.buffer == NULL) { complaint (&symfile_complaints, _("missing .debug_macinfo section")); return; @@ -10180,9 +10146,9 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, CURRENT_FILE accordingly so that any macro definition found before the first DW_MACINFO_start_file can still be associated to the base file. */ - mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset; - mac_end = dwarf2_per_objfile->macinfo_buffer - + dwarf2_per_objfile->macinfo_size; + mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; + mac_end = dwarf2_per_objfile->macinfo.buffer + + dwarf2_per_objfile->macinfo.size; do { @@ -10259,7 +10225,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, command-line macro definitions/undefinitions. This flag is unset when we reach the first DW_MACINFO_start_file entry. */ - mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset; + mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; /* Determines if GDB is still before first DW_MACINFO_start_file. If true GDB is still reading the definitions from command line. First @@ -10477,7 +10443,7 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, /* ".debug_loc" may not exist at all, or the offset may be outside the section. If so, fall through to the complaint in the other branch. */ - && DW_UNSND (attr) < dwarf2_per_objfile->loc_size) + && DW_UNSND (attr) < dwarf2_per_objfile->loc.size) { struct dwarf2_loclist_baton *baton; @@ -10488,8 +10454,8 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, /* We don't know how long the location list is, but make sure we don't run off the edge of the section. */ - baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr); - baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr); + baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr); + baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr); baton->base_address = cu->base_address; if (cu->base_known == 0) complaint (&symfile_complaints, @@ -10558,7 +10524,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) struct objfile *objfile = per_cu->psymtab->objfile; struct dwarf2_per_objfile *per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info_buffer + per_cu->offset; + gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; struct comp_unit_head cu_header; memset (&cu_header, 0, sizeof cu_header); @@ -10951,12 +10917,49 @@ 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->was_mmapped) + { +#ifdef HAVE_MMAP + intptr_t begin = (intptr_t) info->buffer; + intptr_t map_begin = begin & ~(pagesize - 1); + size_t map_length = info->size + begin - map_begin; + gdb_assert (munmap ((void *) map_begin, map_length) == 0); +#else + /* Without HAVE_MMAP, we should never be here to begin with. */ + gdb_assert (0); +#endif + } +} + +/* munmap debug sections for OBJFILE, if necessary. */ + +static void +dwarf2_per_objfile_cleanup (struct objfile *objfile, void *d) +{ + struct dwarf2_per_objfile *data = d; + munmap_section_buffer (&data->info); + munmap_section_buffer (&data->abbrev); + munmap_section_buffer (&data->line); + munmap_section_buffer (&data->str); + munmap_section_buffer (&data->macinfo); + munmap_section_buffer (&data->ranges); + munmap_section_buffer (&data->loc); + munmap_section_buffer (&data->frame); + munmap_section_buffer (&data->eh_frame); +} + void _initialize_dwarf2_read (void); void _initialize_dwarf2_read (void) { - dwarf2_objfile_data_key = register_objfile_data (); + dwarf2_objfile_data_key + = register_objfile_data_with_cleanup (dwarf2_per_objfile_cleanup); add_prefix_cmd ("dwarf2", class_maintenance, set_dwarf2_cmd, _("\ Set DWARF 2 specific variables.\n\ |