* configure.tgt (hppa*-*-bsd*, hppa*-*-osf*, m68*-*-sunos4*,
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index 18cb65e58006536e320bd925e84e9be0c6054660..8a0513d72ced2099c035a09b04603dada1b98cf4 100644 (file)
 #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
@@ -152,11 +156,14 @@ static unsigned int dwarf_str_size;
    translation, looks like this.  */
 struct comp_unit_head
   {
-    unsigned int length;
+    unsigned long length;
     short version;
     unsigned int abbrev_offset;
     unsigned char addr_size;
     unsigned char signed_addr_p;
+    unsigned int offset_size;  /* size of file offsets; either 4 or 8 */
+    unsigned int initial_length_size; /* size of the length field; either
+                                         4 or 12 */
   };
 
 /* The data in the .debug_line statement prologue looks like this.  */
@@ -272,11 +279,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;
 
@@ -604,6 +606,12 @@ static unsigned long read_8_bytes (bfd *, char *);
 static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
                               int *bytes_read);
 
+static LONGEST read_initial_length (bfd *, char *,
+                                    struct comp_unit_head *, int *bytes_read);
+
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+                            int *bytes_read);
+
 static char *read_n_bytes (bfd *, char *, unsigned int);
 
 static char *read_string (bfd *, char *, unsigned int *);
@@ -898,8 +906,12 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
   pubnames_ptr = pubnames_buffer;
   while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
     {
-      entry_length = read_4_bytes (abfd, pubnames_ptr);
-      pubnames_ptr += 4;
+      struct comp_unit_head cu_header;
+      int bytes_read;
+
+      entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
+                                         &bytes_read);
+      pubnames_ptr += bytes_read;
       version = read_1_byte (abfd, pubnames_ptr);
       pubnames_ptr += 1;
       info_offset = read_4_bytes (abfd, pubnames_ptr);
@@ -923,17 +935,20 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
                     char *info_ptr, bfd *abfd)
 {
   int signed_addr;
-  cu_header->length = read_4_bytes (abfd, info_ptr);
-  info_ptr += 4;
+  int bytes_read;
+  cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
+                                           &bytes_read);
+  info_ptr += bytes_read;
   cu_header->version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
-  cu_header->abbrev_offset = read_4_bytes (abfd, info_ptr);
-  info_ptr += 4;
+  cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
+                                          &bytes_read);
+  info_ptr += bytes_read;
   cu_header->addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
   signed_addr = bfd_get_sign_extend_vma (abfd);
   if (signed_addr < 0)
-    internal_error ("dwarf2_build_psymtabs_hard: dwarf from non elf file");
+    internal_error ("read_comp_unit_head: dwarf from non elf file");
   cu_header->signed_addr_p = signed_addr;
   return info_ptr;
 }
@@ -980,7 +995,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
                 (long) (beg_of_comp_unit - dwarf_info_buffer));
          return;
        }
-      if (beg_of_comp_unit + cu_header.length + 4
+      if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
          > dwarf_info_buffer + dwarf_info_size)
        {
          error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
@@ -1014,7 +1029,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
       DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
       DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
       DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
-      baseaddr = ANOFFSET (objfile->section_offsets, 0);
+      baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
       pst->read_symtab = dwarf2_psymtab_to_symtab;
@@ -1049,7 +1064,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
          also happen.) This happens in VxWorks.  */
       free_named_symtabs (pst->filename);
 
-      info_ptr = beg_of_comp_unit + cu_header.length + 4;
+      info_ptr = beg_of_comp_unit + cu_header.length 
+                                  + cu_header.initial_length_size;
     }
   do_cleanups (back_to);
 }
@@ -1314,7 +1330,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
   dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
   dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
-  baseaddr = ANOFFSET (pst->section_offsets, 0);
+  baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
 
@@ -1362,7 +1378,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
            }
        }
     }
-  symtab = end_symtab (highpc + baseaddr, objfile, 0);
+  symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 
   /* Set symtab language to language from DW_AT_language.
      If the compilation is from a C file generated by language preprocessors,
@@ -2884,7 +2900,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 ();
 
@@ -3370,6 +3386,10 @@ read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
       DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
       info_ptr += 4;
       break;
+    case DW_FORM_ref8:
+      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+      break;
     case DW_FORM_ref_udata:
       DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
@@ -3472,6 +3492,89 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
   return retval;
 }
 
+/* Reads the initial length from a section.  The (draft) DWARF 2.1
+   specification allows the initial length to take up either 4 bytes
+   or 12 bytes.  If the first 4 bytes are 0xffffffff, then the next 8
+   bytes describe the length and all offsets will be 8 bytes in length
+   instead of 4.
+
+   The value returned via bytes_read should be used to increment
+   the relevant pointer after calling read_initial_length().
+   
+   As a side effect, this function sets the fields initial_length_size
+   and offset_size in cu_header to the values appropriate for the
+   length field.  (The format of the initial length field determines
+   the width of file offsets to be fetched later with fetch_offset().)
+   
+   [ Note:  read_initial_length() and read_offset() are based on the
+     document entitled "DWARF Debugging Information Format", revision
+     2.1, draft 4, dated July 20, 2000.  This document was obtained
+     from:
+
+       http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+     
+     This document is only a draft and is subject to change.  (So beware.)
+
+     - Kevin, Aug 4, 2000
+   ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+                     int *bytes_read)
+{
+  LONGEST retval = 0;
+
+  retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+
+  if (retval == 0xffffffff)
+    {
+      retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+      *bytes_read = 12;
+      if (cu_header != NULL)
+       {
+         cu_header->initial_length_size = 12;
+         cu_header->offset_size = 8;
+       }
+    }
+  else
+    {
+      *bytes_read = 4;
+      if (cu_header != NULL)
+       {
+         cu_header->initial_length_size = 4;
+         cu_header->offset_size = 4;
+       }
+    }
+
+ return retval;
+}
+
+/* Read an offset from the data stream.  The size of the offset is
+   given by cu_header->offset_size. */
+
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+             int *bytes_read)
+{
+  LONGEST retval = 0;
+
+  switch (cu_header->offset_size)
+    {
+    case 4:
+      retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+      *bytes_read = 4;
+      break;
+    case 8:
+      retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+      *bytes_read = 8;
+      break;
+    default:
+      internal_error ("read_offset: bad switch");
+    }
+
+ return retval;
+}
+
 static char *
 read_n_bytes (bfd *abfd, char *buf, unsigned int size)
 {
@@ -3713,13 +3816,13 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
   line_ptr = dwarf_line_buffer + offset;
 
   /* read in the prologue */
-  lh.total_length = read_4_bytes (abfd, line_ptr);
-  line_ptr += 4;
+  lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+  line_ptr += bytes_read;
   line_end = line_ptr + lh.total_length;
   lh.version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  lh.prologue_length = read_4_bytes (abfd, line_ptr);
-  line_ptr += 4;
+  lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+  line_ptr += bytes_read;
   lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   lh.default_is_stmt = read_1_byte (abfd, line_ptr);
@@ -4081,7 +4184,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
@@ -4099,11 +4205,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)
                    {
@@ -4111,8 +4219,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;
                    }
                }
            }
@@ -4142,6 +4253,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)
                {
@@ -4154,7 +4267,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
@@ -4418,38 +4531,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);
@@ -5496,7 +5578,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
@@ -5512,6 +5593,7 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
     case DW_FORM_ref1:
     case DW_FORM_ref2:
     case DW_FORM_ref4:
+    case DW_FORM_ref8:
     case DW_FORM_ref_udata:
       result = cu_header_offset + DW_UNSND (attr);
       break;
This page took 0.0301 seconds and 4 git commands to generate.