Updated copyright notices for most files.
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index d894696f23a3a998792e7aa33caf7915dd20692e..4f2f7fb3f9e74bb7984c6f85b3bc89506c73c96e 100644 (file)
@@ -1,7 +1,8 @@
 /* DWARF 2 debugging format support for GDB.
 
    Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009
+                 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -234,7 +235,7 @@ asection *dwarf_eh_frame_section;
    translation, looks like this.  */
 struct comp_unit_head
 {
-  unsigned long length;
+  unsigned int length;
   short version;
   unsigned char addr_size;
   unsigned char signed_addr_p;
@@ -299,7 +300,7 @@ struct dwarf2_cu
   htab_t partial_dies;
 
   /* `.debug_ranges' offset for this `DW_TAG_compile_unit' DIE.  */
-  unsigned long ranges_offset;
+  unsigned int ranges_offset;
 
   /* Storage for things with the same lifetime as this read-in compilation
      unit, including partial DIEs.  */
@@ -366,12 +367,12 @@ struct dwarf2_per_cu_data
      - if it doesn't, GDB will fall over anyway.
      NOTE: Unlike comp_unit_head.length, this length includes
      initial_length_size.  */
-  unsigned long offset;
-  unsigned long length : 30;
+  unsigned int offset;
+  unsigned int length : 30;
 
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
-  unsigned long queued : 1;
+  unsigned int queued : 1;
 
   /* This flag will be set if we need to load absolutely all DIEs
      for this compilation unit, instead of just the ones we think
@@ -699,6 +700,13 @@ dwarf2_debug_line_missing_file_complaint (void)
             _(".debug_line section has line data without a file"));
 }
 
+static void
+dwarf2_debug_line_missing_end_sequence_complaint (void)
+{
+  complaint (&symfile_complaints,
+            _(".debug_line section has line program sequence without an end"));
+}
+
 static void
 dwarf2_complex_location_expr_complaint (void)
 {
@@ -801,7 +809,7 @@ static gdb_byte *read_partial_die (struct partial_die_info *,
                                    struct abbrev_info *abbrev, unsigned int,
                                    bfd *, gdb_byte *, struct dwarf2_cu *);
 
-static struct partial_die_info *find_partial_die (unsigned long,
+static struct partial_die_info *find_partial_die (unsigned int,
                                                  struct dwarf2_cu *);
 
 static void fixup_partial_die (struct partial_die_info *,
@@ -829,11 +837,16 @@ static unsigned long read_8_bytes (bfd *, gdb_byte *);
 static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
                               unsigned int *);
 
-static LONGEST read_initial_length (bfd *, gdb_byte *,
-                                    struct comp_unit_head *, unsigned int *);
+static LONGEST read_initial_length (bfd *, gdb_byte *, unsigned int *);
+
+static LONGEST read_checked_initial_length_and_offset
+  (bfd *, gdb_byte *, const struct comp_unit_head *,
+   unsigned int *, unsigned int *);
 
 static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
-                            unsigned int *);
+                           unsigned int *);
+
+static LONGEST read_offset_1 (bfd *, gdb_byte *, unsigned int);
 
 static gdb_byte *read_n_bytes (bfd *, gdb_byte *, unsigned int);
 
@@ -1009,8 +1022,7 @@ static void dump_die_1 (struct ui_file *, int level, int max_level,
 static void store_in_ref_table (struct die_info *,
                                struct dwarf2_cu *);
 
-static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
-                                              struct dwarf2_cu *);
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
 
 static int dwarf2_get_attr_constant_value (struct attribute *, int);
 
@@ -1054,10 +1066,10 @@ static hashval_t partial_die_hash (const void *item);
 static int partial_die_eq (const void *item_lhs, const void *item_rhs);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
-  (unsigned long offset, struct objfile *objfile);
+  (unsigned int offset, struct objfile *objfile);
 
 static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
-  (unsigned long offset, struct objfile *objfile);
+  (unsigned int offset, struct objfile *objfile);
 
 static void free_one_comp_unit (void *);
 
@@ -1309,11 +1321,9 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
   pubnames_ptr = pubnames_buffer;
   while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
     {
-      struct comp_unit_head cu_header;
       unsigned int bytes_read;
 
-      entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
-                                          &bytes_read);
+      entry_length = read_initial_length (abfd, pubnames_ptr, &bytes_read);
       pubnames_ptr += bytes_read;
       version = read_1_byte (abfd, pubnames_ptr);
       pubnames_ptr += 1;
@@ -1350,13 +1360,15 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
 {
   int signed_addr;
   unsigned int bytes_read;
-  cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
-                                           &bytes_read);
+
+  cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
+  cu_header->initial_length_size = bytes_read;
+  cu_header->offset_size = (bytes_read == 4) ? 4 : 8;
   info_ptr += bytes_read;
   cu_header->version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
   cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
-                                          &bytes_read);
+                                         &bytes_read);
   info_ptr += bytes_read;
   cu_header->addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
@@ -1365,6 +1377,7 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
     internal_error (__FILE__, __LINE__,
                    _("read_comp_unit_head: dwarf from non elf file"));
   cu_header->signed_addr_p = signed_addr;
+
   return info_ptr;
 }
 
@@ -1735,26 +1748,24 @@ create_all_comp_units (struct objfile *objfile)
   
   while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
     {
-      struct comp_unit_head cu_header;
+      unsigned int length, initial_length_size;
       gdb_byte *beg_of_comp_unit;
       struct dwarf2_per_cu_data *this_cu;
-      unsigned long offset;
-      unsigned int bytes_read;
+      unsigned int offset;
 
       offset = info_ptr - dwarf2_per_objfile->info_buffer;
 
       /* Read just enough information to find out where the next
         compilation unit is.  */
-      cu_header.initial_length_size = 0;
-      cu_header.length = read_initial_length (objfile->obfd, info_ptr,
-                                             &cu_header, &bytes_read);
+      length = read_initial_length (objfile->obfd, info_ptr,
+                                   &initial_length_size);
 
       /* Save the compilation unit for later lookup.  */
       this_cu = obstack_alloc (&objfile->objfile_obstack,
                               sizeof (struct dwarf2_per_cu_data));
       memset (this_cu, 0, sizeof (*this_cu));
       this_cu->offset = offset;
-      this_cu->length = cu_header.length + cu_header.initial_length_size;
+      this_cu->length = length + initial_length_size;
 
       if (n_comp_units == n_allocated)
        {
@@ -2358,7 +2369,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
            complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
          else
            return dwarf2_per_objfile->info_buffer
-             + dwarf2_get_ref_die_offset (&attr, cu);
+             + dwarf2_get_ref_die_offset (&attr);
        }
 
       /* If it isn't DW_AT_sibling, skip this attribute.  */
@@ -2621,7 +2632,7 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
 {
   bfd *abfd = objfile->obfd;
   struct dwarf2_cu *cu;
-  unsigned long offset;
+  unsigned int offset;
   gdb_byte *info_ptr;
   struct cleanup *back_to, *free_cu_cleanup;
   struct attribute *attr;
@@ -5946,7 +5957,7 @@ read_partial_die (struct partial_die_info *part_die,
        case DW_AT_specification:
        case DW_AT_extension:
          part_die->has_specification = 1;
-         part_die->spec_offset = dwarf2_get_ref_die_offset (&attr, cu);
+         part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
          break;
        case DW_AT_sibling:
          /* Ignore absolute siblings, they might point outside of
@@ -5955,7 +5966,7 @@ read_partial_die (struct partial_die_info *part_die,
            complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
          else
            part_die->sibling = dwarf2_per_objfile->info_buffer
-             + dwarf2_get_ref_die_offset (&attr, cu);
+             + dwarf2_get_ref_die_offset (&attr);
          break;
         case DW_AT_stmt_list:
           part_die->has_stmt_list = 1;
@@ -6015,7 +6026,7 @@ read_partial_die (struct partial_die_info *part_die,
 /* Find a cached partial DIE at OFFSET in CU.  */
 
 static struct partial_die_info *
-find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
+find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu)
 {
   struct partial_die_info *lookup_die = NULL;
   struct partial_die_info part_die;
@@ -6029,7 +6040,7 @@ find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
 /* Find a partial DIE at OFFSET, which may or may not be in CU.  */
 
 static struct partial_die_info *
-find_partial_die (unsigned long offset, struct dwarf2_cu *cu)
+find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
 {
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
@@ -6086,7 +6097,7 @@ find_partial_die (unsigned long offset, struct dwarf2_cu *cu)
 
   if (pd == NULL)
     internal_error (__FILE__, __LINE__,
-                   _("could not find partial DIE 0x%lx in cache [from module %s]\n"),
+                   _("could not find partial DIE 0x%x in cache [from module %s]\n"),
                    offset, bfd_get_filename (cu->objfile->obfd));
   return pd;
 }
@@ -6444,12 +6455,7 @@ read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu,
 
    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 read_offset().)
-   
+
    [ Note:  read_initial_length() and read_offset() are based on the
      document entitled "DWARF Debugging Information Format", revision
      3, draft 8, dated November 19, 2001.  This document was obtained
@@ -6467,8 +6473,7 @@ read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu,
    ] */
 
 static LONGEST
-read_initial_length (bfd *abfd, gdb_byte *buf, struct comp_unit_head *cu_header,
-                     unsigned int *bytes_read)
+read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read)
 {
   LONGEST length = bfd_get_32 (abfd, buf);
 
@@ -6488,22 +6493,34 @@ read_initial_length (bfd *abfd, gdb_byte *buf, struct comp_unit_head *cu_header,
       *bytes_read = 4;
     }
 
-  if (cu_header)
-    {
-      gdb_assert (cu_header->initial_length_size == 0
-                 || cu_header->initial_length_size == 4
-                 || cu_header->initial_length_size == 8
-                 || cu_header->initial_length_size == 12);
+  return length;
+}
 
-      if (cu_header->initial_length_size != 0
-         && cu_header->initial_length_size != *bytes_read)
-       complaint (&symfile_complaints,
-                  _("intermixed 32-bit and 64-bit DWARF sections"));
+/* Cover function for read_initial_length.
+   Returns the length of the object at BUF, and stores the size of the
+   initial length in *BYTES_READ and stores the size that offsets will be in
+   *OFFSET_SIZE.
+   If the initial length size is not equivalent to that specified in
+   CU_HEADER then issue a complaint.
+   This is useful when reading non-comp-unit headers.  */
 
-      cu_header->initial_length_size = *bytes_read;
-      cu_header->offset_size = (*bytes_read == 4) ? 4 : 8;
-    }
+static LONGEST
+read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf,
+                                       const struct comp_unit_head *cu_header,
+                                       unsigned int *bytes_read,
+                                       unsigned int *offset_size)
+{
+  LONGEST length = read_initial_length (abfd, buf, bytes_read);
+
+  gdb_assert (cu_header->initial_length_size == 4
+             || cu_header->initial_length_size == 8
+             || cu_header->initial_length_size == 12);
 
+  if (cu_header->initial_length_size != *bytes_read)
+    complaint (&symfile_complaints,
+              _("intermixed 32-bit and 64-bit DWARF sections"));
+
+  *offset_size = (*bytes_read == 4) ? 4 : 8;
   return length;
 }
 
@@ -6513,22 +6530,30 @@ read_initial_length (bfd *abfd, gdb_byte *buf, struct comp_unit_head *cu_header,
 static LONGEST
 read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
              unsigned int *bytes_read)
+{
+  LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size);
+  *bytes_read = cu_header->offset_size;
+  return offset;
+}
+
+/* Read an offset from the data stream.  */
+
+static LONGEST
+read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size)
 {
   LONGEST retval = 0;
 
-  switch (cu_header->offset_size)
+  switch (offset_size)
     {
     case 4:
       retval = bfd_get_32 (abfd, buf);
-      *bytes_read = 4;
       break;
     case 8:
       retval = bfd_get_64 (abfd, buf);
-      *bytes_read = 8;
       break;
     default:
       internal_error (__FILE__, __LINE__,
-                     _("read_offset: bad switch [in module %s]"),
+                     _("read_offset_1: bad switch [in module %s]"),
                      bfd_get_filename (abfd));
     }
 
@@ -6566,8 +6591,7 @@ read_indirect_string (bfd *abfd, gdb_byte *buf,
                      const struct comp_unit_head *cu_header,
                      unsigned int *bytes_read_ptr)
 {
-  LONGEST str_offset = read_offset (abfd, buf, cu_header,
-                                   bytes_read_ptr);
+  LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
 
   if (dwarf2_per_objfile->str_buffer == NULL)
     {
@@ -6866,7 +6890,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   struct cleanup *back_to;
   struct line_header *lh;
   gdb_byte *line_ptr;
-  unsigned int bytes_read;
+  unsigned int bytes_read, offset_size;
   int i;
   char *cur_dir, *cur_file;
 
@@ -6893,7 +6917,8 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
 
   /* Read in the header.  */
   lh->total_length = 
-    read_initial_length (abfd, line_ptr, &cu->header, &bytes_read);
+    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))
@@ -6904,8 +6929,8 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   lh->statement_program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  lh->header_length = read_offset (abfd, line_ptr, &cu->header, &bytes_read);
-  line_ptr += bytes_read;
+  lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
+  line_ptr += offset_size;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   lh->default_is_stmt = read_1_byte (abfd, line_ptr);
@@ -7075,6 +7100,11 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
        {
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
+          if (line_ptr > line_end)
+            {
+              dwarf2_debug_line_missing_end_sequence_complaint ();
+              break;
+            }
 
          if (op_code >= lh->opcode_base)
            {           
@@ -7083,7 +7113,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
              address += (adj_opcode / lh->line_range)
                * lh->minimum_instruction_length;
              line += lh->line_base + (adj_opcode % lh->line_range);
-             if (lh->num_file_names < file)
+             if (lh->num_file_names < file || file == 0)
                dwarf2_debug_line_missing_file_complaint ();
              else
                {
@@ -7115,15 +7145,6 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
                {
                case DW_LNE_end_sequence:
                  end_sequence = 1;
-
-                 if (lh->num_file_names < file)
-                   dwarf2_debug_line_missing_file_complaint ();
-                 else
-                   {
-                     lh->file_names[file - 1].included_p = 1;
-                     if (!decode_for_pst_p)
-                       record_line (current_subfile, 0, address);
-                   }
                  break;
                case DW_LNE_set_address:
                  address = read_address (abfd, line_ptr, cu, &bytes_read);
@@ -7165,7 +7186,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
                }
              break;
            case DW_LNS_copy:
-             if (lh->num_file_names < file)
+             if (lh->num_file_names < file || file == 0)
                dwarf2_debug_line_missing_file_complaint ();
              else
                {
@@ -7203,7 +7224,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
 
                 file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                 line_ptr += bytes_read;
-                if (lh->num_file_names < file)
+                if (lh->num_file_names < file || file == 0)
                   dwarf2_debug_line_missing_file_complaint ();
                 else
                   {
@@ -7254,6 +7275,14 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
              }
            }
        }
+      if (lh->num_file_names < file || file == 0)
+        dwarf2_debug_line_missing_file_complaint ();
+      else
+        {
+          lh->file_names[file - 1].included_p = 1;
+          if (!decode_for_pst_p)
+            record_line (current_subfile, 0, address);
+        }
     }
 
   if (decode_for_pst_p)
@@ -8064,19 +8093,17 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
   else
     sep = "::";
 
+  if (prefix == NULL)
+    prefix = "";
+  if (suffix == NULL)
+    suffix = "";
+
   if (obs == NULL)
     {
       char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1);
-      retval[0] = '\0';
-      
-      if (prefix)
-       {
-         strcpy (retval, prefix);
-         strcat (retval, sep);
-       }
-      if (suffix)
-       strcat (retval, suffix);
-      
+      strcpy (retval, prefix);
+      strcat (retval, sep);
+      strcat (retval, suffix);
       return retval;
     }
   else
@@ -8477,10 +8504,11 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_pure";
     case DW_AT_recursive:
       return "DW_AT_recursive";
-#ifdef MIPS
     /* SGI/MIPS extensions.  */
+#ifdef MIPS /* collides with DW_AT_HP_block_index */
     case DW_AT_MIPS_fde:
       return "DW_AT_MIPS_fde";
+#endif
     case DW_AT_MIPS_loop_begin:
       return "DW_AT_MIPS_loop_begin";
     case DW_AT_MIPS_tail_loop_begin:
@@ -8501,10 +8529,11 @@ dwarf_attr_name (unsigned attr)
       return "DW_AT_MIPS_clone_origin";
     case DW_AT_MIPS_has_inlines:
       return "DW_AT_MIPS_has_inlines";
-#endif
     /* HP extensions.  */
+#ifndef MIPS /* collides with DW_AT_MIPS_fde */
     case DW_AT_HP_block_index:
       return "DW_AT_HP_block_index";
+#endif
     case DW_AT_HP_unmodifiable:
       return "DW_AT_HP_unmodifiable";
     case DW_AT_HP_actuals_stmt_list:
@@ -9241,7 +9270,7 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
 }
 
 static unsigned int
-dwarf2_get_ref_die_offset (struct attribute *attr, struct dwarf2_cu *cu)
+dwarf2_get_ref_die_offset (struct attribute *attr)
 {
   unsigned int result = 0;
 
@@ -9321,7 +9350,7 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
 
-  offset = dwarf2_get_ref_die_offset (attr, cu);
+  offset = dwarf2_get_ref_die_offset (attr);
 
   if (! offset_in_cu_p (&cu->header, offset))
     {
@@ -10162,7 +10191,7 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
    DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (unsigned long offset,
+dwarf2_find_containing_comp_unit (unsigned int offset,
                                  struct objfile *objfile)
 {
   struct dwarf2_per_cu_data *this_cu;
@@ -10194,7 +10223,7 @@ dwarf2_find_containing_comp_unit (unsigned long offset,
       this_cu = dwarf2_per_objfile->all_comp_units[low];
       if (low == dwarf2_per_objfile->n_comp_units - 1
          && offset >= this_cu->offset + this_cu->length)
-       error (_("invalid dwarf2 offset %ld"), offset);
+       error (_("invalid dwarf2 offset %u"), offset);
       gdb_assert (offset < this_cu->offset + this_cu->length);
       return this_cu;
     }
@@ -10204,12 +10233,12 @@ dwarf2_find_containing_comp_unit (unsigned long offset,
    OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
-dwarf2_find_comp_unit (unsigned long offset, struct objfile *objfile)
+dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile)
 {
   struct dwarf2_per_cu_data *this_cu;
   this_cu = dwarf2_find_containing_comp_unit (offset, objfile);
   if (this_cu->offset != offset)
-    error (_("no compilation unit with offset %ld."), offset);
+    error (_("no compilation unit with offset %u."), offset);
   return this_cu;
 }
 
This page took 0.035524 seconds and 4 git commands to generate.