Whoops, forgot to commit this yesterday:
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index 3d9902c799994738fc8c6fc387a767cec5ccf6c6..16a3e23080e608f033e7272c42820e0f70dadf2c 100644 (file)
@@ -194,6 +194,7 @@ struct partial_die_info
     unsigned int offset;
     unsigned int abbrev;
     char *name;
+    int has_pc_info;
     CORE_ADDR lowpc;
     CORE_ADDR highpc;
     struct dwarf_block *locdesc;
@@ -553,9 +554,6 @@ static struct complaint dwarf2_unsupported_const_value_attr =
   "unsupported const value attribute form: '%s'", 0, 0
 };
 
-/* Externals references.  */
-extern int info_verbose;       /* From main.c; nonzero => verbose */
-
 /* local function prototypes */
 
 static void dwarf2_locate_sections (bfd *, asection *, PTR);
@@ -586,7 +584,7 @@ static void dwarf2_empty_abbrev_table (PTR);
 static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
 
 static char *read_partial_die (struct partial_die_info *,
-                              bfd *, char *, int *,
+                              bfd *, char *,
                               const struct comp_unit_head *);
 
 static char *read_full_die (struct die_info **, bfd *, char *,
@@ -727,7 +725,8 @@ static void read_tag_string_type (struct die_info *, struct objfile *);
 static void read_subroutine_type (struct die_info *, struct objfile *,
                                  const struct comp_unit_head *);
 
-struct die_info *read_comp_unit (char *, bfd *, const struct comp_unit_head *);
+static struct die_info *read_comp_unit (char *, bfd *,
+                                        const struct comp_unit_head *);
 
 static void free_die_list (struct die_info *);
 
@@ -756,19 +755,19 @@ static char *dwarf_cfi_name (unsigned int);
 struct die_info *copy_die (struct die_info *);
 #endif
 
-struct die_info *sibling_die (struct die_info *);
+static struct die_info *sibling_die (struct die_info *);
 
-void dump_die (struct die_info *);
+static void dump_die (struct die_info *);
 
-void dump_die_list (struct die_info *);
+static void dump_die_list (struct die_info *);
 
-void store_in_ref_table (unsigned int, struct die_info *);
+static void store_in_ref_table (unsigned int, struct die_info *);
 
 static void dwarf2_empty_hash_tables (void);
 
 static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
 
-struct die_info *follow_die_ref (unsigned int);
+static struct die_info *follow_die_ref (unsigned int);
 
 static struct type *dwarf2_fundamental_type (struct objfile *, int);
 
@@ -867,8 +866,9 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
                                           dwarf_line_offset,
                                           dwarf_line_size);
 
-  if (mainline || objfile->global_psymbols.size == 0 ||
-      objfile->static_psymbols.size == 0)
+  if (mainline
+      || (objfile->global_psymbols.size == 0
+         && objfile->static_psymbols.size == 0))
     {
       init_psymbol_list (objfile, 1024);
     }
@@ -970,17 +970,56 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
   struct partial_die_info comp_unit_die;
   struct partial_symtab *pst;
   struct cleanup *back_to;
-  int comp_unit_has_pc_info;
   CORE_ADDR lowpc, highpc;
 
   info_ptr = dwarf_info_buffer;
   abbrev_ptr = dwarf_abbrev_buffer;
 
+  /* We use dwarf2_tmp_obstack for objects that don't need to survive
+     the partial symbol scan, like attribute values.
+
+     We could reduce our peak memory consumption during partial symbol
+     table construction by freeing stuff from this obstack more often
+     --- say, after processing each compilation unit, or each die ---
+     but it turns out that this saves almost nothing.  For an
+     executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+     on dwarf2_tmp_obstack.  Some investigation showed:
+
+     1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+        DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*.  These are
+        all fixed-length values not requiring dynamic allocation.
+
+     2) 30% of the attributes used the form DW_FORM_string.  For
+        DW_FORM_string, read_attribute simply hands back a pointer to
+        the null-terminated string in dwarf_info_buffer, so no dynamic
+        allocation is needed there either.
+
+     3) The remaining 1% of the attributes all used DW_FORM_block1.
+        75% of those were DW_AT_frame_base location lists for
+        functions; the rest were DW_AT_location attributes, probably
+        for the global variables.
+
+     Anyway, what this all means is that the memory the dwarf2
+     reader uses as temporary space reading partial symbols is about
+     0.5% as much as we use for dwarf_*_buffer.  That's noise.  */
+
   obstack_init (&dwarf2_tmp_obstack);
   back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
-  while ((unsigned int) (info_ptr - dwarf_info_buffer)
-        + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
+  /* Since the objects we're extracting from dwarf_info_buffer vary in
+     length, only the individual functions to extract them (like
+     read_comp_unit_head and read_partial_die) can really know whether
+     the buffer is large enough to hold another complete object.
+
+     At the moment, they don't actually check that.  If
+     dwarf_info_buffer holds just one extra byte after the last
+     compilation unit's dies, then read_comp_unit_head will happily
+     read off the end of the buffer.  read_partial_die is similarly
+     casual.  Those functions should be fixed.
+
+     For this loop condition, simply checking whether there's any data
+     left at all should be sufficient.  */
+  while (info_ptr < dwarf_info_buffer + dwarf_info_size)
     {
       struct comp_unit_head cu_header;
       beg_of_comp_unit = info_ptr;
@@ -1012,7 +1051,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 
       /* Read the compilation unit die */
       info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
-                                  &comp_unit_has_pc_info, &cu_header);
+                                  &cu_header);
 
       /* Set the language we're debugging */
       set_cu_language (comp_unit_die.language);
@@ -1047,7 +1086,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 
          /* If the compilation unit didn't have an explicit address range,
             then use the information extracted from its child dies.  */
-         if (!comp_unit_has_pc_info)
+         if (! comp_unit_die.has_pc_info)
            {
              comp_unit_die.lowpc = lowpc;
              comp_unit_die.highpc = highpc;
@@ -1090,22 +1129,20 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile,
      back to that level. */
 
   int nesting_level = 1;
-  int has_pc_info;
 
   *lowpc = ((CORE_ADDR) -1);
   *highpc = ((CORE_ADDR) 0);
 
   while (nesting_level)
     {
-      info_ptr = read_partial_die (&pdi, abfd, info_ptr,
-                                  &has_pc_info, cu_header);
+      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
 
       if (pdi.name)
        {
          switch (pdi.tag)
            {
            case DW_TAG_subprogram:
-             if (has_pc_info)
+             if (pdi.has_pc_info)
                {
                  if (pdi.lowpc < *lowpc)
                    {
@@ -2899,7 +2936,7 @@ read_base_type (struct die_info *die, struct objfile *objfile)
 
 /* Read a whole compilation unit into a linked list of dies.  */
 
-struct die_info *
+static struct die_info *
 read_comp_unit (char *info_ptr, bfd *abfd,
                const struct comp_unit_head *cu_header)
 {
@@ -2990,7 +3027,7 @@ dwarf2_read_section (struct objfile *objfile, file_ptr offset,
 
   buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
   if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
-      (bfd_read (buf, size, 1, abfd) != size))
+      (bfd_bread (buf, size, abfd) != size))
     {
       buf = NULL;
       error ("Dwarf Error: Can't read DWARF data from '%s'",
@@ -3123,8 +3160,7 @@ dwarf2_lookup_abbrev (unsigned int number)
 
 static char *
 read_partial_die (struct partial_die_info *part_die, bfd *abfd,
-                 char *info_ptr, int *has_pc_info,
-                 const struct comp_unit_head *cu_header)
+                 char *info_ptr, const struct comp_unit_head *cu_header)
 {
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
@@ -3135,7 +3171,6 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
   int has_high_pc_attr = 0;
 
   *part_die = zeroed_partial_die;
-  *has_pc_info = 0;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
@@ -3221,7 +3256,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
       int dummy;
 
       spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
-      read_partial_die (&spec_die, abfd, spec_ptr, &dummy, cu_header);
+      read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
       if (spec_die.name)
        {
          part_die->name = spec_die.name;
@@ -3244,7 +3279,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
       && part_die->lowpc < part_die->highpc
       && (part_die->lowpc != 0
          || (bfd_get_file_flags (abfd) & HAS_RELOC)))
-    *has_pc_info = 1;
+    part_die->has_pc_info = 1;
   return info_ptr;
 }
 
@@ -4716,7 +4751,7 @@ copy_die (struct die_info *old_die)
 
 /* Return sibling of die, NULL if no sibling.  */
 
-struct die_info *
+static struct die_info *
 sibling_die (struct die_info *die)
 {
   int nesting_level = 0;
@@ -5502,7 +5537,7 @@ dwarf_cfi_name (register unsigned cfi_opc)
 }
 #endif
 
-void
+static void
 dump_die (struct die_info *die)
 {
   unsigned int i;
@@ -5564,7 +5599,7 @@ dump_die (struct die_info *die)
     }
 }
 
-void
+static void
 dump_die_list (struct die_info *die)
 {
   while (die)
@@ -5574,7 +5609,7 @@ dump_die_list (struct die_info *die)
     }
 }
 
-void
+static void
 store_in_ref_table (unsigned int offset, struct die_info *die)
 {
   int h;
@@ -5616,7 +5651,7 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
   return result;
 }
 
-struct die_info *
+static struct die_info *
 follow_die_ref (unsigned int offset)
 {
   struct die_info *die;
This page took 0.029328 seconds and 4 git commands to generate.