bfd: constify a few arrays
[deliverable/binutils-gdb.git] / bfd / dwarf2.c
index 365758a2c498ca8848364f29f2a5c121ba4cbd4f..02e69a8672887426d4414e911b11cfb683f268e3 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 support.
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
    (gavin@cygnus.com).
@@ -17,7 +17,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or (at
+   the Free Software Foundation; either version 3 of the License, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libiberty.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
-#include "elf/dwarf2.h"
+#include "dwarf2.h"
 
 /* The data in the .debug_line statement prologue looks like this.  */
 
@@ -44,6 +45,7 @@ struct line_head
   unsigned short version;
   bfd_vma prologue_length;
   unsigned char minimum_instruction_length;
+  unsigned char maximum_ops_per_insn;
   unsigned char default_is_stmt;
   int line_base;
   unsigned char line_range;
@@ -74,11 +76,20 @@ struct dwarf_block
   bfd_byte *data;
 };
 
+struct adjusted_section
+{
+  asection *section;
+  bfd_vma adj_vma;
+};
+
 struct dwarf2_debug
 {
   /* A list of all previously read comp_units.  */
   struct comp_unit *all_comp_units;
 
+  /* Last comp unit in list above.  */
+  struct comp_unit *last_comp_unit;
+
   /* The next unread compilation unit within the .debug_info section.
      Zero indicates that the .debug_info section has not been loaded
      into a buffer yet.  */
@@ -87,11 +98,19 @@ struct dwarf2_debug
   /* Pointer to the end of the .debug_info section memory buffer.  */
   bfd_byte *info_ptr_end;
 
-  /* Pointer to the section and address of the beginning of the
-     section.  */
+  /* Pointer to the bfd, section and address of the beginning of the
+     section.  The bfd might be different than expected because of
+     gnu_debuglink sections.  */
+  bfd *bfd_ptr;
   asection *sec;
   bfd_byte *sec_info_ptr;
 
+  /* A pointer to the memory block allocated for info_ptr.  Neither
+     info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
+     beginning of the malloc block.  This is used only to free the
+     memory later.  */
+  bfd_byte *info_ptr_memory;
+
   /* Pointer to the symbol table.  */
   asymbol **syms;
 
@@ -99,25 +118,58 @@ struct dwarf2_debug
   bfd_byte *dwarf_abbrev_buffer;
 
   /* Length of the loaded .debug_abbrev section.  */
-  unsigned long dwarf_abbrev_size;
+  bfd_size_type dwarf_abbrev_size;
 
   /* Buffer for decode_line_info.  */
   bfd_byte *dwarf_line_buffer;
 
   /* Length of the loaded .debug_line section.  */
-  unsigned long dwarf_line_size;
+  bfd_size_type dwarf_line_size;
 
   /* Pointer to the .debug_str section loaded into memory.  */
   bfd_byte *dwarf_str_buffer;
 
   /* Length of the loaded .debug_str section.  */
-  unsigned long dwarf_str_size;
+  bfd_size_type dwarf_str_size;
 
   /* Pointer to the .debug_ranges section loaded into memory. */
   bfd_byte *dwarf_ranges_buffer;
 
   /* Length of the loaded .debug_ranges section. */
-  unsigned long dwarf_ranges_size;
+  bfd_size_type dwarf_ranges_size;
+
+  /* If the most recent call to bfd_find_nearest_line was given an
+     address in an inlined function, preserve a pointer into the
+     calling chain for subsequent calls to bfd_find_inliner_info to
+     use. */
+  struct funcinfo *inliner_chain;
+
+  /* Number of sections whose VMA we must adjust.  */
+  unsigned int adjusted_section_count;
+
+  /* Array of sections with adjusted VMA.  */
+  struct adjusted_section *adjusted_sections;
+
+  /* Number of times find_line is called.  This is used in
+     the heuristic for enabling the info hash tables.  */
+  int info_hash_count;
+
+#define STASH_INFO_HASH_TRIGGER    100
+
+  /* Hash table mapping symbol names to function infos.  */
+  struct info_hash_table *funcinfo_hash_table;
+
+  /* Hash table mapping symbol names to variable infos.  */
+  struct info_hash_table *varinfo_hash_table;
+
+  /* Head of comp_unit list in the last hash table update.  */
+  struct comp_unit *hash_units_head;
+
+  /* Status of info hash.  */
+  int info_hash_status;
+#define STASH_INFO_HASH_OFF        0
+#define STASH_INFO_HASH_ON         1
+#define STASH_INFO_HASH_DISABLED   2
 };
 
 struct arange
@@ -135,7 +187,11 @@ struct comp_unit
   /* Chain the previously read compilation units.  */
   struct comp_unit *next_unit;
 
-  /* Keep the bdf convenient (for memory allocation).  */
+  /* Likewise, chain the compilation unit read after this one.
+     The comp units are stored in reversed reading order.  */
+  struct comp_unit *prev_unit;
+
+  /* Keep the bfd convenient (for memory allocation).  */
   bfd *abfd;
 
   /* The lowest and highest addresses contained in this compilation
@@ -161,6 +217,9 @@ struct comp_unit
      by its reference.  */
   bfd_byte *info_ptr_unit;
 
+  /* Pointer to the start of the debug section, for DW_FORM_ref_addr.  */
+  bfd_byte *sec_info_ptr;
+
   /* The offset into .debug_line of the line number table.  */
   unsigned long line_offset;
 
@@ -176,9 +235,15 @@ struct comp_unit
   /* A list of the functions found in this comp. unit.  */
   struct funcinfo *function_table;
 
+  /* A list of the variables found in this comp. unit.  */
+  struct varinfo *variable_table;
+
   /* Pointer to dwarf2_debug structure.  */
   struct dwarf2_debug *stash;
 
+  /* DWARF format version for this unit - from unit header.  */
+  int version;
+
   /* Address size for this unit - from unit header.  */
   unsigned char addr_size;
 
@@ -188,6 +253,9 @@ struct comp_unit
   /* Base address for this unit - from DW_AT_low_pc attribute of
      DW_TAG_compile_unit DIE */
   bfd_vma base_address;
+
+  /* TRUE if symbols are cached in hash table for faster lookup by name.  */
+  bfd_boolean cached;
 };
 
 /* This data structure holds the information of an abbrev.  */
@@ -207,6 +275,60 @@ struct attr_abbrev
   enum dwarf_form form;
 };
 
+/* Map of uncompressed DWARF debug section name to compressed one.  It
+   is terminated by NULL uncompressed_name.  */
+
+const struct dwarf_debug_section dwarf_debug_sections[] =
+{
+  { ".debug_abbrev",           ".zdebug_abbrev" },
+  { ".debug_aranges",          ".zdebug_aranges" },
+  { ".debug_frame",            ".zdebug_frame" },
+  { ".debug_info",             ".zdebug_info" },
+  { ".debug_line",             ".zdebug_line" },
+  { ".debug_loc",              ".zdebug_loc" },
+  { ".debug_macinfo",          ".zdebug_macinfo" },
+  { ".debug_pubnames",         ".zdebug_pubnames" },
+  { ".debug_pubtypes",         ".zdebug_pubtypes" },
+  { ".debug_ranges",           ".zdebug_ranges" },
+  { ".debug_static_func",      ".zdebug_static_func" },
+  { ".debug_static_vars",      ".zdebug_static_vars" },
+  { ".debug_str",              ".zdebug_str", },
+  { ".debug_types",            ".zdebug_types" },
+  /* GNU DWARF 1 extensions */
+  { ".debug_sfnames",          ".zdebug_sfnames" },
+  { ".debug_srcinfo",          ".zebug_srcinfo" },
+  /* SGI/MIPS DWARF 2 extensions */
+  { ".debug_funcnames",                ".zdebug_funcnames" },
+  { ".debug_typenames",                ".zdebug_typenames" },
+  { ".debug_varnames",         ".zdebug_varnames" },
+  { ".debug_weaknames",                ".zdebug_weaknames" },
+  { NULL,                      NULL },
+};
+
+enum dwarf_debug_section_enum
+{
+  debug_abbrev = 0,
+  debug_aranges,
+  debug_frame,
+  debug_info,
+  debug_line,
+  debug_loc,
+  debug_macinfo,
+  debug_pubnames,
+  debug_pubtypes,
+  debug_ranges,
+  debug_static_func,
+  debug_static_vars,
+  debug_str,
+  debug_types,
+  debug_sfnames,
+  debug_srcinfo,
+  debug_funcnames,
+  debug_typenames,
+  debug_varnames,
+  debug_weaknames
+};
+
 #ifndef ABBREV_HASH_SIZE
 #define ABBREV_HASH_SIZE 121
 #endif
@@ -214,6 +336,194 @@ struct attr_abbrev
 #define ATTR_ALLOC_CHUNK 4
 #endif
 
+/* Variable and function hash tables.  This is used to speed up look-up
+   in lookup_symbol_in_var_table() and lookup_symbol_in_function_table().
+   In order to share code between variable and function infos, we use
+   a list of untyped pointer for all variable/function info associated with
+   a symbol.  We waste a bit of memory for list with one node but that
+   simplifies the code.  */
+
+struct info_list_node
+{
+  struct info_list_node *next;
+  void *info;
+};
+
+/* Info hash entry.  */
+struct info_hash_entry
+{
+  struct bfd_hash_entry root;
+  struct info_list_node *head;
+};
+
+struct info_hash_table
+{
+  struct bfd_hash_table base;
+};
+
+/* Function to create a new entry in info hash table. */
+
+static struct bfd_hash_entry *
+info_hash_table_newfunc (struct bfd_hash_entry *entry,
+                        struct bfd_hash_table *table,
+                        const char *string)
+{
+  struct info_hash_entry *ret = (struct info_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     derived class.  */
+  if (ret == NULL)
+    {
+      ret = (struct info_hash_entry *) bfd_hash_allocate (table,
+                                                          sizeof (* ret));
+      if (ret == NULL)
+       return NULL;
+    }
+
+  /* Call the allocation method of the base class.  */
+  ret = ((struct info_hash_entry *)
+        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+  /* Initialize the local fields here.  */
+  if (ret)
+    ret->head = NULL;
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Function to create a new info hash table.  It returns a pointer to the
+   newly created table or NULL if there is any error.  We need abfd
+   solely for memory allocation.  */
+
+static struct info_hash_table *
+create_info_hash_table (bfd *abfd)
+{
+  struct info_hash_table *hash_table;
+
+  hash_table = (struct info_hash_table *)
+      bfd_alloc (abfd, sizeof (struct info_hash_table));
+  if (!hash_table)
+    return hash_table;
+
+  if (!bfd_hash_table_init (&hash_table->base, info_hash_table_newfunc,
+                           sizeof (struct info_hash_entry)))
+    {
+      bfd_release (abfd, hash_table);
+      return NULL;
+    }
+
+  return hash_table;
+}
+
+/* Insert an info entry into an info hash table.  We do not check of
+   duplicate entries.  Also, the caller need to guarantee that the
+   right type of info in inserted as info is passed as a void* pointer.
+   This function returns true if there is no error.  */
+
+static bfd_boolean
+insert_info_hash_table (struct info_hash_table *hash_table,
+                       const char *key,
+                       void *info,
+                       bfd_boolean copy_p)
+{
+  struct info_hash_entry *entry;
+  struct info_list_node *node;
+
+  entry = (struct info_hash_entry*) bfd_hash_lookup (&hash_table->base,
+                                                    key, TRUE, copy_p);
+  if (!entry)
+    return FALSE;
+
+  node = (struct info_list_node *) bfd_hash_allocate (&hash_table->base,
+                                                      sizeof (*node));
+  if (!node)
+    return FALSE;
+
+  node->info = info;
+  node->next = entry->head;
+  entry->head = node;
+
+  return TRUE;
+}
+
+/* Look up an info entry list from an info hash table.  Return NULL
+   if there is none. */
+
+static struct info_list_node *
+lookup_info_hash_table (struct info_hash_table *hash_table, const char *key)
+{
+  struct info_hash_entry *entry;
+
+  entry = (struct info_hash_entry*) bfd_hash_lookup (&hash_table->base, key,
+                                                    FALSE, FALSE);
+  return entry ? entry->head : NULL;
+}
+
+/* Read a section into its appropriate place in the dwarf2_debug
+   struct (indicated by SECTION_BUFFER and SECTION_SIZE).  If SYMS is
+   not NULL, use bfd_simple_get_relocated_section_contents to read the
+   section contents, otherwise use bfd_get_section_contents.  Fail if
+   the located section does not contain at least OFFSET bytes.  */
+
+static bfd_boolean
+read_section (bfd *           abfd,
+             enum dwarf_debug_section_enum sec,
+             asymbol **      syms,
+             bfd_uint64_t    offset,
+             bfd_byte **     section_buffer,
+             bfd_size_type * section_size)
+{
+  asection *msec;
+  const char *section_name = dwarf_debug_sections[sec].uncompressed_name;
+
+  /* read_section is a noop if the section has already been read.  */
+  if (!*section_buffer)
+    {
+      msec = bfd_get_section_by_name (abfd, section_name);
+      if (! msec)
+       {
+         section_name = dwarf_debug_sections[sec].compressed_name;
+         msec = bfd_get_section_by_name (abfd, section_name);
+       }
+      if (! msec)
+       {
+         (*_bfd_error_handler) (_("Dwarf Error: Can't find %s section."), section_name);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
+      *section_size = msec->rawsize ? msec->rawsize : msec->size;
+      if (syms)
+       {
+         *section_buffer
+             = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms);
+         if (! *section_buffer)
+           return FALSE;
+       }
+      else
+       {
+         *section_buffer = (bfd_byte *) bfd_malloc (*section_size);
+         if (! *section_buffer)
+           return FALSE;
+         if (! bfd_get_section_contents (abfd, msec, *section_buffer,
+                                         0, *section_size))
+           return FALSE;
+       }
+    }
+
+  /* It is possible to get a bad value for the offset into the section
+     that the client wants.  Validate it here to avoid trouble later.  */
+  if (offset != 0 && offset >= *section_size)
+    {
+      (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu) greater than or equal to %s size (%lu)."),
+                            (long) offset, section_name, *section_size);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 /* VERBATIM
    The following function up to the END VERBATIM mark are
    copied directly from dwarf2read.c.  */
@@ -255,9 +565,6 @@ read_n_bytes (bfd *abfd ATTRIBUTE_UNUSED,
              bfd_byte *buf,
              unsigned int size ATTRIBUTE_UNUSED)
 {
-  /* If the size of a host char is 8 bits, we can return a pointer
-     to the buffer, otherwise we have to copy the data to a buffer
-     allocated on the temporary obstack.  */
   return buf;
 }
 
@@ -268,6 +575,7 @@ read_string (bfd *abfd ATTRIBUTE_UNUSED,
 {
   /* Return a pointer to the embedded string.  */
   char *str = (char *) buf;
+
   if (*str == '\0')
     {
       *bytes_read_ptr = 1;
@@ -278,10 +586,12 @@ read_string (bfd *abfd ATTRIBUTE_UNUSED,
   return str;
 }
 
+/* END VERBATIM */
+
 static char *
-read_indirect_string (struct comp_unit* unit,
-                     bfd_byte *buf,
-                     unsigned int *bytes_read_ptr)
+read_indirect_string (struct comp_unit * unit,
+                     bfd_byte *         buf,
+                     unsigned int *     bytes_read_ptr)
 {
   bfd_uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
@@ -291,41 +601,12 @@ read_indirect_string (struct comp_unit* unit,
     offset = read_4_bytes (unit->abfd, buf);
   else
     offset = read_8_bytes (unit->abfd, buf);
-  *bytes_read_ptr = unit->offset_size;
-
-  if (! stash->dwarf_str_buffer)
-    {
-      asection *msec;
-      bfd *abfd = unit->abfd;
-      bfd_size_type sz;
-
-      msec = bfd_get_section_by_name (abfd, ".debug_str");
-      if (! msec)
-       {
-         (*_bfd_error_handler)
-           (_("Dwarf Error: Can't find .debug_str section."));
-         bfd_set_error (bfd_error_bad_value);
-         return NULL;
-       }
-
-      sz = msec->rawsize ? msec->rawsize : msec->size;
-      stash->dwarf_str_size = sz;
-      stash->dwarf_str_buffer = bfd_alloc (abfd, sz);
-      if (! stash->dwarf_str_buffer)
-       return NULL;
 
-      if (! bfd_get_section_contents (abfd, msec, stash->dwarf_str_buffer,
-                                     0, sz))
-       return NULL;
-    }
+  *bytes_read_ptr = unit->offset_size;
 
-  if (offset >= stash->dwarf_str_size)
-    {
-      (*_bfd_error_handler) (_("Dwarf Error: DW_FORM_strp offset (%lu) greater than or equal to .debug_str size (%lu)."),
-                            (unsigned long) offset, stash->dwarf_str_size);
-      bfd_set_error (bfd_error_bad_value);
-      return NULL;
-    }
+  if (! read_section (unit->abfd, debug_str, stash->syms, offset,
+                     &stash->dwarf_str_buffer, &stash->dwarf_str_size))
+    return NULL;
 
   str = (char *) stash->dwarf_str_buffer + offset;
   if (*str == '\0')
@@ -333,21 +614,38 @@ read_indirect_string (struct comp_unit* unit,
   return str;
 }
 
-/* END VERBATIM */
-
 static bfd_uint64_t
 read_address (struct comp_unit *unit, bfd_byte *buf)
 {
-  switch (unit->addr_size)
+  int signed_vma = get_elf_backend_data (unit->abfd)->sign_extend_vma;
+
+  if (signed_vma)
     {
-    case 8:
-      return bfd_get_64 (unit->abfd, buf);
-    case 4:
-      return bfd_get_32 (unit->abfd, buf);
-    case 2:
-      return bfd_get_16 (unit->abfd, buf);
-    default:
-      abort ();
+      switch (unit->addr_size)
+       {
+       case 8:
+         return bfd_get_signed_64 (unit->abfd, buf);
+       case 4:
+         return bfd_get_signed_32 (unit->abfd, buf);
+       case 2:
+         return bfd_get_signed_16 (unit->abfd, buf);
+       default:
+         abort ();
+       }
+    }
+  else
+    {
+      switch (unit->addr_size)
+       {
+       case 8:
+         return bfd_get_64 (unit->abfd, buf);
+       case 4:
+         return bfd_get_32 (unit->abfd, buf);
+       case 2:
+         return bfd_get_16 (unit->abfd, buf);
+       default:
+         abort ();
+       }
     }
 }
 
@@ -388,36 +686,14 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
   unsigned int abbrev_form, hash_number;
   bfd_size_type amt;
 
-  if (! stash->dwarf_abbrev_buffer)
-    {
-      asection *msec;
-
-      msec = bfd_get_section_by_name (abfd, ".debug_abbrev");
-      if (! msec)
-       {
-         (*_bfd_error_handler) (_("Dwarf Error: Can't find .debug_abbrev section."));
-         bfd_set_error (bfd_error_bad_value);
-         return 0;
-       }
-
-      stash->dwarf_abbrev_size = msec->size;
-      stash->dwarf_abbrev_buffer
-       = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
-                                                    stash->syms);
-      if (! stash->dwarf_abbrev_buffer)
-         return 0;
-    }
-
-  if (offset >= stash->dwarf_abbrev_size)
-    {
-      (*_bfd_error_handler) (_("Dwarf Error: Abbrev offset (%lu) greater than or equal to .debug_abbrev size (%lu)."),
-                            (unsigned long) offset, stash->dwarf_abbrev_size);
-      bfd_set_error (bfd_error_bad_value);
-      return 0;
-    }
+  if (! read_section (abfd, debug_abbrev, stash->syms, offset,
+                     &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
+    return NULL;
 
   amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE;
-  abbrevs = bfd_zalloc (abfd, amt);
+  abbrevs = (struct abbrev_info **) bfd_zalloc (abfd, amt);
+  if (abbrevs == NULL)
+    return NULL;
 
   abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
@@ -427,7 +703,9 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
   while (abbrev_number)
     {
       amt = sizeof (struct abbrev_info);
-      cur_abbrev = bfd_zalloc (abfd, amt);
+      cur_abbrev = (struct abbrev_info *) bfd_zalloc (abfd, amt);
+      if (cur_abbrev == NULL)
+       return NULL;
 
       /* Read in abbrev header.  */
       cur_abbrev->number = abbrev_number;
@@ -451,23 +729,23 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
 
              amt = cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK;
              amt *= sizeof (struct attr_abbrev);
-             tmp = bfd_realloc (cur_abbrev->attrs, amt);
+             tmp = (struct attr_abbrev *) bfd_realloc (cur_abbrev->attrs, amt);
              if (tmp == NULL)
-               {
-                 size_t i;
-
-                 for (i = 0; i < ABBREV_HASH_SIZE; i++)
-                   {
-                   struct abbrev_info *abbrev = abbrevs[i];
-
-                   while (abbrev)
-                     {
-                       free (abbrev->attrs);
-                       abbrev = abbrev->next;
-                     }
-                   }
-                 return NULL;
-               }
+               {
+                 size_t i;
+
+                 for (i = 0; i < ABBREV_HASH_SIZE; i++)
+                   {
+                     struct abbrev_info *abbrev = abbrevs[i];
+
+                     while (abbrev)
+                       {
+                         free (abbrev->attrs);
+                         abbrev = abbrev->next;
+                       }
+                   }
+                 return NULL;
+               }
              cur_abbrev->attrs = tmp;
            }
 
@@ -493,7 +771,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
         for the next compile unit) or if the end of the abbreviation
         table is reached.  */
       if ((unsigned int) (abbrev_ptr - stash->dwarf_abbrev_buffer)
-           >= stash->dwarf_abbrev_size)
+         >= stash->dwarf_abbrev_size)
        break;
       abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
@@ -521,15 +799,35 @@ read_attribute_value (struct attribute *attr,
 
   switch (form)
     {
-    case DW_FORM_addr:
-      /* FIXME: DWARF3 draft says DW_FORM_ref_addr is offset_size.  */
     case DW_FORM_ref_addr:
+      /* DW_FORM_ref_addr is an address in DWARF2, and an offset in
+        DWARF3.  */
+      if (unit->version == 3 || unit->version == 4)
+       {
+         if (unit->offset_size == 4)
+           attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+         else
+           attr->u.val = read_8_bytes (unit->abfd, info_ptr);
+         info_ptr += unit->offset_size;
+         break;
+       }
+      /* FALLTHROUGH */
+    case DW_FORM_addr:
       attr->u.val = read_address (unit, info_ptr);
       info_ptr += unit->addr_size;
       break;
+    case DW_FORM_sec_offset:
+      if (unit->offset_size == 4)
+       attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+      else
+       attr->u.val = read_8_bytes (unit->abfd, info_ptr);
+      info_ptr += unit->offset_size;
+      break;
     case DW_FORM_block2:
       amt = sizeof (struct dwarf_block);
-      blk = bfd_alloc (abfd, amt);
+      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+      if (blk == NULL)
+       return NULL;
       blk->size = read_2_bytes (abfd, info_ptr);
       info_ptr += 2;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -538,7 +836,9 @@ read_attribute_value (struct attribute *attr,
       break;
     case DW_FORM_block4:
       amt = sizeof (struct dwarf_block);
-      blk = bfd_alloc (abfd, amt);
+      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+      if (blk == NULL)
+       return NULL;
       blk->size = read_4_bytes (abfd, info_ptr);
       info_ptr += 4;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -565,9 +865,12 @@ read_attribute_value (struct attribute *attr,
       attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
+    case DW_FORM_exprloc:
     case DW_FORM_block:
       amt = sizeof (struct dwarf_block);
-      blk = bfd_alloc (abfd, amt);
+      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+      if (blk == NULL)
+       return NULL;
       blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -576,7 +879,9 @@ read_attribute_value (struct attribute *attr,
       break;
     case DW_FORM_block1:
       amt = sizeof (struct dwarf_block);
-      blk = bfd_alloc (abfd, amt);
+      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+      if (blk == NULL)
+       return NULL;
       blk->size = read_1_byte (abfd, info_ptr);
       info_ptr += 1;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -591,6 +896,9 @@ read_attribute_value (struct attribute *attr,
       attr->u.val = read_1_byte (abfd, info_ptr);
       info_ptr += 1;
       break;
+    case DW_FORM_flag_present:
+      attr->u.val = 1;
+      break;
     case DW_FORM_sdata:
       attr->u.sval = read_signed_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
@@ -615,6 +923,10 @@ read_attribute_value (struct attribute *attr,
       attr->u.val = read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
+    case DW_FORM_ref_sig8:
+      attr->u.val = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+      break;
     case DW_FORM_ref_udata:
       attr->u.val = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
@@ -628,6 +940,7 @@ read_attribute_value (struct attribute *attr,
       (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %u."),
                             form);
       bfd_set_error (bfd_error_bad_value);
+      return NULL;
     }
   return info_ptr;
 }
@@ -657,7 +970,8 @@ struct line_info
   char *filename;
   unsigned int line;
   unsigned int column;
-  int end_sequence;            /* End of (sequential) code sequence.  */
+  unsigned char op_index;
+  unsigned char end_sequence;          /* End of (sequential) code sequence.  */
 };
 
 struct fileinfo
@@ -668,40 +982,113 @@ struct fileinfo
   unsigned int size;
 };
 
+struct line_sequence
+{
+  bfd_vma               low_pc;
+  struct line_sequence* prev_sequence;
+  struct line_info*     last_line;  /* Largest VMA.  */
+};
+
 struct line_info_table
 {
-  bfd* abfd;
-  unsigned int num_files;
-  unsigned int num_dirs;
-  char *comp_dir;
-  char **dirs;
-  struct fileinfo* files;
-  struct line_info* last_line;  /* largest VMA */
-  struct line_info* lcl_head;   /* local head; used in 'add_line_info' */
+  bfd*                  abfd;
+  unsigned int          num_files;
+  unsigned int          num_dirs;
+  unsigned int          num_sequences;
+  char *                comp_dir;
+  char **               dirs;
+  struct fileinfo*      files;
+  struct line_sequence* sequences;
+  struct line_info*     lcl_head;   /* Local head; used in 'add_line_info'.  */
 };
 
+/* Remember some information about each function.  If the function is
+   inlined (DW_TAG_inlined_subroutine) it may have two additional
+   attributes, DW_AT_call_file and DW_AT_call_line, which specify the
+   source code location where this function was inlined. */
+
 struct funcinfo
 {
-  struct funcinfo *prev_func;
+  struct funcinfo *prev_func;          /* Pointer to previous function in list of all functions */
+  struct funcinfo *caller_func;                /* Pointer to function one scope higher */
+  char *caller_file;                   /* Source location file name where caller_func inlines this func */
+  int caller_line;                     /* Source location line number where caller_func inlines this func */
+  char *file;                          /* Source location file name */
+  int line;                            /* Source location line number */
+  int tag;
   char *name;
   struct arange arange;
+  asection *sec;                       /* Where the symbol is defined */
+};
+
+struct varinfo
+{
+  /* Pointer to previous variable in list of all variables */
+  struct varinfo *prev_var;
+  /* Source location file name */
+  char *file;
+  /* Source location line number */
+  int line;
+  int tag;
+  char *name;
+  bfd_vma addr;
+  /* Where the symbol is defined */
+  asection *sec;
+  /* Is this a stack variable? */
+  unsigned int stack: 1;
 };
 
+/* Return TRUE if NEW_LINE should sort after LINE.  */
+
+static inline bfd_boolean
+new_line_sorts_after (struct line_info *new_line, struct line_info *line)
+{
+  return (new_line->address > line->address
+         || (new_line->address == line->address
+             && (new_line->op_index > line->op_index
+                 || (new_line->op_index == line->op_index
+                     && new_line->end_sequence < line->end_sequence))));
+}
+
+
 /* Adds a new entry to the line_info list in the line_info_table, ensuring
    that the list is sorted.  Note that the line_info list is sorted from
    highest to lowest VMA (with possible duplicates); that is,
    line_info->prev_line always accesses an equal or smaller VMA.  */
 
-static void
+static bfd_boolean
 add_line_info (struct line_info_table *table,
               bfd_vma address,
+              unsigned char op_index,
               char *filename,
               unsigned int line,
               unsigned int column,
               int end_sequence)
 {
   bfd_size_type amt = sizeof (struct line_info);
-  struct line_info* info = bfd_alloc (table->abfd, amt);
+  struct line_sequence* seq = table->sequences;
+  struct line_info* info = (struct line_info *) bfd_alloc (table->abfd, amt);
+
+  if (info == NULL)
+    return FALSE;
+
+  /* Set member data of 'info'.  */
+  info->prev_line = NULL;
+  info->address = address;
+  info->op_index = op_index;
+  info->line = line;
+  info->column = column;
+  info->end_sequence = end_sequence;
+
+  if (filename && filename[0])
+    {
+      info->filename = (char *) bfd_alloc (table->abfd, strlen (filename) + 1);
+      if (info->filename == NULL)
+       return FALSE;
+      strcpy (info->filename, filename);
+    }
+  else
+    info->filename = NULL;
 
   /* Find the correct location for 'info'.  Normally we will receive
      new line_info data 1) in order and 2) with increasing VMAs.
@@ -713,75 +1100,78 @@ add_line_info (struct line_info_table *table,
        p...z a...j  (where a < j < p < z)
 
      Note: table->lcl_head is used to head an *actual* or *possible*
-     sequence within the list (such as a...j) that is not directly
+     sub-sequence within the list (such as a...j) that is not directly
      headed by table->last_line
 
      Note: we may receive duplicate entries from 'decode_line_info'.  */
 
-  while (1)
-    if (!table->last_line
-       || address >= table->last_line->address)
-      {
-       /* Normal case: add 'info' to the beginning of the list */
-       info->prev_line = table->last_line;
-       table->last_line = info;
-
-       /* lcl_head: initialize to head a *possible* sequence at the end.  */
-       if (!table->lcl_head)
-         table->lcl_head = info;
-       break;
-      }
-    else if (!table->lcl_head->prev_line
-            && table->lcl_head->address > address)
-      {
-       /* Abnormal but easy: lcl_head is 1) at the *end* of the line
-          list and 2) the head of 'info'.  */
-       info->prev_line = NULL;
-       table->lcl_head->prev_line = info;
-       break;
-      }
-    else if (table->lcl_head->prev_line
-            && table->lcl_head->address > address
-            && address >= table->lcl_head->prev_line->address)
-      {
-       /* Abnormal but easy: lcl_head is 1) in the *middle* of the line
-          list and 2) the head of 'info'.  */
-       info->prev_line = table->lcl_head->prev_line;
-       table->lcl_head->prev_line = info;
-       break;
-      }
-    else
-      {
-       /* Abnormal and hard: Neither 'last_line' nor 'lcl_head' are valid
-          heads for 'info'.  Reset 'lcl_head' and repeat.  */
-       struct line_info* li2 = table->last_line; /* always non-NULL */
-       struct line_info* li1 = li2->prev_line;
-
-       while (li1)
-         {
-           if (li2->address > address && address >= li1->address)
-             break;
-
-           li2 = li1; /* always non-NULL */
-           li1 = li1->prev_line;
-         }
-       table->lcl_head = li2;
-      }
-
-  /* Set member data of 'info'.  */
-  info->address = address;
-  info->line = line;
-  info->column = column;
-  info->end_sequence = end_sequence;
+  if (seq
+      && seq->last_line->address == address
+      && seq->last_line->op_index == op_index
+      && seq->last_line->end_sequence == end_sequence)
+    {
+      /* We only keep the last entry with the same address and end
+        sequence.  See PR ld/4986.  */
+      if (table->lcl_head == seq->last_line)
+       table->lcl_head = info;
+      info->prev_line = seq->last_line->prev_line;
+      seq->last_line = info;
+    }
+  else if (!seq || seq->last_line->end_sequence)
+    {
+      /* Start a new line sequence.  */
+      amt = sizeof (struct line_sequence);
+      seq = (struct line_sequence *) bfd_malloc (amt);
+      if (seq == NULL)
+       return FALSE;
+      seq->low_pc = address;
+      seq->prev_sequence = table->sequences;
+      seq->last_line = info;
+      table->lcl_head = info;
+      table->sequences = seq;
+      table->num_sequences++;
+    }
+  else if (new_line_sorts_after (info, seq->last_line))
+    {
+      /* Normal case: add 'info' to the beginning of the current sequence.  */
+      info->prev_line = seq->last_line;
+      seq->last_line = info;
 
-  if (filename && filename[0])
+      /* lcl_head: initialize to head a *possible* sequence at the end.  */
+      if (!table->lcl_head)
+       table->lcl_head = info;
+    }
+  else if (!new_line_sorts_after (info, table->lcl_head)
+          && (!table->lcl_head->prev_line
+              || new_line_sorts_after (info, table->lcl_head->prev_line)))
     {
-      info->filename = bfd_alloc (table->abfd, strlen (filename) + 1);
-      if (info->filename)
-       strcpy (info->filename, filename);
+      /* Abnormal but easy: lcl_head is the head of 'info'.  */
+      info->prev_line = table->lcl_head->prev_line;
+      table->lcl_head->prev_line = info;
     }
   else
-    info->filename = NULL;
+    {
+      /* Abnormal and hard: Neither 'last_line' nor 'lcl_head'
+        are valid heads for 'info'.  Reset 'lcl_head'.  */
+      struct line_info* li2 = seq->last_line; /* Always non-NULL.  */
+      struct line_info* li1 = li2->prev_line;
+
+      while (li1)
+       {
+         if (!new_line_sorts_after (info, li2)
+             && new_line_sorts_after (info, li1))
+           break;
+
+         li2 = li1; /* always non-NULL */
+         li1 = li1->prev_line;
+       }
+      table->lcl_head = li2;
+      info->prev_line = table->lcl_head->prev_line;
+      table->lcl_head->prev_line = info;
+      if (address < seq->low_pc)
+        seq->low_pc = address;
+    }
+  return TRUE;
 }
 
 /* Extract a fully qualified filename from a line info table.
@@ -795,39 +1185,63 @@ concat_filename (struct line_info_table *table, unsigned int file)
 
   if (file - 1 >= table->num_files)
     {
-      (*_bfd_error_handler)
-       (_("Dwarf Error: mangled line number section (bad file number)."));
+      /* FILE == 0 means unknown.  */
+      if (file)
+       (*_bfd_error_handler)
+         (_("Dwarf Error: mangled line number section (bad file number)."));
       return strdup ("<unknown>");
     }
 
   filename = table->files[file - 1].name;
 
-  if (! IS_ABSOLUTE_PATH (filename))
+  if (!IS_ABSOLUTE_PATH (filename))
     {
-      char *dirname = (table->files[file - 1].dir
-                      ? table->dirs[table->files[file - 1].dir - 1]
-                      : table->comp_dir);
+      char *dir_name = NULL;
+      char *subdir_name = NULL;
+      char *name;
+      size_t len;
 
-      /* Not all tools set DW_AT_comp_dir, so dirname may be unknown.
-        The best we can do is return the filename part.  */
-      if (dirname != NULL)
-       {
-         unsigned int len = strlen (dirname) + strlen (filename) + 2;
-         char * name;
+      if (table->files[file - 1].dir)
+       subdir_name = table->dirs[table->files[file - 1].dir - 1];
 
-         name = bfd_malloc (len);
-         if (name)
-           sprintf (name, "%s/%s", dirname, filename);
-         return name;
+      if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name))
+       dir_name = table->comp_dir;
+
+      if (!dir_name)
+       {
+         dir_name = subdir_name;
+         subdir_name = NULL;
        }
-    }
 
-  return strdup (filename);
-}
+      if (!dir_name)
+       return strdup (filename);
 
-static void
-arange_add (bfd *abfd, struct arange *first_arange, bfd_vma low_pc, bfd_vma high_pc)
-{
+      len = strlen (dir_name) + strlen (filename) + 2;
+
+      if (subdir_name)
+       {
+         len += strlen (subdir_name) + 1;
+         name = (char *) bfd_malloc (len);
+         if (name)
+           sprintf (name, "%s/%s/%s", dir_name, subdir_name, filename);
+       }
+      else
+       {
+         name = (char *) bfd_malloc (len);
+         if (name)
+           sprintf (name, "%s/%s", dir_name, filename);
+       }
+
+      return name;
+    }
+
+  return strdup (filename);
+}
+
+static bfd_boolean
+arange_add (bfd *abfd, struct arange *first_arange,
+           bfd_vma low_pc, bfd_vma high_pc)
+{
   struct arange *arange;
 
   /* If the first arange is empty, use it. */
@@ -835,7 +1249,7 @@ arange_add (bfd *abfd, struct arange *first_arange, bfd_vma low_pc, bfd_vma high
     {
       first_arange->low = low_pc;
       first_arange->high = high_pc;
-      return;
+      return TRUE;
     }
 
   /* Next see if we can cheaply extend an existing range.  */
@@ -845,12 +1259,12 @@ arange_add (bfd *abfd, struct arange *first_arange, bfd_vma low_pc, bfd_vma high
       if (low_pc == arange->high)
        {
          arange->high = high_pc;
-         return;
+         return TRUE;
        }
       if (high_pc == arange->low)
        {
          arange->low = low_pc;
-         return;
+         return TRUE;
        }
       arange = arange->next;
     }
@@ -858,11 +1272,111 @@ arange_add (bfd *abfd, struct arange *first_arange, bfd_vma low_pc, bfd_vma high
 
   /* Need to allocate a new arange and insert it into the arange list.
      Order isn't significant, so just insert after the first arange. */
-  arange = bfd_zalloc (abfd, sizeof (*arange));
+  arange = (struct arange *) bfd_zalloc (abfd, sizeof (*arange));
+  if (arange == NULL)
+    return FALSE;
   arange->low = low_pc;
   arange->high = high_pc;
   arange->next = first_arange->next;
   first_arange->next = arange;
+  return TRUE;
+}
+
+/* Compare function for line sequences.  */
+
+static int
+compare_sequences (const void* a, const void* b)
+{
+  const struct line_sequence* seq1 = a;
+  const struct line_sequence* seq2 = b;
+
+  /* Sort by low_pc as the primary key.  */
+  if (seq1->low_pc < seq2->low_pc)
+    return -1;
+  if (seq1->low_pc > seq2->low_pc)
+    return 1;
+
+  /* If low_pc values are equal, sort in reverse order of
+     high_pc, so that the largest region comes first.  */
+  if (seq1->last_line->address < seq2->last_line->address)
+    return 1;
+  if (seq1->last_line->address > seq2->last_line->address)
+    return -1;
+
+  if (seq1->last_line->op_index < seq2->last_line->op_index)
+    return 1;
+  if (seq1->last_line->op_index > seq2->last_line->op_index)
+    return -1;
+
+  return 0;
+}
+
+/* Sort the line sequences for quick lookup.  */
+
+static bfd_boolean
+sort_line_sequences (struct line_info_table* table)
+{
+  bfd_size_type amt;
+  struct line_sequence* sequences;
+  struct line_sequence* seq;
+  unsigned int n = 0;
+  unsigned int num_sequences = table->num_sequences;
+  bfd_vma last_high_pc;
+
+  if (num_sequences == 0)
+    return TRUE;
+
+  /* Allocate space for an array of sequences.  */
+  amt = sizeof (struct line_sequence) * num_sequences;
+  sequences = (struct line_sequence *) bfd_alloc (table->abfd, amt);
+  if (sequences == NULL)
+    return FALSE;
+
+  /* Copy the linked list into the array, freeing the original nodes.  */
+  seq = table->sequences;
+  for (n = 0; n < num_sequences; n++)
+    {
+      struct line_sequence* last_seq = seq;
+
+      BFD_ASSERT (seq);
+      sequences[n].low_pc = seq->low_pc;
+      sequences[n].prev_sequence = NULL;
+      sequences[n].last_line = seq->last_line;
+      seq = seq->prev_sequence;
+      free (last_seq);
+    }
+  BFD_ASSERT (seq == NULL);
+
+  qsort (sequences, n, sizeof (struct line_sequence), compare_sequences);
+
+  /* Make the list binary-searchable by trimming overlapping entries
+     and removing nested entries.  */
+  num_sequences = 1;
+  last_high_pc = sequences[0].last_line->address;
+  for (n = 1; n < table->num_sequences; n++)
+    {
+      if (sequences[n].low_pc < last_high_pc)
+        {
+         if (sequences[n].last_line->address <= last_high_pc)
+           /* Skip nested entries.  */
+           continue;
+
+         /* Trim overlapping entries.  */
+         sequences[n].low_pc = last_high_pc;
+        }
+      last_high_pc = sequences[n].last_line->address;
+      if (n > num_sequences)
+        {
+          /* Close up the gap.  */
+          sequences[num_sequences].low_pc = sequences[n].low_pc;
+          sequences[num_sequences].last_line = sequences[n].last_line;
+        }
+      num_sequences++;
+    }
+
+  table->sequences = sequences;
+  table->num_sequences = num_sequences;
+  return TRUE;
 }
 
 /* Decode the line number information for UNIT.  */
@@ -880,38 +1394,14 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   unsigned char op_code, extended_op, adj_opcode;
   bfd_size_type amt;
 
-  if (! stash->dwarf_line_buffer)
-    {
-      asection *msec;
-
-      msec = bfd_get_section_by_name (abfd, ".debug_line");
-      if (! msec)
-       {
-         (*_bfd_error_handler) (_("Dwarf Error: Can't find .debug_line section."));
-         bfd_set_error (bfd_error_bad_value);
-         return 0;
-       }
-
-      stash->dwarf_line_size = msec->size;
-      stash->dwarf_line_buffer
-       = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
-                                                    stash->syms);
-      if (! stash->dwarf_line_buffer)
-       return 0;
-    }
-
-  /* It is possible to get a bad value for the line_offset.  Validate
-     it here so that we won't get a segfault below.  */
-  if (unit->line_offset >= stash->dwarf_line_size)
-    {
-      (*_bfd_error_handler) (_("Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)."),
-                            unit->line_offset, stash->dwarf_line_size);
-      bfd_set_error (bfd_error_bad_value);
-      return 0;
-    }
+  if (! read_section (abfd, debug_line, stash->syms, unit->line_offset,
+                     &stash->dwarf_line_buffer, &stash->dwarf_line_size))
+    return NULL;
 
   amt = sizeof (struct line_info_table);
-  table = bfd_alloc (abfd, amt);
+  table = (struct line_info_table *) bfd_alloc (abfd, amt);
+  if (table == NULL)
+    return NULL;
   table->abfd = abfd;
   table->comp_dir = unit->comp_dir;
 
@@ -921,8 +1411,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   table->num_dirs = 0;
   table->dirs = NULL;
 
-  table->files = NULL;
-  table->last_line = NULL;
+  table->num_sequences = 0;
+  table->sequences = NULL;
+
   table->lcl_head = NULL;
 
   line_ptr = stash->dwarf_line_buffer + unit->line_offset;
@@ -946,6 +1437,13 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
     }
   line_end = line_ptr + lh.total_length;
   lh.version = read_2_bytes (abfd, line_ptr);
+  if (lh.version < 2 || lh.version > 4)
+    {
+      (*_bfd_error_handler)
+       (_("Dwarf Error: Unhandled .debug_line version %d."), lh.version);
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
   line_ptr += 2;
   if (offset_size == 4)
     lh.prologue_length = read_4_bytes (abfd, line_ptr);
@@ -954,6 +1452,20 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   line_ptr += offset_size;
   lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
+  if (lh.version >= 4)
+    {
+      lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+    }
+  else
+    lh.maximum_ops_per_insn = 1;
+  if (lh.maximum_ops_per_insn == 0)
+    {
+      (*_bfd_error_handler)
+       (_("Dwarf Error: Invalid maximum operations per instruction."));
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
   lh.default_is_stmt = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   lh.line_base = read_1_signed_byte (abfd, line_ptr);
@@ -963,7 +1475,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   lh.opcode_base = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   amt = lh.opcode_base * sizeof (unsigned char);
-  lh.standard_opcode_lengths = bfd_alloc (abfd, amt);
+  lh.standard_opcode_lengths = (unsigned char *) bfd_alloc (abfd, amt);
 
   lh.standard_opcode_lengths[0] = 1;
 
@@ -985,12 +1497,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
          amt = table->num_dirs + DIR_ALLOC_CHUNK;
          amt *= sizeof (char *);
 
-         tmp = bfd_realloc (table->dirs, amt);
+         tmp = (char **) bfd_realloc (table->dirs, amt);
          if (tmp == NULL)
-           {
-             free (table->dirs);
-             return NULL;
-           }
+           goto fail;
          table->dirs = tmp;
        }
 
@@ -1011,13 +1520,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
          amt = table->num_files + FILE_ALLOC_CHUNK;
          amt *= sizeof (struct fileinfo);
 
-         tmp = bfd_realloc (table->files, amt);
+         tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
          if (tmp == NULL)
-           {
-             free (table->files);
-             free (table->dirs);
-             return NULL;
-           }
+           goto fail;
          table->files = tmp;
        }
 
@@ -1041,18 +1546,18 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
     {
       /* State machine registers.  */
       bfd_vma address = 0;
+      unsigned char op_index = 0;
       char * filename = table->num_files ? concat_filename (table, 1) : NULL;
       unsigned int line = 1;
       unsigned int column = 0;
       int is_stmt = lh.default_is_stmt;
-      int basic_block = 0;
       int end_sequence = 0;
       /* eraxxon@alumni.rice.edu: Against the DWARF2 specs, some
         compilers generate address sequences that are wildly out of
         order using DW_LNE_set_address (e.g. Intel C++ 6.0 compiler
         for ia64-Linux).  Thus, to determine the low and high
         address, we must compare on every DW_LNS_copy, etc.  */
-      bfd_vma low_pc  = 0;
+      bfd_vma low_pc  = (bfd_vma) -1;
       bfd_vma high_pc = 0;
 
       /* Decode the table.  */
@@ -1065,13 +1570,23 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
            {
              /* Special operand.  */
              adj_opcode = op_code - lh.opcode_base;
-             address += (adj_opcode / lh.line_range)
-               * lh.minimum_instruction_length;
+             if (lh.maximum_ops_per_insn == 1)
+               address += (adj_opcode / lh.line_range)
+                          * lh.minimum_instruction_length;
+             else
+               {
+                 address += ((op_index + (adj_opcode / lh.line_range))
+                             / lh.maximum_ops_per_insn)
+                            * lh.minimum_instruction_length;
+                 op_index = (op_index + (adj_opcode / lh.line_range))
+                            % lh.maximum_ops_per_insn;
+               }
              line += lh.line_base + (adj_opcode % lh.line_range);
              /* Append row to matrix using current values.  */
-             add_line_info (table, address, filename, line, column, 0);
-             basic_block = 1;
-             if (low_pc == 0 || address < low_pc)
+             if (!add_line_info (table, address, op_index, filename,
+                                 line, column, 0))
+               goto line_fail;
+             if (address < low_pc)
                low_pc = address;
              if (address > high_pc)
                high_pc = address;
@@ -1088,16 +1603,19 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                {
                case DW_LNE_end_sequence:
                  end_sequence = 1;
-                 add_line_info (table, address, filename, line, column,
-                                end_sequence);
-                 if (low_pc == 0 || address < low_pc)
+                 if (!add_line_info (table, address, op_index, filename,
+                                     line, column, end_sequence))
+                   goto line_fail;
+                 if (address < low_pc)
                    low_pc = address;
                  if (address > high_pc)
                    high_pc = address;
-                 arange_add (unit->abfd, &unit->arange, low_pc, high_pc);
+                 if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc))
+                   goto line_fail;
                  break;
                case DW_LNE_set_address:
                  address = read_address (unit, line_ptr);
+                 op_index = 0;
                  line_ptr += unit->addr_size;
                  break;
                case DW_LNE_define_file:
@@ -1109,14 +1627,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 
                      amt = table->num_files + FILE_ALLOC_CHUNK;
                      amt *= sizeof (struct fileinfo);
-                     tmp = bfd_realloc (table->files, amt);
+                     tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
                      if (tmp == NULL)
-                       {
-                         free (table->files);
-                         free (table->dirs);
-                         free (filename);
-                         return NULL;
-                       }
+                       goto line_fail;
                      table->files = tmp;
                    }
                  table->files[table->num_files].name = cur_file;
@@ -1131,26 +1644,41 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                  line_ptr += bytes_read;
                  table->num_files++;
                  break;
+               case DW_LNE_set_discriminator:
+                 (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+                 break;
                default:
                  (*_bfd_error_handler) (_("Dwarf Error: mangled line number section."));
                  bfd_set_error (bfd_error_bad_value);
-                 free (filename);
-                 free (table->files);
-                 free (table->dirs);
-                 return NULL;
+               line_fail:
+                 if (filename != NULL)
+                   free (filename);
+                 goto fail;
                }
              break;
            case DW_LNS_copy:
-             add_line_info (table, address, filename, line, column, 0);
-             basic_block = 0;
-             if (low_pc == 0 || address < low_pc)
+             if (!add_line_info (table, address, op_index,
+                                 filename, line, column, 0))
+               goto line_fail;
+             if (address < low_pc)
                low_pc = address;
              if (address > high_pc)
                high_pc = address;
              break;
            case DW_LNS_advance_pc:
-             address += lh.minimum_instruction_length
-               * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             if (lh.maximum_ops_per_insn == 1)
+               address += lh.minimum_instruction_length
+                          * read_unsigned_leb128 (abfd, line_ptr,
+                                                  &bytes_read);
+             else
+               {
+                 bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr,
+                                                        &bytes_read);
+                 address = ((op_index + adjust) / lh.maximum_ops_per_insn)
+                           * lh.minimum_instruction_length;
+                 op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
+               }
              line_ptr += bytes_read;
              break;
            case DW_LNS_advance_line:
@@ -1178,27 +1706,32 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
              is_stmt = (!is_stmt);
              break;
            case DW_LNS_set_basic_block:
-             basic_block = 1;
              break;
            case DW_LNS_const_add_pc:
-             address += lh.minimum_instruction_length
-                     * ((255 - lh.opcode_base) / lh.line_range);
+             if (lh.maximum_ops_per_insn == 1)
+               address += lh.minimum_instruction_length
+                          * ((255 - lh.opcode_base) / lh.line_range);
+             else
+               {
+                 bfd_vma adjust = ((255 - lh.opcode_base) / lh.line_range);
+                 address += lh.minimum_instruction_length
+                            * ((op_index + adjust) / lh.maximum_ops_per_insn);
+                 op_index = (op_index + adjust) % lh.maximum_ops_per_insn;
+               }
              break;
            case DW_LNS_fixed_advance_pc:
              address += read_2_bytes (abfd, line_ptr);
+             op_index = 0;
              line_ptr += 2;
              break;
            default:
-             {
-               int i;
-
-               /* Unknown standard opcode, ignore it.  */
-               for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
-                 {
-                   (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                   line_ptr += bytes_read;
-                 }
-             }
+             /* Unknown standard opcode, ignore it.  */
+             for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
+               {
+                 (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+               }
+             break;
            }
        }
 
@@ -1206,7 +1739,17 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
        free (filename);
     }
 
-  return table;
+  if (sort_line_sequences (table))
+    return table;
+
+ fail:
+  if (table->sequences != NULL)
+    free (table->sequences);
+  if (table->files != NULL)
+    free (table->files);
+  if (table->dirs != NULL)
+    free (table->dirs);
+  return NULL;
 }
 
 /* If ADDR is within TABLE set the output parameters and return TRUE,
@@ -1216,120 +1759,58 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
 static bfd_boolean
 lookup_address_in_line_info_table (struct line_info_table *table,
                                   bfd_vma addr,
-                                  struct funcinfo *function,
                                   const char **filename_ptr,
                                   unsigned int *linenumber_ptr)
 {
-  /* Note: table->last_line should be a descendingly sorted list. */
-  struct line_info* next_line = table->last_line;
-  struct line_info* each_line = NULL;
-  *filename_ptr = NULL;
-
-  if (!next_line)
-    return FALSE;
-
-  each_line = next_line->prev_line;
-
-  /* Check for large addresses */
-  if (addr > next_line->address)
-    each_line = NULL; /* ensure we skip over the normal case */
-
-  /* Normal case: search the list; save  */
-  while (each_line && next_line)
+  struct line_sequence *seq = NULL;
+  struct line_info *each_line;
+  int low, high, mid;
+
+  /* Binary search the array of sequences.  */
+  low = 0;
+  high = table->num_sequences;
+  while (low < high)
     {
-      /* If we have an address match, save this info.  This allows us
-        to return as good as results as possible for strange debugging
-        info.  */
-      bfd_boolean addr_match = FALSE;
-      if (each_line->address <= addr && addr < next_line->address)
-       {
-         addr_match = TRUE;
-
-         /* If this line appears to span functions, and addr is in the
-            later function, return the first line of that function instead
-            of the last line of the earlier one.  This check is for GCC
-            2.95, which emits the first line number for a function late.  */
-
-         if (function != NULL)
-           {
-             bfd_vma lowest_pc;
-             struct arange *arange;
-
-             /* Find the lowest address in the function's range list */
-             lowest_pc = function->arange.low;
-             for (arange = &function->arange;
-                  arange;
-                  arange = arange->next)
-               {
-                 if (function->arange.low < lowest_pc)
-                   lowest_pc = function->arange.low;
-               }
-             /* Check for spanning function and set outgoing line info */
-             if (addr >= lowest_pc
-                 && each_line->address < lowest_pc
-                 && next_line->address > lowest_pc)
-               {
-                 *filename_ptr = next_line->filename;
-                 *linenumber_ptr = next_line->line;
-               }
-             else
-               {
-                 *filename_ptr = each_line->filename;
-                 *linenumber_ptr = each_line->line;
-               }
-           }
-       }
-
-      if (addr_match && !each_line->end_sequence)
-       return TRUE; /* we have definitely found what we want */
-
-      next_line = each_line;
-      each_line = each_line->prev_line;
+      mid = (low + high) / 2;
+      seq = &table->sequences[mid];
+      if (addr < seq->low_pc)
+       high = mid;
+      else if (addr >= seq->last_line->address)
+       low = mid + 1;
+      else
+       break;
     }
 
-  /* At this point each_line is NULL but next_line is not.  If we found
-     a candidate end-of-sequence point in the loop above, we can return
-     that (compatibility with a bug in the Intel compiler); otherwise,
-     assuming that we found the containing function for this address in
-     this compilation unit, return the first line we have a number for
-     (compatibility with GCC 2.95).  */
-  if (*filename_ptr == NULL && function != NULL)
+  if (seq && addr >= seq->low_pc && addr < seq->last_line->address)
     {
-      *filename_ptr = next_line->filename;
-      *linenumber_ptr = next_line->line;
-      return TRUE;
+      /* Note: seq->last_line should be a descendingly sorted list.  */
+      for (each_line = seq->last_line;
+           each_line;
+           each_line = each_line->prev_line)
+        if (addr >= each_line->address)
+          break;
+
+      if (each_line
+          && !(each_line->end_sequence || each_line == seq->last_line))
+        {
+          *filename_ptr = each_line->filename;
+          *linenumber_ptr = each_line->line;
+          return TRUE;
+        }
     }
 
+  *filename_ptr = NULL;
   return FALSE;
 }
 
-/* Read in the .debug_ranges section for future reference */
+/* Read in the .debug_ranges section for future reference */
 
 static bfd_boolean
 read_debug_ranges (struct comp_unit *unit)
 {
   struct dwarf2_debug *stash = unit->stash;
-  if (! stash->dwarf_ranges_buffer)
-    {
-      bfd *abfd = unit->abfd;
-      asection *msec;
-
-      msec = bfd_get_section_by_name (abfd, ".debug_ranges");
-      if (! msec)
-       {
-         (*_bfd_error_handler) (_("Dwarf Error: Can't find .debug_ranges section."));
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
-       }
-
-      stash->dwarf_ranges_size = msec->size;
-      stash->dwarf_ranges_buffer
-       = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
-                                                    stash->syms);
-      if (! stash->dwarf_ranges_buffer)
-       return FALSE;
-    }
-  return TRUE;
+  return read_section (unit->abfd, debug_ranges, stash->syms, 0,
+                      &stash->dwarf_ranges_buffer, &stash->dwarf_ranges_size);
 }
 
 /* Function table functions.  */
@@ -1340,7 +1821,7 @@ read_debug_ranges (struct comp_unit *unit)
    depending upon them being ordered in TABLE by increasing range. */
 
 static bfd_boolean
-lookup_address_in_function_table (struct funcinfo *table,
+lookup_address_in_function_table (struct comp_unit *unit,
                                  bfd_vma addr,
                                  struct funcinfo **function_ptr,
                                  const char **functionname_ptr)
@@ -1349,7 +1830,7 @@ lookup_address_in_function_table (struct funcinfo *table,
   struct funcinfo* best_fit = NULL;
   struct arange *arange;
 
-  for (each_func = table;
+  for (each_func = unit->function_table;
        each_func;
        each_func = each_func->prev_func)
     {
@@ -1378,17 +1859,114 @@ lookup_address_in_function_table (struct funcinfo *table,
     }
 }
 
+/* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
+   and LINENUMBER_PTR, and return TRUE.  */
+
+static bfd_boolean
+lookup_symbol_in_function_table (struct comp_unit *unit,
+                                asymbol *sym,
+                                bfd_vma addr,
+                                const char **filename_ptr,
+                                unsigned int *linenumber_ptr)
+{
+  struct funcinfo* each_func;
+  struct funcinfo* best_fit = NULL;
+  struct arange *arange;
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+
+  for (each_func = unit->function_table;
+       each_func;
+       each_func = each_func->prev_func)
+    {
+      for (arange = &each_func->arange;
+          arange;
+          arange = arange->next)
+       {
+         if ((!each_func->sec || each_func->sec == sec)
+             && addr >= arange->low
+             && addr < arange->high
+             && each_func->name
+             && strcmp (name, each_func->name) == 0
+             && (!best_fit
+                 || ((arange->high - arange->low)
+                     < (best_fit->arange.high - best_fit->arange.low))))
+           best_fit = each_func;
+       }
+    }
+
+  if (best_fit)
+    {
+      best_fit->sec = sec;
+      *filename_ptr = best_fit->file;
+      *linenumber_ptr = best_fit->line;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/* Variable table functions.  */
+
+/* If SYM is within variable table of UNIT, set FILENAME_PTR and
+   LINENUMBER_PTR, and return TRUE.  */
+
+static bfd_boolean
+lookup_symbol_in_variable_table (struct comp_unit *unit,
+                                asymbol *sym,
+                                bfd_vma addr,
+                                const char **filename_ptr,
+                                unsigned int *linenumber_ptr)
+{
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+  struct varinfo* each;
+
+  for (each = unit->variable_table; each; each = each->prev_var)
+    if (each->stack == 0
+       && each->file != NULL
+       && each->name != NULL
+       && each->addr == addr
+       && (!each->sec || each->sec == sec)
+       && strcmp (name, each->name) == 0)
+      break;
+
+  if (each)
+    {
+      each->sec = sec;
+      *filename_ptr = each->file;
+      *linenumber_ptr = each->line;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
 static char *
-find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
+find_abstract_instance_name (struct comp_unit *unit,
+                            struct attribute *attr_ptr)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr;
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
+  bfd_uint64_t die_ref = attr_ptr->u.val;
   struct attribute attr;
   char *name = 0;
 
-  info_ptr = unit->info_ptr_unit + die_ref;
+  /* DW_FORM_ref_addr can reference an entry in a different CU. It
+     is an offset from the .debug_info section, not the current CU.  */
+  if (attr_ptr->form == DW_FORM_ref_addr)
+    {
+      /* We only support DW_FORM_ref_addr within the same file, so
+        any relocations should be resolved already.  */
+      if (!die_ref)
+       abort ();
+
+      info_ptr = unit->sec_info_ptr + die_ref;
+    }
+  else 
+    info_ptr = unit->info_ptr_unit + die_ref;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
 
@@ -1403,16 +1981,26 @@ find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
        }
       else
        {
-         for (i = 0; i < abbrev->num_attrs && !name; ++i)
+         for (i = 0; i < abbrev->num_attrs; ++i)
            {
-             info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+             info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit,
+                                        info_ptr);
+             if (info_ptr == NULL)
+               break;
              switch (attr.name)
                {
                case DW_AT_name:
-                 name = attr.u.str;
+                 /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
+                    over DW_AT_name.  */
+                 if (name == NULL)
+                   name = attr.u.str;
                  break;
                case DW_AT_specification:
-                 name = find_abstract_instance_name (unit, attr.u.val);
+                 name = find_abstract_instance_name (unit, &attr);
+                 break;
+               case DW_AT_linkage_name:
+               case DW_AT_MIPS_linkage_name:
+                 name = attr.u.str;
                  break;
                default:
                  break;
@@ -1420,11 +2008,12 @@ find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
            }
        }
     }
-  return (name);
+  return name;
 }
 
-static void
-read_rangelist (struct comp_unit *unit, struct arange *arange, bfd_uint64_t offset)
+static bfd_boolean
+read_rangelist (struct comp_unit *unit, struct arange *arange,
+               bfd_uint64_t offset)
 {
   bfd_byte *ranges_ptr;
   bfd_vma base_address = unit->base_address;
@@ -1432,49 +2021,56 @@ read_rangelist (struct comp_unit *unit, struct arange *arange, bfd_uint64_t offs
   if (! unit->stash->dwarf_ranges_buffer)
     {
       if (! read_debug_ranges (unit))
-       return;
+       return FALSE;
     }
   ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
-    
+
   for (;;)
     {
       bfd_vma low_pc;
       bfd_vma high_pc;
 
-      if (unit->offset_size == 4)
-       {
-         low_pc = read_4_bytes (unit->abfd, ranges_ptr);
-         ranges_ptr += 4;
-         high_pc = read_4_bytes (unit->abfd, ranges_ptr);
-         ranges_ptr += 4;
-       }
-      else
-       {
-         low_pc = read_8_bytes (unit->abfd, ranges_ptr);
-         ranges_ptr += 8;
-         high_pc = read_8_bytes (unit->abfd, ranges_ptr);
-         ranges_ptr += 8;
-       }
+      low_pc = read_address (unit, ranges_ptr);
+      ranges_ptr += unit->addr_size;
+      high_pc = read_address (unit, ranges_ptr);
+      ranges_ptr += unit->addr_size;
+
       if (low_pc == 0 && high_pc == 0)
        break;
       if (low_pc == -1UL && high_pc != -1UL)
        base_address = high_pc;
       else
-         arange_add (unit->abfd, arange, base_address + low_pc, base_address + high_pc);
+       {
+         if (!arange_add (unit->abfd, arange,
+                          base_address + low_pc, base_address + high_pc))
+           return FALSE;
+       }
     }
+  return TRUE;
 }
 
 /* DWARF2 Compilation unit functions.  */
 
 /* Scan over each die in a comp. unit looking for functions to add
-   to the function table.  */
+   to the function table and variables to the variable table.  */
 
 static bfd_boolean
-scan_unit_for_functions (struct comp_unit *unit)
+scan_unit_for_symbols (struct comp_unit *unit)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
   int nesting_level = 1;
+  struct funcinfo **nested_funcs;
+  int nested_funcs_size;
+
+  /* Maintain a stack of in-scope functions and inlined functions, which we
+     can use to set the caller_func field.  */
+  nested_funcs_size = 32;
+  nested_funcs = (struct funcinfo **)
+      bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
+  if (nested_funcs == NULL)
+    return FALSE;
+  nested_funcs[nesting_level] = 0;
 
   while (nesting_level)
     {
@@ -1482,6 +2078,7 @@ scan_unit_for_functions (struct comp_unit *unit)
       struct abbrev_info *abbrev;
       struct attribute attr;
       struct funcinfo *func;
+      struct varinfo *var;
       bfd_vma low_pc = 0;
       bfd_vma high_pc = 0;
 
@@ -1497,41 +2094,88 @@ scan_unit_for_functions (struct comp_unit *unit)
       abbrev = lookup_abbrev (abbrev_number,unit->abbrevs);
       if (! abbrev)
        {
-         (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."),
-                            abbrev_number);
+         (*_bfd_error_handler)
+           (_("Dwarf Error: Could not find abbrev number %u."),
+            abbrev_number);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         goto fail;
        }
 
+      var = NULL;
       if (abbrev->tag == DW_TAG_subprogram
+         || abbrev->tag == DW_TAG_entry_point
          || abbrev->tag == DW_TAG_inlined_subroutine)
        {
          bfd_size_type amt = sizeof (struct funcinfo);
-         func = bfd_zalloc (abfd, amt);
+         func = (struct funcinfo *) bfd_zalloc (abfd, amt);
+         if (func == NULL)
+           goto fail;
+         func->tag = abbrev->tag;
          func->prev_func = unit->function_table;
          unit->function_table = func;
+         BFD_ASSERT (!unit->cached);
+
+         if (func->tag == DW_TAG_inlined_subroutine)
+           for (i = nesting_level - 1; i >= 1; i--)
+             if (nested_funcs[i])
+               {
+                 func->caller_func = nested_funcs[i];
+                 break;
+               }
+         nested_funcs[nesting_level] = func;
        }
       else
-       func = NULL;
+       {
+         func = NULL;
+         if (abbrev->tag == DW_TAG_variable)
+           {
+             bfd_size_type amt = sizeof (struct varinfo);
+             var = (struct varinfo *) bfd_zalloc (abfd, amt);
+             if (var == NULL)
+               goto fail;
+             var->tag = abbrev->tag;
+             var->stack = 1;
+             var->prev_var = unit->variable_table;
+             unit->variable_table = var;
+             BFD_ASSERT (!unit->cached);
+           }
+
+         /* No inline function in scope at this nesting level.  */
+         nested_funcs[nesting_level] = 0;
+       }
 
       for (i = 0; i < abbrev->num_attrs; ++i)
        {
          info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+         if (info_ptr == NULL)
+           goto fail;
 
          if (func)
            {
              switch (attr.name)
                {
+               case DW_AT_call_file:
+                 func->caller_file = concat_filename (unit->line_table,
+                                                      attr.u.val);
+                 break;
+
+               case DW_AT_call_line:
+                 func->caller_line = attr.u.val;
+                 break;
+
                case DW_AT_abstract_origin:
-                 func->name = find_abstract_instance_name (unit, attr.u.val);
+               case DW_AT_specification:
+                 func->name = find_abstract_instance_name (unit, &attr);
                  break;
 
                case DW_AT_name:
-                 /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
+                 /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
+                    over DW_AT_name.  */
                  if (func->name == NULL)
                    func->name = attr.u.str;
                  break;
 
+               case DW_AT_linkage_name:
                case DW_AT_MIPS_linkage_name:
                  func->name = attr.u.str;
                  break;
@@ -1545,7 +2189,73 @@ scan_unit_for_functions (struct comp_unit *unit)
                  break;
 
                case DW_AT_ranges:
-                 read_rangelist (unit, &func->arange, attr.u.val);
+                 if (!read_rangelist (unit, &func->arange, attr.u.val))
+                   goto fail;
+                 break;
+
+               case DW_AT_decl_file:
+                 func->file = concat_filename (unit->line_table,
+                                               attr.u.val);
+                 break;
+
+               case DW_AT_decl_line:
+                 func->line = attr.u.val;
+                 break;
+
+               default:
+                 break;
+               }
+           }
+         else if (var)
+           {
+             switch (attr.name)
+               {
+               case DW_AT_name:
+                 var->name = attr.u.str;
+                 break;
+
+               case DW_AT_decl_file:
+                 var->file = concat_filename (unit->line_table,
+                                              attr.u.val);
+                 break;
+
+               case DW_AT_decl_line:
+                 var->line = attr.u.val;
+                 break;
+
+               case DW_AT_external:
+                 if (attr.u.val != 0)
+                   var->stack = 0;
+                 break;
+
+               case DW_AT_location:
+                 switch (attr.form)
+                   {
+                   case DW_FORM_block:
+                   case DW_FORM_block1:
+                   case DW_FORM_block2:
+                   case DW_FORM_block4:
+                   case DW_FORM_exprloc:
+                     if (*attr.u.blk->data == DW_OP_addr)
+                       {
+                         var->stack = 0;
+
+                         /* Verify that DW_OP_addr is the only opcode in the
+                            location, in which case the block size will be 1
+                            plus the address size.  */
+                         /* ??? For TLS variables, gcc can emit
+                            DW_OP_addr <addr> DW_OP_GNU_push_tls_address
+                            which we don't handle here yet.  */
+                         if (attr.u.blk->size == unit->addr_size + 1U)
+                           var->addr = bfd_get (unit->addr_size * 8,
+                                                unit->abfd,
+                                                attr.u.blk->data + 1);
+                       }
+                     break;
+
+                   default:
+                     break;
+                   }
                  break;
 
                default:
@@ -1556,14 +2266,36 @@ scan_unit_for_functions (struct comp_unit *unit)
 
       if (func && high_pc != 0)
        {
-         arange_add (unit->abfd, &func->arange, low_pc, high_pc);
+         if (!arange_add (unit->abfd, &func->arange, low_pc, high_pc))
+           goto fail;
        }
 
       if (abbrev->has_children)
-       nesting_level++;
+       {
+         nesting_level++;
+
+         if (nesting_level >= nested_funcs_size)
+           {
+             struct funcinfo **tmp;
+
+             nested_funcs_size *= 2;
+             tmp = (struct funcinfo **)
+                 bfd_realloc (nested_funcs,
+                              (nested_funcs_size * sizeof (struct funcinfo *)));
+             if (tmp == NULL)
+               goto fail;
+             nested_funcs = tmp;
+           }
+         nested_funcs[nesting_level] = 0;
+       }
     }
 
+  free (nested_funcs);
   return TRUE;
+
+ fail:
+  free (nested_funcs);
+  return FALSE;
 }
 
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  This
@@ -1576,8 +2308,7 @@ scan_unit_for_functions (struct comp_unit *unit)
    to get to the line number information for the compilation unit.  */
 
 static struct comp_unit *
-parse_comp_unit (bfd *abfd,
-                struct dwarf2_debug *stash,
+parse_comp_unit (struct dwarf2_debug *stash,
                 bfd_vma unit_length,
                 bfd_byte *info_ptr_unit,
                 unsigned int offset_size)
@@ -1595,6 +2326,7 @@ parse_comp_unit (bfd *abfd,
   bfd_size_type amt;
   bfd_vma low_pc = 0;
   bfd_vma high_pc = 0;
+  bfd *abfd = stash->bfd_ptr;
 
   version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
@@ -1607,9 +2339,9 @@ parse_comp_unit (bfd *abfd,
   addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
 
-  if (version != 2)
+  if (version != 2 && version != 3 && version != 4)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2 information."), version);
+      (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2, 3 and 4 information."), version);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
@@ -1655,18 +2387,24 @@ parse_comp_unit (bfd *abfd,
     }
 
   amt = sizeof (struct comp_unit);
-  unit = bfd_zalloc (abfd, amt);
+  unit = (struct comp_unit *) bfd_zalloc (abfd, amt);
+  if (unit == NULL)
+    return NULL;
   unit->abfd = abfd;
+  unit->version = version;
   unit->addr_size = addr_size;
   unit->offset_size = offset_size;
   unit->abbrevs = abbrevs;
   unit->end_ptr = end_ptr;
   unit->stash = stash;
   unit->info_ptr_unit = info_ptr_unit;
+  unit->sec_info_ptr = stash->sec_info_ptr;
 
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+      if (info_ptr == NULL)
+       return NULL;
 
       /* Store the data if it is of an attribute we want to keep in a
         partial symbol table.  */
@@ -1694,7 +2432,8 @@ parse_comp_unit (bfd *abfd,
          break;
 
        case DW_AT_ranges:
-         read_rangelist (unit, &unit->arange, attr.u.val);
+         if (!read_rangelist (unit, &unit->arange, attr.u.val))
+           return NULL;
          break;
 
        case DW_AT_comp_dir:
@@ -1719,14 +2458,19 @@ parse_comp_unit (bfd *abfd,
     }
   if (high_pc != 0)
     {
-      arange_add (unit->abfd, &unit->arange, low_pc, high_pc);
+      if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc))
+       return NULL;
     }
 
   unit->first_child_die_ptr = info_ptr;
   return unit;
 }
 
-/* Return TRUE if UNIT contains the address given by ADDR.  */
+/* Return TRUE if UNIT may contain the address given by ADDR.  When
+   there are functions written entirely with inline asm statements, the
+   range info in the compilation unit header may not be correct.  We
+   need to consult the line info table to see if a compilation unit
+   really contains the given address.  */
 
 static bfd_boolean
 comp_unit_contains_address (struct comp_unit *unit, bfd_vma addr)
@@ -1788,7 +2532,7 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
        }
 
       if (unit->first_child_die_ptr < unit->end_ptr
-         && ! scan_unit_for_functions (unit))
+         && ! scan_unit_for_symbols (unit))
        {
          unit->error = 1;
          return FALSE;
@@ -1796,14 +2540,178 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
     }
 
   function = NULL;
-  func_p = lookup_address_in_function_table (unit->function_table, addr,
+  func_p = lookup_address_in_function_table (unit, addr,
                                             &function, functionname_ptr);
+  if (func_p && (function->tag == DW_TAG_inlined_subroutine))
+    stash->inliner_chain = function;
   line_p = lookup_address_in_line_info_table (unit->line_table, addr,
-                                             function, filename_ptr,
+                                             filename_ptr,
                                              linenumber_ptr);
   return line_p || func_p;
 }
 
+/* Check to see if line info is already decoded in a comp_unit.
+   If not, decode it.  Returns TRUE if no errors were encountered;
+   FALSE otherwise.  */
+
+static bfd_boolean
+comp_unit_maybe_decode_line_info (struct comp_unit *unit,
+                                 struct dwarf2_debug *stash)
+{
+  if (unit->error)
+    return FALSE;
+
+  if (! unit->line_table)
+    {
+      if (! unit->stmtlist)
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+
+      unit->line_table = decode_line_info (unit, stash);
+
+      if (! unit->line_table)
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+
+      if (unit->first_child_die_ptr < unit->end_ptr
+         && ! scan_unit_for_symbols (unit))
+       {
+         unit->error = 1;
+         return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+
+/* If UNIT contains SYM at ADDR, set the output parameters to the
+   values for the line containing SYM.  The output parameters,
+   FILENAME_PTR, and LINENUMBER_PTR, are pointers to the objects to be
+   filled in.
+
+   Return TRUE if UNIT contains SYM, and no errors were encountered;
+   FALSE otherwise.  */
+
+static bfd_boolean
+comp_unit_find_line (struct comp_unit *unit,
+                    asymbol *sym,
+                    bfd_vma addr,
+                    const char **filename_ptr,
+                    unsigned int *linenumber_ptr,
+                    struct dwarf2_debug *stash)
+{
+  if (!comp_unit_maybe_decode_line_info (unit, stash))
+    return FALSE;
+
+  if (sym->flags & BSF_FUNCTION)
+    return lookup_symbol_in_function_table (unit, sym, addr,
+                                           filename_ptr,
+                                           linenumber_ptr);
+
+  return lookup_symbol_in_variable_table (unit, sym, addr,
+                                         filename_ptr,
+                                         linenumber_ptr);
+}
+
+static struct funcinfo *
+reverse_funcinfo_list (struct funcinfo *head)
+{
+  struct funcinfo *rhead;
+  struct funcinfo *temp;
+
+  for (rhead = NULL; head; head = temp)
+    {
+      temp = head->prev_func;
+      head->prev_func = rhead;
+      rhead = head;
+    }
+  return rhead;
+}
+
+static struct varinfo *
+reverse_varinfo_list (struct varinfo *head)
+{
+  struct varinfo *rhead;
+  struct varinfo *temp;
+
+  for (rhead = NULL; head; head = temp)
+    {
+      temp = head->prev_var;
+      head->prev_var = rhead;
+      rhead = head;
+    }
+  return rhead;
+}
+
+/* Extract all interesting funcinfos and varinfos of a compilation
+   unit into hash tables for faster lookup.  Returns TRUE if no
+   errors were enountered; FALSE otherwise.  */
+
+static bfd_boolean
+comp_unit_hash_info (struct dwarf2_debug *stash,
+                    struct comp_unit *unit,
+                    struct info_hash_table *funcinfo_hash_table,
+                    struct info_hash_table *varinfo_hash_table)
+{
+  struct funcinfo* each_func;
+  struct varinfo* each_var;
+  bfd_boolean okay = TRUE;
+
+  BFD_ASSERT (stash->info_hash_status != STASH_INFO_HASH_DISABLED);
+
+  if (!comp_unit_maybe_decode_line_info (unit, stash))
+    return FALSE;
+
+  BFD_ASSERT (!unit->cached);
+
+  /* To preserve the original search order, we went to visit the function
+     infos in the reversed order of the list.  However, making the list
+     bi-directional use quite a bit of extra memory.  So we reverse
+     the list first, traverse the list in the now reversed order and
+     finally reverse the list again to get back the original order.  */
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
+  for (each_func = unit->function_table;
+       each_func && okay;
+       each_func = each_func->prev_func)
+    {
+      /* Skip nameless functions. */
+      if (each_func->name)
+       /* There is no need to copy name string into hash table as
+          name string is either in the dwarf string buffer or
+          info in the stash.  */
+       okay = insert_info_hash_table (funcinfo_hash_table, each_func->name,
+                                      (void*) each_func, FALSE);
+    }
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
+  if (!okay)
+    return FALSE;
+
+  /* We do the same for variable infos.  */
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
+  for (each_var = unit->variable_table;
+       each_var && okay;
+       each_var = each_var->prev_var)
+    {
+      /* Skip stack vars and vars with no files or names.  */
+      if (each_var->stack == 0
+         && each_var->file != NULL
+         && each_var->name != NULL)
+       /* There is no need to copy name string into hash table as
+          name string is either in the dwarf string buffer or
+          info in the stash.  */
+       okay = insert_info_hash_table (varinfo_hash_table, each_var->name,
+                                      (void*) each_var, FALSE);
+    }
+
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
+  unit->cached = TRUE;
+  return okay;
+}
+
 /* Locate a section in a BFD containing debugging info.  The search starts
    from the section after AFTER_SEC, or from the first section in the BFD if
    AFTER_SEC is NULL.  The search works by examining the names of the
@@ -1814,6 +2722,7 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
    identify and discard duplicate debugging sections for different
    compilation units.  */
 #define DWARF2_DEBUG_INFO ".debug_info"
+#define DWARF2_COMPRESSED_DEBUG_INFO ".zdebug_info"
 #define GNU_LINKONCE_INFO ".gnu.linkonce.wi."
 
 static asection *
@@ -1821,17 +2730,17 @@ find_debug_info (bfd *abfd, asection *after_sec)
 {
   asection * msec;
 
-  if (after_sec)
-    msec = after_sec->next;
-  else
-    msec = abfd->sections;
+  msec = after_sec != NULL ? after_sec->next : abfd->sections;
 
   while (msec)
     {
       if (strcmp (msec->name, DWARF2_DEBUG_INFO) == 0)
        return msec;
 
-      if (strncmp (msec->name, GNU_LINKONCE_INFO, strlen (GNU_LINKONCE_INFO)) == 0)
+      if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0)
+       return msec;
+
+      if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO))
        return msec;
 
       msec = msec->next;
@@ -1840,22 +2749,380 @@ find_debug_info (bfd *abfd, asection *after_sec)
   return NULL;
 }
 
-/* The DWARF2 version of find_nearest_line.  Return TRUE if the line
-   is found without error.  ADDR_SIZE is the number of bytes in the
-   initial .debug_info length field and in the abbreviation offset.
-   You may use zero to indicate that the default value should be
-   used.  */
+/* Unset vmas for adjusted sections in STASH.  */
 
-bfd_boolean
-_bfd_dwarf2_find_nearest_line (bfd *abfd,
-                              asection *section,
-                              asymbol **symbols,
-                              bfd_vma offset,
-                              const char **filename_ptr,
-                              const char **functionname_ptr,
-                              unsigned int *linenumber_ptr,
-                              unsigned int addr_size,
-                              void **pinfo)
+static void
+unset_sections (struct dwarf2_debug *stash)
+{
+  unsigned int i;
+  struct adjusted_section *p;
+
+  i = stash->adjusted_section_count;
+  p = stash->adjusted_sections;
+  for (; i > 0; i--, p++)
+    p->section->vma = 0;
+}
+
+/* Set unique VMAs for loadable and DWARF sections in ABFD and save
+   VMAs in STASH for unset_sections.  */
+
+static bfd_boolean
+place_sections (bfd *abfd, struct dwarf2_debug *stash)
+{
+  struct adjusted_section *p;
+  unsigned int i;
+
+  if (stash->adjusted_section_count != 0)
+    {
+      i = stash->adjusted_section_count;
+      p = stash->adjusted_sections;
+      for (; i > 0; i--, p++)
+       p->section->vma = p->adj_vma;
+    }
+  else
+    {
+      asection *sect;
+      bfd_vma last_vma = 0, last_dwarf = 0;
+      bfd_size_type amt;
+
+      i = 0;
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+       {
+         bfd_size_type sz;
+         int is_debug_info;
+
+         if (sect->vma != 0)
+           continue;
+
+         /* We need to adjust the VMAs of any .debug_info sections.
+            Skip compressed ones, since no relocations could target
+            them - they should not appear in object files anyway.  */
+         if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0)
+           is_debug_info = 1;
+         else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO))
+           is_debug_info = 1;
+         else
+           is_debug_info = 0;
+
+         if (!is_debug_info && (sect->flags & SEC_LOAD) == 0)
+           continue;
+
+         sz = sect->rawsize ? sect->rawsize : sect->size;
+         if (sz == 0)
+           continue;
+
+         i++;
+       }
+
+      amt = i * sizeof (struct adjusted_section);
+      p = (struct adjusted_section *) bfd_zalloc (abfd, amt);
+      if (! p)
+       return FALSE;
+
+      stash->adjusted_sections = p;
+      stash->adjusted_section_count = i;
+
+      for (sect = abfd->sections; sect != NULL; sect = sect->next)
+       {
+         bfd_size_type sz;
+         int is_debug_info;
+
+         if (sect->vma != 0)
+           continue;
+
+         /* We need to adjust the VMAs of any .debug_info sections.
+            Skip compressed ones, since no relocations could target
+            them - they should not appear in object files anyway.  */
+         if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0)
+           is_debug_info = 1;
+         else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO))
+           is_debug_info = 1;
+         else
+           is_debug_info = 0;
+
+         if (!is_debug_info && (sect->flags & SEC_LOAD) == 0)
+           continue;
+
+         sz = sect->rawsize ? sect->rawsize : sect->size;
+         if (sz == 0)
+           continue;
+
+         p->section = sect;
+         if (is_debug_info)
+           {
+             BFD_ASSERT (sect->alignment_power == 0);
+             sect->vma = last_dwarf;
+             last_dwarf += sz;
+           }
+         else if (last_vma != 0)
+           {
+             /* Align the new address to the current section
+                alignment.  */
+             last_vma = ((last_vma
+                          + ~((bfd_vma) -1 << sect->alignment_power))
+                         & ((bfd_vma) -1 << sect->alignment_power));
+             sect->vma = last_vma;
+             last_vma += sect->vma + sz;
+           }
+         else
+           last_vma += sect->vma + sz;
+
+         p->adj_vma = sect->vma;
+
+         p++;
+       }
+    }
+
+  return TRUE;
+}
+
+/* Look up a funcinfo by name using the given info hash table.  If found,
+   also update the locations pointed to by filename_ptr and linenumber_ptr.
+
+   This function returns TRUE if a funcinfo that matches the given symbol
+   and address is found with any error; otherwise it returns FALSE.  */
+
+static bfd_boolean
+info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
+                          asymbol *sym,
+                          bfd_vma addr,
+                          const char **filename_ptr,
+                          unsigned int *linenumber_ptr)
+{
+  struct funcinfo* each_func;
+  struct funcinfo* best_fit = NULL;
+  struct info_list_node *node;
+  struct arange *arange;
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+
+  for (node = lookup_info_hash_table (hash_table, name);
+       node;
+       node = node->next)
+    {
+      each_func = (struct funcinfo *) node->info;
+      for (arange = &each_func->arange;
+          arange;
+          arange = arange->next)
+       {
+         if ((!each_func->sec || each_func->sec == sec)
+             && addr >= arange->low
+             && addr < arange->high
+             && (!best_fit
+                 || ((arange->high - arange->low)
+                     < (best_fit->arange.high - best_fit->arange.low))))
+           best_fit = each_func;
+       }
+    }
+
+  if (best_fit)
+    {
+      best_fit->sec = sec;
+      *filename_ptr = best_fit->file;
+      *linenumber_ptr = best_fit->line;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* Look up a varinfo by name using the given info hash table.  If found,
+   also update the locations pointed to by filename_ptr and linenumber_ptr.
+
+   This function returns TRUE if a varinfo that matches the given symbol
+   and address is found with any error; otherwise it returns FALSE.  */
+
+static bfd_boolean
+info_hash_lookup_varinfo (struct info_hash_table *hash_table,
+                         asymbol *sym,
+                         bfd_vma addr,
+                         const char **filename_ptr,
+                         unsigned int *linenumber_ptr)
+{
+  const char *name = bfd_asymbol_name (sym);
+  asection *sec = bfd_get_section (sym);
+  struct varinfo* each;
+  struct info_list_node *node;
+
+  for (node = lookup_info_hash_table (hash_table, name);
+       node;
+       node = node->next)
+    {
+      each = (struct varinfo *) node->info;
+      if (each->addr == addr
+         && (!each->sec || each->sec == sec))
+       {
+         each->sec = sec;
+         *filename_ptr = each->file;
+         *linenumber_ptr = each->line;
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+/* Update the funcinfo and varinfo info hash tables if they are
+   not up to date.  Returns TRUE if there is no error; otherwise
+   returns FALSE and disable the info hash tables.  */
+
+static bfd_boolean
+stash_maybe_update_info_hash_tables (struct dwarf2_debug *stash)
+{
+  struct comp_unit *each;
+
+  /* Exit if hash tables are up-to-date.  */
+  if (stash->all_comp_units == stash->hash_units_head)
+    return TRUE;
+
+  if (stash->hash_units_head)
+    each = stash->hash_units_head->prev_unit;
+  else
+    each = stash->last_comp_unit;
+
+  while (each)
+    {
+      if (!comp_unit_hash_info (stash, each, stash->funcinfo_hash_table,
+                               stash->varinfo_hash_table))
+       {
+         stash->info_hash_status = STASH_INFO_HASH_DISABLED;
+         return FALSE;
+       }
+      each = each->prev_unit;
+    }
+
+  stash->hash_units_head = stash->all_comp_units;
+  return TRUE;
+}
+
+/* Check consistency of info hash tables.  This is for debugging only. */
+
+static void ATTRIBUTE_UNUSED
+stash_verify_info_hash_table (struct dwarf2_debug *stash)
+{
+  struct comp_unit *each_unit;
+  struct funcinfo *each_func;
+  struct varinfo *each_var;
+  struct info_list_node *node;
+  bfd_boolean found;
+
+  for (each_unit = stash->all_comp_units;
+       each_unit;
+       each_unit = each_unit->next_unit)
+    {
+      for (each_func = each_unit->function_table;
+          each_func;
+          each_func = each_func->prev_func)
+       {
+         if (!each_func->name)
+           continue;
+         node = lookup_info_hash_table (stash->funcinfo_hash_table,
+                                        each_func->name);
+         BFD_ASSERT (node);
+         found = FALSE;
+         while (node && !found)
+           {
+             found = node->info == each_func;
+             node = node->next;
+           }
+         BFD_ASSERT (found);
+       }
+
+      for (each_var = each_unit->variable_table;
+          each_var;
+          each_var = each_var->prev_var)
+       {
+         if (!each_var->name || !each_var->file || each_var->stack)
+           continue;
+         node = lookup_info_hash_table (stash->varinfo_hash_table,
+                                        each_var->name);
+         BFD_ASSERT (node);
+         found = FALSE;
+         while (node && !found)
+           {
+             found = node->info == each_var;
+             node = node->next;
+           }
+         BFD_ASSERT (found);
+       }
+    }
+}
+
+/* Check to see if we want to enable the info hash tables, which consume
+   quite a bit of memory.  Currently we only check the number times
+   bfd_dwarf2_find_line is called.  In the future, we may also want to
+   take the number of symbols into account.  */
+
+static void
+stash_maybe_enable_info_hash_tables (bfd *abfd, struct dwarf2_debug *stash)
+{
+  BFD_ASSERT (stash->info_hash_status == STASH_INFO_HASH_OFF);
+
+  if (stash->info_hash_count++ < STASH_INFO_HASH_TRIGGER)
+    return;
+
+  /* FIXME: Maybe we should check the reduce_memory_overheads
+     and optimize fields in the bfd_link_info structure ?  */
+
+  /* Create hash tables.  */
+  stash->funcinfo_hash_table = create_info_hash_table (abfd);
+  stash->varinfo_hash_table = create_info_hash_table (abfd);
+  if (!stash->funcinfo_hash_table || !stash->varinfo_hash_table)
+    {
+      /* Turn off info hashes if any allocation above fails.  */
+      stash->info_hash_status = STASH_INFO_HASH_DISABLED;
+      return;
+    }
+  /* We need a forced update so that the info hash tables will
+     be created even though there is no compilation unit.  That
+     happens if STASH_INFO_HASH_TRIGGER is 0.  */
+  stash_maybe_update_info_hash_tables (stash);
+  stash->info_hash_status = STASH_INFO_HASH_ON;
+}
+
+/* Find the file and line associated with a symbol and address using the
+   info hash tables of a stash. If there is a match, the function returns
+   TRUE and update the locations pointed to by filename_ptr and linenumber_ptr;
+   otherwise it returns FALSE.  */
+
+static bfd_boolean
+stash_find_line_fast (struct dwarf2_debug *stash,
+                     asymbol *sym,
+                     bfd_vma addr,
+                     const char **filename_ptr,
+                     unsigned int *linenumber_ptr)
+{
+  BFD_ASSERT (stash->info_hash_status == STASH_INFO_HASH_ON);
+
+  if (sym->flags & BSF_FUNCTION)
+    return info_hash_lookup_funcinfo (stash->funcinfo_hash_table, sym, addr,
+                                     filename_ptr, linenumber_ptr);
+  return info_hash_lookup_varinfo (stash->varinfo_hash_table, sym, addr,
+                                  filename_ptr, linenumber_ptr);
+}
+
+/* Find the source code location of SYMBOL.  If SYMBOL is NULL
+   then find the nearest source code location corresponding to
+   the address SECTION + OFFSET.
+   Returns TRUE if the line is found without error and fills in
+   FILENAME_PTR and LINENUMBER_PTR.  In the case where SYMBOL was
+   NULL the FUNCTIONNAME_PTR is also filled in.
+   SYMBOLS contains the symbol table for ABFD.
+   ADDR_SIZE is the number of bytes in the initial .debug_info length
+   field and in the abbreviation offset, or zero to indicate that the
+   default value should be used.  */
+
+static bfd_boolean
+find_line (bfd *abfd,
+          asection *section,
+          bfd_vma offset,
+          asymbol *symbol,
+          asymbol **symbols,
+          const char **filename_ptr,
+          const char **functionname_ptr,
+          unsigned int *linenumber_ptr,
+          unsigned int addr_size,
+          void **pinfo)
 {
   /* Read each compilation unit from the section .debug_info, and check
      to see if it contains the address we are searching for.  If yes,
@@ -1866,116 +3133,225 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
      a pointer to the next un-read compilation unit.  Check the
      previously read units before reading more.  */
   struct dwarf2_debug *stash;
-
   /* What address are we looking for?  */
   bfd_vma addr;
-
   struct comp_unit* each;
+  bfd_vma found = FALSE;
+  bfd_boolean do_line;
+
+  stash = (struct dwarf2_debug *) *pinfo;
+
+  if (! stash)
+    {
+      bfd_size_type amt = sizeof (struct dwarf2_debug);
+
+      stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt);
+      if (! stash)
+       return FALSE;
+    }
+
+  /* In a relocatable file, 2 functions may have the same address.
+     We change the section vma so that they won't overlap.  */
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    {
+      if (! place_sections (abfd, stash))
+       return FALSE;
+    }
+
+  do_line = (section == NULL
+            && offset == 0
+            && functionname_ptr == NULL
+            && symbol != NULL);
+  if (do_line)
+    {
+      addr = symbol->value;
+      section = bfd_get_section (symbol);
+    }
+  else if (section != NULL
+          && functionname_ptr != NULL
+          && symbol == NULL)
+    addr = offset;
+  else
+    abort ();
 
-  stash = *pinfo;
-  addr = offset;
   if (section->output_section)
     addr += section->output_section->vma + section->output_offset;
   else
     addr += section->vma;
   *filename_ptr = NULL;
-  *functionname_ptr = NULL;
+  if (! do_line)
+    *functionname_ptr = NULL;
   *linenumber_ptr = 0;
 
-  /* The DWARF2 spec says that the initial length field, and the
-     offset of the abbreviation table, should both be 4-byte values.
-     However, some compilers do things differently.  */
-  if (addr_size == 0)
-    addr_size = 4;
-  BFD_ASSERT (addr_size == 4 || addr_size == 8);
-
-  if (! stash)
+  if (! *pinfo)
     {
+      bfd *debug_bfd;
       bfd_size_type total_size;
       asection *msec;
-      bfd_size_type amt = sizeof (struct dwarf2_debug);
-
-      stash = bfd_zalloc (abfd, amt);
-      if (! stash)
-       return FALSE;
 
       *pinfo = stash;
 
       msec = find_debug_info (abfd, NULL);
-      if (! msec)
-       /* No dwarf2 info.  Note that at this point the stash
-          has been allocated, but contains zeros, this lets
-          future calls to this function fail quicker.  */
-        return FALSE;
-
-      /* There can be more than one DWARF2 info section in a BFD these days.
-        Read them all in and produce one large stash.  We do this in two
-        passes - in the first pass we just accumulate the section sizes.
-        In the second pass we read in the section's contents.  The allows
-        us to avoid reallocing the data as we add sections to the stash.  */
-      for (total_size = 0; msec; msec = find_debug_info (abfd, msec))
-       total_size += msec->size;
-
-      stash->info_ptr = bfd_alloc (abfd, total_size);
-      if (stash->info_ptr == NULL)
-       return FALSE;
-
-      stash->info_ptr_end = stash->info_ptr;
-
-      for (msec = find_debug_info (abfd, NULL);
-          msec;
-          msec = find_debug_info (abfd, msec))
+      if (msec == NULL)
        {
-         bfd_size_type size;
-         bfd_size_type start;
-
-         size = msec->size;
-         if (size == 0)
-           continue;
+         char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
+
+         if (debug_filename == NULL)
+           /* No dwarf2 info, and no gnu_debuglink to follow.
+              Note that at this point the stash has been allocated, but
+              contains zeros.  This lets future calls to this function
+              fail more quickly.  */
+           goto done;
+
+         if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
+             || ! bfd_check_format (debug_bfd, bfd_object)
+             || (msec = find_debug_info (debug_bfd, NULL)) == NULL)
+           {
+             if (debug_bfd)
+               bfd_close (debug_bfd);
+             /* FIXME: Should we report our failure to follow the debuglink ?  */
+             free (debug_filename);
+             goto done;
+           }
+       }
+      else
+       debug_bfd = abfd;
+
+      /* There can be more than one DWARF2 info section in a BFD these
+        days.  First handle the easy case when there's only one.  If
+        there's more than one, try case two: none of the sections is
+        compressed.  In that case, read them all in and produce one
+        large stash.  We do this in two passes - in the first pass we
+        just accumulate the section sizes, and in the second pass we
+        read in the section's contents.  (The allows us to avoid
+        reallocing the data as we add sections to the stash.)  If
+        some or all sections are compressed, then do things the slow
+        way, with a bunch of reallocs.  */
+
+      if (! find_debug_info (debug_bfd, msec))
+       {
+         /* Case 1: only one info section.  */
+         total_size = msec->size;
+         if (! read_section (debug_bfd, debug_info, symbols, 0,
+                             &stash->info_ptr_memory, &total_size))
+           goto done;
+       }
+      else
+       {
+         /* Case 2: multiple sections.  */
+         for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec))
+           total_size += msec->size;
+
+         stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
+         if (stash->info_ptr_memory == NULL)
+           goto done;
+
+         total_size = 0;
+         for (msec = find_debug_info (debug_bfd, NULL);
+              msec;
+              msec = find_debug_info (debug_bfd, msec))
+           {
+             bfd_size_type size;
 
-         start = stash->info_ptr_end - stash->info_ptr;
+             size = msec->size;
+             if (size == 0)
+               continue;
 
-         if ((bfd_simple_get_relocated_section_contents
-              (abfd, msec, stash->info_ptr + start, symbols)) == NULL)
-           continue;
+             if (!(bfd_simple_get_relocated_section_contents
+                   (debug_bfd, msec, stash->info_ptr_memory + total_size,
+                    symbols)))
+               goto done;
 
-         stash->info_ptr_end = stash->info_ptr + start + size;
+             total_size += size;
+           }
        }
 
-      BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
-
-      stash->sec = find_debug_info (abfd, NULL);
+      stash->info_ptr = stash->info_ptr_memory;
+      stash->info_ptr_end = stash->info_ptr + total_size;
+      stash->sec = find_debug_info (debug_bfd, NULL);
       stash->sec_info_ptr = stash->info_ptr;
       stash->syms = symbols;
+      stash->bfd_ptr = debug_bfd;
     }
 
   /* A null info_ptr indicates that there is no dwarf2 info
      (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
-    return FALSE;
+    goto done;
+
+  stash->inliner_chain = NULL;
 
   /* Check the previously read comp. units first.  */
-  for (each = stash->all_comp_units; each; each = each->next_unit)
-    if (comp_unit_contains_address (each, addr))
-      return comp_unit_find_nearest_line (each, addr, filename_ptr,
-                                         functionname_ptr, linenumber_ptr,
-                                         stash);
+  if (do_line)
+    {
+      /* The info hash tables use quite a bit of memory.  We may not want to
+        always use them.  We use some heuristics to decide if and when to
+        turn it on.  */
+      if (stash->info_hash_status == STASH_INFO_HASH_OFF)
+       stash_maybe_enable_info_hash_tables (abfd, stash);
+
+      /* Keep info hash table up to date if they are available.  Note that we
+        may disable the hash tables if there is any error duing update. */
+      if (stash->info_hash_status == STASH_INFO_HASH_ON)
+       stash_maybe_update_info_hash_tables (stash);
+
+      if (stash->info_hash_status == STASH_INFO_HASH_ON)
+       {
+         found = stash_find_line_fast (stash, symbol, addr, filename_ptr,
+                                       linenumber_ptr);
+         if (found)
+           goto done;
+       }
+      else
+       {
+         /* Check the previously read comp. units first.  */
+         for (each = stash->all_comp_units; each; each = each->next_unit)
+           if ((symbol->flags & BSF_FUNCTION) == 0
+               || comp_unit_contains_address (each, addr))
+             {
+               found = comp_unit_find_line (each, symbol, addr, filename_ptr,
+                                            linenumber_ptr, stash);
+               if (found)
+                 goto done;
+             }
+       }
+    }
+  else
+    {
+      for (each = stash->all_comp_units; each; each = each->next_unit)
+       {
+         found = (comp_unit_contains_address (each, addr)
+                  && comp_unit_find_nearest_line (each, addr,
+                                                  filename_ptr,
+                                                  functionname_ptr,
+                                                  linenumber_ptr,
+                                                  stash));
+         if (found)
+           goto done;
+       }
+    }
+
+  /* The DWARF2 spec says that the initial length field, and the
+     offset of the abbreviation table, should both be 4-byte values.
+     However, some compilers do things differently.  */
+  if (addr_size == 0)
+    addr_size = 4;
+  BFD_ASSERT (addr_size == 4 || addr_size == 8);
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
     {
       bfd_vma length;
-      bfd_boolean found;
       unsigned int offset_size = addr_size;
       bfd_byte *info_ptr_unit = stash->info_ptr;
 
-      length = read_4_bytes (abfd, stash->info_ptr);
-      /* A 0xffffff length is the DWARF3 way of indicating we use
-        64-bit offsets, instead of 32-bit offsets.  */
+      length = read_4_bytes (stash->bfd_ptr, stash->info_ptr);
+      /* A 0xffffff length is the DWARF3 way of indicating
+        we use 64-bit offsets, instead of 32-bit offsets.  */
       if (length == 0xffffffff)
        {
          offset_size = 8;
-         length = read_8_bytes (abfd, stash->info_ptr + 4);
+         length = read_8_bytes (stash->bfd_ptr, stash->info_ptr + 4);
          stash->info_ptr += 12;
        }
       /* A zero length is the IRIX way of indicating 64-bit offsets,
@@ -1984,63 +3360,142 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
       else if (length == 0)
        {
          offset_size = 8;
-         length = read_4_bytes (abfd, stash->info_ptr + 4);
+         length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4);
          stash->info_ptr += 8;
        }
-      /* In the absence of the hints above, we assume addr_size-sized
-        offsets, for backward-compatibility with pre-DWARF3 64-bit
-        platforms.  */
+      /* In the absence of the hints above, we assume 32-bit DWARF2
+        offsets even for targets with 64-bit addresses, because:
+          a) most of the time these targets will not have generated
+             more than 2Gb of debug info and so will not need 64-bit
+             offsets,
+        and
+          b) if they do use 64-bit offsets but they are not using
+             the size hints that are tested for above then they are
+             not conforming to the DWARF3 standard anyway.  */
       else if (addr_size == 8)
        {
-         length = read_8_bytes (abfd, stash->info_ptr);
-         stash->info_ptr += 8;
+         offset_size = 4;
+         stash->info_ptr += 4;
        }
       else
        stash->info_ptr += 4;
 
       if (length > 0)
        {
-         each = parse_comp_unit (abfd, stash, length, info_ptr_unit,
+         each = parse_comp_unit (stash, length, info_ptr_unit,
                                  offset_size);
+         if (!each)
+           /* The dwarf information is damaged, don't trust it any
+              more.  */
+           break;
          stash->info_ptr += length;
 
+         if (stash->all_comp_units)
+           stash->all_comp_units->prev_unit = each;
+         else
+           stash->last_comp_unit = each;
+         
+         each->next_unit = stash->all_comp_units;
+         stash->all_comp_units = each;
+         
+         /* DW_AT_low_pc and DW_AT_high_pc are optional for
+            compilation units.  If we don't have them (i.e.,
+            unit->high == 0), we need to consult the line info table
+            to see if a compilation unit contains the given
+            address.  */
+         if (do_line)
+           found = (((symbol->flags & BSF_FUNCTION) == 0
+                     || each->arange.high == 0
+                     || comp_unit_contains_address (each, addr))
+                    && comp_unit_find_line (each, symbol, addr,
+                                            filename_ptr,
+                                            linenumber_ptr,
+                                            stash));
+         else
+           found = ((each->arange.high == 0
+                     || comp_unit_contains_address (each, addr))
+                    && comp_unit_find_nearest_line (each, addr,
+                                                    filename_ptr,
+                                                    functionname_ptr,
+                                                    linenumber_ptr,
+                                                    stash));
+
          if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
              == stash->sec->size)
            {
-             stash->sec = find_debug_info (abfd, stash->sec);
+             stash->sec = find_debug_info (stash->bfd_ptr, stash->sec);
              stash->sec_info_ptr = stash->info_ptr;
            }
 
-         if (each)
-           {
-             each->next_unit = stash->all_comp_units;
-             stash->all_comp_units = each;
-
-             /* DW_AT_low_pc and DW_AT_high_pc are optional for
-                compilation units.  If we don't have them (i.e.,
-                unit->high == 0), we need to consult the line info
-                table to see if a compilation unit contains the given
-                address.  */
-             if (each->arange.high > 0)
-               {
-                 if (comp_unit_contains_address (each, addr))
-                   return comp_unit_find_nearest_line (each, addr,
-                                                       filename_ptr,
-                                                       functionname_ptr,
-                                                       linenumber_ptr,
-                                                       stash);
-               }
-             else
-               {
-                 found = comp_unit_find_nearest_line (each, addr,
-                                                      filename_ptr,
-                                                      functionname_ptr,
-                                                      linenumber_ptr,
-                                                      stash);
-                 if (found)
-                   return TRUE;
-               }
-           }
+         if (found)
+           goto done;
+       }
+    }
+
+done:
+  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+    unset_sections (stash);
+
+  return found;
+}
+
+/* The DWARF2 version of find_nearest_line.
+   Return TRUE if the line is found without error.  */
+
+bfd_boolean
+_bfd_dwarf2_find_nearest_line (bfd *abfd,
+                              asection *section,
+                              asymbol **symbols,
+                              bfd_vma offset,
+                              const char **filename_ptr,
+                              const char **functionname_ptr,
+                              unsigned int *linenumber_ptr,
+                              unsigned int addr_size,
+                              void **pinfo)
+{
+  return find_line (abfd, section, offset, NULL, symbols, filename_ptr,
+                   functionname_ptr, linenumber_ptr, addr_size,
+                   pinfo);
+}
+
+/* The DWARF2 version of find_line.
+   Return TRUE if the line is found without error.  */
+
+bfd_boolean
+_bfd_dwarf2_find_line (bfd *abfd,
+                      asymbol **symbols,
+                      asymbol *symbol,
+                      const char **filename_ptr,
+                      unsigned int *linenumber_ptr,
+                      unsigned int addr_size,
+                      void **pinfo)
+{
+  return find_line (abfd, NULL, 0, symbol, symbols, filename_ptr,
+                   NULL, linenumber_ptr, addr_size,
+                   pinfo);
+}
+
+bfd_boolean
+_bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
+                              const char **filename_ptr,
+                              const char **functionname_ptr,
+                              unsigned int *linenumber_ptr,
+                              void **pinfo)
+{
+  struct dwarf2_debug *stash;
+
+  stash = (struct dwarf2_debug *) *pinfo;
+  if (stash)
+    {
+      struct funcinfo *func = stash->inliner_chain;
+
+      if (func && func->caller_func)
+       {
+         *filename_ptr = func->caller_file;
+         *functionname_ptr = func->caller_func->name;
+         *linenumber_ptr = func->caller_line;
+         stash->inliner_chain = func->caller_func;
+         return TRUE;
        }
     }
 
@@ -2056,7 +3511,7 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd)
   if (abfd == NULL || elf_tdata (abfd) == NULL)
     return;
 
-  stash = elf_tdata (abfd)->dwarf2_find_line_info;
+  stash = (struct dwarf2_debug *) elf_tdata (abfd)->dwarf2_find_line_info;
 
   if (stash == NULL)
     return;
@@ -2064,27 +3519,63 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd)
   for (each = stash->all_comp_units; each; each = each->next_unit)
     {
       struct abbrev_info **abbrevs = each->abbrevs;
+      struct funcinfo *function_table = each->function_table;
+      struct varinfo *variable_table = each->variable_table;
       size_t i;
 
       for (i = 0; i < ABBREV_HASH_SIZE; i++)
-        {
-          struct abbrev_info *abbrev = abbrevs[i];
+       {
+         struct abbrev_info *abbrev = abbrevs[i];
 
-          while (abbrev)
-            {
-              free (abbrev->attrs);
-              abbrev = abbrev->next;
-            }
-        }
+         while (abbrev)
+           {
+             free (abbrev->attrs);
+             abbrev = abbrev->next;
+           }
+       }
 
       if (each->line_table)
-        {
-          free (each->line_table->dirs);
-          free (each->line_table->files);
-        }
+       {
+         free (each->line_table->dirs);
+         free (each->line_table->files);
+       }
+
+      while (function_table)
+       {
+         if (function_table->file)
+           {
+             free (function_table->file);
+             function_table->file = NULL;
+           }
+
+         if (function_table->caller_file)
+           {
+             free (function_table->caller_file);
+             function_table->caller_file = NULL;
+           }
+         function_table = function_table->prev_func;
+       }
+
+      while (variable_table)
+       {
+         if (variable_table->file)
+           {
+             free (variable_table->file);
+             variable_table->file = NULL;
+           }
+
+         variable_table = variable_table->prev_var;
+       }
     }
 
-  free (stash->dwarf_abbrev_buffer);
-  free (stash->dwarf_line_buffer);
-  free (stash->dwarf_ranges_buffer);
+  if (stash->dwarf_abbrev_buffer)
+    free (stash->dwarf_abbrev_buffer);
+  if (stash->dwarf_line_buffer)
+    free (stash->dwarf_line_buffer);
+  if (stash->dwarf_str_buffer)
+    free (stash->dwarf_str_buffer);
+  if (stash->dwarf_ranges_buffer)
+    free (stash->dwarf_ranges_buffer);
+  if (stash->info_ptr_memory)
+    free (stash->info_ptr_memory);
 }
This page took 0.085583 seconds and 4 git commands to generate.