* [patch] Use mmap instead of obstack_alloc for dwarf debug sections.
@ 2009-05-27 0:12 Paul Pluzhnikov
2009-05-28 1:16 ` Tom Tromey
0 siblings, 1 reply; 29+ messages in thread
From: Paul Pluzhnikov @ 2009-05-27 0:12 UTC (permalink / raw)
To: gdb-patches
Greetings,
After the "avoid repeated breakpoint resets" patches, my 1500+ solib
test case goes from 2m+ to under 1m on a 16GB machine (GDB needs 2.4GB on
this test case):
real 0m51.400s
user 0m46.087s
sys 0m4.940s
Notice that wall time is approximately user+system, and GDB gets 100%
cpu-bound.
Unfortunately, on a (faster) 4GB machine, I see this:
real 2m10.766s
user 0m30.734s
sys 0m3.708s
Here GDB is fighting buffer cache for memory, and never gets above 30% CPU.
Attached patch mmap()s DWARF2 debug sections instead of obstack_alloc()ing
and reading them, and that reduces startup time (on a 4GB machine)
significantly:
real 0m32.109s
user 0m29.214s
sys 0m2.832s
It also gets rid of a bunch of globals in dwarf2read.c, and reduces the
coupling between dwarf2read.c and dwarf2-frame.c :-)
Tested on Linux/x86_64 with no regressions.
Thanks,
--
Paul Pluzhnikov
ChangeLog
2009-05-26 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 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.
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.305
diff -u -p -u -r1.305 dwarf2read.c
--- dwarf2read.c 26 May 2009 21:24:07 -0000 1.305
+++ dwarf2read.c 27 May 2009 00:10:47 -0000
@@ -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_mmaped;
+};
+
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 (st
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,262 @@ section_is_p (asection *sectp, const cha
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)
+zlib_decompress_section (struct objfile *objfile, asection *sectp,
+ gdb_byte **outbuf, bfd_size_type *outsize)
{
- 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);
+ 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_mmaped = 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 (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 = mmap (0, map_length, PROT_READ, MAP_PRIVATE,
+ fileno ((FILE *)abfd->iostream),
+ pg_offset);
- if (dwarf_ranges_section)
- dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section);
- else
- dwarf2_per_objfile->ranges_buffer = NULL;
+ if (retbuf != MAP_FAILED)
+ {
+ info->was_mmaped = 1;
+ info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ;
+ return;
+ }
+ }
+#endif
- if (dwarf_loc_section)
- dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
- else
- dwarf2_per_objfile->loc_buffer = NULL;
+ /* 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. */
+
+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
+ 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 +1424,7 @@ dwarf2_build_psymtabs_easy (struct objfi
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 +1499,19 @@ partial_read_comp_unit_head (struct comp
"(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 +1593,7 @@ dwarf2_build_psymtabs_hard (struct objfi
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 +1617,8 @@ dwarf2_build_psymtabs_hard (struct objfi
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 +1638,7 @@ dwarf2_build_psymtabs_hard (struct objfi
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 +1795,7 @@ load_comp_unit (struct dwarf2_per_cu_dat
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 +1807,7 @@ load_comp_unit (struct dwarf2_per_cu_dat
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 +1847,21 @@ create_all_comp_units (struct objfile *o
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 +2507,7 @@ skip_one_die (gdb_byte *info_ptr, struct
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);
}
@@ -2693,7 +2780,7 @@ load_full_comp_unit (struct dwarf2_per_c
/* 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));
@@ -3358,14 +3445,14 @@ dwarf2_ranges_read (unsigned offset, COR
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);
@@ -3640,7 +3727,7 @@ dwarf2_record_block_ranges (struct die_i
/* 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.
@@ -3659,7 +3746,7 @@ dwarf2_record_block_ranges (struct die_i
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"),
@@ -5497,131 +5584,6 @@ read_die_and_siblings (gdb_byte *info_pt
}
}
-/* 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
@@ -5647,7 +5609,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
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;
@@ -5719,8 +5681,8 @@ dwarf2_read_abbrevs (bfd *abfd, struct d
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;
@@ -6038,7 +6000,7 @@ read_partial_die (struct partial_die_inf
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;
@@ -6151,7 +6113,7 @@ read_partial_die (struct partial_die_inf
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:
@@ -6267,7 +6229,7 @@ find_partial_die (unsigned int offset, s
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);
@@ -6343,7 +6305,7 @@ read_full_die (struct die_info **diep, b
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)
@@ -6779,22 +6741,22 @@ read_indirect_string (bfd *abfd, gdb_byt
{
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
@@ -7081,7 +7043,7 @@ dwarf_decode_line_header (unsigned int o
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;
@@ -7089,7 +7051,7 @@ dwarf_decode_line_header (unsigned int o
/* 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;
@@ -7100,15 +7062,15 @@ dwarf_decode_line_header (unsigned int o
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;
@@ -7164,8 +7126,8 @@ dwarf_decode_line_header (unsigned int o
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"));
@@ -10145,7 +10107,7 @@ dwarf_decode_macros (struct line_header
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;
@@ -10162,9 +10124,9 @@ dwarf_decode_macros (struct line_header
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
{
@@ -10241,7 +10203,7 @@ dwarf_decode_macros (struct line_header
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
@@ -10459,7 +10421,7 @@ dwarf2_symbol_mark_computed (struct attr
/* ".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;
@@ -10470,8 +10432,8 @@ dwarf2_symbol_mark_computed (struct attr
/* 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,
@@ -10540,7 +10502,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_p
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);
@@ -10933,12 +10895,49 @@ show_dwarf2_cmd (char *args, int from_tt
cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
}
+/* If section described by INFO was mmaped, munmap it now. */
+
+static void
+munmap_section_buffer (struct dwarf2_section_info *info)
+{
+ if (info->was_mmaped)
+ {
+#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\
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.87
diff -u -p -u -r1.87 dwarf2-frame.c
--- dwarf2-frame.c 3 Jan 2009 05:57:51 -0000 1.87
+++ dwarf2-frame.c 27 May 2009 00:10:47 -0000
@@ -1896,15 +1896,9 @@ decode_frame_entry (struct comp_unit *un
}
\f
-/* FIXME: kettenis/20030504: This still needs to be integrated with
- dwarf2read.c in a better way. */
-
-/* Imported from dwarf2read.c. */
-extern asection *dwarf_frame_section;
-extern asection *dwarf_eh_frame_section;
-
/* Imported from dwarf2read.c. */
-extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp);
+extern void dwarf2_get_section_info(struct objfile *, const char *, asection **,
+ gdb_byte **, bfd_size_type *);
void
dwarf2_build_frame_info (struct objfile *objfile)
@@ -1922,17 +1916,15 @@ dwarf2_build_frame_info (struct objfile
/* First add the information from the .eh_frame section. That way,
the FDEs from that section are searched last. */
- if (dwarf_eh_frame_section)
+ dwarf2_get_section_info(objfile, ".eh_frame",
+ &unit->dwarf_frame_section,
+ &unit->dwarf_frame_buffer,
+ &unit->dwarf_frame_size);
+ if (unit->dwarf_frame_size)
{
asection *got, *txt;
unit->cie = NULL;
- unit->dwarf_frame_buffer = dwarf2_read_section (objfile,
- dwarf_eh_frame_section);
-
- unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section);
- unit->dwarf_frame_section = dwarf_eh_frame_section;
-
/* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base
that is used for the i386/amd64 target, which currently is
the only target in GCC that supports/uses the
@@ -1952,13 +1944,13 @@ dwarf2_build_frame_info (struct objfile
frame_ptr = decode_frame_entry (unit, frame_ptr, 1);
}
- if (dwarf_frame_section)
+ dwarf2_get_section_info(objfile, ".debug_frame",
+ &unit->dwarf_frame_section,
+ &unit->dwarf_frame_buffer,
+ &unit->dwarf_frame_size);
+ if (unit->dwarf_frame_size)
{
unit->cie = NULL;
- unit->dwarf_frame_buffer = dwarf2_read_section (objfile,
- dwarf_frame_section);
- unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section);
- unit->dwarf_frame_section = dwarf_frame_section;
frame_ptr = unit->dwarf_frame_buffer;
while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size)
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-05-27 0:12 [patch] Use mmap instead of obstack_alloc for dwarf debug sections Paul Pluzhnikov @ 2009-05-28 1:16 ` Tom Tromey 2009-05-28 16:57 ` Paul Pluzhnikov 0 siblings, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-05-28 1:16 UTC (permalink / raw) To: gdb-patches >>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes: I like this patch quite a bit. It has a number of minor formatting problems, mostly missing spaces before open parens. Paul> + caddr_t retbuf = mmap (0, map_length, PROT_READ, MAP_PRIVATE, Paul> + fileno ((FILE *)abfd->iostream), Paul> + pg_offset); I don't know for sure, but I assume that it is not valid in general to cast iostream like this. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-05-28 1:16 ` Tom Tromey @ 2009-05-28 16:57 ` Paul Pluzhnikov 2009-05-30 22:36 ` Tom Tromey 0 siblings, 1 reply; 29+ messages in thread From: Paul Pluzhnikov @ 2009-05-28 16:57 UTC (permalink / raw) To: tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1274 bytes --] On Wed, May 27, 2009 at 6:16 PM, Tom Tromey <tromey@redhat.com> wrote: > I like this patch quite a bit. > > It has a number of minor formatting problems, mostly missing spaces > before open parens. Sorry, these get me every time :-( I've corrected all I could find in the updated patch (attached). > Paul> + fileno ((FILE *)abfd->iostream), > > I don't know for sure, but I assume that it is not valid in general to > cast iostream like this. I would have used bfd_get_file_window(), but it's only compiled in when --use-mmap was given to bfd/configure. Is there a way to turn that on for GDB? The bfd_get_file_window() performs above cast, after checking for: (abfd->flags & BFD_IN_MEMORY) == 0) and later if (abfd->iostream == NULL && (abfd->iovec == NULL || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0)) The last 3 conditions can not be true because we just performed bfd_seek and bfd_bread on abfd. Looks like BFD_IN_MEMORY could be set if the file was add-symbol-file-from-memory'd. Is it ok to do this in gdb/dwarf2read.c: if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0 && (abfd->flags & BFD_IN_MEMORY) == 0) Thanks, -- Paul Pluzhnikov [-- Attachment #2: gdb-dwarf2-mmap-20090528.txt --] [-- Type: text/plain, Size: 43435 bytes --] Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.305 diff -u -p -u -r1.305 dwarf2read.c --- dwarf2read.c 26 May 2009 21:24:07 -0000 1.305 +++ dwarf2read.c 28 May 2009 16:38:18 -0000 @@ -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_mmaped; +}; + 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 (st 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,262 @@ section_is_p (asection *sectp, const cha 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) +zlib_decompress_section (struct objfile *objfile, asection *sectp, + gdb_byte **outbuf, bfd_size_type *outsize) { - 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); + 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_mmaped = 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 (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 = mmap (0, map_length, PROT_READ, MAP_PRIVATE, + fileno ((FILE *)abfd->iostream), + pg_offset); - if (dwarf_ranges_section) - dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section); - else - dwarf2_per_objfile->ranges_buffer = NULL; + if (retbuf != MAP_FAILED) + { + info->was_mmaped = 1; + info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; + return; + } + } +#endif - if (dwarf_loc_section) - dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section); - else - dwarf2_per_objfile->loc_buffer = NULL; + /* 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. */ + +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 + 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 +1424,7 @@ dwarf2_build_psymtabs_easy (struct objfi 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 +1499,19 @@ partial_read_comp_unit_head (struct comp "(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 +1593,7 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1617,8 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1638,7 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1795,7 @@ load_comp_unit (struct dwarf2_per_cu_dat 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 +1807,7 @@ load_comp_unit (struct dwarf2_per_cu_dat 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 +1847,21 @@ create_all_comp_units (struct objfile *o 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 +2507,7 @@ skip_one_die (gdb_byte *info_ptr, struct 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); } @@ -2693,7 +2780,7 @@ load_full_comp_unit (struct dwarf2_per_c /* 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)); @@ -3358,14 +3445,14 @@ dwarf2_ranges_read (unsigned offset, COR 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); @@ -3640,7 +3727,7 @@ dwarf2_record_block_ranges (struct die_i /* 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. @@ -3659,7 +3746,7 @@ dwarf2_record_block_ranges (struct die_i 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"), @@ -5497,131 +5584,6 @@ read_die_and_siblings (gdb_byte *info_pt } } -/* 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 @@ -5647,7 +5609,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct d 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; @@ -5719,8 +5681,8 @@ dwarf2_read_abbrevs (bfd *abfd, struct d 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; @@ -6038,7 +6000,7 @@ read_partial_die (struct partial_die_inf 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; @@ -6151,7 +6113,7 @@ read_partial_die (struct partial_die_inf 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: @@ -6267,7 +6229,7 @@ find_partial_die (unsigned int offset, s 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); @@ -6343,7 +6305,7 @@ read_full_die (struct die_info **diep, b 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) @@ -6779,22 +6741,22 @@ read_indirect_string (bfd *abfd, gdb_byt { 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 @@ -7081,7 +7043,7 @@ dwarf_decode_line_header (unsigned int o 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; @@ -7089,7 +7051,7 @@ dwarf_decode_line_header (unsigned int o /* 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; @@ -7100,15 +7062,15 @@ dwarf_decode_line_header (unsigned int o 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; @@ -7164,8 +7126,8 @@ dwarf_decode_line_header (unsigned int o 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")); @@ -10145,7 +10107,7 @@ dwarf_decode_macros (struct line_header 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; @@ -10162,9 +10124,9 @@ dwarf_decode_macros (struct line_header 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 { @@ -10241,7 +10203,7 @@ dwarf_decode_macros (struct line_header 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 @@ -10459,7 +10421,7 @@ dwarf2_symbol_mark_computed (struct attr /* ".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; @@ -10470,8 +10432,8 @@ dwarf2_symbol_mark_computed (struct attr /* 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, @@ -10540,7 +10502,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_p 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); @@ -10933,12 +10895,49 @@ show_dwarf2_cmd (char *args, int from_tt cmd_show_list (show_dwarf2_cmdlist, from_tty, ""); } +/* If section described by INFO was mmaped, munmap it now. */ + +static void +munmap_section_buffer (struct dwarf2_section_info *info) +{ + if (info->was_mmaped) + { +#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\ Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.87 diff -u -p -u -r1.87 dwarf2-frame.c --- dwarf2-frame.c 3 Jan 2009 05:57:51 -0000 1.87 +++ dwarf2-frame.c 28 May 2009 16:38:18 -0000 @@ -1896,15 +1896,9 @@ decode_frame_entry (struct comp_unit *un } \f -/* FIXME: kettenis/20030504: This still needs to be integrated with - dwarf2read.c in a better way. */ - -/* Imported from dwarf2read.c. */ -extern asection *dwarf_frame_section; -extern asection *dwarf_eh_frame_section; - /* Imported from dwarf2read.c. */ -extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp); +extern void dwarf2_get_section_info (struct objfile *, const char *, asection **, + gdb_byte **, bfd_size_type *); void dwarf2_build_frame_info (struct objfile *objfile) @@ -1922,17 +1916,15 @@ dwarf2_build_frame_info (struct objfile /* First add the information from the .eh_frame section. That way, the FDEs from that section are searched last. */ - if (dwarf_eh_frame_section) + dwarf2_get_section_info (objfile, ".eh_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { asection *got, *txt; unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_section); - - unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); - unit->dwarf_frame_section = dwarf_eh_frame_section; - /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the @@ -1952,13 +1944,13 @@ dwarf2_build_frame_info (struct objfile frame_ptr = decode_frame_entry (unit, frame_ptr, 1); } - if (dwarf_frame_section) + dwarf2_get_section_info (objfile, ".debug_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_section); - unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); - unit->dwarf_frame_section = dwarf_frame_section; frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-05-28 16:57 ` Paul Pluzhnikov @ 2009-05-30 22:36 ` Tom Tromey 2009-06-11 1:40 ` Paul Pluzhnikov 0 siblings, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-05-30 22:36 UTC (permalink / raw) To: Paul Pluzhnikov; +Cc: gdb-patches >>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes: Tom> It has a number of minor formatting problems, mostly missing spaces Tom> before open parens. Paul> Sorry, these get me every time :-( Yeah. Whatever happened to running gdb_indent.sh? Paul> I would have used bfd_get_file_window(), but it's only compiled in Paul> when --use-mmap was given to bfd/configure. Paul> Is there a way to turn that on for GDB? Paul> Is it ok to do this in gdb/dwarf2read.c: Paul> if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0 Paul> && (abfd->flags & BFD_IN_MEMORY) == 0) I don't know the answer to either of these. If nobody here knows, I suggest asking on the binutils list. If they aren't ok, maybe we could add a new BFD function for this. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-05-30 22:36 ` Tom Tromey @ 2009-06-11 1:40 ` Paul Pluzhnikov 2009-06-11 1:43 ` Paul Pluzhnikov 0 siblings, 1 reply; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-11 1:40 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1186 bytes --] On Sat, May 30, 2009 at 3:36 PM, Tom Tromey<tromey@redhat.com> wrote: >>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes: > > Tom> It has a number of minor formatting problems, mostly missing spaces > Tom> before open parens. > > Paul> Sorry, these get me every time :-( > > Yeah. Whatever happened to running gdb_indent.sh? Running gdb_indent.sh on these sources produces way too many incorrect indentations :-( I tried my best to have a space before parens this time. > Paul> I would have used bfd_get_file_window(), but it's only compiled in > Paul> when --use-mmap was given to bfd/configure. > Paul> Is there a way to turn that on for GDB? > > Paul> Is it ok to do this in gdb/dwarf2read.c: > Paul> if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0 > Paul> && (abfd->flags & BFD_IN_MEMORY) == 0) > > I don't know the answer to either of these. > If nobody here knows, I suggest asking on the binutils list. > If they aren't ok, maybe we could add a new BFD function for this. bfd_mmap is now checking in; attached patch uses it. Tested on Linux/x86_64 with no regressions. Thanks, -- Paul Pluzhnikov [-- Attachment #2: bfd-mmap-patch-20090610.txt --] [-- Type: text/plain, Size: 4922 bytes --] Index: bfd-in2.h =================================================================== RCS file: /cvs/src/src/bfd/bfd-in2.h,v retrieving revision 1.482 diff -u -p -u -r1.482 bfd-in2.h --- bfd-in2.h 1 Jun 2009 13:11:51 -0000 1.482 +++ bfd-in2.h 10 Jun 2009 17:01:28 -0000 @@ -463,6 +463,7 @@ extern int bfd_seek (bfd *, file_ptr, in extern file_ptr bfd_tell (bfd *); extern int bfd_flush (bfd *); extern int bfd_stat (bfd *, struct stat *); +extern void *bfd_mmap (bfd *, void *, bfd_size_type, int, int, file_ptr); /* Deprecated old routines. */ #if __GNUC__ Index: bfdio.c =================================================================== RCS file: /cvs/src/src/bfd/bfdio.c,v retrieving revision 1.21 diff -u -p -u -r1.21 bfdio.c --- bfdio.c 24 May 2009 11:47:27 -0000 1.21 +++ bfdio.c 10 Jun 2009 17:01:28 -0000 @@ -158,6 +158,8 @@ DESCRIPTION . int (*bclose) (struct bfd *abfd); . int (*bflush) (struct bfd *abfd); . int (*bstat) (struct bfd *abfd, struct stat *sb); +. void* (*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, +. int prot, int flags, file_ptr offset); .}; */ @@ -511,3 +513,31 @@ bfd_get_size (bfd *abfd) return buf.st_size; } + + +/* +FUNCTION + bfd_mmap + +SYNOPSIS + void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, + int prot, int flags, file_ptr offset); + +DESCRIPTION + Return mmap()ed region of the file, if possible and implemented. + +*/ + +void * +bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, + int prot, int flags, file_ptr offset) +{ + void *ret = (void *)-1; + if ((abfd->flags & BFD_IN_MEMORY) != 0) + return ret; + + if (abfd->iovec == NULL) + return ret; + + return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset); +} Index: cache.c =================================================================== RCS file: /cvs/src/src/bfd/cache.c,v retrieving revision 1.34 diff -u -p -u -r1.34 cache.c --- cache.c 30 Oct 2008 09:05:32 -0000 1.34 +++ cache.c 10 Jun 2009 17:01:28 -0000 @@ -46,6 +46,10 @@ SUBSECTION #include "libbfd.h" #include "libiberty.h" +#ifdef HAVE_MMAP +#include <sys/mman.h> +#endif + /* In some cases we can optimize cache operation when reopening files. For instance, a flush is entirely unnecessary if the file is already closed, so a flush would use CACHE_NO_OPEN. Similarly, a seek using @@ -388,10 +392,38 @@ cache_bstat (struct bfd *abfd, struct st return sts; } +static void * +cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, + void *addr ATTRIBUTE_UNUSED, + bfd_size_type len ATTRIBUTE_UNUSED, + int prot ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + file_ptr offset ATTRIBUTE_UNUSED) +{ + void *ret = (void *) -1; + + if ((abfd->flags & BFD_IN_MEMORY) != 0) + abort (); +#ifdef HAVE_MMAP + else + { + FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); + if (f == NULL) + return ret; + + ret = mmap (addr, len, prot, flags, fileno (f), offset); + if (ret == (void *) -1) + bfd_set_error (bfd_error_system_call); + } +#endif + + return ret; +} + static const struct bfd_iovec cache_iovec = { &cache_bread, &cache_bwrite, &cache_btell, &cache_bseek, - &cache_bclose, &cache_bflush, &cache_bstat + &cache_bclose, &cache_bflush, &cache_bstat, &cache_bmmap }; /* Index: libbfd.h =================================================================== RCS file: /cvs/src/src/bfd/libbfd.h,v retrieving revision 1.216 diff -u -p -u -r1.216 libbfd.h --- libbfd.h 1 Jun 2009 13:11:52 -0000 1.216 +++ libbfd.h 10 Jun 2009 17:01:28 -0000 @@ -773,6 +773,9 @@ struct bfd_iovec int (*bclose) (struct bfd *abfd); int (*bflush) (struct bfd *abfd); int (*bstat) (struct bfd *abfd, struct stat *sb); + /* Just like mmap: (void*)-1 on failure, mmapped address on success. */ + void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, + int prot, int flags, file_ptr offset); }; /* Extracted from bfdwin.c. */ struct _bfd_window_internal { Index: opncls.c =================================================================== RCS file: /cvs/src/src/bfd/opncls.c,v retrieving revision 1.53 diff -u -p -u -r1.53 opncls.c --- opncls.c 23 Aug 2008 08:08:58 -0000 1.53 +++ opncls.c 10 Jun 2009 17:01:28 -0000 @@ -505,9 +505,20 @@ opncls_bstat (struct bfd *abfd, struct s return (vec->stat) (abfd, vec->stream, sb); } +static void * +opncls_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, + void *addr ATTRIBUTE_UNUSED, + bfd_size_type len ATTRIBUTE_UNUSED, + int prot ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + file_ptr offset ATTRIBUTE_UNUSED) +{ + return (void *) -1; +} + static const struct bfd_iovec opncls_iovec = { &opncls_bread, &opncls_bwrite, &opncls_btell, &opncls_bseek, - &opncls_bclose, &opncls_bflush, &opncls_bstat + &opncls_bclose, &opncls_bflush, &opncls_bstat, &opncls_bmmap }; bfd * ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-11 1:40 ` Paul Pluzhnikov @ 2009-06-11 1:43 ` Paul Pluzhnikov 2009-06-16 19:19 ` Tom Tromey 0 siblings, 1 reply; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-11 1:43 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 246 bytes --] On Wed, Jun 10, 2009 at 6:39 PM, Paul Pluzhnikov<ppluzhnikov@google.com> wrote: > bfd_mmap is now checking in; attached patch uses it. Sorry, attached the bfd patch instead of the gdb one :-( Here is the right one. Thanks, -- Paul Pluzhnikov [-- Attachment #2: gdb-dwarf2-mmap-20090610.txt --] [-- Type: text/plain, Size: 43596 bytes --] Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.307 diff -u -p -u -r1.307 dwarf2read.c --- dwarf2read.c 10 Jun 2009 14:55:14 -0000 1.307 +++ dwarf2read.c 11 Jun 2009 01:01:35 -0000 @@ -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_mmaped; +}; + 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 (st 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,261 @@ section_is_p (asection *sectp, const cha 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) +zlib_decompress_section (struct objfile *objfile, asection *sectp, + gdb_byte **outbuf, bfd_size_type *outsize) { - 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); + 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_mmaped = 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 (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 (dwarf_ranges_section) - dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section); - else - dwarf2_per_objfile->ranges_buffer = NULL; + if (retbuf != MAP_FAILED) + { + info->was_mmaped = 1; + info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; + return; + } + } +#endif - if (dwarf_loc_section) - dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section); - else - dwarf2_per_objfile->loc_buffer = NULL; + /* 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. */ + +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 + 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 +1423,7 @@ dwarf2_build_psymtabs_easy (struct objfi 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 +1498,19 @@ partial_read_comp_unit_head (struct comp "(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 +1592,7 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1616,8 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1637,7 @@ dwarf2_build_psymtabs_hard (struct objfi 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 +1794,7 @@ load_comp_unit (struct dwarf2_per_cu_dat 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 +1806,7 @@ load_comp_unit (struct dwarf2_per_cu_dat 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 +1846,21 @@ create_all_comp_units (struct objfile *o 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 +2506,7 @@ skip_one_die (gdb_byte *info_ptr, struct 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); } @@ -2693,7 +2779,7 @@ load_full_comp_unit (struct dwarf2_per_c /* 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)); @@ -3358,14 +3444,14 @@ dwarf2_ranges_read (unsigned offset, COR 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); @@ -3640,7 +3726,7 @@ dwarf2_record_block_ranges (struct die_i /* 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. @@ -3659,7 +3745,7 @@ dwarf2_record_block_ranges (struct die_i 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"), @@ -5497,131 +5583,6 @@ read_die_and_siblings (gdb_byte *info_pt } } -/* 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 @@ -5647,7 +5608,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct d 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; @@ -5719,8 +5680,8 @@ dwarf2_read_abbrevs (bfd *abfd, struct d 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; @@ -6038,7 +5999,7 @@ read_partial_die (struct partial_die_inf 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; @@ -6151,7 +6112,7 @@ read_partial_die (struct partial_die_inf 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: @@ -6267,7 +6228,7 @@ find_partial_die (unsigned int offset, s 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); @@ -6343,7 +6304,7 @@ read_full_die (struct die_info **diep, b 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) @@ -6779,22 +6740,22 @@ read_indirect_string (bfd *abfd, gdb_byt { 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 @@ -7081,7 +7042,7 @@ dwarf_decode_line_header (unsigned int o 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; @@ -7089,7 +7050,7 @@ dwarf_decode_line_header (unsigned int o /* 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; @@ -7100,15 +7061,15 @@ dwarf_decode_line_header (unsigned int o 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; @@ -7164,8 +7125,8 @@ dwarf_decode_line_header (unsigned int o 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")); @@ -10150,7 +10111,7 @@ dwarf_decode_macros (struct line_header 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; @@ -10167,9 +10128,9 @@ dwarf_decode_macros (struct line_header 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 { @@ -10246,7 +10207,7 @@ dwarf_decode_macros (struct line_header 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 @@ -10464,7 +10425,7 @@ dwarf2_symbol_mark_computed (struct attr /* ".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; @@ -10475,8 +10436,8 @@ dwarf2_symbol_mark_computed (struct attr /* 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, @@ -10545,7 +10506,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_p 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); @@ -10938,12 +10899,49 @@ show_dwarf2_cmd (char *args, int from_tt cmd_show_list (show_dwarf2_cmdlist, from_tty, ""); } +/* If section described by INFO was mmaped, munmap it now. */ + +static void +munmap_section_buffer (struct dwarf2_section_info *info) +{ + if (info->was_mmaped) + { +#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\ Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.87 diff -u -p -u -r1.87 dwarf2-frame.c --- dwarf2-frame.c 3 Jan 2009 05:57:51 -0000 1.87 +++ dwarf2-frame.c 11 Jun 2009 01:01:35 -0000 @@ -1896,15 +1896,9 @@ decode_frame_entry (struct comp_unit *un } \f -/* FIXME: kettenis/20030504: This still needs to be integrated with - dwarf2read.c in a better way. */ - -/* Imported from dwarf2read.c. */ -extern asection *dwarf_frame_section; -extern asection *dwarf_eh_frame_section; - /* Imported from dwarf2read.c. */ -extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp); +extern void dwarf2_get_section_info (struct objfile *, const char *, asection **, + gdb_byte **, bfd_size_type *); void dwarf2_build_frame_info (struct objfile *objfile) @@ -1922,17 +1916,15 @@ dwarf2_build_frame_info (struct objfile /* First add the information from the .eh_frame section. That way, the FDEs from that section are searched last. */ - if (dwarf_eh_frame_section) + dwarf2_get_section_info (objfile, ".eh_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { asection *got, *txt; unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_section); - - unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); - unit->dwarf_frame_section = dwarf_eh_frame_section; - /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the @@ -1952,13 +1944,13 @@ dwarf2_build_frame_info (struct objfile frame_ptr = decode_frame_entry (unit, frame_ptr, 1); } - if (dwarf_frame_section) + dwarf2_get_section_info (objfile, ".debug_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_section); - unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); - unit->dwarf_frame_section = dwarf_frame_section; frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-11 1:43 ` Paul Pluzhnikov @ 2009-06-16 19:19 ` Tom Tromey 2009-06-16 20:43 ` Paul Pluzhnikov 0 siblings, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-06-16 19:19 UTC (permalink / raw) To: Paul Pluzhnikov; +Cc: gdb-patches >>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes: Paul> Sorry, attached the bfd patch instead of the gdb one :-( Paul> Here is the right one. Thanks. One point of order -- if you re-send a patch, re-send the ChangeLog entry too. Not a big deal, but it makes things simpler when reviewing. Thanks. I saw in your original post that this patch helps on memory-constrained machines; your example was 2G of debug info on a 4G machine. I just want to make sure that this doesn't hurt other cases; I don't expect it would, but it is good to cross the t's... I like how this patch cleans up some globals in dwarf2read.c. I have a few comments, mostly nits, but one real one. Paul> +struct dwarf2_section_info Paul> +{ Paul> + asection *asection; Paul> + gdb_byte *buffer; Paul> + bfd_size_type size; Paul> + int was_mmaped; I would spell this "was_mmapped" (two "p"s). Paul> +zlib_decompress_section (struct objfile *objfile, asection *sectp, Paul> + gdb_byte **outbuf, bfd_size_type *outsize) [...] Paul> + bfd_size_type compressed_size = bfd_get_section_size (sectp); Paul> + gdb_byte *compressed_buffer = xmalloc (compressed_size); Paul> + bfd_size_type uncompressed_size; Paul> + gdb_byte *uncompressed_buffer; Paul> + z_stream strm; Paul> + int rc; Paul> + int header_size = 12; Paul> + Paul> + if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 Paul> + || bfd_bread (compressed_buffer, compressed_size, abfd) != compressed_size) Paul> + error (_("Dwarf Error: Can't read DWARF data from '%s'"), Paul> + bfd_get_filename (abfd)); This isn't your problem -- but I noticed that this will leak compressed_buffer if there is an error. This code needs to use a cleanup. I'll fix this after your patch goes in. Paul> +static void Paul> +dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) [...] Paul> +#ifdef HAVE_MMAP [...] Paul> + { Paul> + info->was_mmaped = 1; Paul> + info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; Paul> + return; Paul> + } [...] Paul> + /* When debugging .o files, we may need to apply relocations; see Paul> + http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . Paul> + We never compress sections in .o files, so we only need to Paul> + try this when the section is not compressed. */ Paul> + retbuf = symfile_relocate_debug_section (abfd, sectp, buf); If we're using mmap then we seem to skip this relocation step. This seems like a bug. IIUC, this is an unusual case. So perhaps one fix would be to introduce a new symfile_debug_section_needs_relocate_p, then protect the mmap branch with that. Paul> +static void Paul> +munmap_section_buffer (struct dwarf2_section_info *info) [...] Paul> + gdb_assert (munmap ((void *)map_begin, map_length) == 0); Space after the ")" of the cast to void *. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-16 19:19 ` Tom Tromey @ 2009-06-16 20:43 ` Paul Pluzhnikov 2009-06-16 20:59 ` Tom Tromey 0 siblings, 1 reply; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-16 20:43 UTC (permalink / raw) To: tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 2668 bytes --] On Tue, Jun 16, 2009 at 12:19 PM, Tom Tromey<tromey@redhat.com> wrote: > Thanks. One point of order -- if you re-send a patch, re-send the > ChangeLog entry too. Not a big deal, but it makes things simpler when > reviewing. Thanks. Will do, thanks. > I saw in your original post that this patch helps on > memory-constrained machines; your example was 2G of debug info on a 4G > machine. I just want to make sure that this doesn't hurt other cases; > I don't expect it would, but it is good to cross the t's... I saw minor gain on 16GB machine. I don't see how this could hurt: we aren't using any more memory by doing mmap, we just cooperate with buffer cache instead of fighting with it. > > Paul> + int was_mmaped; > > I would spell this "was_mmapped" (two "p"s). Fixed. > Paul> + /* When debugging .o files, we may need to apply relocations; see > Paul> + http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . > Paul> + We never compress sections in .o files, so we only need to > Paul> + try this when the section is not compressed. */ > Paul> + retbuf = symfile_relocate_debug_section (abfd, sectp, buf); > > If we're using mmap then we seem to skip this relocation step. > This seems like a bug. That's what "&& (sectp->flags & SEC_RELOC) == 0)" check before mmap is for. In symfile_relocate_debug_section(): /* We're only interested in sections with relocation information. */ if ((sectp->flags & SEC_RELOC) == 0) return NULL; I've added a comment to that effect. > IIUC, this is an unusual case. So perhaps one fix would be to > introduce a new symfile_debug_section_needs_relocate_p, then protect > the mmap branch with that. I can add symfile_debug_section_needs_relocate_p() if that's preferable. > Paul> + gdb_assert (munmap ((void *)map_begin, map_length) == 0); > > Space after the ")" of the cast to void *. Fixed. Thanks, -- Paul Pluzhnikov 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. [-- Attachment #2: gdb-dwarf2-mmap-20090616.txt --] [-- Type: text/plain, Size: 43784 bytes --] Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.308 diff -u -p -u -r1.308 dwarf2read.c --- dwarf2read.c 13 Jun 2009 04:23:34 -0000 1.308 +++ dwarf2read.c 16 Jun 2009 20:41:52 -0000 @@ -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 (st 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 cha 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) +zlib_decompress_section (struct objfile *objfile, asection *sectp, + gdb_byte **outbuf, bfd_size_type *outsize) { - 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); + 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 (dwarf_loc_section) - dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section); - else - dwarf2_per_objfile->loc_buffer = NULL; + 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. */ + +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 + 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 objfi 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 "(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 objfi 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 objfi 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 objfi 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_dat 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_dat 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 *o 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 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_c /* 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, COR 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_i /* 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_i 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_pt } } -/* 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 d 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 d 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_inf 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_inf 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, s 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, b 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_byt { 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 o 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 o /* 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 o 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 o 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 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 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 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 attr /* ".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 attr /* 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_p 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_tt 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\ Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.87 diff -u -p -u -r1.87 dwarf2-frame.c --- dwarf2-frame.c 3 Jan 2009 05:57:51 -0000 1.87 +++ dwarf2-frame.c 16 Jun 2009 20:41:52 -0000 @@ -1896,15 +1896,9 @@ decode_frame_entry (struct comp_unit *un } \f -/* FIXME: kettenis/20030504: This still needs to be integrated with - dwarf2read.c in a better way. */ - -/* Imported from dwarf2read.c. */ -extern asection *dwarf_frame_section; -extern asection *dwarf_eh_frame_section; - /* Imported from dwarf2read.c. */ -extern gdb_byte *dwarf2_read_section (struct objfile *objfile, asection *sectp); +extern void dwarf2_get_section_info (struct objfile *, const char *, asection **, + gdb_byte **, bfd_size_type *); void dwarf2_build_frame_info (struct objfile *objfile) @@ -1922,17 +1916,15 @@ dwarf2_build_frame_info (struct objfile /* First add the information from the .eh_frame section. That way, the FDEs from that section are searched last. */ - if (dwarf_eh_frame_section) + dwarf2_get_section_info (objfile, ".eh_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { asection *got, *txt; unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_eh_frame_section); - - unit->dwarf_frame_size = bfd_get_section_size (dwarf_eh_frame_section); - unit->dwarf_frame_section = dwarf_eh_frame_section; - /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base that is used for the i386/amd64 target, which currently is the only target in GCC that supports/uses the @@ -1952,13 +1944,13 @@ dwarf2_build_frame_info (struct objfile frame_ptr = decode_frame_entry (unit, frame_ptr, 1); } - if (dwarf_frame_section) + dwarf2_get_section_info (objfile, ".debug_frame", + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { unit->cie = NULL; - unit->dwarf_frame_buffer = dwarf2_read_section (objfile, - dwarf_frame_section); - unit->dwarf_frame_size = bfd_get_section_size (dwarf_frame_section); - unit->dwarf_frame_section = dwarf_frame_section; frame_ptr = unit->dwarf_frame_buffer; while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-16 20:43 ` Paul Pluzhnikov @ 2009-06-16 20:59 ` Tom Tromey 2009-06-16 21:07 ` Paul Pluzhnikov 0 siblings, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-06-16 20:59 UTC (permalink / raw) To: Paul Pluzhnikov; +Cc: gdb-patches >>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes: Paul> That's what "&& (sectp->flags & SEC_RELOC) == 0)" check before Paul> mmap is for. In symfile_relocate_debug_section(): Oops, I missed that. Sorry about that. This patch ok. Thanks. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-16 20:59 ` Tom Tromey @ 2009-06-16 21:07 ` Paul Pluzhnikov 2009-06-18 9:20 ` Ken Werner 2009-06-23 15:03 ` [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] Jan Kratochvil 0 siblings, 2 replies; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-16 21:07 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Tue, Jun 16, 2009 at 1:58 PM, Tom Tromey<tromey@redhat.com> wrote: > This patch ok. So committed. Thanks, -- Paul Pluzhnikov ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-16 21:07 ` Paul Pluzhnikov @ 2009-06-18 9:20 ` Ken Werner 2009-06-18 14:06 ` Paul Pluzhnikov 2009-06-23 15:03 ` [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] Jan Kratochvil 1 sibling, 1 reply; 29+ messages in thread From: Ken Werner @ 2009-06-18 9:20 UTC (permalink / raw) To: Paul Pluzhnikov, gdb-patches Paul Pluzhnikov wrote: > On Tue, Jun 16, 2009 at 1:58 PM, Tom Tromey<tromey@redhat.com> wrote: > >> This patch ok. > > So committed. > > Thanks, Hi, I noticed gdb/dwarf2-frame.c:1922 (and :1950) calls dwarf2_get_section_info with unsigned long* (5th argument). The function expects a bfd_size_type * (a pointer to an unsigned long long on my machine). Thus the compiler issues a warning and the gdb build fails because of -Werror. Is it sufficient to just cast to (bfd_size_type *) or am I missing something? Regards -ken ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-18 9:20 ` Ken Werner @ 2009-06-18 14:06 ` Paul Pluzhnikov 2009-06-18 14:11 ` Paul Pluzhnikov 2009-06-18 15:02 ` Ken Werner 0 siblings, 2 replies; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-18 14:06 UTC (permalink / raw) To: Ken Werner; +Cc: gdb-patches On Thu, Jun 18, 2009 at 2:19 AM, Ken Werner <ken@linux.vnet.ibm.com> wrote: > I noticed gdb/dwarf2-frame.c:1922 (and :1950) calls dwarf2_get_section_info > with unsigned long* (5th argument). The function expects a bfd_size_type * > (a pointer to an unsigned long long on my machine). Thus the compiler issues > a warning and the gdb build fails because of -Werror. Is it sufficient to > just cast to (bfd_size_type *) or am I missing something? I think the cast would be wrong, as dwarf2_get_section_info would really write 'unsigned long long' and corrupt your stack. I've checked in the patch below under the obvious rule. -- Paul Pluzhnikov 2009-06-18 Paul Pluzhnikov <ppluzhnikov@google.com> * dwarf2-frame.c (struct comp_unit): Use bfd_size_type for dwarf_frame_size. Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.88 diff -u -p -u -r1.88 dwarf2-frame.c --- dwarf2-frame.c 16 Jun 2009 21:06:40 -0000 1.88 +++ dwarf2-frame.c 18 Jun 2009 13:57:58 -0000 @@ -130,7 +130,7 @@ struct comp_unit gdb_byte *dwarf_frame_buffer; /* Length of the loaded .debug_frame section. */ - unsigned long dwarf_frame_size; + bfd_size_type dwarf_frame_size; /* Pointer to the .debug_frame section. */ asection *dwarf_frame_section; ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-18 14:06 ` Paul Pluzhnikov @ 2009-06-18 14:11 ` Paul Pluzhnikov 2009-06-18 15:02 ` Ken Werner 1 sibling, 0 replies; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-18 14:11 UTC (permalink / raw) To: Ken Werner; +Cc: gdb-patches On Thu, Jun 18, 2009 at 7:06 AM, Paul Pluzhnikov<ppluzhnikov@google.com> wrote: > I think the cast would be wrong, as dwarf2_get_section_info would really > write 'unsigned long long' and corrupt your stack. Assuming 'sizeof(long long) > sizeof(long)' on your machine of course. -- Paul Pluzhnikov ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-18 14:06 ` Paul Pluzhnikov 2009-06-18 14:11 ` Paul Pluzhnikov @ 2009-06-18 15:02 ` Ken Werner 2009-06-18 16:33 ` Paul Pluzhnikov 1 sibling, 1 reply; 29+ messages in thread From: Ken Werner @ 2009-06-18 15:02 UTC (permalink / raw) To: Paul Pluzhnikov, gdb-patches On Thursday 18 June 2009 04:06:14 pm you wrote: > I've checked in the patch below under the obvious rule. Changing the type of dwarf_frame_size to bfd_size_type sounds perfect. GDB head compiles flawlessy again. Thanks -ken ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-18 15:02 ` Ken Werner @ 2009-06-18 16:33 ` Paul Pluzhnikov 2009-06-19 7:10 ` Ken Werner 0 siblings, 1 reply; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-18 16:33 UTC (permalink / raw) To: Ken Werner; +Cc: gdb-patches On Thu, Jun 18, 2009 at 8:02 AM, Ken Werner<ken@linux.vnet.ibm.com> wrote: > Changing the type of dwarf_frame_size to bfd_size_type sounds perfect. GDB > head compiles flawlessy again. Out of curiosity, what are your host and target triplets? Thanks, -- Paul Pluzhnikov ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections. 2009-06-18 16:33 ` Paul Pluzhnikov @ 2009-06-19 7:10 ` Ken Werner 0 siblings, 0 replies; 29+ messages in thread From: Ken Werner @ 2009-06-19 7:10 UTC (permalink / raw) To: Paul Pluzhnikov, gdb-patches On Thursday 18 June 2009 06:32:57 pm you wrote: > On Thu, Jun 18, 2009 at 8:02 AM, Ken Werner<ken@linux.vnet.ibm.com> wrote: > > Changing the type of dwarf_frame_size to bfd_size_type sounds perfect. > > GDB head compiles flawlessy again. > > Out of curiosity, what are your host and target triplets? > > Thanks, Hi Paul, I'm building on ppc for the SPU target: --build=powerpc64-unknown-linux-gnu \ --host=powerpc64-unknown-linux-gnu \ --target=spu. I've setup a daily build script primarily for testing gcc with newlib which builds the gdb too. Regards -ken ^ permalink raw reply [flat|nested] 29+ messages in thread
* [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] 2009-06-16 21:07 ` Paul Pluzhnikov 2009-06-18 9:20 ` Ken Werner @ 2009-06-23 15:03 ` Jan Kratochvil 2009-06-23 17:35 ` Paul Pluzhnikov 2009-06-23 18:08 ` Tom Tromey 1 sibling, 2 replies; 29+ messages in thread From: Jan Kratochvil @ 2009-06-23 15:03 UTC (permalink / raw) To: Paul Pluzhnikov; +Cc: Tom Tromey, gdb-patches Hi Paul, while sure your patch is great it has a regression. Assuming a regression reproducer needs to link GDB with -lmcheck (but did verify it). (I do not try to advocate reread_symbols but its code is there now.) Thanks, Jan This patch will fix back (tested on {x86_64,i686}-fedora-linux-gnu): -FAIL: gdb.ada/exec_changed.exp: start second -dwarf2read.c:10943: internal-error: munmap_section_buffer: Assertion `munmap ((void *) map_begin, map_length) == 0' failed.^M +PASS: gdb.ada/exec_changed.exp: start second -FAIL: gdb.base/chng-syms.exp: (timeout) running with invalidated bpt condition after executable changes -dwarf2read.c:10943: internal-error: munmap_section_buffer: Assertion `munmap ((void *) map_begin, map_length) == 0' failed.^M +PASS: gdb.base/chng-syms.exp: running with invalidated bpt condition after executable changes -FAIL: gdb.base/reread.exp: run to foo() second time (timeout) -dwarf2read.c:10943: internal-error: munmap_section_buffer: Assertion `munmap ((void *) map_begin, map_length) == 0' failed.^M -FAIL: gdb.base/reread.exp: shell mv /home/jkratoch/hammock/20090623build-gdbcvs/fedora-11-i386/build/src/gdb/testsuite.unix.-m32/gdb.base/reread /home/jkratoch/hammock/20090623build-gdbcvs/fedora-11-i386/build/src/gdb/testsuite.unix.-m32/gdb.base/reread2 (GDB internal error) -ERROR: Could not resync from internal error (timeout) -[more mess] +PASS: gdb.base/reread.exp: run to foo() second time +PASS: gdb.base/reread.exp: second pass: breakpoint foo in first file +PASS: gdb.base/reread.exp: second pass: run to foo() +PASS: gdb.base/reread.exp: second pass: continue to completion +PASS: gdb.base/reread.exp: second pass: run to foo() second time munmap(0x9595959595959000, 10778685752873425706) = -1 EINVAL (Invalid argument) write(1, "dwarf2read.c:10943: internal-error: munmap_section_buffer: Assertion `munmap ((void *) map_begin, map_length) == 0' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unre"..., 209) = 209 2009-06-23 Jan Kratochvil <jan.kratochvil@redhat.com> Fix a regression by the mmap patch from 2009-06-16. * symfile.c (reread_symbols): Move sym_finish and clear_objfile_data calls before deleting the OBJFILE obstack. Extend the comment. --- gdb/symfile.c 17 Jun 2009 18:34:34 -0000 1.232 +++ gdb/symfile.c 23 Jun 2009 14:56:34 -0000 @@ -2334,7 +2334,16 @@ reread_symbols (void) /* Nuke all the state that we will re-read. Much of the following code which sets things to NULL really is necessary to tell - other parts of GDB that there is nothing currently there. */ + other parts of GDB that there is nothing currently there. + + Try to keep the freeing order compatible with free_objfile. */ + + if (objfile->sf != NULL) + { + (*objfile->sf->sym_finish) (objfile); + } + + clear_objfile_data (objfile); /* FIXME: Do we have to free a whole linked list, or is this enough? */ @@ -2371,11 +2380,6 @@ reread_symbols (void) sizeof (objfile->msymbol_hash)); memset (&objfile->msymbol_demangled_hash, 0, sizeof (objfile->msymbol_demangled_hash)); - clear_objfile_data (objfile); - if (objfile->sf != NULL) - { - (*objfile->sf->sym_finish) (objfile); - } objfile->psymbol_cache = bcache_xmalloc (); objfile->macro_cache = bcache_xmalloc (); ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] 2009-06-23 15:03 ` [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] Jan Kratochvil @ 2009-06-23 17:35 ` Paul Pluzhnikov 2009-06-23 18:08 ` Tom Tromey 1 sibling, 0 replies; 29+ messages in thread From: Paul Pluzhnikov @ 2009-06-23 17:35 UTC (permalink / raw) To: Jan Kratochvil; +Cc: Tom Tromey, gdb-patches [-- Attachment #1: Type: text/plain, Size: 419 bytes --] On Tue, Jun 23, 2009 at 8:03 AM, Jan Kratochvil<jan.kratochvil@redhat.com> wrote: > while sure your patch is great it has a regression. Assuming a regression > reproducer needs to link GDB with -lmcheck (but did verify it). The problem also shows up under Valgrind (log attached). > This patch will fix back (tested on {x86_64,i686}-fedora-linux-gnu): Looks good to me. Thanks, -- Paul Pluzhnikov [-- Attachment #2: gdb-valgrind.txt --] [-- Type: text/plain, Size: 3567 bytes --] (gdb) shell touch /usr/local/google/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/testsuite/gdb.base/reread^M (gdb) run ^M The program being debugged has been started already.^M Start it from the beginning? (y or n) y^M `/usr/local/google/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/testsuite/gdb.base/reread' has changed; re-reading symbols.^M ==8569== Invalid read of size 4^M ==8569== at 0x52E264: munmap_section_buffer /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/dwarf2read.c:10937^M ==8569== by 0x52E2DB: dwarf2_per_objfile_cleanup /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/dwarf2read.c:10957^M ==8569== by 0x448209: clear_objfile_data /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/objfiles.c:875^M ==8569== by 0x4E4152: reread_symbols /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/symfile.c:2374^M ==8569== by 0x4EF305: run_command_1 /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/infcmd.c:490^M ==8569== by 0x44D433: execute_command /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/top.c:442^M ==8569== by 0x5042F8: command_handler /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:511^M ==8569== by 0x504E4B: command_line_handler /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:735^M ==8569== by 0x5B53D2: rl_callback_read_char /usr/local/google/ppluzhnikov/Archive/sourceware.org/gdb/build/readline/../../src/readline/callback.c:205^M ==8569== by 0x504428: rl_callback_read_char_wrapper /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:178^M ==8569== by 0x502F20: process_event /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-loop.c:394^M ==8569== by 0x503D97: gdb_do_one_event /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-loop.c:447^M ==8569== Address 0x5b78aa0 is 3,480 bytes inside a block of size 4,072 free'd^M ==8569== at 0x4C1DE0F: free /tmp/vg/coregrind/m_replacemalloc/vg_replace_malloc.c:322^M ==8569== by 0x576D0E7: obstack_free /usr/grte/v1/debug-src/src/glibc-2.3.6/malloc/obstack.c:347^M ==8569== by 0x4E40CD: reread_symbols /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/symfile.c:2360^M ==8569== by 0x4EF305: run_command_1 /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/infcmd.c:490^M ==8569== by 0x44D433: execute_command /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/top.c:442^M ==8569== by 0x5042F8: command_handler /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:511^M ==8569== by 0x504E4B: command_line_handler /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:735^M ==8569== by 0x5B53D2: rl_callback_read_char /usr/local/google/ppluzhnikov/Archive/sourceware.org/gdb/build/readline/../../src/readline/callback.c:205^M ==8569== by 0x504428: rl_callback_read_char_wrapper /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-top.c:178^M ==8569== by 0x502F20: process_event /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-loop.c:394^M ==8569== by 0x503D97: gdb_do_one_event /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/event-loop.c:447^M ==8569== by 0x4FE6AA: catch_errors /home/ppluzhnikov/Archive/sourceware.org/gdb/build/gdb/../../src/gdb/exceptions.c:510^M ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] 2009-06-23 15:03 ` [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] Jan Kratochvil 2009-06-23 17:35 ` Paul Pluzhnikov @ 2009-06-23 18:08 ` Tom Tromey 2009-06-23 18:21 ` Jan Kratochvil 1 sibling, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-06-23 18:08 UTC (permalink / raw) To: Jan Kratochvil; +Cc: Paul Pluzhnikov, gdb-patches >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: Jan> while sure your patch is great it has a regression. Assuming a regression Jan> reproducer needs to link GDB with -lmcheck (but did verify it). Thanks for finding this. Jan> 2009-06-23 Jan Kratochvil <jan.kratochvil@redhat.com> Jan> Fix a regression by the mmap patch from 2009-06-16. Jan> * symfile.c (reread_symbols): Move sym_finish and clear_objfile_data Jan> calls before deleting the OBJFILE obstack. Extend the comment. This is ok. Jan> + Try to keep the freeing order compatible with free_objfile. */ It seems like it would be nice to have a single function here. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] 2009-06-23 18:08 ` Tom Tromey @ 2009-06-23 18:21 ` Jan Kratochvil 2009-06-23 20:00 ` Tom Tromey 0 siblings, 1 reply; 29+ messages in thread From: Jan Kratochvil @ 2009-06-23 18:21 UTC (permalink / raw) To: Tom Tromey; +Cc: Paul Pluzhnikov, gdb-patches On Tue, 23 Jun 2009 20:08:41 +0200, Tom Tromey wrote: > >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: > > Jan> while sure your patch is great it has a regression. Assuming a regression > Jan> reproducer needs to link GDB with -lmcheck (but did verify it). ^I ^not > This is ok. Checked-in. http://sourceware.org/ml/gdb-cvs/2009-06/msg00148.html > Jan> + Try to keep the freeing order compatible with free_objfile. */ > > It seems like it would be nice to have a single function here. IMO the whole `struct objfile' should replaced by a new one (instead of its in-place patching). Which will probably have other dependencies... Thanks, Jan ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] 2009-06-23 18:21 ` Jan Kratochvil @ 2009-06-23 20:00 ` Tom Tromey 2009-06-25 19:21 ` [patch] Replace reread_symbols by load+free calls Jan Kratochvil 0 siblings, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-06-23 20:00 UTC (permalink / raw) To: Jan Kratochvil; +Cc: Paul Pluzhnikov, gdb-patches >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: Jan> IMO the whole `struct objfile' should replaced by a new one Jan> (instead of its in-place patching). Which will probably have Jan> other dependencies... I'm interested to hear your idea and reasoning. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* [patch] Replace reread_symbols by load+free calls 2009-06-23 20:00 ` Tom Tromey @ 2009-06-25 19:21 ` Jan Kratochvil 2009-06-25 19:57 ` Pedro Alves 2009-08-14 23:09 ` Tom Tromey 0 siblings, 2 replies; 29+ messages in thread From: Jan Kratochvil @ 2009-06-25 19:21 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On Tue, 23 Jun 2009 22:00:25 +0200, Tom Tromey wrote: > >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: > > Jan> IMO the whole `struct objfile' should replaced by a new one > Jan> (instead of its in-place patching). Which will probably have > Jan> other dependencies... > > I'm interested to hear your idea and reasoning. Sometimes there are differentiations between complete objects destructors (objfile_free_data) and in-place object deletions (clear_objfile_data); OK did not briefly found more such cases now. Expecting it was there for some performance improvements which not worth it nowadays. reread_symbols was also trying to be in-place variant but thus it had to redefine functions loading+freeing objfiles. Expecting this patch may affect the behavior a bit but it should only improve. The exec_bfd handling is ugly but it is left as is, for some different patch. No regressions on {x86_64,i686}-fedora-linux-gnu. Thanks, Jan 2009-06-25 Jan Kratochvil <jan.kratochvil@redhat.com> Simplify reread_symbols. * objfiles.h (struct objfile <mtime>): New FIXME comment. * solib.c (update_solib_list): Reload the library if it has changed. * symfile.c: Include solist.h. (reread_symbols): Replace the in-place rereading by calls to symbol_file_add and free_objfile. Call now also solib_add. Move the variables new_modtime, new_statbuf and res with the OBJFILE change checking code to ... (objfile_has_changed): ... a new function. (reread_separate_symbols): Remove the function. * symfile.h (objfile_has_changed): New prototype. diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 60d3143..e03861f 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -236,7 +236,7 @@ struct objfile struct gdbarch *gdbarch; /* The modification timestamp of the object file, as of the last time - we read its symbols. */ + we read its symbols. FIXME: Replace it by a bfd_get_mtime call. */ long mtime; diff --git a/gdb/solib.c b/gdb/solib.c index d194ac7..fae0f4a 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -615,7 +615,7 @@ update_solib_list (int from_tty, struct target_ops *target) /* If the shared object appears on the inferior's list too, then it's still loaded, so we don't need to do anything. Delete it from the inferior's list, and leave it on GDB's list. */ - if (i) + if (i && (gdb->objfile == NULL || !objfile_has_changed (gdb->objfile))) { *i_link = i->next; free_so (i); diff --git a/gdb/symfile.c b/gdb/symfile.c index 25f3f26..f503756 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -55,6 +55,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "solist.h" #include <sys/types.h> #include <fcntl.h> @@ -96,8 +97,6 @@ static void symbol_file_add_main_1 (char *args, int from_tty, int flags); static void add_symbol_file_command (char *, int); -static void reread_separate_symbols (struct objfile *objfile); - static void cashier_psymtab (struct partial_symtab *); bfd *symfile_bfd_open (char *); @@ -2231,17 +2230,58 @@ add_symbol_file_command (char *args, int from_tty) reinit_frame_cache (); do_cleanups (my_cleanups); } -\f + +/* Return non-zero if OBJFILE (or its SEPARATE_DEBUG_OBJFILE) has changed on + the disk since its load. You should not call this function for the separate + debug info file itself. */ + +int +objfile_has_changed (struct objfile *objfile) +{ + long new_modtime; + struct stat new_statbuf; + int res; + + if (objfile->obfd == NULL) + return 0; + +#ifdef DEPRECATED_IBM6000_TARGET + /* If this object is from a shared library, then you should + stat on the library name, not member name. */ + + if (objfile->obfd->my_archive) + res = stat (objfile->obfd->my_archive->filename, &new_statbuf); + else +#endif + res = stat (objfile->name, &new_statbuf); + if (res != 0) + { + /* FIXME, should use print_sys_errmsg but it's not filtered. */ + printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), + objfile->name); + return 0; + } + + new_modtime = new_statbuf.st_mtime; + if (new_modtime != objfile->mtime) + { + printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"), + objfile->name); + return 1; + } + + if (objfile->separate_debug_objfile) + return objfile_has_changed (objfile->separate_debug_objfile); + + return 0; +} /* Re-read symbols if a symbol-file has changed. */ void reread_symbols (void) { - struct objfile *objfile; - long new_modtime; + struct objfile *objfile, *objfile_next; int reread_one = 0; - struct stat new_statbuf; - int res; /* With the addition of shared libraries, this should be modified, the load time should be saved in the partial symbol tables, since @@ -2249,283 +2289,85 @@ reread_symbols (void) This routine should then walk down each partial symbol table and see if the symbol table that it originates from has been changed */ - for (objfile = object_files; objfile; objfile = objfile->next) + for (objfile = object_files; objfile != NULL; objfile = objfile_next) { - if (objfile->obfd) - { -#ifdef DEPRECATED_IBM6000_TARGET - /* If this object is from a shared library, then you should - stat on the library name, not member name. */ + struct so_list *so; + int add_flags; - if (objfile->obfd->my_archive) - res = stat (objfile->obfd->my_archive->filename, &new_statbuf); - else -#endif - res = stat (objfile->name, &new_statbuf); - if (res != 0) - { - /* FIXME, should use print_sys_errmsg but it's not filtered. */ - printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), - objfile->name); - continue; - } - new_modtime = new_statbuf.st_mtime; - if (new_modtime != objfile->mtime) - { - struct cleanup *old_cleanups; - struct section_offsets *offsets; - int num_offsets; - char *obfd_filename; - - printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"), - objfile->name); - - /* There are various functions like symbol_file_add, - symfile_bfd_open, syms_from_objfile, etc., which might - appear to do what we want. But they have various other - effects which we *don't* want. So we just do stuff - ourselves. We don't worry about mapped files (for one thing, - any mapped file will be out of date). */ - - /* If we get an error, blow away this objfile (not sure if - that is the correct response for things like shared - libraries). */ - old_cleanups = make_cleanup_free_objfile (objfile); - /* We need to do this whenever any symbols go away. */ - make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); - - if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd), - bfd_get_filename (exec_bfd)) == 0) - { - /* Reload EXEC_BFD without asking anything. */ + objfile_next = objfile->next; - exec_file_attach (bfd_get_filename (objfile->obfd), 0); - } + if (objfile->obfd == NULL) + continue; - /* Clean up any state BFD has sitting around. We don't need - to close the descriptor but BFD lacks a way of closing the - BFD without closing the descriptor. */ - obfd_filename = bfd_get_filename (objfile->obfd); - if (!bfd_close (objfile->obfd)) - error (_("Can't close BFD for %s: %s"), objfile->name, - bfd_errmsg (bfd_get_error ())); - if (remote_filename_p (obfd_filename)) - objfile->obfd = remote_bfd_open (obfd_filename, gnutarget); - else - objfile->obfd = bfd_openr (obfd_filename, gnutarget); - if (objfile->obfd == NULL) - error (_("Can't open %s to read symbols."), objfile->name); - /* bfd_openr sets cacheable to true, which is what we want. */ - if (!bfd_check_format (objfile->obfd, bfd_object)) - error (_("Can't read symbols from %s: %s."), objfile->name, - bfd_errmsg (bfd_get_error ())); - - /* Save the offsets, we will nuke them with the rest of the - objfile_obstack. */ - num_offsets = objfile->num_sections; - offsets = ((struct section_offsets *) - alloca (SIZEOF_N_SECTION_OFFSETS (num_offsets))); - memcpy (offsets, objfile->section_offsets, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - - /* Remove any references to this objfile in the global - value lists. */ - preserve_values (objfile); - - /* Nuke all the state that we will re-read. Much of the following - code which sets things to NULL really is necessary to tell - other parts of GDB that there is nothing currently there. - - Try to keep the freeing order compatible with free_objfile. */ - - if (objfile->sf != NULL) - { - (*objfile->sf->sym_finish) (objfile); - } + /* Separate debug info files are always checked/loaded/unloaded by the + called functions together with their main binary file. */ - clear_objfile_data (objfile); - - /* FIXME: Do we have to free a whole linked list, or is this - enough? */ - if (objfile->global_psymbols.list) - xfree (objfile->global_psymbols.list); - memset (&objfile->global_psymbols, 0, - sizeof (objfile->global_psymbols)); - if (objfile->static_psymbols.list) - xfree (objfile->static_psymbols.list); - memset (&objfile->static_psymbols, 0, - sizeof (objfile->static_psymbols)); - - /* Free the obstacks for non-reusable objfiles */ - bcache_xfree (objfile->psymbol_cache); - objfile->psymbol_cache = bcache_xmalloc (); - bcache_xfree (objfile->macro_cache); - objfile->macro_cache = bcache_xmalloc (); - if (objfile->demangled_names_hash != NULL) - { - htab_delete (objfile->demangled_names_hash); - objfile->demangled_names_hash = NULL; - } - obstack_free (&objfile->objfile_obstack, 0); - objfile->sections = NULL; - objfile->symtabs = NULL; - objfile->psymtabs = NULL; - objfile->psymtabs_addrmap = NULL; - objfile->free_psymtabs = NULL; - objfile->cp_namespace_symtab = NULL; - objfile->msymbols = NULL; - objfile->deprecated_sym_private = NULL; - objfile->minimal_symbol_count = 0; - memset (&objfile->msymbol_hash, 0, - sizeof (objfile->msymbol_hash)); - memset (&objfile->msymbol_demangled_hash, 0, - sizeof (objfile->msymbol_demangled_hash)); - - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_cache = bcache_xmalloc (); - /* obstack_init also initializes the obstack so it is - empty. We could use obstack_specify_allocation but - gdb_obstack.h specifies the alloc/dealloc - functions. */ - obstack_init (&objfile->objfile_obstack); - if (build_objfile_section_table (objfile)) - { - error (_("Can't find the file sections in `%s': %s"), - objfile->name, bfd_errmsg (bfd_get_error ())); - } - terminate_minimal_symbol_table (objfile); - - /* We use the same section offsets as from last time. I'm not - sure whether that is always correct for shared libraries. */ - objfile->section_offsets = (struct section_offsets *) - obstack_alloc (&objfile->objfile_obstack, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - memcpy (objfile->section_offsets, offsets, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - objfile->num_sections = num_offsets; - - /* What the hell is sym_new_init for, anyway? The concept of - distinguishing between the main file and additional files - in this way seems rather dubious. */ - if (objfile == symfile_objfile) - { - (*objfile->sf->sym_new_init) (objfile); - } + if (objfile->separate_debug_objfile_backlink != NULL) + continue; - (*objfile->sf->sym_init) (objfile); - clear_complaints (&symfile_complaints, 1, 1); - /* The "mainline" parameter is a hideous hack; I think leaving it - zero is OK since dbxread.c also does what it needs to do if - objfile->global_psymbols.size is 0. */ - (*objfile->sf->sym_read) (objfile, 0); - if (!have_partial_symbols () && !have_full_symbols ()) - { - wrap_here (""); - printf_unfiltered (_("(no debugging symbols found)\n")); - wrap_here (""); - } + /* OBJFILE listed as a shared library would get a stale pointer in + SO_LIST. The OBJFILE update will be taken care of by solib_add below. + Thus we also do not need to call build_section_table ourselves. */ - /* We're done reading the symbol file; finish off complaints. */ - clear_complaints (&symfile_complaints, 0, 1); + for (so = master_so_list (); so != NULL; so = so->next) + if (so->objfile == objfile) + break; + if (so != NULL) + continue; - /* Getting new symbols may change our opinion about what is - frameless. */ + if (!objfile_has_changed (objfile)) + continue; - reinit_frame_cache (); + /* FIXME: EXEC_BFD should be always referenced only through + SYMFILE_OBJFILE. Currently exec_bfd exists on its own and it does not + have to be listed among OBJECT_FILES. exec_bfd_mtime should either be + used or rather dropped. */ - /* Discard cleanups as symbol reading was successful. */ - discard_cleanups (old_cleanups); + if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd), + bfd_get_filename (exec_bfd)) == 0) + { + /* Reload EXEC_BFD without asking anything. */ - /* If the mtime has changed between the time we set new_modtime - and now, we *want* this to be out of date, so don't call stat - again now. */ - objfile->mtime = new_modtime; - reread_one = 1; - reread_separate_symbols (objfile); - init_entry_point_info (objfile); - } + exec_file_attach (bfd_get_filename (objfile->obfd), 0); + } + + add_flags = SYMFILE_DEFER_BP_RESET; + if (objfile == symfile_objfile) + { + add_flags |= SYMFILE_MAINLINE; + + /* SYMFILE_OBJFILE could get freed as it has no reference counter. */ + symfile_objfile = NULL; } + + symbol_file_add (bfd_get_filename (objfile->obfd), add_flags, NULL, + objfile->flags); + + /* free_objfile will free also SEPARATE_DEBUG_OBJFILE, if it exists. */ + if (objfile_next && objfile_next == objfile->separate_debug_objfile) + objfile_next = objfile_next->next; + + free_objfile (objfile); + + reread_one = 1; } if (reread_one) { + /* breakpoint_re_set gets called to comply with SYMFILE_DEFER_BP_RESET + above. */ clear_symtab_users (); + /* At least one objfile has changed, so we can consider that the executable we're debugging has changed too. */ observer_notify_executable_changed (); } - -} + /* Perform functionality of this function also for the shared libraries. */ -/* Handle separate debug info for OBJFILE, which has just been - re-read: - - If we had separate debug info before, but now we don't, get rid - of the separated objfile. - - If we didn't have separated debug info before, but now we do, - read in the new separated debug info file. - - If the debug link points to a different file, toss the old one - and read the new one. - This function does *not* handle the case where objfile is still - using the same separate debug info file, but that file's timestamp - has changed. That case should be handled by the loop in - reread_symbols already. */ -static void -reread_separate_symbols (struct objfile *objfile) -{ - char *debug_file; - unsigned long crc32; - - /* Does the updated objfile's debug info live in a - separate file? */ - debug_file = find_separate_debug_file (objfile); - - if (objfile->separate_debug_objfile) - { - /* There are two cases where we need to get rid of - the old separated debug info objfile: - - if the new primary objfile doesn't have - separated debug info, or - - if the new primary objfile has separate debug - info, but it's under a different filename. - - If the old and new objfiles both have separate - debug info, under the same filename, then we're - okay --- if the separated file's contents have - changed, we will have caught that when we - visited it in this function's outermost - loop. */ - if (! debug_file - || strcmp (debug_file, objfile->separate_debug_objfile->name) != 0) - free_objfile (objfile->separate_debug_objfile); - } - - /* If the new objfile has separate debug info, and we - haven't loaded it already, do so now. */ - if (debug_file - && ! objfile->separate_debug_objfile) - { - /* Use the same section offset table as objfile itself. - Preserve the flags from objfile that make sense. */ - objfile->separate_debug_objfile - = (symbol_file_add_with_addrs_or_offsets - (symfile_bfd_open (debug_file), - info_verbose ? SYMFILE_VERBOSE : 0, - 0, /* No addr table. */ - objfile->section_offsets, objfile->num_sections, - objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW - | OBJF_USERLOADED))); - objfile->separate_debug_objfile->separate_debug_objfile_backlink - = objfile; - } - if (debug_file) - xfree (debug_file); + solib_add (NULL, 0, NULL, auto_solib_add); } - -\f - - typedef struct { char *ext; diff --git a/gdb/symfile.h b/gdb/symfile.h index bba242c..86e51f6 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -382,6 +382,8 @@ extern int symfile_map_offsets_to_segments (bfd *, struct symfile_segment_data *get_symfile_segment_data (bfd *abfd); void free_symfile_segment_data (struct symfile_segment_data *data); +extern int objfile_has_changed (struct objfile *objfile); + /* From dwarf2read.c */ extern int dwarf2_has_info (struct objfile *); ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-06-25 19:21 ` [patch] Replace reread_symbols by load+free calls Jan Kratochvil @ 2009-06-25 19:57 ` Pedro Alves 2009-06-25 23:25 ` Jan Kratochvil 2009-08-14 23:09 ` Tom Tromey 1 sibling, 1 reply; 29+ messages in thread From: Pedro Alves @ 2009-06-25 19:57 UTC (permalink / raw) To: gdb-patches; +Cc: Jan Kratochvil, Tom Tromey On Thursday 25 June 2009 20:21:20, Jan Kratochvil wrote: > + for (so = master_so_list (); so != NULL; so = so->next) > + if (so->objfile == objfile) > + break; > + if (so != NULL) > + continue; > Would this work instead? if ((objfile->flags & (OBJF_SHARED | OBJF_USERLOADED) == OBJF_SHARED)) continue; The OBJF_USERLOADED check is to take care of the windows-nat.c "dll-symbols" command... Referencing to master_so_list outside of the solib files doesn't sound right. On Thursday 25 June 2009 20:21:20, Jan Kratochvil wrote: > + /* FIXME: EXEC_BFD should be always referenced only through > + SYMFILE_OBJFILE. Currently exec_bfd exists on its own and it does not > + have to be listed among OBJECT_FILES. exec_bfd_mtime should either be > + used or rather dropped. */ Can you elaborate on this FIXME note? exec_bfd may or not have symbols in it. It may or not be the same bfd as symfile_objfile. Note that there are "exec-file" and "symbol-file" separate commands. In fact, I believe, historicaly, the "file" command that does both things at once was only added later. Do you plan on somehow eliminating exec_bfd? > if (reread_one) > { > + /* breakpoint_re_set gets called to comply with SYMFILE_DEFER_BP_RESET > + above. */ > clear_symtab_users (); I can't quite parse what this comment is really saying. Who calls breakpoint_re_set? Who is complying? -- Pedro Alves ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-06-25 19:57 ` Pedro Alves @ 2009-06-25 23:25 ` Jan Kratochvil 2009-08-02 21:04 ` cancelled: " Jan Kratochvil 0 siblings, 1 reply; 29+ messages in thread From: Jan Kratochvil @ 2009-06-25 23:25 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Tom Tromey On Thu, 25 Jun 2009 21:58:04 +0200, Pedro Alves wrote: > On Thursday 25 June 2009 20:21:20, Jan Kratochvil wrote: > > + Â Â Â for (so = master_so_list (); so != NULL; so = so->next) > > +Â Â Â Â Â Â Â if (so->objfile == objfile) > > +Â Â Â Â Â Â Â Â break; > > + Â Â Â if (so != NULL) > > +Â Â Â Â Â Â Â continue; > > Would this work instead? > > if ((objfile->flags & (OBJF_SHARED | OBJF_USERLOADED) == OBJF_SHARED)) > continue; It got me some time but yes, in practice it should work, thanks. > On Thursday 25 June 2009 20:21:20, Jan Kratochvil wrote: > > + /* FIXME: EXEC_BFD should be always referenced only through > > + SYMFILE_OBJFILE. Currently exec_bfd exists on its own and it does not > > + have to be listed among OBJECT_FILES. exec_bfd_mtime should either be > > + used or rather dropped. */ > > Can you elaborate on this FIXME note? exec_bfd may or not have symbols in it. > It may or not be the same bfd as symfile_objfile. Note that there are > "exec-file" and "symbol-file" separate commands. In fact, I believe, > historicaly, the "file" command that does both things at once was only > added later. Do you plan on somehow eliminating exec_bfd? Currently for "file /bin/sleep" the binary itself has three separate open bfds: (gdb) p object_files->obfd $1 = (bfd *) 0x1c71770 (gdb) p object_files->obfd->filename $2 = 0x1c82750 "/usr/lib/debug/bin/sleep.debug" (gdb) p object_files->next->obfd $3 = (bfd *) 0x1c708d0 (gdb) p object_files->next->obfd->filename $4 = 0x1c6f6d0 "/bin/sleep" (gdb) p exec_bfd $5 = (bfd *) 0x1c6f740 (gdb) p exec_bfd->filename $6 = 0x1a29600 "/bin/sleep" (gdb) p symfile_objfile == object_files->next $7 = 1 I would like to have only two separate open bfds in this case. Currently object_files are iterated as symbol sources. Such unification would mean that in this case FILEBIN would _also_ get searched for symbols. Is it a problem? (gdb) exec-file FILEBIN (gdb) symbol-file FILESYM It would provide a common list + structure (objfile) for handling all open inferior files. > I can't quite parse what this comment is really saying. Who calls > breakpoint_re_set? Who is complying? OK, updated: /* SYMFILE_DEFER_BP_RESET being used below requires one to call breakpoint_re_set before returning the control to user. clear_symtab_users already calls breakpoint_re_set. BACK_TO is set to call clear_symtab_users. clear_symtab_users should be also called whenever any symbols go away by free_objfile below. */ Put there in also back an equivalent for former: - /* We need to do this whenever any symbols go away. */ - make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); Regression tested on {x86_64,i686}-fedora-linux-gnu. Thanks, Jan 2009-06-26 Jan Kratochvil <jan.kratochvil@redhat.com> Simplify reread_symbols. * objfiles.h (struct objfile <mtime>): New FIXME comment. * solib.c (update_solib_list): Reload the library if it has changed. * symfile.c: Include solist.h. (reread_symbols): Replace the in-place rereading by calls to symbol_file_add and free_objfile. Call now also solib_add. Move the variables new_modtime, new_statbuf and res with the OBJFILE change checking code to ... (objfile_has_changed): ... a new function. (reread_separate_symbols): Remove the function. * symfile.h (objfile_has_changed): New prototype. diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 60d3143..e03861f 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -236,7 +236,7 @@ struct objfile struct gdbarch *gdbarch; /* The modification timestamp of the object file, as of the last time - we read its symbols. */ + we read its symbols. FIXME: Replace it by a bfd_get_mtime call. */ long mtime; diff --git a/gdb/solib.c b/gdb/solib.c index d194ac7..fae0f4a 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -615,7 +615,7 @@ update_solib_list (int from_tty, struct target_ops *target) /* If the shared object appears on the inferior's list too, then it's still loaded, so we don't need to do anything. Delete it from the inferior's list, and leave it on GDB's list. */ - if (i) + if (i && (gdb->objfile == NULL || !objfile_has_changed (gdb->objfile))) { *i_link = i->next; free_so (i); diff --git a/gdb/symfile.c b/gdb/symfile.c index 25f3f26..c02b856 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -55,6 +55,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "solist.h" #include <sys/types.h> #include <fcntl.h> @@ -96,8 +97,6 @@ static void symbol_file_add_main_1 (char *args, int from_tty, int flags); static void add_symbol_file_command (char *, int); -static void reread_separate_symbols (struct objfile *objfile); - static void cashier_psymtab (struct partial_symtab *); bfd *symfile_bfd_open (char *); @@ -2231,17 +2230,59 @@ add_symbol_file_command (char *args, int from_tty) reinit_frame_cache (); do_cleanups (my_cleanups); } -\f + +/* Return non-zero if OBJFILE (or its SEPARATE_DEBUG_OBJFILE) has changed on + the disk since its load. You should not call this function for the separate + debug info file itself. */ + +int +objfile_has_changed (struct objfile *objfile) +{ + long new_modtime; + struct stat new_statbuf; + int res; + + if (objfile->obfd == NULL) + return 0; + +#ifdef DEPRECATED_IBM6000_TARGET + /* If this object is from a shared library, then you should + stat on the library name, not member name. */ + + if (objfile->obfd->my_archive) + res = stat (objfile->obfd->my_archive->filename, &new_statbuf); + else +#endif + res = stat (objfile->name, &new_statbuf); + if (res != 0) + { + /* FIXME, should use print_sys_errmsg but it's not filtered. */ + printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), + objfile->name); + return 0; + } + + new_modtime = new_statbuf.st_mtime; + if (new_modtime != objfile->mtime) + { + printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"), + objfile->name); + return 1; + } + + if (objfile->separate_debug_objfile) + return objfile_has_changed (objfile->separate_debug_objfile); + + return 0; +} /* Re-read symbols if a symbol-file has changed. */ void reread_symbols (void) { - struct objfile *objfile; - long new_modtime; + struct objfile *objfile, *objfile_next; int reread_one = 0; - struct stat new_statbuf; - int res; + struct cleanup *back_to = NULL; /* With the addition of shared libraries, this should be modified, the load time should be saved in the partial symbol tables, since @@ -2249,282 +2290,96 @@ reread_symbols (void) This routine should then walk down each partial symbol table and see if the symbol table that it originates from has been changed */ - for (objfile = object_files; objfile; objfile = objfile->next) + for (objfile = object_files; objfile != NULL; objfile = objfile_next) { - if (objfile->obfd) - { -#ifdef DEPRECATED_IBM6000_TARGET - /* If this object is from a shared library, then you should - stat on the library name, not member name. */ + int add_flags; - if (objfile->obfd->my_archive) - res = stat (objfile->obfd->my_archive->filename, &new_statbuf); - else -#endif - res = stat (objfile->name, &new_statbuf); - if (res != 0) - { - /* FIXME, should use print_sys_errmsg but it's not filtered. */ - printf_unfiltered (_("`%s' has disappeared; keeping its symbols.\n"), - objfile->name); - continue; - } - new_modtime = new_statbuf.st_mtime; - if (new_modtime != objfile->mtime) - { - struct cleanup *old_cleanups; - struct section_offsets *offsets; - int num_offsets; - char *obfd_filename; - - printf_unfiltered (_("`%s' has changed; re-reading symbols.\n"), - objfile->name); - - /* There are various functions like symbol_file_add, - symfile_bfd_open, syms_from_objfile, etc., which might - appear to do what we want. But they have various other - effects which we *don't* want. So we just do stuff - ourselves. We don't worry about mapped files (for one thing, - any mapped file will be out of date). */ - - /* If we get an error, blow away this objfile (not sure if - that is the correct response for things like shared - libraries). */ - old_cleanups = make_cleanup_free_objfile (objfile); - /* We need to do this whenever any symbols go away. */ - make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/); - - if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd), - bfd_get_filename (exec_bfd)) == 0) - { - /* Reload EXEC_BFD without asking anything. */ + objfile_next = objfile->next; - exec_file_attach (bfd_get_filename (objfile->obfd), 0); - } + if (objfile->obfd == NULL) + continue; - /* Clean up any state BFD has sitting around. We don't need - to close the descriptor but BFD lacks a way of closing the - BFD without closing the descriptor. */ - obfd_filename = bfd_get_filename (objfile->obfd); - if (!bfd_close (objfile->obfd)) - error (_("Can't close BFD for %s: %s"), objfile->name, - bfd_errmsg (bfd_get_error ())); - if (remote_filename_p (obfd_filename)) - objfile->obfd = remote_bfd_open (obfd_filename, gnutarget); - else - objfile->obfd = bfd_openr (obfd_filename, gnutarget); - if (objfile->obfd == NULL) - error (_("Can't open %s to read symbols."), objfile->name); - /* bfd_openr sets cacheable to true, which is what we want. */ - if (!bfd_check_format (objfile->obfd, bfd_object)) - error (_("Can't read symbols from %s: %s."), objfile->name, - bfd_errmsg (bfd_get_error ())); - - /* Save the offsets, we will nuke them with the rest of the - objfile_obstack. */ - num_offsets = objfile->num_sections; - offsets = ((struct section_offsets *) - alloca (SIZEOF_N_SECTION_OFFSETS (num_offsets))); - memcpy (offsets, objfile->section_offsets, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - - /* Remove any references to this objfile in the global - value lists. */ - preserve_values (objfile); - - /* Nuke all the state that we will re-read. Much of the following - code which sets things to NULL really is necessary to tell - other parts of GDB that there is nothing currently there. - - Try to keep the freeing order compatible with free_objfile. */ - - if (objfile->sf != NULL) - { - (*objfile->sf->sym_finish) (objfile); - } + /* Separate debug info files are always checked/loaded/unloaded by the + called functions together with their main binary file. */ - clear_objfile_data (objfile); - - /* FIXME: Do we have to free a whole linked list, or is this - enough? */ - if (objfile->global_psymbols.list) - xfree (objfile->global_psymbols.list); - memset (&objfile->global_psymbols, 0, - sizeof (objfile->global_psymbols)); - if (objfile->static_psymbols.list) - xfree (objfile->static_psymbols.list); - memset (&objfile->static_psymbols, 0, - sizeof (objfile->static_psymbols)); - - /* Free the obstacks for non-reusable objfiles */ - bcache_xfree (objfile->psymbol_cache); - objfile->psymbol_cache = bcache_xmalloc (); - bcache_xfree (objfile->macro_cache); - objfile->macro_cache = bcache_xmalloc (); - if (objfile->demangled_names_hash != NULL) - { - htab_delete (objfile->demangled_names_hash); - objfile->demangled_names_hash = NULL; - } - obstack_free (&objfile->objfile_obstack, 0); - objfile->sections = NULL; - objfile->symtabs = NULL; - objfile->psymtabs = NULL; - objfile->psymtabs_addrmap = NULL; - objfile->free_psymtabs = NULL; - objfile->cp_namespace_symtab = NULL; - objfile->msymbols = NULL; - objfile->deprecated_sym_private = NULL; - objfile->minimal_symbol_count = 0; - memset (&objfile->msymbol_hash, 0, - sizeof (objfile->msymbol_hash)); - memset (&objfile->msymbol_demangled_hash, 0, - sizeof (objfile->msymbol_demangled_hash)); - - objfile->psymbol_cache = bcache_xmalloc (); - objfile->macro_cache = bcache_xmalloc (); - /* obstack_init also initializes the obstack so it is - empty. We could use obstack_specify_allocation but - gdb_obstack.h specifies the alloc/dealloc - functions. */ - obstack_init (&objfile->objfile_obstack); - if (build_objfile_section_table (objfile)) - { - error (_("Can't find the file sections in `%s': %s"), - objfile->name, bfd_errmsg (bfd_get_error ())); - } - terminate_minimal_symbol_table (objfile); - - /* We use the same section offsets as from last time. I'm not - sure whether that is always correct for shared libraries. */ - objfile->section_offsets = (struct section_offsets *) - obstack_alloc (&objfile->objfile_obstack, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - memcpy (objfile->section_offsets, offsets, - SIZEOF_N_SECTION_OFFSETS (num_offsets)); - objfile->num_sections = num_offsets; - - /* What the hell is sym_new_init for, anyway? The concept of - distinguishing between the main file and additional files - in this way seems rather dubious. */ - if (objfile == symfile_objfile) - { - (*objfile->sf->sym_new_init) (objfile); - } + if (objfile->separate_debug_objfile_backlink != NULL) + continue; - (*objfile->sf->sym_init) (objfile); - clear_complaints (&symfile_complaints, 1, 1); - /* The "mainline" parameter is a hideous hack; I think leaving it - zero is OK since dbxread.c also does what it needs to do if - objfile->global_psymbols.size is 0. */ - (*objfile->sf->sym_read) (objfile, 0); - if (!have_partial_symbols () && !have_full_symbols ()) - { - wrap_here (""); - printf_unfiltered (_("(no debugging symbols found)\n")); - wrap_here (""); - } + /* OBJFILE listed as a shared library would get a stale pointer in + SO_LIST. The OBJFILE update will be taken care of by solib_add below. + Thus we also do not need to prepare section_addr_info ourselves. + + The condition here is in this case equivalent to the presence in + so_list_head. OBJF_USERLOADED libraries need to be still handled here + as they are not listed in so_list_head. Fortunately the only such + libraries having (OBJF_SHARED | OBJF_USERLOADED) do not need + section_addr_info. */ + + if ((objfile->flags & (OBJF_SHARED | OBJF_USERLOADED)) == OBJF_SHARED) + continue; + + if (!objfile_has_changed (objfile)) + continue; + + /* FIXME: EXEC_BFD should be always referenced only through + SYMFILE_OBJFILE. Currently exec_bfd exists on its own and it does not + have to be listed among OBJECT_FILES. exec_bfd_mtime should either be + used or rather dropped. */ - /* We're done reading the symbol file; finish off complaints. */ - clear_complaints (&symfile_complaints, 0, 1); + if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd), + bfd_get_filename (exec_bfd)) == 0) + { + /* Reload EXEC_BFD without asking anything. */ - /* Getting new symbols may change our opinion about what is - frameless. */ + exec_file_attach (bfd_get_filename (objfile->obfd), 0); + } - reinit_frame_cache (); + if (!reread_one) + { + /* SYMFILE_DEFER_BP_RESET being used below requires one to call + breakpoint_re_set before returning the control to user. + clear_symtab_users already calls breakpoint_re_set. BACK_TO is + set to call clear_symtab_users. clear_symtab_users should be also + called whenever any symbols go away by free_objfile below. */ - /* Discard cleanups as symbol reading was successful. */ - discard_cleanups (old_cleanups); + back_to = make_cleanup (clear_symtab_users_cleanup, NULL /*ignore*/); - /* If the mtime has changed between the time we set new_modtime - and now, we *want* this to be out of date, so don't call stat - again now. */ - objfile->mtime = new_modtime; - reread_one = 1; - reread_separate_symbols (objfile); - init_entry_point_info (objfile); - } + reread_one = 1; } - } - if (reread_one) - { - clear_symtab_users (); - /* At least one objfile has changed, so we can consider that - the executable we're debugging has changed too. */ - observer_notify_executable_changed (); - } - -} + add_flags = SYMFILE_DEFER_BP_RESET; + if (objfile == symfile_objfile) + { + add_flags |= SYMFILE_MAINLINE; + /* SYMFILE_OBJFILE could get freed as it has no reference counter. */ + symfile_objfile = NULL; + } -/* Handle separate debug info for OBJFILE, which has just been - re-read: - - If we had separate debug info before, but now we don't, get rid - of the separated objfile. - - If we didn't have separated debug info before, but now we do, - read in the new separated debug info file. - - If the debug link points to a different file, toss the old one - and read the new one. - This function does *not* handle the case where objfile is still - using the same separate debug info file, but that file's timestamp - has changed. That case should be handled by the loop in - reread_symbols already. */ -static void -reread_separate_symbols (struct objfile *objfile) -{ - char *debug_file; - unsigned long crc32; + symbol_file_add (bfd_get_filename (objfile->obfd), add_flags, NULL, + objfile->flags); - /* Does the updated objfile's debug info live in a - separate file? */ - debug_file = find_separate_debug_file (objfile); + /* free_objfile will free also SEPARATE_DEBUG_OBJFILE, if it exists. */ + if (objfile_next && objfile_next == objfile->separate_debug_objfile) + objfile_next = objfile_next->next; - if (objfile->separate_debug_objfile) - { - /* There are two cases where we need to get rid of - the old separated debug info objfile: - - if the new primary objfile doesn't have - separated debug info, or - - if the new primary objfile has separate debug - info, but it's under a different filename. - - If the old and new objfiles both have separate - debug info, under the same filename, then we're - okay --- if the separated file's contents have - changed, we will have caught that when we - visited it in this function's outermost - loop. */ - if (! debug_file - || strcmp (debug_file, objfile->separate_debug_objfile->name) != 0) - free_objfile (objfile->separate_debug_objfile); + free_objfile (objfile); } - /* If the new objfile has separate debug info, and we - haven't loaded it already, do so now. */ - if (debug_file - && ! objfile->separate_debug_objfile) + if (reread_one) { - /* Use the same section offset table as objfile itself. - Preserve the flags from objfile that make sense. */ - objfile->separate_debug_objfile - = (symbol_file_add_with_addrs_or_offsets - (symfile_bfd_open (debug_file), - info_verbose ? SYMFILE_VERBOSE : 0, - 0, /* No addr table. */ - objfile->section_offsets, objfile->num_sections, - objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW - | OBJF_USERLOADED))); - objfile->separate_debug_objfile->separate_debug_objfile_backlink - = objfile; - } - if (debug_file) - xfree (debug_file); -} + /* Call clear_symtab_users before the notification below. */ + do_cleanups (back_to); + /* At least one objfile has changed, so we can consider that + the executable we're debugging has changed too. */ + observer_notify_executable_changed (); + } -\f + /* Perform functionality of this function also for the shared libraries. */ + solib_add (NULL, 0, NULL, auto_solib_add); +} typedef struct { diff --git a/gdb/symfile.h b/gdb/symfile.h index bba242c..86e51f6 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -382,6 +382,8 @@ extern int symfile_map_offsets_to_segments (bfd *, struct symfile_segment_data *get_symfile_segment_data (bfd *abfd); void free_symfile_segment_data (struct symfile_segment_data *data); +extern int objfile_has_changed (struct objfile *objfile); + /* From dwarf2read.c */ extern int dwarf2_has_info (struct objfile *); ^ permalink raw reply [flat|nested] 29+ messages in thread
* cancelled: Re: [patch] Replace reread_symbols by load+free calls 2009-06-25 23:25 ` Jan Kratochvil @ 2009-08-02 21:04 ` Jan Kratochvil 0 siblings, 0 replies; 29+ messages in thread From: Jan Kratochvil @ 2009-08-02 21:04 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Tom Tromey Hi, this patch got out of sync and it now needs a non-trivial update, removing it from the possible review queue. Thanks, Jan ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-06-25 19:21 ` [patch] Replace reread_symbols by load+free calls Jan Kratochvil 2009-06-25 19:57 ` Pedro Alves @ 2009-08-14 23:09 ` Tom Tromey 2009-08-14 23:12 ` Pedro Alves 1 sibling, 1 reply; 29+ messages in thread From: Tom Tromey @ 2009-08-14 23:09 UTC (permalink / raw) To: Jan Kratochvil; +Cc: gdb-patches >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes: Sorry about the long delay on this. I try not to just drop threads I'm involved in, but sometimes I get distracted. Jan> IMO the whole `struct objfile' should replaced by a new one Jan> (instead of its in-place patching). Which will probably have Jan> other dependencies... Tom> I'm interested to hear your idea and reasoning. Jan> Sometimes there are differentiations between complete objects Jan> destructors (objfile_free_data) and in-place object deletions Jan> (clear_objfile_data); OK did not briefly found more such cases now. Jan> Expecting it was there for some performance improvements which not Jan> worth it nowadays. I misunderstood something you were saying earlier in the thread -- I thought you were talking about dropping 'struct objfile' itself in favor of some new datastructure (as opposed to slowly refactoring it). But, now I understand that you really meant that reread_symbols should be rewritten. I realize you pulled this patch from consideration. But, FWIW, I tend to think it is a good idea, because it ensures that all the hooks and observers will be run identically in both cases. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-08-14 23:09 ` Tom Tromey @ 2009-08-14 23:12 ` Pedro Alves 2009-08-17 15:41 ` Tom Tromey 2011-12-18 11:54 ` Jan Kratochvil 0 siblings, 2 replies; 29+ messages in thread From: Pedro Alves @ 2009-08-14 23:12 UTC (permalink / raw) To: gdb-patches, tromey; +Cc: Jan Kratochvil I have to apologize too, since I dropped the conversation too. On Friday 14 August 2009 23:34:31, Tom Tromey wrote: > I realize you pulled this patch from consideration. But, FWIW, I tend > to think it is a good idea, because it ensures that all the hooks and > observers will be run identically in both cases. I have to say that I didn't think it was a good idea, because of the way the change ties the objfiles to solib.c, and the fact that it makes it so that an objfile pointer becomes more volatile. That is, with that change, all roots holding an objfile pointer need to be crawled, while as is today, an objfile object's internals are the business of objfile.c and symfile.c, and an objfile client can hold a pointer across objfile rereads, while the pointer stays valid. There were also some FIXME comments related to bfd_get_mtime in the patch that looked like misunderstandings, and that threw me off. Maybe I just didn't understand them. :-/ There's also this comment in the current code that makes that suggested change scare me: /* There are various functions like symbol_file_add, symfile_bfd_open, syms_from_objfile, etc., which might appear to do what we want. But they have various other effects which we *don't* want. So we just do stuff ourselves. (...) */ ... as we'd be going in the opposite direction (the patch uses symbol_file_add). I wonder how much would we simplify reread_symbols by moving the each-objfile rereading code to objfile.c, and refactor it to share code with allocate_objfile, free_objfile, etc., and thus also making it easier to make hooks and observers be consistent. -- Pedro Alves ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-08-14 23:12 ` Pedro Alves @ 2009-08-17 15:41 ` Tom Tromey 2011-12-18 11:54 ` Jan Kratochvil 1 sibling, 0 replies; 29+ messages in thread From: Tom Tromey @ 2009-08-17 15:41 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Jan Kratochvil >>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes: Pedro> There were also some FIXME comments related to bfd_get_mtime Pedro> in the patch that looked like misunderstandings, and that threw Pedro> me off. Maybe I just didn't understand them. :-/ I was wondering about those too. Pedro> There's also this comment in the current code that makes that Pedro> suggested change scare me: Pedro> /* There are various functions like symbol_file_add, Pedro> symfile_bfd_open, syms_from_objfile, etc., which might Pedro> appear to do what we want. But they have various other Pedro> effects which we *don't* want. So we just do stuff Pedro> ourselves. (...) */ Pedro> ... as we'd be going in the opposite direction (the patch uses Pedro> symbol_file_add). That comment looks stale. It mentions mapped files, as well, which IIUC gdb hasn't had for years. Pedro> I wonder how much would we simplify reread_symbols by moving the Pedro> each-objfile rereading code to objfile.c, and refactor it to share code Pedro> with allocate_objfile, free_objfile, etc., and thus also making it easier Pedro> to make hooks and observers be consistent. Yeah, that would work for me. Tom ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [patch] Replace reread_symbols by load+free calls 2009-08-14 23:12 ` Pedro Alves 2009-08-17 15:41 ` Tom Tromey @ 2011-12-18 11:54 ` Jan Kratochvil 1 sibling, 0 replies; 29+ messages in thread From: Jan Kratochvil @ 2011-12-18 11:54 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, tromey On Sat, 15 Aug 2009 01:09:59 +0200, Pedro Alves wrote: > On Friday 14 August 2009 23:34:31, Tom Tromey wrote: > > > I realize you pulled this patch from consideration. But, FWIW, I tend > > to think it is a good idea, because it ensures that all the hooks and > > observers will be run identically in both cases. > > I have to say that I didn't think it was a good idea, because of the > way the change ties the objfiles to solib.c, and the fact that > it makes it so that an objfile pointer becomes more volatile. This is correct, because when someone holds a pointer to volatile data valgrind should report it as invalid. And each such code needs to be reviewed anyway so changing it along is not such a concern. Regards, Jan ^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2011-12-18 11:42 UTC | newest] Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-05-27 0:12 [patch] Use mmap instead of obstack_alloc for dwarf debug sections Paul Pluzhnikov 2009-05-28 1:16 ` Tom Tromey 2009-05-28 16:57 ` Paul Pluzhnikov 2009-05-30 22:36 ` Tom Tromey 2009-06-11 1:40 ` Paul Pluzhnikov 2009-06-11 1:43 ` Paul Pluzhnikov 2009-06-16 19:19 ` Tom Tromey 2009-06-16 20:43 ` Paul Pluzhnikov 2009-06-16 20:59 ` Tom Tromey 2009-06-16 21:07 ` Paul Pluzhnikov 2009-06-18 9:20 ` Ken Werner 2009-06-18 14:06 ` Paul Pluzhnikov 2009-06-18 14:11 ` Paul Pluzhnikov 2009-06-18 15:02 ` Ken Werner 2009-06-18 16:33 ` Paul Pluzhnikov 2009-06-19 7:10 ` Ken Werner 2009-06-23 15:03 ` [patch] Fix a reread_symbols regression by mmap [Re: [patch] Use mmap instead of obstack_alloc for dwarf debug sections.] Jan Kratochvil 2009-06-23 17:35 ` Paul Pluzhnikov 2009-06-23 18:08 ` Tom Tromey 2009-06-23 18:21 ` Jan Kratochvil 2009-06-23 20:00 ` Tom Tromey 2009-06-25 19:21 ` [patch] Replace reread_symbols by load+free calls Jan Kratochvil 2009-06-25 19:57 ` Pedro Alves 2009-06-25 23:25 ` Jan Kratochvil 2009-08-02 21:04 ` cancelled: " Jan Kratochvil 2009-08-14 23:09 ` Tom Tromey 2009-08-14 23:12 ` Pedro Alves 2009-08-17 15:41 ` Tom Tromey 2011-12-18 11:54 ` Jan Kratochvil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox