This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [3/4] RFC: refactor partial symbol tables


>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> This patch changes the DWARF reader to lazily read all section data.
Tom> It also now lazily reads and does processing on the FDE data.  Finally,
Tom> it uses posix_madvise when mapping sections.

Tom> These changes provide a small speedup, at the cost of a bit more
Tom> complexity in the reader.  Now, a function that references some section
Tom> contents must ensure that the section has been read first.

Here's the updated patch.

Tom

2010-03-09  Tom Tromey  <tromey@redhat.com>

	* elfread.c (elf_symfile_read): Don't call
	dwarf2_build_frame_info.
	* dwarf2read.c (struct dwarf2_section_info) <readin>: New field.
	(struct dwarf2_per_objfile) <objfile>: New field.
	(dwarf2_has_info): Now idempotent.  Set objfile field.
	(dwarf2_read_section): Check and set readin field.  Call
	posix_madvise.
	(dwarf2_build_psymtabs): Don't read all sections.
	(read_type_comp_unit_head): Read types section.
	(create_debug_types_hash_table): Likewise.
	(init_cu_die_reader): Add asserts.
	(process_type_comp_unit): Add assert.
	(dwarf2_build_psymtabs_hard): Read info section.
	(load_partial_comp_unit): Add assert.
	(create_all_comp_units): Read info section.
	(load_full_comp_unit): Likewise.
	(dwarf2_ranges_read): Read ranges section.
	(dwarf2_record_block_ranges): Add assert.
	(dwarf2_read_abbrevs): Read abbrev section.
	(read_indirect_string): Read str section.
	(dwarf_decode_line_header): Read line section.
	(read_signatured_type_at_offset): Read types section.
	(dwarf_decode_macros): Read macinfo section.
	(dwarf2_symbol_mark_computed): Read loc section.
	* dwarf2-frame.c (dwarf2_frame_find_fde): Call
	dwarf2_build_frame_info.
	(dwarf2_build_frame_info): Unconditionally set
	dwarf2_frame_objfile_data on the objfile.
	* configure.ac: Check for posix_madvise.
	* config.in, configure: Rebuild.

diff --git a/gdb/config.in b/gdb/config.in
index ebde876..5414b08 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -294,6 +294,9 @@
 /* Define to 1 if you have the <poll.h> header file. */
 #undef HAVE_POLL_H
 
+/* Define to 1 if you have the `posix_madvise' function. */
+#undef HAVE_POSIX_MADVISE
+
 /* Define to 1 if you have the `pread64' function. */
 #undef HAVE_PREAD64
 
diff --git a/gdb/configure b/gdb/configure
index d444b08..6b05993 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -11234,7 +11234,7 @@ for ac_func in canonicalize_file_name realpath getrusage getuid \
 		getgid pipe poll pread64 sbrk setpgid setpgrp setsid \
 		sigaction sigprocmask sigsetmask socketpair syscall \
 		ttrace wborder setlocale iconvlist libiconvlist btowc \
-		setrlimit getrlimit
+		setrlimit getrlimit posix_madvise
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 8da6867..5e77f59 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -802,7 +802,7 @@ AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \
 		getgid pipe poll pread64 sbrk setpgid setpgrp setsid \
 		sigaction sigprocmask sigsetmask socketpair syscall \
 		ttrace wborder setlocale iconvlist libiconvlist btowc \
-		setrlimit getrlimit])
+		setrlimit getrlimit posix_madvise])
 AM_LANGINFO_CODESET
 
 # Check the return and argument types of ptrace.  No canned test for
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 99100d7..7323ca4 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -1584,6 +1584,13 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
 
       fde_table = objfile_data (objfile, dwarf2_frame_objfile_data);
       if (fde_table == NULL)
+	{
+	  dwarf2_build_frame_info (objfile);
+	  fde_table = objfile_data (objfile, dwarf2_frame_objfile_data);
+	}
+      gdb_assert (fde_table != NULL);
+
+      if (fde_table->num_entries == 0)
 	continue;
 
       gdb_assert (objfile->section_offsets);
@@ -2027,6 +2034,7 @@ dwarf2_build_frame_info (struct objfile *objfile)
   gdb_byte *frame_ptr;
   struct dwarf2_cie_table cie_table;
   struct dwarf2_fde_table fde_table;
+  struct dwarf2_fde_table *fde_table2;
 
   cie_table.num_entries = 0;
   cie_table.entries = NULL;
@@ -2098,9 +2106,17 @@ dwarf2_build_frame_info (struct objfile *objfile)
       cie_table.num_entries = 0;  /* Paranoia.  */
     }
 
-  if (fde_table.num_entries != 0)
+  /* Copy fde_table to obstack: it is needed at runtime.  */
+  fde_table2 = (struct dwarf2_fde_table *)
+    obstack_alloc (&objfile->objfile_obstack, sizeof (*fde_table2));
+
+  if (fde_table.num_entries == 0)
+    {
+      fde_table2->entries = NULL;
+      fde_table2->num_entries = 0;
+    }
+  else
     {
-      struct dwarf2_fde_table *fde_table2;
       struct dwarf2_fde *fde_prev = NULL;
       struct dwarf2_fde *first_non_zero_fde = NULL;
       int i;
@@ -2109,11 +2125,6 @@ dwarf2_build_frame_info (struct objfile *objfile)
       qsort (fde_table.entries, fde_table.num_entries,
              sizeof (fde_table.entries[0]), qsort_fde_cmp);
 
-      /* Copy fde_table to obstack: it is needed at runtime.  */
-      fde_table2 = (struct dwarf2_fde_table *)
-          obstack_alloc (&objfile->objfile_obstack, sizeof (*fde_table2));
-      fde_table2->num_entries = 0;
-
       /* Check for leftovers from --gc-sections.  The GNU linker sets
 	 the relevant symbols to zero, but doesn't zero the FDE *end*
 	 ranges because there's no relocation there.  It's (offset,
@@ -2140,6 +2151,7 @@ dwarf2_build_frame_info (struct objfile *objfile)
       /* Since we'll be doing bsearch, squeeze out identical (except
 	 for eh_frame_p) fde entries so bsearch result is predictable.
 	 Also discard leftovers from --gc-sections.  */
+      fde_table2->num_entries = 0;
       for (i = 0; i < fde_table.num_entries; i++)
 	{
 	  struct dwarf2_fde *fde = fde_table.entries[i];
@@ -2160,11 +2172,12 @@ dwarf2_build_frame_info (struct objfile *objfile)
 	  fde_prev = fde;
 	}
       fde_table2->entries = obstack_finish (&objfile->objfile_obstack);
-      set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2);
 
       /* Discard the original fde_table.  */
       xfree (fde_table.entries);
     }
+
+  set_objfile_data (objfile, dwarf2_frame_objfile_data, fde_table2);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index d9ee13c..df607ab 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -157,6 +157,8 @@ struct dwarf2_section_info
   gdb_byte *buffer;
   bfd_size_type size;
   int was_mmapped;
+  /* True if we have tried to read this section.  */
+  int readin;
 };
 
 struct dwarf2_per_objfile
@@ -174,6 +176,9 @@ struct dwarf2_per_objfile
   struct dwarf2_section_info frame;
   struct dwarf2_section_info eh_frame;
 
+  /* Back link.  */
+  struct objfile *objfile;
+
   /* A list of all the compilation units.  This is used to locate
      the target compilation unit of a particular reference.  */
   struct dwarf2_per_cu_data **all_comp_units;
@@ -1164,16 +1169,21 @@ static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
 int
 dwarf2_has_info (struct objfile *objfile)
 {
-  struct dwarf2_per_objfile *data;
-
-  /* Initialize per-objfile state.  */
-  data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
-  memset (data, 0, sizeof (*data));
-  set_objfile_data (objfile, dwarf2_objfile_data_key, data);
-  dwarf2_per_objfile = data;
+  dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
+  if (!dwarf2_per_objfile)
+    {
+      /* Initialize per-objfile state.  */
+      struct dwarf2_per_objfile *data
+	= obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
+      memset (data, 0, sizeof (*data));
+      set_objfile_data (objfile, dwarf2_objfile_data_key, data);
+      dwarf2_per_objfile = data;
 
-  bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
-  return (data->info.asection != NULL && data->abbrev.asection != NULL);
+      bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
+      dwarf2_per_objfile->objfile = objfile;
+    }
+  return (dwarf2_per_objfile->info.asection != NULL
+	  && dwarf2_per_objfile->abbrev.asection != NULL);
 }
 
 /* When loading sections, we can either look for ".<name>", or for
@@ -1355,8 +1365,11 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
   gdb_byte *buf, *retbuf;
   unsigned char header[4];
 
+  if (info->readin)
+    return;
   info->buffer = NULL;
   info->was_mmapped = 0;
+  info->readin = 1;
 
   if (info->asection == NULL || info->size == 0)
     return;
@@ -1394,6 +1407,9 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
 	{
 	  info->was_mmapped = 1;
 	  info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ;
+#if HAVE_POSIX_MADVISE
+	  posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED);
+#endif
 	  return;
 	}
     }
@@ -1452,17 +1468,6 @@ dwarf2_get_section_info (struct objfile *objfile, const char *section_name,
 void
 dwarf2_build_psymtabs (struct objfile *objfile)
 {
-  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->types);
-  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 (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
     {
       init_psymbol_list (objfile, 1024);
@@ -1606,6 +1611,7 @@ read_type_comp_unit_head (struct comp_unit_head *cu_header,
   unsigned int bytes_read;
   gdb_byte *initial_types_ptr = types_ptr;
 
+  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->types);
   cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer;
 
   types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
@@ -1702,9 +1708,12 @@ eq_type_signature (const void *item_lhs, const void *item_rhs)
 static int
 create_debug_types_hash_table (struct objfile *objfile)
 {
-  gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer;
+  gdb_byte *info_ptr;
   htab_t types_htab;
 
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
+  info_ptr = dwarf2_per_objfile->types.buffer;
+
   if (info_ptr == NULL)
     {
       dwarf2_per_objfile->signatured_types = NULL;
@@ -1810,9 +1819,15 @@ init_cu_die_reader (struct die_reader_specs *reader,
   reader->abfd = cu->objfile->obfd;
   reader->cu = cu;
   if (cu->per_cu->from_debug_types)
-    reader->buffer = dwarf2_per_objfile->types.buffer;
+    {
+      gdb_assert (dwarf2_per_objfile->types.readin);
+      reader->buffer = dwarf2_per_objfile->types.buffer;
+    }
   else
-    reader->buffer = dwarf2_per_objfile->info.buffer;
+    {
+      gdb_assert (dwarf2_per_objfile->info.readin);
+      reader->buffer = dwarf2_per_objfile->info.buffer;
+    }
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -2044,6 +2059,7 @@ process_type_comp_unit (void **slot, void *info)
   this_cu = &entry->per_cu;
   this_cu->from_debug_types = 1;
 
+  gdb_assert (dwarf2_per_objfile->types.readin);
   process_psymtab_comp_unit (objfile, this_cu,
 			     dwarf2_per_objfile->types.buffer,
 			     dwarf2_per_objfile->types.buffer + entry->offset,
@@ -2071,12 +2087,11 @@ build_type_psymtabs (struct objfile *objfile)
 static void
 dwarf2_build_psymtabs_hard (struct objfile *objfile)
 {
-  /* Instead of reading this into a big buffer, we should probably use
-     mmap()  on architectures that support it. (FIXME) */
   bfd *abfd = objfile->obfd;
   gdb_byte *info_ptr;
   struct cleanup *back_to;
 
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
   info_ptr = dwarf2_per_objfile->info.buffer;
 
   /* Any cached compilation units will be linked by the per-objfile
@@ -2142,6 +2157,7 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu,
 
   gdb_assert (! this_cu->from_debug_types);
 
+  gdb_assert (dwarf2_per_objfile->info.readin);
   info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
   beg_of_comp_unit = info_ptr;
 
@@ -2199,7 +2215,10 @@ create_all_comp_units (struct objfile *objfile)
   int n_allocated;
   int n_comp_units;
   struct dwarf2_per_cu_data **all_comp_units;
-  gdb_byte *info_ptr = dwarf2_per_objfile->info.buffer;
+  gdb_byte *info_ptr;
+
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
+  info_ptr = dwarf2_per_objfile->info.buffer;
 
   n_comp_units = 0;
   n_allocated = 10;
@@ -3101,6 +3120,7 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
   /* Set local variables from the partial symbol table info.  */
   offset = per_cu->offset;
 
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
   info_ptr = dwarf2_per_objfile->info.buffer + offset;
   beg_of_comp_unit = info_ptr;
 
@@ -4062,6 +4082,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   found_base = cu->base_known;
   base = cu->base_address;
 
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
   if (offset >= dwarf2_per_objfile->ranges.size)
     {
       complaint (&symfile_complaints,
@@ -4364,6 +4385,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
       CORE_ADDR base = cu->base_address;
       int base_known = cu->base_known;
 
+      gdb_assert (dwarf2_per_objfile->ranges.readin);
       if (offset >= dwarf2_per_objfile->ranges.size)
         {
           complaint (&symfile_complaints,
@@ -6362,6 +6384,8 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
   memset (cu->dwarf2_abbrevs, 0,
           ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
 
+  dwarf2_read_section (dwarf2_per_objfile->objfile,
+		       &dwarf2_per_objfile->abbrev);
   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;
@@ -7434,6 +7458,7 @@ read_indirect_string (bfd *abfd, gdb_byte *buf,
 {
   LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
 
+  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str);
   if (dwarf2_per_objfile->str.buffer == NULL)
     {
       error (_("DW_FORM_strp used without .debug_str section [in module %s]"),
@@ -7760,6 +7785,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   int i;
   char *cur_dir, *cur_file;
 
+  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line);
   if (dwarf2_per_objfile->line.buffer == NULL)
     {
       complaint (&symfile_complaints, _("missing .debug_line section"));
@@ -10528,6 +10554,8 @@ read_signatured_type_at_offset (struct objfile *objfile,
 {
   struct signatured_type *type_sig;
 
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
+
   /* We have the section offset, but we need the signature to do the
      hash table lookup.	 */
   type_sig = lookup_signatured_type_at_offset (objfile, offset);
@@ -11134,6 +11162,8 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
   enum dwarf_macinfo_record_type macinfo_type;
   int at_commandline;
 
+  dwarf2_read_section (dwarf2_per_objfile->objfile,
+		       &dwarf2_per_objfile->macinfo);
   if (dwarf2_per_objfile->macinfo.buffer == NULL)
     {
       complaint (&symfile_complaints, _("missing .debug_macinfo section"));
@@ -11459,6 +11489,9 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
       baton->per_cu = cu->per_cu;
       gdb_assert (baton->per_cu);
 
+      dwarf2_read_section (dwarf2_per_objfile->objfile,
+			   &dwarf2_per_objfile->loc);
+
       /* 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);
diff --git a/gdb/elfread.c b/gdb/elfread.c
index e32a1a9..97c0163 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -886,10 +886,6 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags)
       dwarf2_build_psymtabs (objfile);
     }
 
-  /* FIXME: kettenis/20030504: This still needs to be integrated with
-     dwarf2read.c in a better way.  */
-  dwarf2_build_frame_info (objfile);
-
   /* If the file has its own symbol tables it has no separate debug info.
      `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
      `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]