Whoops, forgot to commit this yesterday:
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index d3dba4e74c0a1f13e854d2c6cc59866c48eab848..16a3e23080e608f033e7272c42820e0f70dadf2c 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
-   Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -35,6 +36,7 @@
 #include "buildsym.h"
 #include "demangle.h"
 #include "expression.h"
+#include "filenames.h" /* for DOSish file names */
 
 #include "language.h"
 #include "complaints.h"
 #include "gdb_string.h"
 #include <sys/types.h>
 
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
 #if 0
 /* .debug_info header for a compilation unit
    Because of alignment constraints, this structure has padding and cannot
@@ -188,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;
@@ -275,11 +282,6 @@ static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
 
 static struct die_info *die_ref_table[REF_HASH_SIZE];
 
-#ifndef TYPE_HASH_SIZE
-#define TYPE_HASH_SIZE 4096
-#endif
-static struct type *dwarf2_cached_types[TYPE_HASH_SIZE];
-
 /* Obstack for allocating temporary storage used during symbol reading.  */
 static struct obstack dwarf2_tmp_obstack;
 
@@ -552,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);
@@ -585,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 *,
@@ -726,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 *);
 
@@ -755,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);
 
@@ -866,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);
     }
@@ -949,7 +950,8 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   info_ptr += 1;
   signed_addr = bfd_get_sign_extend_vma (abfd);
   if (signed_addr < 0)
-    internal_error ("read_comp_unit_head: dwarf from non elf file");
+    internal_error (__FILE__, __LINE__,
+                   "read_comp_unit_head: dwarf from non elf file");
   cu_header->signed_addr_p = signed_addr;
   return info_ptr;
 }
@@ -968,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;
@@ -1010,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);
@@ -1045,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;
@@ -1088,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)
                    {
@@ -1740,7 +1779,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   /* Allocate a new field list entry and link it in.  */
   new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
-  make_cleanup (free, new_field);
+  make_cleanup (xfree, new_field);
   memset (new_field, 0, sizeof (struct nextfield));
   new_field->next = fip->fields;
   fip->fields = new_field;
@@ -2027,7 +2066,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   /* Create a new member function field and chain it to the field list
      entry. */
   new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
-  make_cleanup (free, new_fnfield);
+  make_cleanup (xfree, new_fnfield);
   memset (new_fnfield, 0, sizeof (struct nextfnfield));
   new_fnfield->next = flp->head;
   flp->head = new_fnfield;
@@ -2387,7 +2426,7 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
            TYPE_ALLOC (type, sizeof (struct field) * num_fields);
          memcpy (TYPE_FIELDS (type), fields,
                  sizeof (struct field) * num_fields);
-         free (fields);
+         xfree (fields);
        }
       if (unsigned_enum)
        TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
@@ -2654,26 +2693,30 @@ static void
 read_tag_const_type (struct die_info *die, struct objfile *objfile,
                     const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  complain (&dwarf2_const_ignored);
-  die->type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
 }
 
 static void
 read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
                        const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  complain (&dwarf2_volatile_ignored);
-  die->type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
 }
 
 /* Extract all information from a DW_TAG_string_type DIE and add to
@@ -2893,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)
 {
@@ -2901,7 +2944,7 @@ read_comp_unit (char *info_ptr, bfd *abfd,
   char *cur_ptr;
   int nesting_level;
 
-  /* Reset die reference table and cached types table; we are
+  /* Reset die reference table; we are
      building new ones now.  */
   dwarf2_empty_hash_tables ();
 
@@ -2950,8 +2993,8 @@ free_die_list (struct die_info *dies)
   while (die)
     {
       next = die->next;
-      free (die->attrs);
-      free (die);
+      xfree (die->attrs);
+      xfree (die);
       die = next;
     }
 }
@@ -2984,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'",
@@ -3084,8 +3127,8 @@ dwarf2_empty_abbrev_table (PTR ignore)
       while (abbrev)
        {
          next = abbrev->next;
-         free (abbrev->attrs);
-         free (abbrev);
+         xfree (abbrev->attrs);
+         xfree (abbrev);
          abbrev = next;
        }
       dwarf2_abbrevs[i] = NULL;
@@ -3117,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;
@@ -3129,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)
@@ -3215,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;
@@ -3238,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;
 }
 
@@ -3468,7 +3509,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
          break;
        default:
-         internal_error ("read_address: bad switch, signed");
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, signed");
        }
     }
   else
@@ -3485,7 +3527,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          retval = bfd_get_64 (abfd, (bfd_byte *) buf);
          break;
        default:
-         internal_error ("read_address: bad switch, unsigned");
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, unsigned");
        }
     }
 
@@ -3570,7 +3613,8 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
       *bytes_read = 8;
       break;
     default:
-      internal_error ("read_offset: bad switch");
+      internal_error (__FILE__, __LINE__,
+                     "read_offset: bad switch");
     }
 
  return retval;
@@ -3712,6 +3756,9 @@ set_cu_language (unsigned int lang)
     case DW_LANG_Mips_Assembler:
       cu_language = language_asm;
       break;
+    case DW_LANG_Java:
+      cu_language = language_java;
+      break;
     case DW_LANG_Ada83:
     case DW_LANG_Cobol74:
     case DW_LANG_Cobol85:
@@ -4055,21 +4102,21 @@ dwarf2_start_subfile (char *filename, char *dirname)
   /* If the filename isn't absolute, try to match an existing subfile
      with the full pathname.  */
 
-  if (*filename != '/' && dirname != NULL)
+  if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
     {
       struct subfile *subfile;
       char *fullname = concat (dirname, "/", filename, NULL);
 
       for (subfile = subfiles; subfile; subfile = subfile->next)
        {
-         if (STREQ (subfile->name, fullname))
+         if (FILENAME_CMP (subfile->name, fullname) == 0)
            {
              current_subfile = subfile;
-             free (fullname);
+             xfree (fullname);
              return;
            }
        }
-      free (fullname);
+      xfree (fullname);
     }
   start_subfile (filename, dirname);
 }
@@ -4185,7 +4232,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                     the variable is referenced.  */
                  if (SYMBOL_VALUE_ADDRESS (sym))
                    {
-                     SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+                     fixup_symbol_section (sym, objfile);
+                     SYMBOL_VALUE_ADDRESS (sym) +=
+                       ANOFFSET (objfile->section_offsets,
+                                 SYMBOL_SECTION (sym));
                      SYMBOL_CLASS (sym) = LOC_STATIC;
                    }
                  else
@@ -4203,11 +4253,13 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                  else if (isreg)
                    {
                      SYMBOL_CLASS (sym) = LOC_REGISTER;
+                     SYMBOL_VALUE (sym) = 
+                       DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
                    }
                  else if (offreg)
                    {
                      SYMBOL_CLASS (sym) = LOC_BASEREG;
-                     SYMBOL_BASEREG (sym) = basereg;
+                     SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
                    }
                  else if (islocal)
                    {
@@ -4215,8 +4267,11 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                    }
                  else
                    {
+                     fixup_symbol_section (sym, objfile);
+                     SYMBOL_VALUE_ADDRESS (sym) =
+                       addr + ANOFFSET (objfile->section_offsets,
+                                        SYMBOL_SECTION (sym));
                      SYMBOL_CLASS (sym) = LOC_STATIC;
-                     SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
                    }
                }
            }
@@ -4246,6 +4301,8 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
              if (isreg)
                {
                  SYMBOL_CLASS (sym) = LOC_REGPARM;
+                 SYMBOL_VALUE (sym) = 
+                   DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
                }
              else if (offreg)
                {
@@ -4258,7 +4315,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                  else
                    {
                      SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
-                     SYMBOL_BASEREG (sym) = basereg;
+                     SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
                    }
                }
              else
@@ -4522,38 +4579,7 @@ tag_type_to_type (struct die_info *die, struct objfile *objfile,
     }
   else
     {
-      struct attribute *attr;
-      attr = dwarf_attr (die, DW_AT_name);
-      if (attr && DW_STRING (attr))
-       {
-         char *attrname=DW_STRING (attr);
-         unsigned long hashval=hash(attrname, strlen(attrname)) % TYPE_HASH_SIZE;
-
-         if (dwarf2_cached_types[hashval] != NULL)
-           {
-             const char *nameoftype;
-             nameoftype = TYPE_NAME(dwarf2_cached_types[hashval]) == NULL ? TYPE_TAG_NAME(dwarf2_cached_types[hashval]) : TYPE_NAME(dwarf2_cached_types[hashval]);
-             if (strcmp(attrname, nameoftype) == 0)
-               {
-                 die->type=dwarf2_cached_types[hashval];
-               }
-             else
-               {
-                 read_type_die (die, objfile, cu_header);
-                 dwarf2_cached_types[hashval] = die->type;
-               }
-           }
-         else
-           {
-             read_type_die (die, objfile, cu_header);
-             dwarf2_cached_types[hashval] = die->type;
-           }
-       }
-      else
-       {
-         read_type_die (die, objfile, cu_header);
-       }
-
+      read_type_die (die, objfile, cu_header);
       if (!die->type)
        {
          dump_die (die);
@@ -4725,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;
@@ -5511,7 +5537,7 @@ dwarf_cfi_name (register unsigned cfi_opc)
 }
 #endif
 
-void
+static void
 dump_die (struct die_info *die)
 {
   unsigned int i;
@@ -5573,7 +5599,7 @@ dump_die (struct die_info *die)
     }
 }
 
-void
+static void
 dump_die_list (struct die_info *die)
 {
   while (die)
@@ -5583,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;
@@ -5600,7 +5626,6 @@ static void
 dwarf2_empty_hash_tables (void)
 {
   memset (die_ref_table, 0, sizeof (die_ref_table));
-  memset (dwarf2_cached_types, 0, sizeof(dwarf2_cached_types));
 }
 
 static unsigned int
@@ -5626,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.032303 seconds and 4 git commands to generate.