]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/dwarf2.c
Fix the BFD library's find_nearest_line feature to produce consistent results.
[thirdparty/binutils-gdb.git] / bfd / dwarf2.c
index 248e621ad3305dd73b17dd5996ea274ca760b13b..8c9bd7a3026dc7c583fbb8bc7079505b24759b86 100644 (file)
@@ -1,5 +1,5 @@
 /* DWARF 2 support.
-   Copyright (C) 1994-2017 Free Software Foundation, Inc.
+   Copyright (C) 1994-2023 Free Software Foundation, Inc.
 
    Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
    (gavin@cygnus.com).
 #include "sysdep.h"
 #include "bfd.h"
 #include "libiberty.h"
+#include "demangle.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "dwarf2.h"
+#include "hashtab.h"
+#include "splay-tree.h"
 
 /* The data in the .debug_line statement prologue looks like this.  */
 
@@ -62,8 +65,8 @@ struct attribute
   {
     char *str;
     struct dwarf_block *blk;
-    bfd_uint64_t val;
-    bfd_int64_t sval;
+    uint64_t val;
+    int64_t sval;
   }
   u;
 };
@@ -79,58 +82,136 @@ struct adjusted_section
 {
   asection *section;
   bfd_vma adj_vma;
+  bfd_vma orig_vma;
 };
 
-struct dwarf2_debug
+/* A trie to map quickly from address range to compilation unit.
+
+   This is a fairly standard radix-256 trie, used to quickly locate which
+   compilation unit any given address belongs to.  Given that each compilation
+   unit may register hundreds of very small and unaligned ranges (which may
+   potentially overlap, due to inlining and other concerns), and a large
+   program may end up containing hundreds of thousands of such ranges, we cannot
+   scan through them linearly without undue slowdown.
+
+   We use a hybrid trie to avoid memory explosion: There are two types of trie
+   nodes, leaves and interior nodes.  (Almost all nodes are leaves, so they
+   take up the bulk of the memory usage.) Leaves contain a simple array of
+   ranges (high/low address) and which compilation unit contains those ranges,
+   and when we get to a leaf, we scan through it linearly.  Interior nodes
+   contain pointers to 256 other nodes, keyed by the next byte of the address.
+   So for a 64-bit address like 0x1234567abcd, we would start at the root and go
+   down child[0x00]->child[0x00]->child[0x01]->child[0x23]->child[0x45] etc.,
+   until we hit a leaf.  (Nodes are, in general, leaves until they exceed the
+   default allocation of 16 elements, at which point they are converted to
+   interior node if possible.) This gives us near-constant lookup times;
+   the only thing that can be costly is if there are lots of overlapping ranges
+   within a single 256-byte segment of the binary, in which case we have to
+   scan through them all to find the best match.
+
+   For a binary with few ranges, we will in practice only have a single leaf
+   node at the root, containing a simple array.  Thus, the scheme is efficient
+   for both small and large binaries.
+ */
+
+/* Experiments have shown 16 to be a memory-efficient default leaf size.
+   The only case where a leaf will hold more memory than this, is at the
+   bottomost level (covering 256 bytes in the binary), where we'll expand
+   the leaf to be able to hold more ranges if needed.
+ */
+#define TRIE_LEAF_SIZE 16
+
+/* All trie_node pointers will really be trie_leaf or trie_interior,
+   but they have this common head.  */
+struct trie_node
 {
-  /* A list of all previously read comp_units.  */
-  struct comp_unit *all_comp_units;
+  /* If zero, we are an interior node.
+     Otherwise, how many ranges we have room for in this leaf.  */
+  unsigned int num_room_in_leaf;
+};
 
-  /* Last comp unit in list above.  */
-  struct comp_unit *last_comp_unit;
+struct trie_leaf
+{
+  struct trie_node head;
+  unsigned int num_stored_in_leaf;
+  struct {
+    struct comp_unit *unit;
+    bfd_vma low_pc, high_pc;
+  } ranges[TRIE_LEAF_SIZE];
+};
 
-  /* Names of the debug sections.  */
-  const struct dwarf_debug_section *debug_sections;
+struct trie_interior
+{
+  struct trie_node head;
+  struct trie_node *children[256];
+};
 
-  /* 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.  */
-  bfd_byte *info_ptr;
+static struct trie_node *alloc_trie_leaf (bfd *abfd)
+{
+  struct trie_leaf *leaf = bfd_zalloc (abfd, sizeof (struct trie_leaf));
+  if (leaf == NULL)
+    return NULL;
+  leaf->head.num_room_in_leaf = TRIE_LEAF_SIZE;
+  return &leaf->head;
+}
 
-  /* Pointer to the end of the .debug_info section memory buffer.  */
-  bfd_byte *info_ptr_end;
+struct addr_range
+{
+  bfd_byte *start;
+  bfd_byte *end;
+};
 
-  /* Pointer to the original bfd for which debug was loaded.  This is what
-     we use to compare and so check that the cached debug data is still
-     valid - it saves having to possibly dereference the gnu_debuglink each
-     time.  */
-  bfd *orig_bfd;
+/* Return true if address range do intersect.  */
+
+static bool
+addr_range_intersects (struct addr_range *r1, struct addr_range *r2)
+{
+  return (r1->start <= r2->start && r2->start < r1->end)
+    || (r1->start <= (r2->end - 1) && (r2->end - 1) < r1->end);
+}
+
+/* Compare function for splay tree of addr_ranges.  */
+
+static int
+splay_tree_compare_addr_range (splay_tree_key xa, splay_tree_key xb)
+{
+  struct addr_range *r1 = (struct addr_range *) xa;
+  struct addr_range *r2 = (struct addr_range *) xb;
+
+  if (addr_range_intersects (r1, r2) || addr_range_intersects (r2, r1))
+    return 0;
+  else if (r1->end <= r2->start)
+    return -1;
+  else
+    return 1;
+}
+
+/* Splay tree release function for keys (addr_range).  */
+
+static void
+splay_tree_free_addr_range (splay_tree_key key)
+{
+  free ((struct addr_range *)key);
+}
 
-  /* 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.  */
+struct dwarf2_debug_file
+{
+  /* The actual bfd from which debug info was loaded.  Might be
+     different to orig_bfd because of gnu_debuglink sections.  */
   bfd *bfd_ptr;
-  asection *sec;
-  bfd_byte *sec_info_ptr;
-
-  /* Support for alternate debug info sections created by the DWZ utility:
-     This includes a pointer to an alternate bfd which contains *extra*,
-     possibly duplicate debug sections, and pointers to the loaded
-     .debug_str and .debug_info sections from this bfd.  */
-  bfd *          alt_bfd_ptr;
-  bfd_byte *     alt_dwarf_str_buffer;
-  bfd_size_type  alt_dwarf_str_size;
-  bfd_byte *     alt_dwarf_info_buffer;
-  bfd_size_type  alt_dwarf_info_size;
-
-  /* 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.  */
-  bfd_byte *info_ptr_memory;
 
   /* Pointer to the symbol table.  */
   asymbol **syms;
 
+  /* The current info pointer for the .debug_info section being parsed.  */
+  bfd_byte *info_ptr;
+
+  /* A pointer to the memory block allocated for .debug_info sections.  */
+  bfd_byte *dwarf_info_buffer;
+
+  /* Length of the loaded .debug_info sections.  */
+  bfd_size_type dwarf_info_size;
+
   /* Pointer to the .debug_abbrev section loaded into memory.  */
   bfd_byte *dwarf_abbrev_buffer;
 
@@ -149,6 +230,18 @@ struct dwarf2_debug
   /* Length of the loaded .debug_str section.  */
   bfd_size_type dwarf_str_size;
 
+  /* Pointer to the .debug_str_offsets section loaded into memory.  */
+  bfd_byte *dwarf_str_offsets_buffer;
+
+  /* Length of the loaded .debug_str_offsets section.  */
+  bfd_size_type dwarf_str_offsets_size;
+
+  /* Pointer to the .debug_addr section loaded into memory.  */
+  bfd_byte *dwarf_addr_buffer;
+
+  /* Length of the loaded .debug_addr section.  */
+  bfd_size_type dwarf_addr_size;
+
   /* Pointer to the .debug_line_str section loaded into memory.  */
   bfd_byte *dwarf_line_str_buffer;
 
@@ -161,6 +254,48 @@ struct dwarf2_debug
   /* Length of the loaded .debug_ranges section.  */
   bfd_size_type dwarf_ranges_size;
 
+  /* Pointer to the .debug_rnglists section loaded into memory.  */
+  bfd_byte *dwarf_rnglists_buffer;
+
+  /* Length of the loaded .debug_rnglists section.  */
+  bfd_size_type dwarf_rnglists_size;
+
+  /* A list of all previously read comp_units.  */
+  struct comp_unit *all_comp_units;
+
+  /* A list of all previously read comp_units with no ranges (yet).  */
+  struct comp_unit *all_comp_units_without_ranges;
+
+  /* Last comp unit in list above.  */
+  struct comp_unit *last_comp_unit;
+
+  /* Line table at line_offset zero.  */
+  struct line_info_table *line_table;
+
+  /* Hash table to map offsets to decoded abbrevs.  */
+  htab_t abbrev_offsets;
+
+  /* Root of a trie to map addresses to compilation units.  */
+  struct trie_node *trie_root;
+
+  /* Splay tree to map info_ptr address to compilation units.  */
+  splay_tree comp_unit_tree;
+};
+
+struct dwarf2_debug
+{
+  /* Names of the debug sections.  */
+  const struct dwarf_debug_section *debug_sections;
+
+  /* Per-file stuff.  */
+  struct dwarf2_debug_file f, alt;
+
+  /* Pointer to the original bfd for which debug was loaded.  This is what
+     we use to compare and so check that the cached debug data is still
+     valid - it saves having to possibly dereference the gnu_debuglink each
+     time.  */
+  bfd *orig_bfd;
+
   /* 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
@@ -169,6 +304,8 @@ struct dwarf2_debug
 
   /* Section VMAs at the time the stash was built.  */
   bfd_vma *sec_vma;
+  /* Number of sections in the SEC_VMA table.  */
+  unsigned int sec_vma_count;
 
   /* Number of sections whose VMA we must adjust.  */
   int adjusted_section_count;
@@ -193,12 +330,12 @@ struct dwarf2_debug
 
   /* Status of info hash.  */
   int info_hash_status;
-#define STASH_INFO_HASH_OFF        0
-#define STASH_INFO_HASH_ON         1
+#define STASH_INFO_HASH_OFF       0
+#define STASH_INFO_HASH_ON        1
 #define STASH_INFO_HASH_DISABLED   2
 
   /* True if we opened bfd_ptr.  */
-  bfd_boolean close_on_cleanup;
+  bool close_on_cleanup;
 };
 
 struct arange
@@ -216,6 +353,11 @@ struct comp_unit
   /* Chain the previously read compilation units.  */
   struct comp_unit *next_unit;
 
+  /* Chain the previously read compilation units that have no ranges yet.
+     We scan these separately when we have a trie over the ranges.
+     Unused if arange.high != 0. */
+  struct comp_unit *next_unit_without_ranges;
+
   /* Likewise, chain the compilation unit read after this one.
      The comp units are stored in reversed reading order.  */
   struct comp_unit *prev_unit;
@@ -273,8 +415,9 @@ struct comp_unit
   /* A list of the variables found in this comp. unit.  */
   struct varinfo *variable_table;
 
-  /* Pointer to dwarf2_debug structure.  */
+  /* Pointers to dwarf2_debug structures.  */
   struct dwarf2_debug *stash;
+  struct dwarf2_debug_file *file;
 
   /* DWARF format version for this unit - from unit header.  */
   int version;
@@ -290,18 +433,28 @@ struct comp_unit
   bfd_vma base_address;
 
   /* TRUE if symbols are cached in hash table for faster lookup by name.  */
-  bfd_boolean cached;
+  bool cached;
+
+  /* Used when iterating over trie leaves to know which units we have
+     already seen in this iteration.  */
+  bool mark;
+
+ /* Base address of debug_addr section.  */
+  size_t dwarf_addr_offset;
+
+  /* Base address of string offset table.  */
+  size_t dwarf_str_offset;
 };
 
 /* This data structure holds the information of an abbrev.  */
 struct abbrev_info
 {
-  unsigned int number;         /* Number identifying abbrev.  */
-  enum dwarf_tag tag;          /* DWARF tag.  */
-  int has_children;            /* Boolean.  */
-  unsigned int num_attrs;      /* Number of attributes.  */
-  struct attr_abbrev *attrs;   /* An array of attribute descriptions.  */
-  struct abbrev_info *next;    /* Next in chain.  */
+  unsigned int         number;         /* Number identifying abbrev.  */
+  enum dwarf_tag       tag;            /* DWARF tag.  */
+  bool                 has_children;   /* TRUE if the abbrev has children.  */
+  unsigned int         num_attrs;      /* Number of attributes.  */
+  struct attr_abbrev * attrs;          /* An array of attribute descriptions.  */
+  struct abbrev_info * next;           /* Next in chain.  */
 };
 
 struct attr_abbrev
@@ -328,10 +481,13 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { ".debug_pubnames",         ".zdebug_pubnames" },
   { ".debug_pubtypes",         ".zdebug_pubtypes" },
   { ".debug_ranges",           ".zdebug_ranges" },
+  { ".debug_rnglists",         ".zdebug_rnglist" },
   { ".debug_static_func",      ".zdebug_static_func" },
   { ".debug_static_vars",      ".zdebug_static_vars" },
   { ".debug_str",              ".zdebug_str", },
   { ".debug_str",              ".zdebug_str", },
+  { ".debug_str_offsets",      ".zdebug_str_offsets", },
+  { ".debug_addr",             ".zdebug_addr", },
   { ".debug_line_str",         ".zdebug_line_str", },
   { ".debug_types",            ".zdebug_types" },
   /* GNU DWARF 1 extensions */
@@ -345,7 +501,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { NULL,                      NULL },
 };
 
-/* NB/ Numbers in this enum must match up with indicies
+/* NB/ Numbers in this enum must match up with indices
    into the dwarf_debug_sections[] array above.  */
 enum dwarf_debug_section_enum
 {
@@ -361,10 +517,13 @@ enum dwarf_debug_section_enum
   debug_pubnames,
   debug_pubtypes,
   debug_ranges,
+  debug_rnglists,
   debug_static_func,
   debug_static_vars,
   debug_str,
   debug_str_alt,
+  debug_str_offsets,
+  debug_addr,
   debug_line_str,
   debug_types,
   debug_sfnames,
@@ -471,30 +630,30 @@ create_info_hash_table (bfd *abfd)
    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
+static bool
 insert_info_hash_table (struct info_hash_table *hash_table,
                        const char *key,
                        void *info,
-                       bfd_boolean copy_p)
+                       bool 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);
+                                                    key, true, copy_p);
   if (!entry)
-    return FALSE;
+    return false;
 
   node = (struct info_list_node *) bfd_hash_allocate (&hash_table->base,
                                                      sizeof (*node));
   if (!node)
-    return FALSE;
+    return false;
 
   node->info = info;
   node->next = entry->head;
   entry->head = node;
 
-  return TRUE;
+  return true;
 }
 
 /* Look up an info entry list from an info hash table.  Return NULL
@@ -506,7 +665,7 @@ 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);
+                                                    false, false);
   return entry ? entry->head : NULL;
 }
 
@@ -516,49 +675,73 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key)
    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,
+static bool
+read_section (bfd *abfd,
              const struct dwarf_debug_section *sec,
-             asymbol **      syms,
-             bfd_uint64_t    offset,
-             bfd_byte **     section_buffer,
-             bfd_size_type * section_size)
+             asymbol **syms,
+             uint64_t offset,
+             bfd_byte **section_buffer,
+             bfd_size_type *section_size)
 {
-  asection *msec;
   const char *section_name = sec->uncompressed_name;
   bfd_byte *contents = *section_buffer;
 
   /* The section may have already been read.  */
   if (contents == NULL)
     {
+      bfd_size_type amt;
+      asection *msec;
+
       msec = bfd_get_section_by_name (abfd, section_name);
-      if (! msec)
+      if (msec == NULL)
        {
          section_name = sec->compressed_name;
-         if (section_name != NULL)
-           msec = bfd_get_section_by_name (abfd, section_name);
+          msec = bfd_get_section_by_name (abfd, section_name);
        }
-      if (! msec)
+      if (msec == NULL)
        {
-         _bfd_error_handler (_("Dwarf Error: Can't find %s section."),
+         _bfd_error_handler (_("DWARF error: can't find %s section."),
                              sec->uncompressed_name);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
+       }
+
+      if ((msec->flags & SEC_HAS_CONTENTS) == 0)
+       {
+         _bfd_error_handler (_("DWARF error: section %s has no contents"),
+                             section_name);
+         bfd_set_error (bfd_error_no_contents);
+         return false;
        }
 
-      *section_size = msec->rawsize ? msec->rawsize : msec->size;
+      if (_bfd_section_size_insane (abfd, msec))
+       {
+         /* PR 26946 */
+         _bfd_error_handler (_("DWARF error: section %s is too big"),
+                             section_name);
+         return false;
+       }
+      amt = bfd_get_section_limit_octets (abfd, msec);
+      *section_size = amt;
       /* Paranoia - alloc one extra so that we can make sure a string
         section is NUL terminated.  */
-      contents = (bfd_byte *) bfd_malloc (*section_size + 1);
+      amt += 1;
+      if (amt == 0)
+       {
+         /* Paranoia - this should never happen.  */
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+      contents = (bfd_byte *) bfd_malloc (amt);
       if (contents == NULL)
-       return FALSE;
+       return false;
       if (syms
          ? !bfd_simple_get_relocated_section_contents (abfd, msec, contents,
                                                        syms)
          : !bfd_get_section_contents (abfd, msec, contents, 0, *section_size))
        {
          free (contents);
-         return FALSE;
+         return false;
        }
       contents[*section_size] = 0;
       *section_buffer = contents;
@@ -569,145 +752,169 @@ read_section (bfd *           abfd,
   if (offset != 0 && offset >= *section_size)
     {
       /* xgettext: c-format */
-      _bfd_error_handler (_("Dwarf Error: Offset (%llu)"
-                           " greater than or equal to %s size (%Lu)."),
-                         (long long) offset, section_name, *section_size);
+      _bfd_error_handler (_("DWARF error: offset (%" PRIu64 ")"
+                           " greater than or equal to %s size (%" PRIu64 ")"),
+                         (uint64_t) offset, section_name,
+                         (uint64_t) *section_size);
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Read dwarf information from a buffer.  */
 
+static inline uint64_t
+read_n_bytes (bfd *abfd, bfd_byte **ptr, bfd_byte *end, int n)
+{
+  bfd_byte *buf = *ptr;
+  if (end - buf < n)
+    {
+      *ptr = end;
+      return 0;
+    }
+  *ptr = buf + n;
+  return bfd_get (n * 8, abfd, buf);
+}
+
 static unsigned int
-read_1_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
+read_1_byte (bfd *abfd, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + 1 > end)
-    return 0;
-  return bfd_get_8 (abfd, buf);
+  return read_n_bytes (abfd, ptr, end, 1);
 }
 
 static int
-read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *buf, bfd_byte *end)
+read_1_signed_byte (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + 1 > end)
-    return 0;
+  bfd_byte *buf = *ptr;
+  if (end - buf < 1)
+    {
+      *ptr = end;
+      return 0;
+    }
+  *ptr = buf + 1;
   return bfd_get_signed_8 (abfd, buf);
 }
 
 static unsigned int
-read_2_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
+read_2_bytes (bfd *abfd, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + 2 > end)
-    return 0;
-  return bfd_get_16 (abfd, buf);
+  return read_n_bytes (abfd, ptr, end, 2);
 }
 
 static unsigned int
-read_4_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
+read_3_bytes (bfd *abfd, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + 4 > end)
-    return 0;
-  return bfd_get_32 (abfd, buf);
+  unsigned int val = read_1_byte (abfd, ptr, end);
+  val <<= 8;
+  val |= read_1_byte (abfd, ptr, end);
+  val <<= 8;
+  val |= read_1_byte (abfd, ptr, end);
+  if (bfd_little_endian (abfd))
+    val = (((val >> 16) & 0xff)
+          | (val & 0xff00)
+          | ((val & 0xff) << 16));
+  return val;
 }
 
-static bfd_uint64_t
-read_8_bytes (bfd *abfd, bfd_byte *buf, bfd_byte *end)
+static unsigned int
+read_4_bytes (bfd *abfd, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + 8 > end)
-    return 0;
-  return bfd_get_64 (abfd, buf);
+  return read_n_bytes (abfd, ptr, end, 4);
 }
 
-static bfd_byte *
-read_n_bytes (bfd *abfd ATTRIBUTE_UNUSED,
-             bfd_byte *buf,
-             bfd_byte *end,
-             unsigned int size ATTRIBUTE_UNUSED)
+static uint64_t
+read_8_bytes (bfd *abfd, bfd_byte **ptr, bfd_byte *end)
 {
-  if (buf + size > end)
-    return NULL;
-  return buf;
+  return read_n_bytes (abfd, ptr, end, 8);
 }
 
-/* Scans a NUL terminated string starting at BUF, returning a pointer to it.
-   Returns the number of characters in the string, *including* the NUL byte,
-   in BYTES_READ_PTR.  This value is set even if the function fails.  Bytes
-   at or beyond BUF_END will not be read.  Returns NULL if there was a
-   problem, or if the string is empty.  */
-
-static char *
-read_string (bfd *          abfd ATTRIBUTE_UNUSED,
-            bfd_byte *     buf,
-            bfd_byte *     buf_end,
-            unsigned int * bytes_read_ptr)
+static struct dwarf_block *
+read_blk (bfd *abfd, bfd_byte **ptr, bfd_byte *end, size_t size)
 {
-  bfd_byte *str = buf;
+  bfd_byte *buf = *ptr;
+  struct dwarf_block *block;
+
+  block = (struct dwarf_block *) bfd_alloc (abfd, sizeof (*block));
+  if (block == NULL)
+    return NULL;
 
-  if (buf >= buf_end)
+  if (size > (size_t) (end - buf))
     {
-      * bytes_read_ptr = 0;
-      return NULL;
+      *ptr = end;
+      block->data = NULL;
+      block->size = 0;
     }
-
-  if (*str == '\0')
+  else
     {
-      * bytes_read_ptr = 1;
-      return NULL;
+      *ptr = buf + size;
+      block->data = buf;
+      block->size = size;
     }
+  return block;
+}
+
+/* Scans a NUL terminated string starting at *PTR, returning a pointer to it.
+   Bytes at or beyond BUF_END will not be read.  Returns NULL if the
+   terminator is not found or if the string is empty.  *PTR is
+   incremented over the bytes scanned, including the terminator.  */
+
+static char *
+read_string (bfd_byte **ptr,
+            bfd_byte *buf_end)
+{
+  bfd_byte *buf = *ptr;
+  bfd_byte *str = buf;
 
   while (buf < buf_end)
-    if (* buf ++ == 0)
+    if (*buf++ == 0)
       {
-       * bytes_read_ptr = buf - str;
+       if (str == buf - 1)
+         break;
+       *ptr = buf;
        return (char *) str;
       }
 
-  * bytes_read_ptr = buf - str;
+  *ptr = buf;
   return NULL;
 }
 
-/* Reads an offset from BUF and then locates the string at this offset
+/* Reads an offset from *PTR and then locates the string at this offset
    inside the debug string section.  Returns a pointer to the string.
-   Returns the number of bytes read from BUF, *not* the length of the string,
-   in BYTES_READ_PTR.  This value is set even if the function fails.  Bytes
-   at or beyond BUF_END will not be read from BUF.  Returns NULL if there was
-   a problem, or if the string is empty.  Does not check for NUL termination
-   of the string.  */
+   Increments *PTR by the number of bytes read for the offset.  This
+   value is set even if the function fails.  Bytes at or beyond
+   BUF_END will not be read.  Returns NULL if there was a problem, or
+   if the string is empty.  Does not check for NUL termination of the
+   string.  */
 
 static char *
-read_indirect_string (struct comp_unit * unit,
-                     bfd_byte *         buf,
-                     bfd_byte *         buf_end,
-                     unsigned int *     bytes_read_ptr)
+read_indirect_string (struct comp_unit *unit,
+                     bfd_byte **ptr,
+                     bfd_byte *buf_end)
 {
-  bfd_uint64_t offset;
+  uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
   char *str;
 
-  if (buf + unit->offset_size > buf_end)
+  if (unit->offset_size > (size_t) (buf_end - *ptr))
     {
-      * bytes_read_ptr = 0;
+      *ptr = buf_end;
       return NULL;
     }
 
   if (unit->offset_size == 4)
-    offset = read_4_bytes (unit->abfd, buf, buf_end);
+    offset = read_4_bytes (unit->abfd, ptr, buf_end);
   else
-    offset = read_8_bytes (unit->abfd, buf, buf_end);
-
-  *bytes_read_ptr = unit->offset_size;
+    offset = read_8_bytes (unit->abfd, ptr, buf_end);
 
   if (! read_section (unit->abfd, &stash->debug_sections[debug_str],
-                     stash->syms, offset,
-                     &stash->dwarf_str_buffer, &stash->dwarf_str_size))
+                     file->syms, offset,
+                     &file->dwarf_str_buffer, &file->dwarf_str_size))
     return NULL;
 
-  if (offset >= stash->dwarf_str_size)
-    return NULL;
-  str = (char *) stash->dwarf_str_buffer + offset;
+  str = (char *) file->dwarf_str_buffer + offset;
   if (*str == '\0')
     return NULL;
   return str;
@@ -716,37 +923,33 @@ read_indirect_string (struct comp_unit * unit,
 /* Like read_indirect_string but from .debug_line_str section.  */
 
 static char *
-read_indirect_line_string (struct comp_unit * unit,
-                          bfd_byte *         buf,
-                          bfd_byte *         buf_end,
-                          unsigned int *     bytes_read_ptr)
+read_indirect_line_string (struct comp_unit *unit,
+                          bfd_byte **ptr,
+                          bfd_byte *buf_end)
 {
-  bfd_uint64_t offset;
+  uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
   char *str;
 
-  if (buf + unit->offset_size > buf_end)
+  if (unit->offset_size > (size_t) (buf_end - *ptr))
     {
-      * bytes_read_ptr = 0;
+      *ptr = buf_end;
       return NULL;
     }
 
   if (unit->offset_size == 4)
-    offset = read_4_bytes (unit->abfd, buf, buf_end);
+    offset = read_4_bytes (unit->abfd, ptr, buf_end);
   else
-    offset = read_8_bytes (unit->abfd, buf, buf_end);
-
-  *bytes_read_ptr = unit->offset_size;
+    offset = read_8_bytes (unit->abfd, ptr, buf_end);
 
   if (! read_section (unit->abfd, &stash->debug_sections[debug_line_str],
-                     stash->syms, offset,
-                     &stash->dwarf_line_str_buffer,
-                     &stash->dwarf_line_str_size))
+                     file->syms, offset,
+                     &file->dwarf_line_str_buffer,
+                     &file->dwarf_line_str_size))
     return NULL;
 
-  if (offset >= stash->dwarf_line_str_size)
-    return NULL;
-  str = (char *) stash->dwarf_line_str_buffer + offset;
+  str = (char *) file->dwarf_line_str_buffer + offset;
   if (*str == '\0')
     return NULL;
   return str;
@@ -757,60 +960,55 @@ read_indirect_line_string (struct comp_unit * unit,
    Used to impement DW_FORM_GNU_strp_alt.  */
 
 static char *
-read_alt_indirect_string (struct comp_unit * unit,
-                         bfd_byte *         buf,
-                         bfd_byte *         buf_end,
-                         unsigned int *     bytes_read_ptr)
+read_alt_indirect_string (struct comp_unit *unit,
+                         bfd_byte **ptr,
+                         bfd_byte *buf_end)
 {
-  bfd_uint64_t offset;
+  uint64_t offset;
   struct dwarf2_debug *stash = unit->stash;
   char *str;
 
-  if (buf + unit->offset_size > buf_end)
+  if (unit->offset_size > (size_t) (buf_end - *ptr))
     {
-      * bytes_read_ptr = 0;
+      *ptr = buf_end;
       return NULL;
     }
 
   if (unit->offset_size == 4)
-    offset = read_4_bytes (unit->abfd, buf, buf_end);
+    offset = read_4_bytes (unit->abfd, ptr, buf_end);
   else
-    offset = read_8_bytes (unit->abfd, buf, buf_end);
+    offset = read_8_bytes (unit->abfd, ptr, buf_end);
 
-  *bytes_read_ptr = unit->offset_size;
-
-  if (stash->alt_bfd_ptr == NULL)
+  if (stash->alt.bfd_ptr == NULL)
     {
-      bfd *  debug_bfd;
-      char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
+      bfd *debug_bfd;
+      char *debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
 
       if (debug_filename == NULL)
        return NULL;
 
-      if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
-         || ! bfd_check_format (debug_bfd, bfd_object))
-       {
-         if (debug_bfd)
-           bfd_close (debug_bfd);
+      debug_bfd = bfd_openr (debug_filename, NULL);
+      free (debug_filename);
+      if (debug_bfd == NULL)
+       /* FIXME: Should we report our failure to follow the debuglink ?  */
+       return NULL;
 
-         /* FIXME: Should we report our failure to follow the debuglink ?  */
-         free (debug_filename);
+      if (!bfd_check_format (debug_bfd, bfd_object))
+       {
+         bfd_close (debug_bfd);
          return NULL;
        }
-      stash->alt_bfd_ptr = debug_bfd;
+      stash->alt.bfd_ptr = debug_bfd;
     }
 
-  if (! read_section (unit->stash->alt_bfd_ptr,
+  if (! read_section (unit->stash->alt.bfd_ptr,
                      stash->debug_sections + debug_str_alt,
-                     NULL, /* FIXME: Do we need to load alternate symbols ?  */
-                     offset,
-                     &stash->alt_dwarf_str_buffer,
-                     &stash->alt_dwarf_str_size))
+                     stash->alt.syms, offset,
+                     &stash->alt.dwarf_str_buffer,
+                     &stash->alt.dwarf_str_size))
     return NULL;
 
-  if (offset >= stash->alt_dwarf_str_size)
-    return NULL;
-  str = (char *) stash->alt_dwarf_str_buffer + offset;
+  str = (char *) stash->alt.dwarf_str_buffer + offset;
   if (*str == '\0')
     return NULL;
 
@@ -822,56 +1020,58 @@ read_alt_indirect_string (struct comp_unit * unit,
    or NULL upon failure.  */
 
 static bfd_byte *
-read_alt_indirect_ref (struct comp_unit * unit,
-                      bfd_uint64_t       offset)
+read_alt_indirect_ref (struct comp_unit *unit, uint64_t offset)
 {
   struct dwarf2_debug *stash = unit->stash;
 
-  if (stash->alt_bfd_ptr == NULL)
+  if (stash->alt.bfd_ptr == NULL)
     {
-      bfd *  debug_bfd;
-      char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
+      bfd *debug_bfd;
+      char *debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
 
       if (debug_filename == NULL)
-       return FALSE;
+       return NULL;
 
-      if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
-         || ! bfd_check_format (debug_bfd, bfd_object))
-       {
-         if (debug_bfd)
-           bfd_close (debug_bfd);
+      debug_bfd = bfd_openr (debug_filename, NULL);
+      free (debug_filename);
+      if (debug_bfd == NULL)
+       /* FIXME: Should we report our failure to follow the debuglink ?  */
+       return NULL;
 
-         /* FIXME: Should we report our failure to follow the debuglink ?  */
-         free (debug_filename);
+      if (!bfd_check_format (debug_bfd, bfd_object))
+       {
+         bfd_close (debug_bfd);
          return NULL;
        }
-      stash->alt_bfd_ptr = debug_bfd;
+      stash->alt.bfd_ptr = debug_bfd;
     }
 
-  if (! read_section (unit->stash->alt_bfd_ptr,
+  if (! read_section (unit->stash->alt.bfd_ptr,
                      stash->debug_sections + debug_info_alt,
-                     NULL, /* FIXME: Do we need to load alternate symbols ?  */
-                     offset,
-                     &stash->alt_dwarf_info_buffer,
-                     &stash->alt_dwarf_info_size))
+                     stash->alt.syms, offset,
+                     &stash->alt.dwarf_info_buffer,
+                     &stash->alt.dwarf_info_size))
     return NULL;
 
-  if (offset >= stash->alt_dwarf_info_size)
-    return NULL;
-  return stash->alt_dwarf_info_buffer + offset;
+  return stash->alt.dwarf_info_buffer + offset;
 }
 
-static bfd_uint64_t
-read_address (struct comp_unit *unit, bfd_byte *buf, bfd_byte * buf_end)
+static uint64_t
+read_address (struct comp_unit *unit, bfd_byte **ptr, bfd_byte *buf_end)
 {
+  bfd_byte *buf = *ptr;
   int signed_vma = 0;
 
   if (bfd_get_flavour (unit->abfd) == bfd_target_elf_flavour)
     signed_vma = get_elf_backend_data (unit->abfd)->sign_extend_vma;
 
-  if (buf + unit->addr_size > buf_end)
-    return 0;
+  if (unit->addr_size > (size_t) (buf_end - buf))
+    {
+      *ptr = buf_end;
+      return 0;
+    }
 
+  *ptr = buf + unit->addr_size;
   if (signed_vma)
     {
       switch (unit->addr_size)
@@ -924,28 +1124,83 @@ lookup_abbrev (unsigned int number, struct abbrev_info **abbrevs)
   return NULL;
 }
 
+/* We keep a hash table to map .debug_abbrev section offsets to the
+   array of abbrevs, so that compilation units using the same set of
+   abbrevs do not waste memory.  */
+
+struct abbrev_offset_entry
+{
+  size_t offset;
+  struct abbrev_info **abbrevs;
+};
+
+static hashval_t
+hash_abbrev (const void *p)
+{
+  const struct abbrev_offset_entry *ent = p;
+  return htab_hash_pointer ((void *) ent->offset);
+}
+
+static int
+eq_abbrev (const void *pa, const void *pb)
+{
+  const struct abbrev_offset_entry *a = pa;
+  const struct abbrev_offset_entry *b = pb;
+  return a->offset == b->offset;
+}
+
+static void
+del_abbrev (void *p)
+{
+  struct abbrev_offset_entry *ent = p;
+  struct abbrev_info **abbrevs = ent->abbrevs;
+  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;
+       }
+    }
+  free (ent);
+}
+
 /* In DWARF version 2, the description of the debugging information is
    stored in a separate .debug_abbrev section.  Before we read any
    dies from a section we read in all abbreviations and install them
    in a hash table.  */
 
 static struct abbrev_info**
-read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
+read_abbrevs (bfd *abfd, uint64_t offset, struct dwarf2_debug *stash,
+             struct dwarf2_debug_file *file)
 {
   struct abbrev_info **abbrevs;
   bfd_byte *abbrev_ptr;
   bfd_byte *abbrev_end;
   struct abbrev_info *cur_abbrev;
-  unsigned int abbrev_number, bytes_read, abbrev_name;
+  unsigned int abbrev_number, abbrev_name;
   unsigned int abbrev_form, hash_number;
-  bfd_size_type amt;
+  size_t amt;
+  void **slot;
+  struct abbrev_offset_entry ent = { offset, NULL };
 
-  if (! read_section (abfd, &stash->debug_sections[debug_abbrev],
-                     stash->syms, offset,
-                     &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
+  if (ent.offset != offset)
     return NULL;
 
-  if (offset >= stash->dwarf_abbrev_size)
+  slot = htab_find_slot (file->abbrev_offsets, &ent, INSERT);
+  if (slot == NULL)
+    return NULL;
+  if (*slot != NULL)
+    return ((struct abbrev_offset_entry *) (*slot))->abbrevs;
+
+  if (! read_section (abfd, &stash->debug_sections[debug_abbrev],
+                     file->syms, offset,
+                     &file->dwarf_abbrev_buffer,
+                     &file->dwarf_abbrev_size))
     return NULL;
 
   amt = sizeof (struct abbrev_info*) * ABBREV_HASH_SIZE;
@@ -953,11 +1208,10 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
   if (abbrevs == NULL)
     return NULL;
 
-  abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
-  abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
-  abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
-                                        FALSE, abbrev_end);
-  abbrev_ptr += bytes_read;
+  abbrev_ptr = file->dwarf_abbrev_buffer + offset;
+  abbrev_end = file->dwarf_abbrev_buffer + file->dwarf_abbrev_size;
+  abbrev_number = _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                                        false, abbrev_end);
 
   /* Loop until we reach an abbrev number of 0.  */
   while (abbrev_number)
@@ -965,16 +1219,14 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
       amt = sizeof (struct abbrev_info);
       cur_abbrev = (struct abbrev_info *) bfd_zalloc (abfd, amt);
       if (cur_abbrev == NULL)
-       return NULL;
+       goto fail;
 
       /* Read in abbrev header.  */
       cur_abbrev->number = abbrev_number;
       cur_abbrev->tag = (enum dwarf_tag)
-       _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
-                              FALSE, abbrev_end);
-      abbrev_ptr += bytes_read;
-      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr, abbrev_end);
-      abbrev_ptr += 1;
+       _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                              false, abbrev_end);
+      cur_abbrev->has_children = read_1_byte (abfd, &abbrev_ptr, abbrev_end);
 
       /* Now read in declarations.  */
       for (;;)
@@ -982,20 +1234,13 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
          /* Initialize it just to avoid a GCC false warning.  */
          bfd_vma implicit_const = -1;
 
-         abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
-                                              FALSE, abbrev_end);
-         abbrev_ptr += bytes_read;
-         abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read,
-                                              FALSE, abbrev_end);
-         abbrev_ptr += bytes_read;
+         abbrev_name = _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                                              false, abbrev_end);
+         abbrev_form = _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                                              false, abbrev_end);
          if (abbrev_form == DW_FORM_implicit_const)
-           {
-             implicit_const = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
-                                                     &bytes_read, TRUE,
-                                                     abbrev_end);
-             abbrev_ptr += bytes_read;
-           }
-
+           implicit_const = _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                                                   true, abbrev_end);
          if (abbrev_name == 0)
            break;
 
@@ -1007,21 +1252,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
              amt *= sizeof (struct attr_abbrev);
              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;
-               }
+               goto fail;
              cur_abbrev->attrs = tmp;
            }
 
@@ -1045,211 +1276,405 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
         already read (which means we are about to read the abbreviations
         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)
+      if ((size_t) (abbrev_ptr - file->dwarf_abbrev_buffer)
+         >= file->dwarf_abbrev_size)
        break;
-      abbrev_number = _bfd_safe_read_leb128 (abfd, abbrev_ptr,
-                                            &bytes_read, FALSE, abbrev_end);
-      abbrev_ptr += bytes_read;
+      abbrev_number = _bfd_safe_read_leb128 (abfd, &abbrev_ptr,
+                                            false, abbrev_end);
       if (lookup_abbrev (abbrev_number, abbrevs) != NULL)
        break;
     }
 
+  *slot = bfd_malloc (sizeof ent);
+  if (!*slot)
+    goto fail;
+  ent.abbrevs = abbrevs;
+  memcpy (*slot, &ent, sizeof ent);
   return abbrevs;
-}
 
-/* Returns true if the form is one which has a string value.  */
+ fail:
+  if (abbrevs != NULL)
+    {
+      size_t i;
 
-static inline bfd_boolean
-is_str_attr (enum dwarf_form form)
-{
-  return (form == DW_FORM_string || form == DW_FORM_strp
-         || form == DW_FORM_line_strp || form == DW_FORM_GNU_strp_alt);
+      for (i = 0; i < ABBREV_HASH_SIZE; i++)
+       {
+         struct abbrev_info *abbrev = abbrevs[i];
+
+         while (abbrev)
+           {
+             free (abbrev->attrs);
+             abbrev = abbrev->next;
+           }
+       }
+      free (abbrevs);
+    }
+  return NULL;
 }
 
-/* Read and fill in the value of attribute ATTR as described by FORM.
-   Read data starting from INFO_PTR, but never at or beyond INFO_PTR_END.
-   Returns an updated INFO_PTR taking into account the amount of data read.  */
+/* Returns true if the form is one which has a string value.  */
 
-static bfd_byte *
-read_attribute_value (struct attribute *  attr,
-                     unsigned            form,
-                     bfd_vma             implicit_const,
-                     struct comp_unit *  unit,
-                     bfd_byte *          info_ptr,
-                     bfd_byte *          info_ptr_end)
+static bool
+is_str_form (const struct attribute *attr)
 {
-  bfd *abfd = unit->abfd;
-  unsigned int bytes_read;
-  struct dwarf_block *blk;
-  bfd_size_type amt;
-
-  if (info_ptr >= info_ptr_end && form != DW_FORM_flag_present)
+  switch (attr->form)
     {
-      _bfd_error_handler (_("Dwarf Error: Info pointer extends beyond end of attributes"));
-      bfd_set_error (bfd_error_bad_value);
-      return info_ptr;
+    case DW_FORM_string:
+    case DW_FORM_strp:
+    case DW_FORM_strx:
+    case DW_FORM_strx1:
+    case DW_FORM_strx2:
+    case DW_FORM_strx3:
+    case DW_FORM_strx4:
+    case DW_FORM_line_strp:
+    case DW_FORM_GNU_strp_alt:
+      return true;
+
+    default:
+      return false;
     }
+}
 
-  attr->form = (enum dwarf_form) form;
+/* Returns true if the form is one which has an integer value.  */
 
-  switch (form)
+static bool
+is_int_form (const struct attribute *attr)
+{
+  switch (attr->form)
     {
-    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, info_ptr_end);
-         else
-           attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
-         info_ptr += unit->offset_size;
-         break;
-       }
-      /* FALLTHROUGH */
     case DW_FORM_addr:
-      attr->u.val = read_address (unit, info_ptr, info_ptr_end);
-      info_ptr += unit->addr_size;
-      break;
-    case DW_FORM_GNU_ref_alt:
-    case DW_FORM_sec_offset:
-      if (unit->offset_size == 4)
-       attr->u.val = read_4_bytes (unit->abfd, info_ptr, info_ptr_end);
-      else
-       attr->u.val = read_8_bytes (unit->abfd, info_ptr, info_ptr_end);
-      info_ptr += unit->offset_size;
-      break;
-    case DW_FORM_block2:
-      amt = sizeof (struct dwarf_block);
-      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
-      if (blk == NULL)
-       return NULL;
-      blk->size = read_2_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 2;
-      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
-      info_ptr += blk->size;
-      attr->u.blk = blk;
-      break;
-    case DW_FORM_block4:
-      amt = sizeof (struct dwarf_block);
-      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
-      if (blk == NULL)
-       return NULL;
-      blk->size = read_4_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 4;
-      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
-      info_ptr += blk->size;
-      attr->u.blk = blk;
-      break;
     case DW_FORM_data2:
-      attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 2;
-      break;
     case DW_FORM_data4:
-      attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 4;
-      break;
     case DW_FORM_data8:
-      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 8;
-      break;
-    case DW_FORM_string:
-      attr->u.str = read_string (abfd, info_ptr, info_ptr_end, &bytes_read);
-      info_ptr += bytes_read;
-      break;
-    case DW_FORM_strp:
-      attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
-      info_ptr += bytes_read;
-      break;
-    case DW_FORM_line_strp:
-      attr->u.str = read_indirect_line_string (unit, info_ptr, info_ptr_end, &bytes_read);
-      info_ptr += bytes_read;
-      break;
-    case DW_FORM_GNU_strp_alt:
-      attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read);
-      info_ptr += bytes_read;
-      break;
-    case DW_FORM_exprloc:
-    case DW_FORM_block:
-      amt = sizeof (struct dwarf_block);
-      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
-      if (blk == NULL)
-       return NULL;
-      blk->size = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                        FALSE, info_ptr_end);
-      info_ptr += bytes_read;
-      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
-      info_ptr += blk->size;
-      attr->u.blk = blk;
-      break;
-    case DW_FORM_block1:
-      amt = sizeof (struct dwarf_block);
-      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
-      if (blk == NULL)
-       return NULL;
-      blk->size = read_1_byte (abfd, info_ptr, info_ptr_end);
-      info_ptr += 1;
-      blk->data = read_n_bytes (abfd, info_ptr, info_ptr_end, blk->size);
-      info_ptr += blk->size;
-      attr->u.blk = blk;
-      break;
     case DW_FORM_data1:
-      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
-      info_ptr += 1;
-      break;
     case DW_FORM_flag:
-      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
-      info_ptr += 1;
-      break;
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_ref_addr:
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+    case DW_FORM_sec_offset:
+    case DW_FORM_flag_present:
+    case DW_FORM_ref_sig8:
+    case DW_FORM_addrx:
+    case DW_FORM_implicit_const:
+    case DW_FORM_addrx1:
+    case DW_FORM_addrx2:
+    case DW_FORM_addrx3:
+    case DW_FORM_addrx4:
+    case DW_FORM_GNU_ref_alt:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* Returns true if the form is strx[1-4].  */
+
+static inline bool
+is_strx_form (enum dwarf_form form)
+{
+  return (form == DW_FORM_strx
+         || form == DW_FORM_strx1
+         || form == DW_FORM_strx2
+         || form == DW_FORM_strx3
+         || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4].  */
+
+static inline bool
+is_addrx_form (enum dwarf_form form)
+{
+  return (form == DW_FORM_addrx
+         || form == DW_FORM_addrx1
+         || form == DW_FORM_addrx2
+         || form == DW_FORM_addrx3
+         || form == DW_FORM_addrx4);
+}
+
+/* Returns the address in .debug_addr section using DW_AT_addr_base.
+   Used to implement DW_FORM_addrx*.  */
+static uint64_t
+read_indexed_address (uint64_t idx, struct comp_unit *unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  bfd_byte *info_ptr;
+  size_t offset;
+
+  if (stash == NULL)
+    return 0;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
+                    file->syms, 0,
+                    &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+    return 0;
+
+  if (_bfd_mul_overflow (idx, unit->addr_size, &offset))
+    return 0;
+
+  offset += unit->dwarf_addr_offset;
+  if (offset < unit->dwarf_addr_offset
+      || offset > file->dwarf_addr_size
+      || file->dwarf_addr_size - offset < unit->addr_size)
+    return 0;
+
+  info_ptr = file->dwarf_addr_buffer + offset;
+
+  if (unit->addr_size == 4)
+    return bfd_get_32 (unit->abfd, info_ptr);
+  else if (unit->addr_size == 8)
+    return bfd_get_64 (unit->abfd, info_ptr);
+  else
+    return 0;
+}
+
+/* Returns the string using DW_AT_str_offsets_base.
+   Used to implement DW_FORM_strx*.  */
+static const char *
+read_indexed_string (uint64_t idx, struct comp_unit *unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+  bfd_byte *info_ptr;
+  uint64_t str_offset;
+  size_t offset;
+
+  if (stash == NULL)
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
+                    file->syms, 0,
+                    &file->dwarf_str_buffer, &file->dwarf_str_size))
+    return NULL;
+
+  if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+                    file->syms, 0,
+                    &file->dwarf_str_offsets_buffer,
+                    &file->dwarf_str_offsets_size))
+    return NULL;
+
+  if (_bfd_mul_overflow (idx, unit->offset_size, &offset))
+    return NULL;
+
+  offset += unit->dwarf_str_offset;
+  if (offset < unit->dwarf_str_offset
+      || offset > file->dwarf_str_offsets_size
+      || file->dwarf_str_offsets_size - offset < unit->offset_size)
+    return NULL;
+
+  info_ptr = file->dwarf_str_offsets_buffer + offset;
+
+  if (unit->offset_size == 4)
+    str_offset = bfd_get_32 (unit->abfd, info_ptr);
+  else if (unit->offset_size == 8)
+    str_offset = bfd_get_64 (unit->abfd, info_ptr);
+  else
+    return NULL;
+
+  if (str_offset >= file->dwarf_str_size)
+    return NULL;
+  return (const char *) file->dwarf_str_buffer + str_offset;
+}
+
+/* Read and fill in the value of attribute ATTR as described by FORM.
+   Read data starting from INFO_PTR, but never at or beyond INFO_PTR_END.
+   Returns an updated INFO_PTR taking into account the amount of data read.  */
+
+static bfd_byte *
+read_attribute_value (struct attribute *  attr,
+                     unsigned            form,
+                     bfd_vma             implicit_const,
+                     struct comp_unit *  unit,
+                     bfd_byte *          info_ptr,
+                     bfd_byte *          info_ptr_end)
+{
+  bfd *abfd = unit->abfd;
+  size_t amt;
+
+  if (info_ptr >= info_ptr_end && form != DW_FORM_flag_present)
+    {
+      _bfd_error_handler (_("DWARF error: info pointer extends beyond end of attributes"));
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+
+  attr->form = (enum dwarf_form) form;
+
+  switch (form)
+    {
     case DW_FORM_flag_present:
       attr->u.val = 1;
       break;
-    case DW_FORM_sdata:
-      attr->u.sval = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                           TRUE, info_ptr_end);
-      info_ptr += bytes_read;
+    case DW_FORM_ref_addr:
+      /* DW_FORM_ref_addr is an address in DWARF2, and an offset in
+        DWARF3.  */
+      if (unit->version >= 3)
+       {
+         if (unit->offset_size == 4)
+           attr->u.val = read_4_bytes (unit->abfd, &info_ptr, info_ptr_end);
+         else
+           attr->u.val = read_8_bytes (unit->abfd, &info_ptr, info_ptr_end);
+         break;
+       }
+      /* FALLTHROUGH */
+    case DW_FORM_addr:
+      attr->u.val = read_address (unit, &info_ptr, info_ptr_end);
       break;
-    case DW_FORM_udata:
-      attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                          FALSE, info_ptr_end);
-      info_ptr += bytes_read;
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_sec_offset:
+      if (unit->offset_size == 4)
+       attr->u.val = read_4_bytes (unit->abfd, &info_ptr, info_ptr_end);
+      else
+       attr->u.val = read_8_bytes (unit->abfd, &info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_block2:
+      amt = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      attr->u.blk = read_blk (abfd, &info_ptr, info_ptr_end, amt);
+      if (attr->u.blk == NULL)
+       return NULL;
+      break;
+    case DW_FORM_block4:
+      amt = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      attr->u.blk = read_blk (abfd, &info_ptr, info_ptr_end, amt);
+      if (attr->u.blk == NULL)
+       return NULL;
       break;
     case DW_FORM_ref1:
-      attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end);
-      info_ptr += 1;
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
       break;
+    case DW_FORM_addrx1:
+      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
+        is not yet read.  */
+      if (unit->dwarf_addr_offset != 0)
+       attr->u.val = read_indexed_address (attr->u.val, unit);
+      break;
+    case DW_FORM_data2:
     case DW_FORM_ref2:
-      attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 2;
+      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_addrx2:
+      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+       attr->u.val = read_indexed_address (attr->u.val, unit);
+      break;
+    case DW_FORM_addrx3:
+      attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+       attr->u.val = read_indexed_address(attr->u.val, unit);
       break;
     case DW_FORM_ref4:
-      attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 4;
+    case DW_FORM_data4:
+      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
       break;
-    case DW_FORM_ref8:
-      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 8;
+    case DW_FORM_addrx4:
+      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+       attr->u.val = read_indexed_address (attr->u.val, unit);
       break;
+    case DW_FORM_data8:
+    case DW_FORM_ref8:
     case DW_FORM_ref_sig8:
-      attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end);
-      info_ptr += 8;
+      attr->u.val = read_8_bytes (abfd, &info_ptr, info_ptr_end);
       break;
+    case DW_FORM_string:
+      attr->u.str = read_string (&info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_strp:
+      attr->u.str = read_indirect_string (unit, &info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_line_strp:
+      attr->u.str = read_indirect_line_string (unit, &info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_GNU_strp_alt:
+      attr->u.str = read_alt_indirect_string (unit, &info_ptr, info_ptr_end);
+      break;
+    case DW_FORM_strx1:
+      attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
+        is not yet read.  */
+      if (unit->dwarf_str_offset != 0)
+       attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+       attr->u.str = NULL;
+      break;
+    case DW_FORM_strx2:
+      attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_str_offset != 0)
+       attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+       attr->u.str = NULL;
+      break;
+    case DW_FORM_strx3:
+      attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_str_offset != 0)
+       attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+       attr->u.str = NULL;
+      break;
+    case DW_FORM_strx4:
+      attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+      if (unit->dwarf_str_offset != 0)
+       attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+       attr->u.str = NULL;
+      break;
+    case DW_FORM_strx:
+      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                          false, info_ptr_end);
+      if (unit->dwarf_str_offset != 0)
+       attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+      else
+       attr->u.str = NULL;
+      break;
+    case DW_FORM_exprloc:
+    case DW_FORM_block:
+      amt = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                  false, info_ptr_end);
+      attr->u.blk = read_blk (abfd, &info_ptr, info_ptr_end, amt);
+      if (attr->u.blk == NULL)
+       return NULL;
+      break;
+    case DW_FORM_block1:
+      amt = read_1_byte (abfd, &info_ptr, info_ptr_end);
+      attr->u.blk = read_blk (abfd, &info_ptr, info_ptr_end, amt);
+      if (attr->u.blk == NULL)
+       return NULL;
+      break;
+    case DW_FORM_sdata:
+      attr->u.sval = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                           true, info_ptr_end);
+      break;
+
+    case DW_FORM_rnglistx:
+    case DW_FORM_loclistx:
+      /* FIXME: Add support for these forms!  */
+      /* Fall through.  */
     case DW_FORM_ref_udata:
-      attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                          FALSE, info_ptr_end);
-      info_ptr += bytes_read;
+    case DW_FORM_udata:
+      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                          false, info_ptr_end);
+      break;
+    case DW_FORM_addrx:
+      attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                          false, info_ptr_end);
+      if (unit->dwarf_addr_offset != 0)
+       attr->u.val = read_indexed_address (attr->u.val, unit);
       break;
     case DW_FORM_indirect:
-      form = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                   FALSE, info_ptr_end);
-      info_ptr += bytes_read;
+      form = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                   false, info_ptr_end);
       if (form == DW_FORM_implicit_const)
-       {
-         implicit_const = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                                 TRUE, info_ptr_end);
-         info_ptr += bytes_read;
-       }
+       implicit_const = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                               true, info_ptr_end);
       info_ptr = read_attribute_value (attr, form, implicit_const, unit,
                                       info_ptr, info_ptr_end);
       break;
@@ -1257,8 +1682,16 @@ read_attribute_value (struct attribute *  attr,
       attr->form = DW_FORM_sdata;
       attr->u.sval = implicit_const;
       break;
+    case DW_FORM_data16:
+      /* This is really a "constant", but there is no way to store that
+         so pretend it is a 16 byte block instead.  */
+      attr->u.blk = read_blk (abfd, &info_ptr, info_ptr_end, 16);
+      if (attr->u.blk == NULL)
+       return NULL;
+      break;
+
     default:
-      _bfd_error_handler (_("Dwarf Error: Invalid or unhandled FORM value: %#x."),
+      _bfd_error_handler (_("DWARF error: invalid or unhandled FORM value: %#x"),
                          form);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -1272,8 +1705,8 @@ static bfd_byte *
 read_attribute (struct attribute *    attr,
                struct attr_abbrev *  abbrev,
                struct comp_unit *    unit,
-               bfd_byte *            info_ptr,
-               bfd_byte *            info_ptr_end)
+               bfd_byte *            info_ptr,
+               bfd_byte *            info_ptr_end)
 {
   attr->name = abbrev->name;
   info_ptr = read_attribute_value (attr, abbrev->form, abbrev->implicit_const,
@@ -1281,30 +1714,52 @@ read_attribute (struct attribute *    attr,
   return info_ptr;
 }
 
-/* Return whether DW_AT_name will return the same as DW_AT_linkage_name
-   for a function.  */
+/* Return mangling style given LANG.  */
 
-static bfd_boolean
-non_mangled (int lang)
+static int
+mangle_style (int lang)
 {
   switch (lang)
     {
+    case DW_LANG_Ada83:
+    case DW_LANG_Ada95:
+      return DMGL_GNAT;
+
+    case DW_LANG_C_plus_plus:
+    case DW_LANG_C_plus_plus_03:
+    case DW_LANG_C_plus_plus_11:
+    case DW_LANG_C_plus_plus_14:
+      return DMGL_GNU_V3;
+
+    case DW_LANG_Java:
+      return DMGL_JAVA;
+
+    case DW_LANG_D:
+      return DMGL_DLANG;
+
+    case DW_LANG_Rust:
+    case DW_LANG_Rust_old:
+      return DMGL_RUST;
+
     default:
-      return FALSE;
+      return DMGL_AUTO;
 
     case DW_LANG_C89:
     case DW_LANG_C:
-    case DW_LANG_Ada83:
     case DW_LANG_Cobol74:
     case DW_LANG_Cobol85:
     case DW_LANG_Fortran77:
     case DW_LANG_Pascal83:
-    case DW_LANG_C99:
-    case DW_LANG_Ada95:
     case DW_LANG_PLI:
+    case DW_LANG_C99:
     case DW_LANG_UPC:
     case DW_LANG_C11:
-      return TRUE;
+    case DW_LANG_Mips_Assembler:
+    case DW_LANG_Upc:
+    case DW_LANG_HP_Basic91:
+    case DW_LANG_HP_IMacro:
+    case DW_LANG_HP_Assembler:
+      return 0;
     }
 }
 
@@ -1335,24 +1790,25 @@ struct fileinfo
 
 struct line_sequence
 {
-  bfd_vma               low_pc;
+  bfd_vma              low_pc;
   struct line_sequence* prev_sequence;
-  struct line_info*     last_line;  /* Largest VMA.  */
-  struct line_info**    line_info_lookup;
+  struct line_info*    last_line;  /* Largest VMA.  */
+  struct line_info**   line_info_lookup;
   bfd_size_type                num_lines;
 };
 
 struct line_info_table
 {
-  bfd *                 abfd;
-  unsigned int          num_files;
-  unsigned int          num_dirs;
-  unsigned int          num_sequences;
-  char *                comp_dir;
-  char **               dirs;
-  struct fileinfo*      files;
+  bfd *                        abfd;
+  unsigned int         num_files;
+  unsigned int         num_dirs;
+  unsigned int         num_sequences;
+  bool                  use_dir_and_file_0;
+  char *               comp_dir;
+  char **              dirs;
+  struct fileinfo*     files;
   struct line_sequence* sequences;
-  struct line_info*     lcl_head;   /* Local head; used in 'add_line_info'.  */
+  struct line_info*    lcl_head;   /* Local head; used in 'add_line_info'.  */
 };
 
 /* Remember some information about each function.  If the function is
@@ -1363,59 +1819,64 @@ struct line_info_table
 struct funcinfo
 {
   /* Pointer to previous function in list of all functions.  */
-  struct funcinfo *    prev_func;
+  struct funcinfo *prev_func;
   /* Pointer to function one scope higher.  */
-  struct funcinfo *    caller_func;
+  struct funcinfo *caller_func;
   /* Source location file name where caller_func inlines this func.  */
-  char *               caller_file;
+  char *caller_file;
   /* Source location file name.  */
-  char *               file;
+  char *file;
   /* Source location line number where caller_func inlines this func.  */
-  int                  caller_line;
+  int caller_line;
   /* Source location line number.  */
-  int                  line;
-  int                  tag;
-  bfd_boolean          is_linkage;
-  const char *         name;
-  struct arange                arange;
-  /* Where the symbol is defined.  */
-  asection *           sec;
+  int line;
+  int tag;
+  bool is_linkage;
+  const char *name;
+  struct arange arange;
+  /* The offset of the funcinfo from the start of the unit.  */
+  uint64_t unit_offset;
 };
 
 struct lookup_funcinfo
 {
   /* Function information corresponding to this lookup table entry.  */
-  struct funcinfo *    funcinfo;
+  struct funcinfo *funcinfo;
 
   /* The lowest address for this specific function.  */
-  bfd_vma              low_addr;
+  bfd_vma low_addr;
 
   /* The highest address of this function before the lookup table is sorted.
      The highest address of all prior functions after the lookup table is
      sorted, which is used for binary search.  */
-  bfd_vma              high_addr;
+  bfd_vma high_addr;
+  /* Index of this function, used to ensure qsort is stable.  */
+  unsigned int idx;
 };
 
 struct varinfo
 {
-  /* Pointer to previous variable in list of all variables */
+  /* Pointer to previous variable in list of all variables */
   struct varinfo *prev_var;
-  /* Source location file name */
+  /* The offset of the varinfo from the start of the unit.  */
+  uint64_t unit_offset;
+  /* Source location file name.  */
   char *file;
-  /* Source location line number */
+  /* Source location line number */
   int line;
+  /* The type of this variable.  */
   int tag;
-  char *name;
+  /* The name of the variable, if it has one.  */
+  const char *name;
+  /* The address of the variable.  */
   bfd_vma addr;
-  /* Where the symbol is defined */
-  asection *sec;
-  /* Is this a stack variable? */
-  unsigned int stack: 1;
+  /* Is this a stack variable?  */
+  bool stack;
 };
 
 /* Return TRUE if NEW_LINE should sort after LINE.  */
 
-static inline bfd_boolean
+static inline bool
 new_line_sorts_after (struct line_info *new_line, struct line_info *line)
 {
   return (new_line->address > line->address
@@ -1429,7 +1890,7 @@ new_line_sorts_after (struct line_info *new_line, struct line_info *line)
    highest to lowest VMA (with possible duplicates); that is,
    line_info->prev_line always accesses an equal or smaller VMA.  */
 
-static bfd_boolean
+static bool
 add_line_info (struct line_info_table *table,
               bfd_vma address,
               unsigned char op_index,
@@ -1439,12 +1900,12 @@ add_line_info (struct line_info_table *table,
               unsigned int discriminator,
               int end_sequence)
 {
-  bfd_size_type amt = sizeof (struct line_info);
+  size_t amt = sizeof (struct line_info);
   struct line_sequence* seq = table->sequences;
   struct line_info* info = (struct line_info *) bfd_alloc (table->abfd, amt);
 
   if (info == NULL)
-    return FALSE;
+    return false;
 
   /* Set member data of 'info'.  */
   info->prev_line = NULL;
@@ -1459,7 +1920,7 @@ add_line_info (struct line_info_table *table,
     {
       info->filename = (char *) bfd_alloc (table->abfd, strlen (filename) + 1);
       if (info->filename == NULL)
-       return FALSE;
+       return false;
       strcpy (info->filename, filename);
     }
   else
@@ -1498,7 +1959,7 @@ add_line_info (struct line_info_table *table,
       amt = sizeof (struct line_sequence);
       seq = (struct line_sequence *) bfd_malloc (amt);
       if (seq == NULL)
-       return FALSE;
+       return false;
       seq->low_pc = address;
       seq->prev_sequence = table->sequences;
       seq->last_line = info;
@@ -1547,7 +2008,7 @@ add_line_info (struct line_info_table *table,
       if (address < seq->low_pc)
        seq->low_pc = address;
     }
-  return TRUE;
+  return true;
 }
 
 /* Extract a fully qualified filename from a line info table.
@@ -1559,16 +2020,30 @@ concat_filename (struct line_info_table *table, unsigned int file)
 {
   char *filename;
 
-  if (file - 1 >= table->num_files)
+  /* Pre DWARF-5 entry 0 in the directory and filename tables was not used.
+     So in order to save space in the tables used here the info for, eg
+     directory 1 is stored in slot 0 of the directory table, directory 2
+     in slot 1 and so on.
+
+     Starting with DWARF-5 the 0'th entry is used so there is a one to one
+     mapping between DWARF slots and internal table entries.  */
+  if (! table->use_dir_and_file_0)
+    {
+      /* Pre DWARF-5, FILE == 0 means unknown.  */
+      if (file == 0)
+       return strdup ("<unknown>");
+      -- file;
+    }
+
+  if (table == NULL || file >= table->num_files)
     {
-      /* FILE == 0 means unknown.  */
-      if (file)
-       _bfd_error_handler
-         (_("Dwarf Error: mangled line number section (bad file number)."));
+      _bfd_error_handler
+       (_("DWARF error: mangled line number section (bad file number)"));
       return strdup ("<unknown>");
     }
 
-  filename = table->files[file - 1].name;
+  filename = table->files[file].name;
+
   if (filename == NULL)
     return strdup ("<unknown>");
 
@@ -1578,13 +2053,16 @@ concat_filename (struct line_info_table *table, unsigned int file)
       char *subdir_name = NULL;
       char *name;
       size_t len;
+      unsigned int dir = table->files[file].dir;
 
-      if (table->files[file - 1].dir
-         /* PR 17512: file: 0317e960.  */
-         && table->files[file - 1].dir <= table->num_dirs
-         /* PR 17512: file: 7f3d2e4b.  */
-         && table->dirs != NULL)
-       subdir_name = table->dirs[table->files[file - 1].dir - 1];
+      if (!table->use_dir_and_file_0)
+       --dir;
+      /* Wrapping from 0 to -1u above gives the intended result with
+        the test below of leaving subdir_name NULL for pre-DWARF5 dir
+        of 0.  */
+      /* PR 17512: file: 0317e960, file: 7f3d2e4b.  */
+      if (dir < table->num_dirs)
+       subdir_name = table->dirs[dir];
 
       if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name))
        dir_name = table->comp_dir;
@@ -1620,22 +2098,219 @@ concat_filename (struct line_info_table *table, unsigned int file)
   return strdup (filename);
 }
 
-static bfd_boolean
-arange_add (const struct comp_unit *unit, struct arange *first_arange,
-           bfd_vma low_pc, bfd_vma high_pc)
+/* Number of bits in a bfd_vma.  */
+#define VMA_BITS (8 * sizeof (bfd_vma))
+
+/* Check whether [low1, high1) can be combined with [low2, high2),
+   i.e., they touch or overlap.  */
+
+static bool
+ranges_overlap (bfd_vma low1,
+               bfd_vma high1,
+               bfd_vma low2,
+               bfd_vma high2)
+{
+  if (low1 == low2 || high1 == high2)
+    return true;
+
+  /* Sort so that low1 is below low2. */
+  if (low1 > low2)
+    {
+      bfd_vma tmp;
+
+      tmp = low1;
+      low1 = low2;
+      low2 = tmp;
+
+      tmp = high1;
+      high1 = high2;
+      high2 = tmp;
+    }
+
+  /* We touch iff low2 == high1.
+     We overlap iff low2 is within [low1, high1). */
+  return low2 <= high1;
+}
+
+/* Insert an address range in the trie mapping addresses to compilation units.
+   Will return the new trie node (usually the same as is being sent in, but
+   in case of a leaf-to-interior conversion, or expansion of a leaf, it may be
+   different), or NULL on failure.  */
+
+static struct trie_node *
+insert_arange_in_trie (bfd *abfd,
+                      struct trie_node *trie,
+                      bfd_vma trie_pc,
+                      unsigned int trie_pc_bits,
+                      struct comp_unit *unit,
+                      bfd_vma low_pc,
+                      bfd_vma high_pc)
+{
+  bfd_vma clamped_low_pc, clamped_high_pc;
+  int ch, from_ch, to_ch;
+  bool is_full_leaf = false;
+
+  /* See if we can extend any of the existing ranges.  This merging
+     isn't perfect (if merging opens up the possibility of merging two existing
+     ranges, we won't find them), but it takes the majority of the cases.  */
+  if (trie->num_room_in_leaf > 0)
+    {
+      struct trie_leaf *leaf = (struct trie_leaf *) trie;
+      unsigned int i;
+
+      for (i = 0; i < leaf->num_stored_in_leaf; ++i)
+       {
+         if (leaf->ranges[i].unit == unit
+             && ranges_overlap (low_pc, high_pc,
+                                leaf->ranges[i].low_pc,
+                                leaf->ranges[i].high_pc))
+           {
+             if (low_pc < leaf->ranges[i].low_pc)
+               leaf->ranges[i].low_pc = low_pc;
+             if (high_pc > leaf->ranges[i].high_pc)
+               leaf->ranges[i].high_pc = high_pc;
+             return trie;
+           }
+       }
+
+      is_full_leaf = leaf->num_stored_in_leaf == trie->num_room_in_leaf;
+    }
+
+  /* If we're a leaf with no more room and we're _not_ at the bottom,
+     convert to an interior node.  */
+  if (is_full_leaf && trie_pc_bits < VMA_BITS)
+    {
+      const struct trie_leaf *leaf = (struct trie_leaf *) trie;
+      unsigned int i;
+
+      trie = bfd_zalloc (abfd, sizeof (struct trie_interior));
+      if (!trie)
+       return NULL;
+      is_full_leaf = false;
+
+      /* TODO: If we wanted to save a little more memory at the cost of
+        complexity, we could have reused the old leaf node as one of the
+        children of the new interior node, instead of throwing it away.  */
+      for (i = 0; i < leaf->num_stored_in_leaf; ++i)
+        {
+         if (!insert_arange_in_trie (abfd, trie, trie_pc, trie_pc_bits,
+                                     leaf->ranges[i].unit, leaf->ranges[i].low_pc,
+                                     leaf->ranges[i].high_pc))
+           return NULL;
+       }
+    }
+
+  /* If we're a leaf with no more room and we _are_ at the bottom,
+     we have no choice but to just make it larger. */
+  if (is_full_leaf)
+    {
+      const struct trie_leaf *leaf = (struct trie_leaf *) trie;
+      unsigned int new_room_in_leaf = trie->num_room_in_leaf * 2;
+      struct trie_leaf *new_leaf;
+      size_t amt = (sizeof (struct trie_leaf)
+                   + ((new_room_in_leaf - TRIE_LEAF_SIZE)
+                      * sizeof (leaf->ranges[0])));
+      new_leaf = bfd_zalloc (abfd, amt);
+      new_leaf->head.num_room_in_leaf = new_room_in_leaf;
+      new_leaf->num_stored_in_leaf = leaf->num_stored_in_leaf;
+
+      memcpy (new_leaf->ranges,
+             leaf->ranges,
+             leaf->num_stored_in_leaf * sizeof (leaf->ranges[0]));
+      trie = &new_leaf->head;
+      is_full_leaf = false;
+
+      /* Now the insert below will go through.  */
+    }
+
+  /* If we're a leaf (now with room), we can just insert at the end.  */
+  if (trie->num_room_in_leaf > 0)
+    {
+      struct trie_leaf *leaf = (struct trie_leaf *) trie;
+
+      unsigned int i = leaf->num_stored_in_leaf++;
+      leaf->ranges[i].unit = unit;
+      leaf->ranges[i].low_pc = low_pc;
+      leaf->ranges[i].high_pc = high_pc;
+      return trie;
+    }
+
+  /* Now we are definitely an interior node, so recurse into all
+     the relevant buckets.  */
+
+  /* Clamp the range to the current trie bucket.  */
+  clamped_low_pc = low_pc;
+  clamped_high_pc = high_pc;
+  if (trie_pc_bits > 0)
+    {
+      bfd_vma bucket_high_pc =
+       trie_pc + ((bfd_vma) -1 >> trie_pc_bits);  /* Inclusive.  */
+      if (clamped_low_pc < trie_pc)
+       clamped_low_pc = trie_pc;
+      if (clamped_high_pc > bucket_high_pc)
+       clamped_high_pc = bucket_high_pc;
+    }
+
+  /* Insert the ranges in all buckets that it spans.  */
+  from_ch = (clamped_low_pc >> (VMA_BITS - trie_pc_bits - 8)) & 0xff;
+  to_ch = ((clamped_high_pc - 1) >> (VMA_BITS - trie_pc_bits - 8)) & 0xff;
+  for (ch = from_ch; ch <= to_ch; ++ch)
+    {
+      struct trie_interior *interior = (struct trie_interior *) trie;
+      struct trie_node *child = interior->children[ch];
+
+      if (child == NULL)
+        {
+         child = alloc_trie_leaf (abfd);
+         if (!child)
+           return NULL;
+       }
+      bfd_vma bucket = (bfd_vma) ch << (VMA_BITS - trie_pc_bits - 8);
+      child = insert_arange_in_trie (abfd,
+                                    child,
+                                    trie_pc + bucket,
+                                    trie_pc_bits + 8,
+                                    unit,
+                                    low_pc,
+                                    high_pc);
+      if (!child)
+       return NULL;
+
+      interior->children[ch] = child;
+    }
+
+    return trie;
+}
+
+static bool
+arange_add (struct comp_unit *unit, struct arange *first_arange,
+           struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc)
 {
   struct arange *arange;
 
   /* Ignore empty ranges.  */
   if (low_pc == high_pc)
-    return TRUE;
+    return true;
+
+  if (trie_root != NULL)
+    {
+      *trie_root = insert_arange_in_trie (unit->file->bfd_ptr,
+                                         *trie_root,
+                                         0,
+                                         0,
+                                         unit,
+                                         low_pc,
+                                         high_pc);
+      if (*trie_root == NULL)
+       return false;
+    }
 
   /* If the first arange is empty, use it.  */
   if (first_arange->high == 0)
     {
       first_arange->low = low_pc;
       first_arange->high = high_pc;
-      return TRUE;
+      return true;
     }
 
   /* Next see if we can cheaply extend an existing range.  */
@@ -1645,12 +2320,12 @@ arange_add (const struct comp_unit *unit, struct arange *first_arange,
       if (low_pc == arange->high)
        {
          arange->high = high_pc;
-         return TRUE;
+         return true;
        }
       if (high_pc == arange->low)
        {
          arange->low = low_pc;
-         return TRUE;
+         return true;
        }
       arange = arange->next;
     }
@@ -1660,12 +2335,12 @@ arange_add (const struct comp_unit *unit, struct arange *first_arange,
      Order isn't significant, so just insert after the first arange.  */
   arange = (struct arange *) bfd_alloc (unit->abfd, sizeof (*arange));
   if (arange == NULL)
-    return FALSE;
+    return false;
   arange->low = low_pc;
   arange->high = high_pc;
   arange->next = first_arange->next;
   first_arange->next = arange;
-  return TRUE;
+  return true;
 }
 
 /* Compare function for line sequences.  */
@@ -1694,23 +2369,28 @@ compare_sequences (const void* a, const void* b)
   if (seq1->last_line->op_index > seq2->last_line->op_index)
     return -1;
 
+  /* num_lines is initially an index, to make the sort stable.  */
+  if (seq1->num_lines < seq2->num_lines)
+    return -1;
+  if (seq1->num_lines > seq2->num_lines)
+    return 1;
   return 0;
 }
 
 /* Construct the line information table for quick lookup.  */
 
-static bfd_boolean
+static bool
 build_line_info_table (struct line_info_table *  table,
                       struct line_sequence *    seq)
 {
-  bfd_size_type      amt;
-  struct line_info** line_info_lookup;
-  struct line_info*  each_line;
-  unsigned int       num_lines;
-  unsigned int       line_index;
+  size_t amt;
+  struct line_info **line_info_lookup;
+  struct line_info *each_line;
+  unsigned int num_lines;
+  unsigned int line_index;
 
   if (seq->line_info_lookup != NULL)
-    return TRUE;
+    return true;
 
   /* Count the number of line information entries.  We could do this while
      scanning the debug information, but some entries may be added via
@@ -1720,14 +2400,16 @@ build_line_info_table (struct line_info_table *  table,
   for (each_line = seq->last_line; each_line; each_line = each_line->prev_line)
     num_lines++;
 
+  seq->num_lines = num_lines;
   if (num_lines == 0)
-    return TRUE;
+    return true;
 
   /* Allocate space for the line information lookup table.  */
   amt = sizeof (struct line_info*) * num_lines;
   line_info_lookup = (struct line_info**) bfd_alloc (table->abfd, amt);
+  seq->line_info_lookup = line_info_lookup;
   if (line_info_lookup == NULL)
-    return FALSE;
+    return false;
 
   /* Create the line information lookup table.  */
   line_index = num_lines;
@@ -1735,33 +2417,29 @@ build_line_info_table (struct line_info_table *  table,
     line_info_lookup[--line_index] = each_line;
 
   BFD_ASSERT (line_index == 0);
-
-  seq->num_lines = num_lines;
-  seq->line_info_lookup = line_info_lookup;
-
-  return TRUE;
+  return true;
 }
 
 /* Sort the line sequences for quick lookup.  */
 
-static bfd_boolean
+static bool
 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;
+  size_t 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;
+    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;
+    return false;
 
   /* Copy the linked list into the array, freeing the original nodes.  */
   seq = table->sequences;
@@ -1774,7 +2452,7 @@ sort_line_sequences (struct line_info_table* table)
       sequences[n].prev_sequence = NULL;
       sequences[n].last_line = seq->last_line;
       sequences[n].line_info_lookup = NULL;
-      sequences[n].num_lines = 0;
+      sequences[n].num_lines = n;
       seq = seq->prev_sequence;
       free (last_seq);
     }
@@ -1809,33 +2487,33 @@ sort_line_sequences (struct line_info_table* table)
 
   table->sequences = sequences;
   table->num_sequences = num_sequences;
-  return TRUE;
+  return true;
 }
 
 /* Add directory to TABLE.  CUR_DIR memory ownership is taken by TABLE.  */
 
-static bfd_boolean
+static bool
 line_info_add_include_dir (struct line_info_table *table, char *cur_dir)
 {
   if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
     {
       char **tmp;
-      bfd_size_type amt;
+      size_t amt;
 
       amt = table->num_dirs + DIR_ALLOC_CHUNK;
       amt *= sizeof (char *);
 
       tmp = (char **) bfd_realloc (table->dirs, amt);
       if (tmp == NULL)
-       return FALSE;
+       return false;
       table->dirs = tmp;
     }
 
   table->dirs[table->num_dirs++] = cur_dir;
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 line_info_add_include_dir_stub (struct line_info_table *table, char *cur_dir,
                                unsigned int dir ATTRIBUTE_UNUSED,
                                unsigned int xtime ATTRIBUTE_UNUSED,
@@ -1846,7 +2524,7 @@ line_info_add_include_dir_stub (struct line_info_table *table, char *cur_dir,
 
 /* Add file to TABLE.  CUR_FILE memory ownership is taken by TABLE.  */
 
-static bfd_boolean
+static bool
 line_info_add_file_name (struct line_info_table *table, char *cur_file,
                         unsigned int dir, unsigned int xtime,
                         unsigned int size)
@@ -1854,14 +2532,14 @@ line_info_add_file_name (struct line_info_table *table, char *cur_file,
   if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
     {
       struct fileinfo *tmp;
-      bfd_size_type amt;
+      size_t amt;
 
       amt = table->num_files + FILE_ALLOC_CHUNK;
       amt *= sizeof (struct fileinfo);
 
       tmp = (struct fileinfo *) bfd_realloc (table->files, amt);
       if (tmp == NULL)
-       return FALSE;
+       return false;
       table->files = tmp;
     }
 
@@ -1870,7 +2548,7 @@ line_info_add_file_name (struct line_info_table *table, char *cur_file,
   table->files[table->num_files].time = xtime;
   table->files[table->num_files].size = size;
   table->num_files++;
-  return TRUE;
+  return true;
 }
 
 /* Read directory or file name entry format, starting with byte of
@@ -1878,50 +2556,46 @@ line_info_add_file_name (struct line_info_table *table, char *cur_file,
    entries count and the entries themselves in the described entry
    format.  */
 
-static bfd_boolean
+static bool
 read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
                        bfd_byte *buf_end, struct line_info_table *table,
-                       bfd_boolean (*callback) (struct line_info_table *table,
-                                                char *cur_file,
-                                                unsigned int dir,
-                                                unsigned int time,
-                                                unsigned int size))
+                       bool (*callback) (struct line_info_table *table,
+                                         char *cur_file,
+                                         unsigned int dir,
+                                         unsigned int time,
+                                         unsigned int size))
 {
   bfd *abfd = unit->abfd;
   bfd_byte format_count, formati;
   bfd_vma data_count, datai;
   bfd_byte *buf = *bufp;
   bfd_byte *format_header_data;
-  unsigned int bytes_read;
 
-  format_count = read_1_byte (abfd, buf, buf_end);
-  buf += 1;
+  format_count = read_1_byte (abfd, &buf, buf_end);
   format_header_data = buf;
   for (formati = 0; formati < format_count; formati++)
     {
-      _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
-      buf += bytes_read;
-      _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
-      buf += bytes_read;
+      _bfd_safe_read_leb128 (abfd, &buf, false, buf_end);
+      _bfd_safe_read_leb128 (abfd, &buf, false, buf_end);
     }
 
-  data_count = _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end);
-  buf += bytes_read;
+  data_count = _bfd_safe_read_leb128 (abfd, &buf, false, buf_end);
   if (format_count == 0 && data_count != 0)
     {
-      _bfd_error_handler (_("Dwarf Error: Zero format count."));
+      _bfd_error_handler (_("DWARF error: zero format count"));
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   /* PR 22210.  Paranoia check.  Don't bother running the loop
      if we know that we are going to run out of buffer.  */
   if (data_count > (bfd_vma) (buf_end - buf))
     {
-      _bfd_error_handler (_("Dwarf Error: data count (%Lx) larger than buffer size."),
-                         data_count);
+      _bfd_error_handler
+       (_("DWARF error: data count (%" PRIx64 ") larger than buffer size"),
+        (uint64_t) data_count);
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
   for (datai = 0; datai < data_count; datai++)
@@ -1938,9 +2612,7 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
          unsigned int uint_trash, *uintp = &uint_trash;
          struct attribute attr;
 
-         content_type = _bfd_safe_read_leb128 (abfd, format, &bytes_read,
-                                               FALSE, buf_end);
-         format += bytes_read;
+         content_type = _bfd_safe_read_leb128 (abfd, &format, false, buf_end);
          switch (content_type)
            {
            case DW_LNCT_path:
@@ -1959,23 +2631,25 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
              break;
            default:
              _bfd_error_handler
-               (_("Dwarf Error: Unknown format content type %Lu."),
-                content_type);
+               (_("DWARF error: unknown format content type %" PRIu64),
+                (uint64_t) content_type);
              bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             return false;
            }
 
-         form = _bfd_safe_read_leb128 (abfd, format, &bytes_read, FALSE,
-                                       buf_end);
-         format += bytes_read;
-
+         form = _bfd_safe_read_leb128 (abfd, &format, false, buf_end);
          buf = read_attribute_value (&attr, form, 0, unit, buf, buf_end);
          if (buf == NULL)
-           return FALSE;
+           return false;
          switch (form)
            {
            case DW_FORM_string:
            case DW_FORM_line_strp:
+           case DW_FORM_strx:
+           case DW_FORM_strx1:
+           case DW_FORM_strx2:
+           case DW_FORM_strx3:
+           case DW_FORM_strx4:
              *stringp = attr.u.str;
              break;
 
@@ -1986,82 +2660,70 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
            case DW_FORM_udata:
              *uintp = attr.u.val;
              break;
-           }
+
+           case DW_FORM_data16:
+             /* MD5 data is in the attr.blk, but we are ignoring those.  */
+             break;
+           }
        }
 
       if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
-       return FALSE;
+       return false;
     }
 
   *bufp = buf;
-  return TRUE;
+  return true;
 }
 
 /* Decode the line number information for UNIT.  */
 
 static struct line_info_table*
-decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
+decode_line_info (struct comp_unit *unit)
 {
   bfd *abfd = unit->abfd;
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
   struct line_info_table* table;
   bfd_byte *line_ptr;
   bfd_byte *line_end;
   struct line_head lh;
-  unsigned int i, bytes_read, offset_size;
+  unsigned int i, offset_size;
   char *cur_file, *cur_dir;
   unsigned char op_code, extended_op, adj_opcode;
   unsigned int exop_len;
-  bfd_size_type amt;
+  size_t amt;
 
-  if (! read_section (abfd, &stash->debug_sections[debug_line],
-                     stash->syms, unit->line_offset,
-                     &stash->dwarf_line_buffer, &stash->dwarf_line_size))
-    return NULL;
+  if (unit->line_offset == 0 && file->line_table)
+    return file->line_table;
 
-  amt = sizeof (struct line_info_table);
-  table = (struct line_info_table *) bfd_alloc (abfd, amt);
-  if (table == NULL)
+  if (! read_section (abfd, &stash->debug_sections[debug_line],
+                     file->syms, unit->line_offset,
+                     &file->dwarf_line_buffer, &file->dwarf_line_size))
     return NULL;
-  table->abfd = abfd;
-  table->comp_dir = unit->comp_dir;
 
-  table->num_files = 0;
-  table->files = NULL;
-
-  table->num_dirs = 0;
-  table->dirs = NULL;
-
-  table->num_sequences = 0;
-  table->sequences = NULL;
-
-  table->lcl_head = NULL;
-
-  if (stash->dwarf_line_size < 16)
+  if (file->dwarf_line_size < 16)
     {
       _bfd_error_handler
-       (_("Dwarf Error: Line info section is too small (%Ld)"),
-        stash->dwarf_line_size);
+       (_("DWARF error: line info section is too small (%" PRId64 ")"),
+        (int64_t) file->dwarf_line_size);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
-  line_ptr = stash->dwarf_line_buffer + unit->line_offset;
-  line_end = stash->dwarf_line_buffer + stash->dwarf_line_size;
+  line_ptr = file->dwarf_line_buffer + unit->line_offset;
+  line_end = file->dwarf_line_buffer + file->dwarf_line_size;
 
   /* Read in the prologue.  */
-  lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
-  line_ptr += 4;
+  lh.total_length = read_4_bytes (abfd, &line_ptr, line_end);
   offset_size = 4;
   if (lh.total_length == 0xffffffff)
     {
-      lh.total_length = read_8_bytes (abfd, line_ptr, line_end);
-      line_ptr += 8;
+      lh.total_length = read_8_bytes (abfd, &line_ptr, line_end);
       offset_size = 8;
     }
   else if (lh.total_length == 0 && unit->addr_size == 8)
     {
       /* Handle (non-standard) 64-bit DWARF2 formats.  */
-      lh.total_length = read_4_bytes (abfd, line_ptr, line_end);
-      line_ptr += 4;
+      lh.total_length = read_4_bytes (abfd, &line_ptr, line_end);
       offset_size = 8;
     }
 
@@ -2069,30 +2731,29 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
     {
       _bfd_error_handler
        /* xgettext: c-format */
-       (_("Dwarf Error: Line info data is bigger (%#Lx)"
+       (_("DWARF error: line info data is bigger (%#" PRIx64 ")"
           " than the space remaining in the section (%#lx)"),
-        lh.total_length, (unsigned long) (line_end - line_ptr));
+        (uint64_t) lh.total_length, (unsigned long) (line_end - line_ptr));
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
 
   line_end = line_ptr + lh.total_length;
 
-  lh.version = read_2_bytes (abfd, line_ptr, line_end);
+  lh.version = read_2_bytes (abfd, &line_ptr, line_end);
   if (lh.version < 2 || lh.version > 5)
     {
       _bfd_error_handler
-       (_("Dwarf Error: Unhandled .debug_line version %d."), lh.version);
+       (_("DWARF error: unhandled .debug_line version %d"), lh.version);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
-  line_ptr += 2;
 
   if (line_ptr + offset_size + (lh.version >= 5 ? 8 : (lh.version >= 4 ? 6 : 5))
       >= line_end)
     {
       _bfd_error_handler
-       (_("Dwarf Error: Ran out of room reading prologue"));
+       (_("DWARF error: ran out of room reading prologue"));
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
@@ -2102,15 +2763,13 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       unsigned int segment_selector_size;
 
       /* Skip address size.  */
-      read_1_byte (abfd, line_ptr, line_end);
-      line_ptr += 1;
+      read_1_byte (abfd, &line_ptr, line_end);
 
-      segment_selector_size = read_1_byte (abfd, line_ptr, line_end);
-      line_ptr += 1;
+      segment_selector_size = read_1_byte (abfd, &line_ptr, line_end);
       if (segment_selector_size != 0)
        {
          _bfd_error_handler
-           (_("Dwarf Error: Line info unsupported segment selector size %u."),
+           (_("DWARF error: line info unsupported segment selector size %u"),
             segment_selector_size);
          bfd_set_error (bfd_error_bad_value);
          return NULL;
@@ -2118,45 +2777,33 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
     }
 
   if (offset_size == 4)
-    lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end);
+    lh.prologue_length = read_4_bytes (abfd, &line_ptr, line_end);
   else
-    lh.prologue_length = read_8_bytes (abfd, line_ptr, line_end);
-  line_ptr += offset_size;
+    lh.prologue_length = read_8_bytes (abfd, &line_ptr, line_end);
 
-  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr, line_end);
-  line_ptr += 1;
+  lh.minimum_instruction_length = read_1_byte (abfd, &line_ptr, line_end);
 
   if (lh.version >= 4)
-    {
-      lh.maximum_ops_per_insn = read_1_byte (abfd, line_ptr, line_end);
-      line_ptr += 1;
-    }
+    lh.maximum_ops_per_insn = read_1_byte (abfd, &line_ptr, line_end);
   else
     lh.maximum_ops_per_insn = 1;
 
   if (lh.maximum_ops_per_insn == 0)
     {
       _bfd_error_handler
-       (_("Dwarf Error: Invalid maximum operations per instruction."));
+       (_("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_end);
-  line_ptr += 1;
-
-  lh.line_base = read_1_signed_byte (abfd, line_ptr, line_end);
-  line_ptr += 1;
-
-  lh.line_range = read_1_byte (abfd, line_ptr, line_end);
-  line_ptr += 1;
-
-  lh.opcode_base = read_1_byte (abfd, line_ptr, line_end);
-  line_ptr += 1;
+  lh.default_is_stmt = read_1_byte (abfd, &line_ptr, line_end);
+  lh.line_base = read_1_signed_byte (abfd, &line_ptr, line_end);
+  lh.line_range = read_1_byte (abfd, &line_ptr, line_end);
+  lh.opcode_base = read_1_byte (abfd, &line_ptr, line_end);
 
   if (line_ptr + (lh.opcode_base - 1) >= line_end)
     {
-      _bfd_error_handler (_("Dwarf Error: Ran out of room reading opcodes"));
+      _bfd_error_handler (_("DWARF error: ran out of room reading opcodes"));
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
@@ -2167,10 +2814,25 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
   lh.standard_opcode_lengths[0] = 1;
 
   for (i = 1; i < lh.opcode_base; ++i)
-    {
-      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr, line_end);
-      line_ptr += 1;
-    }
+    lh.standard_opcode_lengths[i] = read_1_byte (abfd, &line_ptr, line_end);
+
+  amt = sizeof (struct line_info_table);
+  table = (struct line_info_table *) bfd_alloc (abfd, amt);
+  if (table == NULL)
+    return NULL;
+  table->abfd = abfd;
+  table->comp_dir = unit->comp_dir;
+
+  table->num_files = 0;
+  table->files = NULL;
+
+  table->num_dirs = 0;
+  table->dirs = NULL;
+
+  table->num_sequences = 0;
+  table->sequences = NULL;
+
+  table->lcl_head = NULL;
 
   if (lh.version >= 5)
     {
@@ -2183,39 +2845,30 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       if (!read_formatted_entries (unit, &line_ptr, line_end, table,
                                   line_info_add_file_name))
        goto fail;
+      table->use_dir_and_file_0 = true;
     }
   else
     {
       /* Read directory table.  */
-      while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
+      while ((cur_dir = read_string (&line_ptr, line_end)) != NULL)
        {
-         line_ptr += bytes_read;
-
          if (!line_info_add_include_dir (table, cur_dir))
            goto fail;
        }
 
-      line_ptr += bytes_read;
-
       /* Read file name table.  */
-      while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL)
+      while ((cur_file = read_string (&line_ptr, line_end)) != NULL)
        {
          unsigned int dir, xtime, size;
 
-         line_ptr += bytes_read;
-
-         dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
-         line_ptr += bytes_read;
-         xtime = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
-         line_ptr += bytes_read;
-         size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end);
-         line_ptr += bytes_read;
+         dir = _bfd_safe_read_leb128 (abfd, &line_ptr, false, line_end);
+         xtime = _bfd_safe_read_leb128 (abfd, &line_ptr, false, line_end);
+         size = _bfd_safe_read_leb128 (abfd, &line_ptr, false, line_end);
 
          if (!line_info_add_file_name (table, cur_file, dir, xtime, size))
            goto fail;
        }
-
-      line_ptr += bytes_read;
+      table->use_dir_and_file_0 = false;
     }
 
   /* Read the statement sequences until there's nothing left.  */
@@ -2224,7 +2877,7 @@ 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;
+      char * filename = NULL;
       unsigned int line = 1;
       unsigned int column = 0;
       unsigned int discriminator = 0;
@@ -2239,11 +2892,18 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       bfd_vma low_pc  = (bfd_vma) -1;
       bfd_vma high_pc = 0;
 
+      if (table->num_files)
+       {
+         if (table->use_dir_and_file_0)
+           filename = concat_filename (table, 0);
+         else
+           filename = concat_filename (table, 1);
+       }
+
       /* Decode the table.  */
       while (!end_sequence && line_ptr < line_end)
        {
-         op_code = read_1_byte (abfd, line_ptr, line_end);
-         line_ptr += 1;
+         op_code = read_1_byte (abfd, &line_ptr, line_end);
 
          if (op_code >= lh.opcode_base)
            {
@@ -2276,11 +2936,9 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
          else switch (op_code)
            {
            case DW_LNS_extended_op:
-             exop_len = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                               FALSE, line_end);
-             line_ptr += bytes_read;
-             extended_op = read_1_byte (abfd, line_ptr, line_end);
-             line_ptr += 1;
+             exop_len = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                               false, line_end);
+             extended_op = read_1_byte (abfd, &line_ptr, line_end);
 
              switch (extended_op)
                {
@@ -2294,46 +2952,39 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                    low_pc = address;
                  if (address > high_pc)
                    high_pc = address;
-                 if (!arange_add (unit, &unit->arange, low_pc, high_pc))
+                 if (!arange_add (unit, &unit->arange, &unit->file->trie_root,
+                                  low_pc, high_pc))
                    goto line_fail;
                  break;
                case DW_LNE_set_address:
-                 address = read_address (unit, line_ptr, line_end);
+                 address = read_address (unit, &line_ptr, line_end);
                  op_index = 0;
-                 line_ptr += unit->addr_size;
                  break;
                case DW_LNE_define_file:
-                 cur_file = read_string (abfd, line_ptr, line_end, &bytes_read);
-                 line_ptr += bytes_read;
-                 dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                              FALSE, line_end);
-                 line_ptr += bytes_read;
-                 xtime = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                                FALSE, line_end);
-                 line_ptr += bytes_read;
-                 size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                               FALSE, line_end);
-                 line_ptr += bytes_read;
+                 cur_file = read_string (&line_ptr, line_end);
+                 dir = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                              false, line_end);
+                 xtime = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                                false, line_end);
+                 size = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                               false, line_end);
                  if (!line_info_add_file_name (table, cur_file, dir,
                                                xtime, size))
                    goto line_fail;
                  break;
                case DW_LNE_set_discriminator:
-                 discriminator =
-                   _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                          FALSE, line_end);
-                 line_ptr += bytes_read;
+                 discriminator = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                                        false, line_end);
                  break;
                case DW_LNE_HP_source_file_correlation:
                  line_ptr += exop_len - 1;
                  break;
                default:
                  _bfd_error_handler
-                   (_("Dwarf Error: mangled line number section."));
+                   (_("DWARF error: mangled line number section"));
                  bfd_set_error (bfd_error_bad_value);
                line_fail:
-                 if (filename != NULL)
-                   free (filename);
+                 free (filename);
                  goto fail;
                }
              break;
@@ -2350,43 +3001,36 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
            case DW_LNS_advance_pc:
              if (lh.maximum_ops_per_insn == 1)
                address += (lh.minimum_instruction_length
-                           * _bfd_safe_read_leb128 (abfd, line_ptr,
-                                                    &bytes_read,
-                                                    FALSE, line_end));
+                           * _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                                    false, line_end));
              else
                {
-                 bfd_vma adjust = _bfd_safe_read_leb128 (abfd, line_ptr,
-                                                         &bytes_read,
-                                                         FALSE, line_end);
+                 bfd_vma adjust = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                                         false, line_end);
                  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:
-             line += _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                            TRUE, line_end);
-             line_ptr += bytes_read;
+             line += _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                            true, line_end);
              break;
            case DW_LNS_set_file:
              {
-               unsigned int file;
+               unsigned int filenum;
 
                /* The file and directory tables are 0
                   based, the references are 1 based.  */
-               file = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                             FALSE, line_end);
-               line_ptr += bytes_read;
-               if (filename)
-                 free (filename);
-               filename = concat_filename (table, file);
+               filenum = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                                false, line_end);
+               free (filename);
+               filename = concat_filename (table, filenum);
                break;
              }
            case DW_LNS_set_column:
-             column = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                             FALSE, line_end);
-             line_ptr += bytes_read;
+             column = _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                             false, line_end);
              break;
            case DW_LNS_negate_stmt:
              is_stmt = (!is_stmt);
@@ -2409,26 +3053,23 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
                }
              break;
            case DW_LNS_fixed_advance_pc:
-             address += read_2_bytes (abfd, line_ptr, line_end);
+             address += read_2_bytes (abfd, &line_ptr, line_end);
              op_index = 0;
-             line_ptr += 2;
              break;
            default:
              /* Unknown standard opcode, ignore it.  */
              for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
-               {
-                 (void) _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read,
-                                               FALSE, line_end);
-                 line_ptr += bytes_read;
-               }
+               (void) _bfd_safe_read_leb128 (abfd, &line_ptr,
+                                             false, line_end);
              break;
            }
        }
 
-      if (filename)
-       free (filename);
+      free (filename);
     }
 
+  if (unit->line_offset == 0)
+    file->line_table = table;
   if (sort_line_sequences (table))
     return table;
 
@@ -2439,20 +3080,17 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
       table->sequences = table->sequences->prev_sequence;
       free (seq);
     }
-  if (table->files != NULL)
-    free (table->files);
-  if (table->dirs != NULL)
-    free (table->dirs);
+  free (table->files);
+  free (table->dirs);
   return NULL;
 }
 
-/* If ADDR is within TABLE set the output parameters and return the
-   range of addresses covered by the entry used to fill them out.
-   Otherwise set * FILENAME_PTR to NULL and return 0.
+/* If ADDR is within TABLE set the output parameters and return TRUE,
+   otherwise set *FILENAME_PTR to NULL and return FALSE.
    The parameters FILENAME_PTR, LINENUMBER_PTR and DISCRIMINATOR_PTR
    are pointers to the objects to be filled in.  */
 
-static bfd_vma
+static bool
 lookup_address_in_line_info_table (struct line_info_table *table,
                                   bfd_vma addr,
                                   const char **filename_ptr,
@@ -2511,25 +3149,38 @@ lookup_address_in_line_info_table (struct line_info_table *table,
       *linenumber_ptr = info->line;
       if (discriminator_ptr)
        *discriminator_ptr = info->discriminator;
-      return seq->last_line->address - seq->low_pc;
+      return true;
     }
 
-fail:
+ fail:
   *filename_ptr = NULL;
-  return 0;
+  return false;
 }
 
 /* Read in the .debug_ranges section for future reference.  */
 
-static bfd_boolean
+static bool
 read_debug_ranges (struct comp_unit * unit)
 {
-  struct dwarf2_debug * stash = unit->stash;
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
 
   return read_section (unit->abfd, &stash->debug_sections[debug_ranges],
-                      stash->syms, 0,
-                      &stash->dwarf_ranges_buffer,
-                      &stash->dwarf_ranges_size);
+                      file->syms, 0,
+                      &file->dwarf_ranges_buffer, &file->dwarf_ranges_size);
+}
+
+/* Read in the .debug_rnglists section for future reference.  */
+
+static bool
+read_debug_rnglists (struct comp_unit * unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+
+  return read_section (unit->abfd, &stash->debug_sections[debug_rnglists],
+                      file->syms, 0,
+                      &file->dwarf_rnglists_buffer, &file->dwarf_rnglists_size);
 }
 
 /* Function table functions.  */
@@ -2549,10 +3200,14 @@ compare_lookup_funcinfos (const void * a, const void * b)
   if (lookup1->high_addr > lookup2->high_addr)
     return 1;
 
+  if (lookup1->idx < lookup2->idx)
+    return -1;
+  if (lookup1->idx > lookup2->idx)
+    return 1;
   return 0;
 }
 
-static bfd_boolean
+static bool
 build_lookup_funcinfo_table (struct comp_unit * unit)
 {
   struct lookup_funcinfo *lookup_funcinfo_table = unit->lookup_funcinfo_table;
@@ -2564,13 +3219,13 @@ build_lookup_funcinfo_table (struct comp_unit * unit)
   bfd_vma low_addr, high_addr;
 
   if (lookup_funcinfo_table || number_of_functions == 0)
-    return TRUE;
+    return true;
 
   /* Create the function info lookup table.  */
   lookup_funcinfo_table = (struct lookup_funcinfo *)
     bfd_malloc (number_of_functions * sizeof (struct lookup_funcinfo));
   if (lookup_funcinfo_table == NULL)
-    return FALSE;
+    return false;
 
   /* Populate the function info lookup table.  */
   func_index = number_of_functions;
@@ -2578,6 +3233,7 @@ build_lookup_funcinfo_table (struct comp_unit * unit)
     {
       entry = &lookup_funcinfo_table[--func_index];
       entry->funcinfo = each;
+      entry->idx = func_index;
 
       /* Calculate the lowest and highest address for this function entry.  */
       low_addr  = entry->funcinfo->arange.low;
@@ -2615,7 +3271,7 @@ build_lookup_funcinfo_table (struct comp_unit * unit)
     }
 
   unit->lookup_funcinfo_table = lookup_funcinfo_table;
-  return TRUE;
+  return true;
 }
 
 /* If ADDR is within UNIT's function tables, set FUNCTION_PTR, and return
@@ -2623,7 +3279,7 @@ build_lookup_funcinfo_table (struct comp_unit * unit)
    that contains ADDR, to handle inlined functions without depending upon
    them being ordered in TABLE by increasing range.  */
 
-static bfd_boolean
+static bool
 lookup_address_in_function_table (struct comp_unit *unit,
                                  bfd_vma addr,
                                  struct funcinfo **function_ptr)
@@ -2632,19 +3288,19 @@ lookup_address_in_function_table (struct comp_unit *unit,
   struct lookup_funcinfo* lookup_funcinfo = NULL;
   struct funcinfo* funcinfo = NULL;
   struct funcinfo* best_fit = NULL;
-  bfd_vma best_fit_len = 0;
+  bfd_vma best_fit_len = (bfd_vma) -1;
   bfd_size_type low, high, mid, first;
   struct arange *arange;
 
   if (number_of_functions == 0)
-    return FALSE;
+    return false;
 
   if (!build_lookup_funcinfo_table (unit))
-    return FALSE;
+    return false;
 
   if (unit->lookup_funcinfo_table[number_of_functions - 1].high_addr < addr)
-    return FALSE;
-  
+    return false;
+
   /* Find the first function in the lookup table which may contain the
      specified address.  */
   low = 0;
@@ -2678,8 +3334,7 @@ lookup_address_in_function_table (struct comp_unit *unit,
          if (addr < arange->low || addr >= arange->high)
            continue;
 
-         if (!best_fit
-             || arange->high - arange->low < best_fit_len
+         if (arange->high - arange->low < best_fit_len
              /* The following comparison is designed to return the same
                 match as the previous algorithm for routines which have the
                 same best fit length.  */
@@ -2695,60 +3350,49 @@ lookup_address_in_function_table (struct comp_unit *unit,
     }
 
   if (!best_fit)
-    return FALSE;
+    return false;
 
   *function_ptr = best_fit;
-  return TRUE;
+  return true;
 }
 
 /* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
    and LINENUMBER_PTR, and return TRUE.  */
 
-static bfd_boolean
+static bool
 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* each;
   struct funcinfo* best_fit = NULL;
-  bfd_vma best_fit_len = 0;
+  bfd_vma best_fit_len = (bfd_vma) -1;
   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)
+  for (each = unit->function_table; each; each = each->prev_func)
+    for (arange = &each->arange; arange; arange = arange->next)
+      if (addr >= arange->low
+         && addr < arange->high
+         && arange->high - arange->low < best_fit_len
+         && each->file
+         && each->name
+         && strstr (name, each->name) != NULL)
        {
-         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_len))
-           {
-             best_fit = each_func;
-             best_fit_len = arange->high - arange->low;
-           }
+         best_fit = each;
+         best_fit_len = arange->high - arange->low;
        }
-    }
 
   if (best_fit)
     {
-      best_fit->sec = sec;
       *filename_ptr = best_fit->file;
       *linenumber_ptr = best_fit->line;
-      return TRUE;
+      return true;
     }
-  else
-    return FALSE;
+
+  return false;
 }
 
 /* Variable table functions.  */
@@ -2756,52 +3400,62 @@ lookup_symbol_in_function_table (struct comp_unit *unit,
 /* If SYM is within variable table of UNIT, set FILENAME_PTR and
    LINENUMBER_PTR, and return TRUE.  */
 
-static bfd_boolean
+static bool
 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;
+  const char *name = bfd_asymbol_name (sym);
 
   for (each = unit->variable_table; each; each = each->prev_var)
-    if (each->stack == 0
+    if (each->addr == addr
+       && !each->stack
        && each->file != NULL
        && each->name != NULL
-       && each->addr == addr
-       && (!each->sec || each->sec == sec)
-       && strcmp (name, each->name) == 0)
+       && strstr (name, each->name) != NULL)
       break;
 
   if (each)
     {
-      each->sec = sec;
       *filename_ptr = each->file;
       *linenumber_ptr = each->line;
-      return TRUE;
+      return true;
     }
 
-  return FALSE;
+  return false;
 }
 
-static bfd_boolean
-find_abstract_instance_name (struct comp_unit *unit,
-                            bfd_byte *orig_info_ptr,
-                            struct attribute *attr_ptr,
-                            const char **pname,
-                            bfd_boolean *is_linkage)
+static struct comp_unit *stash_comp_unit (struct dwarf2_debug *,
+                                         struct dwarf2_debug_file *);
+static bool comp_unit_maybe_decode_line_info (struct comp_unit *);
+
+static bool
+find_abstract_instance (struct comp_unit *unit,
+                       struct attribute *attr_ptr,
+                       unsigned int recur_count,
+                       const char **pname,
+                       bool *is_linkage,
+                       char **filename_ptr,
+                       int *linenumber_ptr)
 {
   bfd *abfd = unit->abfd;
-  bfd_byte *info_ptr;
+  bfd_byte *info_ptr = NULL;
   bfd_byte *info_ptr_end;
-  unsigned int abbrev_number, bytes_read, i;
+  unsigned int abbrev_number, i;
   struct abbrev_info *abbrev;
-  bfd_uint64_t die_ref = attr_ptr->u.val;
+  uint64_t die_ref = attr_ptr->u.val;
   struct attribute attr;
-  const char *name = NULL;
+
+  if (recur_count == 100)
+    {
+      _bfd_error_handler
+       (_("DWARF error: abstract instance recursion detected"));
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
 
   /* 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.  */
@@ -2820,64 +3474,95 @@ find_abstract_instance_name (struct comp_unit *unit,
         a symbolic reference to a label in any .debug_info section
         might be used.  Since we lay out multiple .debug_info
         sections at non-zero VMAs (see place_sections), and read
-        them contiguously into stash->info_ptr_memory, that means
-        the reference is relative to stash->info_ptr_memory.  */
+        them contiguously into dwarf_info_buffer, that means the
+        reference is relative to dwarf_info_buffer.  */
       size_t total;
 
-      info_ptr = unit->stash->info_ptr_memory;
-      info_ptr_end = unit->stash->info_ptr_end;
+      info_ptr = unit->file->dwarf_info_buffer;
+      info_ptr_end = info_ptr + unit->file->dwarf_info_size;
       total = info_ptr_end - info_ptr;
-      if (!die_ref || die_ref >= total)
+      if (!die_ref)
+       return true;
+      else if (die_ref >= total)
        {
          _bfd_error_handler
-           (_("Dwarf Error: Invalid abstract instance DIE ref."));
+           (_("DWARF error: invalid abstract instance DIE ref"));
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
       info_ptr += die_ref;
+    }
+  else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
+    {
+      bool first_time = unit->stash->alt.dwarf_info_buffer == NULL;
+
+      info_ptr = read_alt_indirect_ref (unit, die_ref);
+      if (first_time)
+       unit->stash->alt.info_ptr = unit->stash->alt.dwarf_info_buffer;
+      if (info_ptr == NULL)
+       {
+         _bfd_error_handler
+           (_("DWARF error: unable to read alt ref %" PRIu64),
+            (uint64_t) die_ref);
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+      info_ptr_end = (unit->stash->alt.dwarf_info_buffer
+                     + unit->stash->alt.dwarf_info_size);
+      if (unit->stash->alt.all_comp_units)
+       unit = unit->stash->alt.all_comp_units;
+    }
 
+  if (attr_ptr->form == DW_FORM_ref_addr
+      || attr_ptr->form == DW_FORM_GNU_ref_alt)
+    {
       /* Now find the CU containing this pointer.  */
       if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
        info_ptr_end = unit->end_ptr;
       else
        {
          /* Check other CUs to see if they contain the abbrev.  */
-         struct comp_unit * u;
+         struct comp_unit *u = NULL;
+         struct addr_range range = { info_ptr, info_ptr };
+         splay_tree_node v = splay_tree_lookup (unit->file->comp_unit_tree,
+                                                (splay_tree_key)&range);
+         if (v != NULL)
+           u = (struct comp_unit *)v->value;
+
+         if (attr_ptr->form == DW_FORM_ref_addr)
+           while (u == NULL)
+             {
+               u = stash_comp_unit (unit->stash, &unit->stash->f);
+               if (u == NULL)
+                 break;
+               if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
+                 break;
+               u = NULL;
+             }
 
-         for (u = unit->prev_unit; u != NULL; u = u->prev_unit)
-           if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
-             break;
+         if (attr_ptr->form == DW_FORM_GNU_ref_alt)
+           while (u == NULL)
+             {
+               u = stash_comp_unit (unit->stash, &unit->stash->alt);
+               if (u == NULL)
+                 break;
+               if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
+                 break;
+               u = NULL;
+             }
 
          if (u == NULL)
-           for (u = unit->next_unit; u != NULL; u = u->next_unit)
-             if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
-               break;
-
-         if (u)
            {
-             unit = u;
-             info_ptr_end = unit->end_ptr;
+             _bfd_error_handler
+               (_("DWARF error: unable to locate abstract instance DIE ref %"
+                  PRIu64), (uint64_t) die_ref);
+             bfd_set_error (bfd_error_bad_value);
+             return false;
            }
-         /* else FIXME: What do we do now ?  */
+         unit = u;
+         info_ptr_end = unit->end_ptr;
        }
     }
-  else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
-    {
-      info_ptr = read_alt_indirect_ref (unit, die_ref);
-      if (info_ptr == NULL)
-       {
-         _bfd_error_handler
-           (_("Dwarf Error: Unable to read alt ref %llu."),
-            (long long) die_ref);
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
-       }
-      info_ptr_end = (unit->stash->alt_dwarf_info_buffer
-                     + unit->stash->alt_dwarf_info_size);
-
-      /* FIXME: Do we need to locate the correct CU, in a similar
-        fashion to the code in the DW_FORM_ref_addr case above ?  */
-    }
   else
     {
       /* DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8 or
@@ -2891,26 +3576,24 @@ find_abstract_instance_name (struct comp_unit *unit,
       if (!die_ref || die_ref >= total)
        {
          _bfd_error_handler
-           (_("Dwarf Error: Invalid abstract instance DIE ref."));
+           (_("DWARF error: invalid abstract instance DIE ref"));
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
       info_ptr += die_ref;
     }
 
-  abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                        FALSE, info_ptr_end);
-  info_ptr += bytes_read;
-
+  abbrev_number = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                        false, info_ptr_end);
   if (abbrev_number)
     {
       abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
       if (! abbrev)
        {
          _bfd_error_handler
-           (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
+           (_("DWARF error: could not find abbrev number %u"), abbrev_number);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
       else
        {
@@ -2920,70 +3603,76 @@ find_abstract_instance_name (struct comp_unit *unit,
                                         info_ptr, info_ptr_end);
              if (info_ptr == NULL)
                break;
-             /* It doesn't ever make sense for DW_AT_specification to
-                refer to the same DIE.  Stop simple recursion.  */
-             if (info_ptr == orig_info_ptr)
-               {
-                 _bfd_error_handler
-                   (_("Dwarf Error: Abstract instance recursion detected."));
-                 bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
-               }
              switch (attr.name)
                {
                case DW_AT_name:
                  /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
                     over DW_AT_name.  */
-                 if (name == NULL && is_str_attr (attr.form))
+                 if (*pname == NULL && is_str_form (&attr))
                    {
-                     name = attr.u.str;
-                     if (non_mangled (unit->lang))
-                       *is_linkage = TRUE;
+                     *pname = attr.u.str;
+                     if (mangle_style (unit->lang) == 0)
+                       *is_linkage = true;
                    }
                  break;
                case DW_AT_specification:
-                 if (!find_abstract_instance_name (unit, info_ptr, &attr,
-                                                   pname, is_linkage))
-                   return FALSE;
+                 if (is_int_form (&attr)
+                     && !find_abstract_instance (unit, &attr, recur_count + 1,
+                                                 pname, is_linkage,
+                                                 filename_ptr, linenumber_ptr))
+                   return false;
                  break;
                case DW_AT_linkage_name:
                case DW_AT_MIPS_linkage_name:
                  /* PR 16949:  Corrupt debug info can place
                     non-string forms into these attributes.  */
-                 if (is_str_attr (attr.form))
+                 if (is_str_form (&attr))
                    {
-                     name = attr.u.str;
-                     *is_linkage = TRUE;
+                     *pname = attr.u.str;
+                     *is_linkage = true;
                    }
                  break;
+               case DW_AT_decl_file:
+                 if (!comp_unit_maybe_decode_line_info (unit))
+                   return false;
+                 if (is_int_form (&attr))
+                   {
+                     free (*filename_ptr);
+                     *filename_ptr = concat_filename (unit->line_table,
+                                                      attr.u.val);
+                   }
+                 break;
+               case DW_AT_decl_line:
+                 if (is_int_form (&attr))
+                   *linenumber_ptr = attr.u.val;
+                 break;
                default:
                  break;
                }
            }
        }
     }
-  *pname = name;
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
-read_rangelist (struct comp_unit *unit, struct arange *arange,
-               bfd_uint64_t offset)
+static bool
+read_ranges (struct comp_unit *unit, struct arange *arange,
+            struct trie_node **trie_root, uint64_t offset)
 {
   bfd_byte *ranges_ptr;
   bfd_byte *ranges_end;
   bfd_vma base_address = unit->base_address;
 
-  if (! unit->stash->dwarf_ranges_buffer)
+  if (! unit->file->dwarf_ranges_buffer)
     {
       if (! read_debug_ranges (unit))
-       return FALSE;
+       return false;
     }
 
-  ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
-  if (ranges_ptr < unit->stash->dwarf_ranges_buffer)
-    return FALSE;
-  ranges_end = unit->stash->dwarf_ranges_buffer + unit->stash->dwarf_ranges_size;
+  if (offset > unit->file->dwarf_ranges_size)
+    return false;
+  ranges_ptr = unit->file->dwarf_ranges_buffer + offset;
+  ranges_end = unit->file->dwarf_ranges_buffer + unit->file->dwarf_ranges_size;
 
   for (;;)
     {
@@ -2991,13 +3680,11 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
       bfd_vma high_pc;
 
       /* PR 17512: file: 62cada7d.  */
-      if (ranges_ptr + 2 * unit->addr_size > ranges_end)
-       return FALSE;
+      if (2u * unit->addr_size > (size_t) (ranges_end - ranges_ptr))
+       return false;
 
-      low_pc = read_address (unit, ranges_ptr, ranges_end);
-      ranges_ptr += unit->addr_size;
-      high_pc = read_address (unit, ranges_ptr, ranges_end);
-      ranges_ptr += unit->addr_size;
+      low_pc = read_address (unit, &ranges_ptr, ranges_end);
+      high_pc = read_address (unit, &ranges_ptr, ranges_end);
 
       if (low_pc == 0 && high_pc == 0)
        break;
@@ -3005,60 +3692,207 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
        base_address = high_pc;
       else
        {
-         if (!arange_add (unit, arange,
+         if (!arange_add (unit, arange, trie_root,
                           base_address + low_pc, base_address + high_pc))
-           return FALSE;
+           return false;
        }
     }
-  return TRUE;
+  return true;
 }
 
+static bool
+read_rnglists (struct comp_unit *unit, struct arange *arange,
+              struct trie_node **trie_root, uint64_t offset)
+{
+  bfd_byte *rngs_ptr;
+  bfd_byte *rngs_end;
+  bfd_vma base_address = unit->base_address;
+  bfd_vma low_pc;
+  bfd_vma high_pc;
+  bfd *abfd = unit->abfd;
+
+  if (! unit->file->dwarf_rnglists_buffer)
+    {
+      if (! read_debug_rnglists (unit))
+       return false;
+    }
+
+  rngs_ptr = unit->file->dwarf_rnglists_buffer + offset;
+  if (rngs_ptr < unit->file->dwarf_rnglists_buffer)
+    return false;
+  rngs_end = unit->file->dwarf_rnglists_buffer;
+  rngs_end +=  unit->file->dwarf_rnglists_size;
+
+  for (;;)
+    {
+      enum dwarf_range_list_entry rlet;
+
+      if (rngs_ptr >= rngs_end)
+       return false;
+
+      rlet = read_1_byte (abfd, &rngs_ptr, rngs_end);
+
+      switch (rlet)
+       {
+       case DW_RLE_end_of_list:
+         return true;
+
+       case DW_RLE_base_address:
+         if (unit->addr_size > (size_t) (rngs_end - rngs_ptr))
+           return false;
+         base_address = read_address (unit, &rngs_ptr, rngs_end);
+         continue;
+
+       case DW_RLE_start_length:
+         if (unit->addr_size > (size_t) (rngs_end - rngs_ptr))
+           return false;
+         low_pc = read_address (unit, &rngs_ptr, rngs_end);
+         high_pc = low_pc;
+         high_pc += _bfd_safe_read_leb128 (abfd, &rngs_ptr,
+                                           false, rngs_end);
+         break;
+
+       case DW_RLE_offset_pair:
+         low_pc = base_address;
+         low_pc += _bfd_safe_read_leb128 (abfd, &rngs_ptr,
+                                          false, rngs_end);
+         high_pc = base_address;
+         high_pc += _bfd_safe_read_leb128 (abfd, &rngs_ptr,
+                                           false, rngs_end);
+         break;
+
+       case DW_RLE_start_end:
+         if (2u * unit->addr_size > (size_t) (rngs_end - rngs_ptr))
+           return false;
+         low_pc = read_address (unit, &rngs_ptr, rngs_end);
+         high_pc = read_address (unit, &rngs_ptr, rngs_end);
+         break;
+
+       /* TODO x-variants need .debug_addr support used for split-dwarf.  */
+       case DW_RLE_base_addressx:
+       case DW_RLE_startx_endx:
+       case DW_RLE_startx_length:
+       default:
+         return false;
+       }
+
+      if (!arange_add (unit, arange, trie_root, low_pc, high_pc))
+       return false;
+    }
+}
+
+static bool
+read_rangelist (struct comp_unit *unit, struct arange *arange,
+               struct trie_node **trie_root, uint64_t offset)
+{
+  if (unit->version <= 4)
+    return read_ranges (unit, arange, trie_root, offset);
+  else
+    return read_rnglists (unit, arange, trie_root, offset);
+}
+
+static struct funcinfo *
+lookup_func_by_offset (uint64_t offset, struct funcinfo * table)
+{
+  for (; table != NULL; table = table->prev_func)
+    if (table->unit_offset == offset)
+      return table;
+  return NULL;
+}
+
+static struct varinfo *
+lookup_var_by_offset (uint64_t offset, struct varinfo * table)
+{
+  while (table)
+    {
+      if (table->unit_offset == offset)
+       return table;
+      table = table->prev_var;
+    }
+
+  return NULL;
+}
+
+
 /* DWARF2 Compilation unit functions.  */
 
+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;
+}
+
 /* Scan over each die in a comp. unit looking for functions to add
    to the function table and variables to the variable table.  */
 
-static bfd_boolean
+static bool
 scan_unit_for_symbols (struct comp_unit *unit)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
-  bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
+  bfd_byte *info_ptr_end = unit->end_ptr;
   int nesting_level = 0;
-  struct nest_funcinfo {
+  struct nest_funcinfo
+  {
     struct funcinfo *func;
   } *nested_funcs;
   int nested_funcs_size;
-
+  struct funcinfo *last_func;
+  struct varinfo *last_var;
+  
   /* 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 nest_funcinfo *)
     bfd_malloc (nested_funcs_size * sizeof (*nested_funcs));
   if (nested_funcs == NULL)
-    return FALSE;
+    return false;
   nested_funcs[nesting_level].func = 0;
 
+  /* PR 27484: We must scan the DIEs twice.  The first time we look for
+     function and variable tags and accumulate them into their respective
+     tables.  The second time through we process the attributes of the
+     functions/variables and augment the table entries.  */
   while (nesting_level >= 0)
     {
-      unsigned int abbrev_number, bytes_read, i;
+      unsigned int abbrev_number, i;
       struct abbrev_info *abbrev;
-      struct attribute attr;
       struct funcinfo *func;
       struct varinfo *var;
-      bfd_vma low_pc = 0;
-      bfd_vma high_pc = 0;
-      bfd_boolean high_pc_relative = FALSE;
+      uint64_t current_offset;
 
       /* PR 17512: file: 9f405d9d.  */
       if (info_ptr >= info_ptr_end)
        goto fail;
 
-      abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                            FALSE, info_ptr_end);
-      info_ptr += bytes_read;
-
-      if (! abbrev_number)
+      current_offset = info_ptr - unit->info_ptr_unit;
+      abbrev_number = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                            false, info_ptr_end);
+      if (abbrev_number == 0)
        {
          nesting_level--;
          continue;
@@ -3073,7 +3907,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
          if (abbrev_number != previous_failed_abbrev)
            {
              _bfd_error_handler
-               (_("Dwarf Error: Could not find abbrev number %u."),
+               (_("DWARF error: could not find abbrev number %u"),
                 abbrev_number);
              previous_failed_abbrev = abbrev_number;
            }
@@ -3081,17 +3915,19 @@ scan_unit_for_symbols (struct comp_unit *unit)
          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);
+         size_t amt = sizeof (struct funcinfo);
+
+         var = NULL;
          func = (struct funcinfo *) bfd_zalloc (abfd, amt);
          if (func == NULL)
            goto fail;
          func->tag = abbrev->tag;
          func->prev_func = unit->function_table;
+         func->unit_offset = current_offset;
          unit->function_table = func;
          unit->number_of_functions++;
          BFD_ASSERT (!unit->cached);
@@ -3108,24 +3944,132 @@ scan_unit_for_symbols (struct comp_unit *unit)
       else
        {
          func = NULL;
-         if (abbrev->tag == DW_TAG_variable)
+         if (abbrev->tag == DW_TAG_variable
+             || abbrev->tag == DW_TAG_member)
            {
-             bfd_size_type amt = sizeof (struct varinfo);
+             size_t amt = sizeof (struct varinfo);
+
              var = (struct varinfo *) bfd_zalloc (abfd, amt);
              if (var == NULL)
                goto fail;
              var->tag = abbrev->tag;
-             var->stack = 1;
+             var->stack = true;
              var->prev_var = unit->variable_table;
              unit->variable_table = var;
+             var->unit_offset = current_offset;
              /* PR 18205: Missing debug information can cause this
                 var to be attached to an already cached unit.  */
            }
+         else
+           var = NULL;
 
          /* No inline function in scope at this nesting level.  */
          nested_funcs[nesting_level].func = 0;
        }
 
+      for (i = 0; i < abbrev->num_attrs; ++i)
+       {
+         struct attribute attr;
+
+         info_ptr = read_attribute (&attr, &abbrev->attrs[i],
+                                    unit, info_ptr, info_ptr_end);
+         if (info_ptr == NULL)
+           goto fail;
+       }
+
+      if (abbrev->has_children)
+       {
+         nesting_level++;
+
+         if (nesting_level >= nested_funcs_size)
+           {
+             struct nest_funcinfo *tmp;
+
+             nested_funcs_size *= 2;
+             tmp = (struct nest_funcinfo *)
+               bfd_realloc (nested_funcs,
+                            nested_funcs_size * sizeof (*nested_funcs));
+             if (tmp == NULL)
+               goto fail;
+             nested_funcs = tmp;
+           }
+         nested_funcs[nesting_level].func = 0;
+       }
+    }
+
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
+
+  /* This is the second pass over the abbrevs.  */      
+  info_ptr = unit->first_child_die_ptr;
+  nesting_level = 0;
+  
+  last_func = NULL;
+  last_var = NULL;
+
+  while (nesting_level >= 0)
+    {
+      unsigned int abbrev_number, i;
+      struct abbrev_info *abbrev;
+      struct attribute attr;
+      struct funcinfo *func;
+      struct varinfo *var;
+      bfd_vma low_pc = 0;
+      bfd_vma high_pc = 0;
+      bool high_pc_relative = false;
+      uint64_t current_offset;
+
+      /* PR 17512: file: 9f405d9d.  */
+      if (info_ptr >= info_ptr_end)
+       goto fail;
+
+      current_offset = info_ptr - unit->info_ptr_unit;
+      abbrev_number = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                            false, info_ptr_end);
+      if (! abbrev_number)
+       {
+         nesting_level--;
+         continue;
+       }
+
+      abbrev = lookup_abbrev (abbrev_number, unit->abbrevs);
+      /* This should have been handled above.  */
+      BFD_ASSERT (abbrev != NULL);
+
+      func = NULL;
+      var = NULL;
+      if (abbrev->tag == DW_TAG_subprogram
+         || abbrev->tag == DW_TAG_entry_point
+         || abbrev->tag == DW_TAG_inlined_subroutine)
+       {
+         if (last_func
+             && last_func->prev_func
+             && last_func->prev_func->unit_offset == current_offset)
+           func = last_func->prev_func;
+         else
+           func = lookup_func_by_offset (current_offset, unit->function_table);
+
+         if (func == NULL)
+           goto fail;
+
+         last_func = func;
+       }
+      else if (abbrev->tag == DW_TAG_variable
+              || abbrev->tag == DW_TAG_member)
+       {
+         if (last_var
+             && last_var->prev_var
+             && last_var->prev_var->unit_offset == current_offset)
+           var = last_var->prev_var;
+         else
+           var = lookup_var_by_offset (current_offset, unit->variable_table);
+
+         if (var == NULL)
+           goto fail;
+
+         last_var = var;
+       }
+
       for (i = 0; i < abbrev->num_attrs; ++i)
        {
          info_ptr = read_attribute (&attr, &abbrev->attrs[i],
@@ -3138,30 +4082,35 @@ scan_unit_for_symbols (struct comp_unit *unit)
              switch (attr.name)
                {
                case DW_AT_call_file:
-                 func->caller_file = concat_filename (unit->line_table,
-                                                      attr.u.val);
+                 if (is_int_form (&attr))
+                   func->caller_file = concat_filename (unit->line_table,
+                                                        attr.u.val);
                  break;
 
                case DW_AT_call_line:
-                 func->caller_line = attr.u.val;
+                 if (is_int_form (&attr))
+                   func->caller_line = attr.u.val;
                  break;
 
                case DW_AT_abstract_origin:
                case DW_AT_specification:
-                 if (!find_abstract_instance_name (unit, info_ptr, &attr,
-                                                   &func->name,
-                                                   &func->is_linkage))
+                 if (is_int_form (&attr)
+                     && !find_abstract_instance (unit, &attr, 0,
+                                                 &func->name,
+                                                 &func->is_linkage,
+                                                 &func->file,
+                                                 &func->line))
                    goto fail;
                  break;
 
                case DW_AT_name:
                  /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
                     over DW_AT_name.  */
-                 if (func->name == NULL && is_str_attr (attr.form))
+                 if (func->name == NULL && is_str_form (&attr))
                    {
                      func->name = attr.u.str;
-                     if (non_mangled (unit->lang))
-                       func->is_linkage = TRUE;
+                     if (mangle_style (unit->lang) == 0)
+                       func->is_linkage = true;
                    }
                  break;
 
@@ -3169,34 +4118,45 @@ scan_unit_for_symbols (struct comp_unit *unit)
                case DW_AT_MIPS_linkage_name:
                  /* PR 16949:  Corrupt debug info can place
                     non-string forms into these attributes.  */
-                 if (is_str_attr (attr.form))
+                 if (is_str_form (&attr))
                    {
                      func->name = attr.u.str;
-                     func->is_linkage = TRUE;
+                     func->is_linkage = true;
                    }
                  break;
 
                case DW_AT_low_pc:
-                 low_pc = attr.u.val;
+                 if (is_int_form (&attr))
+                   low_pc = attr.u.val;
                  break;
 
                case DW_AT_high_pc:
-                 high_pc = attr.u.val;
-                 high_pc_relative = attr.form != DW_FORM_addr;
+                 if (is_int_form (&attr))
+                   {
+                     high_pc = attr.u.val;
+                     high_pc_relative = attr.form != DW_FORM_addr;
+                   }
                  break;
 
                case DW_AT_ranges:
-                 if (!read_rangelist (unit, &func->arange, attr.u.val))
+                 if (is_int_form (&attr)
+                     && !read_rangelist (unit, &func->arange,
+                                         &unit->file->trie_root, attr.u.val))
                    goto fail;
                  break;
 
                case DW_AT_decl_file:
-                 func->file = concat_filename (unit->line_table,
-                                               attr.u.val);
+                 if (is_int_form (&attr))
+                   {
+                     free (func->file);
+                     func->file = concat_filename (unit->line_table,
+                                                   attr.u.val);
+                   }
                  break;
 
                case DW_AT_decl_line:
-                 func->line = attr.u.val;
+                 if (is_int_form (&attr))
+                   func->line = attr.u.val;
                  break;
 
                default:
@@ -3207,23 +4167,47 @@ scan_unit_for_symbols (struct comp_unit *unit)
            {
              switch (attr.name)
                {
+               case DW_AT_specification:
+                 if (is_int_form (&attr) && attr.u.val)
+                   {
+                     bool is_linkage;
+                     if (!find_abstract_instance (unit, &attr, 0,
+                                                  &var->name,
+                                                  &is_linkage,
+                                                  &var->file,
+                                                  &var->line))
+                       {
+                         _bfd_error_handler (_("DWARF error: could not find "
+                                               "variable specification "
+                                               "at offset 0x%lx"),
+                                             (unsigned long) attr.u.val);
+                         break;
+                       }
+                   }
+                 break;
+
                case DW_AT_name:
-                 if (is_str_attr (attr.form))
+                 if (is_str_form (&attr))
                    var->name = attr.u.str;
                  break;
 
                case DW_AT_decl_file:
-                 var->file = concat_filename (unit->line_table,
-                                              attr.u.val);
+                 if (is_int_form (&attr))
+                   {
+                     free (var->file);
+                     var->file = concat_filename (unit->line_table,
+                                                  attr.u.val);
+                   }
                  break;
 
                case DW_AT_decl_line:
-                 var->line = attr.u.val;
+                 if (is_int_form (&attr))
+                   var->line = attr.u.val;
                  break;
 
                case DW_AT_external:
-                 if (attr.u.val != 0)
-                   var->stack = 0;
+                 if (is_int_form (&attr) && attr.u.val != 0)
+                   var->stack = false;
                  break;
 
                case DW_AT_location:
@@ -3237,7 +4221,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
                      if (attr.u.blk->data != NULL
                          && *attr.u.blk->data == DW_OP_addr)
                        {
-                         var->stack = 0;
+                         var->stack = false;
 
                          /* Verify that DW_OP_addr is the only opcode in the
                             location, in which case the block size will be 1
@@ -3263,44 +4247,106 @@ scan_unit_for_symbols (struct comp_unit *unit)
            }
        }
 
+      if (abbrev->has_children)
+       nesting_level++;
+
       if (high_pc_relative)
        high_pc += low_pc;
 
       if (func && high_pc != 0)
        {
-         if (!arange_add (unit, &func->arange, low_pc, high_pc))
+         if (!arange_add (unit, &func->arange, &unit->file->trie_root,
+                          low_pc, high_pc))
            goto fail;
        }
-
-      if (abbrev->has_children)
-       {
-         nesting_level++;
-
-         if (nesting_level >= nested_funcs_size)
-           {
-             struct nest_funcinfo *tmp;
-
-             nested_funcs_size *= 2;
-             tmp = (struct nest_funcinfo *)
-               bfd_realloc (nested_funcs,
-                            nested_funcs_size * sizeof (*nested_funcs));
-             if (tmp == NULL)
-               goto fail;
-             nested_funcs = tmp;
-           }
-         nested_funcs[nesting_level].func = 0;
-       }
     }
 
+  unit->function_table = reverse_funcinfo_list (unit->function_table);
+  unit->variable_table = reverse_varinfo_list (unit->variable_table);
+
   free (nested_funcs);
-  return TRUE;
+  return true;
 
  fail:
   free (nested_funcs);
-  return FALSE;
+  return false;
 }
 
-/* Parse a DWARF2 compilation unit starting at INFO_PTR.  This
+/* Read the attributes of the form strx and addrx.  */
+
+static void
+reread_attribute (struct comp_unit *unit,
+                 struct attribute *attr,
+                 bfd_vma *low_pc,
+                 bfd_vma *high_pc,
+                 bool *high_pc_relative,
+                 bool compunit)
+{
+  if (is_strx_form (attr->form))
+    attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+  if (is_addrx_form (attr->form))
+    attr->u.val = read_indexed_address (attr->u.val, unit);
+
+  switch (attr->name)
+    {
+    case DW_AT_stmt_list:
+      unit->stmtlist = 1;
+      unit->line_offset = attr->u.val;
+      break;
+
+    case DW_AT_name:
+      if (is_str_form (attr))
+       unit->name = attr->u.str;
+      break;
+
+    case DW_AT_low_pc:
+      *low_pc = attr->u.val;
+      if (compunit)
+       unit->base_address = *low_pc;
+      break;
+
+    case DW_AT_high_pc:
+      *high_pc = attr->u.val;
+      *high_pc_relative = attr->form != DW_FORM_addr;
+      break;
+
+    case DW_AT_ranges:
+      if (!read_rangelist (unit, &unit->arange,
+                          &unit->file->trie_root, attr->u.val))
+       return;
+      break;
+
+    case DW_AT_comp_dir:
+      {
+       char *comp_dir = attr->u.str;
+
+       if (!is_str_form (attr))
+         {
+           _bfd_error_handler
+             (_("DWARF error: DW_AT_comp_dir attribute encountered "
+                "with a non-string form"));
+           comp_dir = NULL;
+         }
+
+       if (comp_dir)
+         {
+           char *cp = strchr (comp_dir, ':');
+
+           if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+             comp_dir = cp + 1;
+         }
+       unit->comp_dir = comp_dir;
+       break;
+      }
+
+    case DW_AT_language:
+      unit->lang = attr->u.val;
+    default:
+      break;
+    }
+}
+
+/* Parse a DWARF2 compilation unit starting at INFO_PTR.  UNIT_LENGTH
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that precedes each compilation
    unit header.  END_PTR points one past the end of this comp unit.
@@ -3311,30 +4357,34 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
 static struct comp_unit *
 parse_comp_unit (struct dwarf2_debug *stash,
+                struct dwarf2_debug_file *file,
+                bfd_byte *info_ptr,
                 bfd_vma unit_length,
                 bfd_byte *info_ptr_unit,
                 unsigned int offset_size)
 {
   struct comp_unit* unit;
   unsigned int version;
-  bfd_uint64_t abbrev_offset = 0;
+  uint64_t abbrev_offset = 0;
   /* Initialize it just to avoid a GCC false warning.  */
   unsigned int addr_size = -1;
   struct abbrev_info** abbrevs;
-  unsigned int abbrev_number, bytes_read, i;
+  unsigned int abbrev_number, i;
   struct abbrev_info *abbrev;
   struct attribute attr;
-  bfd_byte *info_ptr = stash->info_ptr;
   bfd_byte *end_ptr = info_ptr + unit_length;
-  bfd_size_type amt;
+  size_t amt;
   bfd_vma low_pc = 0;
   bfd_vma high_pc = 0;
-  bfd *abfd = stash->bfd_ptr;
-  bfd_boolean high_pc_relative = FALSE;
+  bfd *abfd = file->bfd_ptr;
+  bool high_pc_relative = false;
   enum dwarf_unit_type unit_type;
+  struct attribute *str_addrp = NULL;
+  size_t str_count = 0;
+  size_t str_alloc = 0;
+  bool compunit_flag = false;
 
-  version = read_2_bytes (abfd, info_ptr, end_ptr);
-  info_ptr += 2;
+  version = read_2_bytes (abfd, &info_ptr, end_ptr);
   if (version < 2 || version > 5)
     {
       /* PR 19872: A version number of 0 probably means that there is padding
@@ -3344,8 +4394,8 @@ parse_comp_unit (struct dwarf2_debug *stash,
       if (version)
        {
          _bfd_error_handler
-           (_("Dwarf Error: found dwarf version '%u', this reader"
-              " only handles version 2, 3, 4 and 5 information."), version);
+           (_("DWARF error: found dwarf version '%u', this reader"
+              " only handles version 2, 3, 4 and 5 information"), version);
          bfd_set_error (bfd_error_bad_value);
        }
       return NULL;
@@ -3355,41 +4405,44 @@ parse_comp_unit (struct dwarf2_debug *stash,
     unit_type = DW_UT_compile;
   else
     {
-      unit_type = read_1_byte (abfd, info_ptr, end_ptr);
-      info_ptr += 1;
-
-      addr_size = read_1_byte (abfd, info_ptr, end_ptr);
-      info_ptr += 1;
+      unit_type = read_1_byte (abfd, &info_ptr, end_ptr);
+      addr_size = read_1_byte (abfd, &info_ptr, end_ptr);
     }
 
   BFD_ASSERT (offset_size == 4 || offset_size == 8);
   if (offset_size == 4)
-    abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr);
+    abbrev_offset = read_4_bytes (abfd, &info_ptr, end_ptr);
   else
-    abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr);
-  info_ptr += offset_size;
+    abbrev_offset = read_8_bytes (abfd, &info_ptr, end_ptr);
 
   if (version < 5)
-    {
-      addr_size = read_1_byte (abfd, info_ptr, end_ptr);
-      info_ptr += 1;
-    }
+    addr_size = read_1_byte (abfd, &info_ptr, end_ptr);
 
-  if (unit_type == DW_UT_type)
+  switch (unit_type)
     {
+    case DW_UT_type:
       /* Skip type signature.  */
       info_ptr += 8;
 
       /* Skip type offset.  */
       info_ptr += offset_size;
+      break;
+
+    case DW_UT_skeleton:
+      /* Skip DWO_id field.  */
+      info_ptr += 8;
+      break;
+
+    default:
+      break;
     }
 
   if (addr_size > sizeof (bfd_vma))
     {
       _bfd_error_handler
        /* xgettext: c-format */
-       (_("Dwarf Error: found address size '%u', this reader"
-          " can not handle sizes greater than '%u'."),
+       (_("DWARF error: found address size '%u', this reader"
+          " can not handle sizes greater than '%u'"),
         addr_size,
         (unsigned int) sizeof (bfd_vma));
       bfd_set_error (bfd_error_bad_value);
@@ -3399,20 +4452,19 @@ parse_comp_unit (struct dwarf2_debug *stash,
   if (addr_size != 2 && addr_size != 4 && addr_size != 8)
     {
       _bfd_error_handler
-       ("Dwarf Error: found address size '%u', this reader"
-        " can only handle address sizes '2', '4' and '8'.", addr_size);
+       ("DWARF error: found address size '%u', this reader"
+        " can only handle address sizes '2', '4' and '8'", addr_size);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
 
   /* Read the abbrevs for this compilation unit into a table.  */
-  abbrevs = read_abbrevs (abfd, abbrev_offset, stash);
+  abbrevs = read_abbrevs (abfd, abbrev_offset, stash, file);
   if (! abbrevs)
     return NULL;
 
-  abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read,
-                                        FALSE, end_ptr);
-  info_ptr += bytes_read;
+  abbrev_number = _bfd_safe_read_leb128 (abfd, &info_ptr,
+                                        false, end_ptr);
   if (! abbrev_number)
     {
       /* PR 19872: An abbrev number of 0 probably means that there is padding
@@ -3425,7 +4477,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
   abbrev = lookup_abbrev (abbrev_number, abbrevs);
   if (! abbrev)
     {
-      _bfd_error_handler (_("Dwarf Error: Could not find abbrev number %u."),
+      _bfd_error_handler (_("DWARF error: could not find abbrev number %u"),
                          abbrev_number);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -3442,45 +4494,79 @@ parse_comp_unit (struct dwarf2_debug *stash,
   unit->abbrevs = abbrevs;
   unit->end_ptr = end_ptr;
   unit->stash = stash;
+  unit->file = file;
   unit->info_ptr_unit = info_ptr_unit;
 
+  if (abbrev->tag == DW_TAG_compile_unit)
+    compunit_flag = true;
+
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
       if (info_ptr == NULL)
-       return NULL;
+       goto err_exit;
+
+      /* Identify attributes of the form strx* and addrx* which come before
+        DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
+        Store the attributes in an array and process them later.  */
+      if ((unit->dwarf_str_offset == 0 && is_strx_form (attr.form))
+         || (unit->dwarf_addr_offset == 0 && is_addrx_form (attr.form)))
+       {
+         if (str_count <= str_alloc)
+           {
+             str_alloc = 2 * str_alloc + 200;
+             str_addrp = bfd_realloc (str_addrp,
+                                      str_alloc * sizeof (*str_addrp));
+             if (str_addrp == NULL)
+               goto err_exit;
+           }
+         str_addrp[str_count] = attr;
+         str_count++;
+         continue;
+       }
 
       /* Store the data if it is of an attribute we want to keep in a
         partial symbol table.  */
       switch (attr.name)
        {
        case DW_AT_stmt_list:
-         unit->stmtlist = 1;
-         unit->line_offset = attr.u.val;
+         if (is_int_form (&attr))
+           {
+             unit->stmtlist = 1;
+             unit->line_offset = attr.u.val;
+           }
          break;
 
        case DW_AT_name:
-         if (is_str_attr (attr.form))
+         if (is_str_form (&attr))
            unit->name = attr.u.str;
          break;
 
        case DW_AT_low_pc:
-         low_pc = attr.u.val;
-         /* If the compilation unit DIE has a DW_AT_low_pc attribute,
-            this is the base address to use when reading location
-            lists or range lists.  */
-         if (abbrev->tag == DW_TAG_compile_unit)
-           unit->base_address = low_pc;
+         if (is_int_form (&attr))
+           {
+             low_pc = attr.u.val;
+             /* If the compilation unit DIE has a DW_AT_low_pc attribute,
+                this is the base address to use when reading location
+                lists or range lists.  */
+             if (compunit_flag)
+               unit->base_address = low_pc;
+           }
          break;
 
        case DW_AT_high_pc:
-         high_pc = attr.u.val;
-         high_pc_relative = attr.form != DW_FORM_addr;
+         if (is_int_form (&attr))
+           {
+             high_pc = attr.u.val;
+             high_pc_relative = attr.form != DW_FORM_addr;
+           }
          break;
 
        case DW_AT_ranges:
-         if (!read_rangelist (unit, &unit->arange, attr.u.val))
-           return NULL;
+         if (is_int_form (&attr)
+             && !read_rangelist (unit, &unit->arange,
+                                 &unit->file->trie_root, attr.u.val))
+           goto err_exit;
          break;
 
        case DW_AT_comp_dir:
@@ -3488,10 +4574,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
            char *comp_dir = attr.u.str;
 
            /* PR 17512: file: 1fe726be.  */
-           if (! is_str_attr (attr.form))
+           if (!is_str_form (&attr))
              {
                _bfd_error_handler
-                 (_("Dwarf Error: DW_AT_comp_dir attribute encountered with a non-string form."));
+                 (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
                comp_dir = NULL;
              }
 
@@ -3509,23 +4595,45 @@ parse_comp_unit (struct dwarf2_debug *stash,
          }
 
        case DW_AT_language:
-         unit->lang = attr.u.val;
+         if (is_int_form (&attr))
+           unit->lang = attr.u.val;
+         break;
+
+       case DW_AT_addr_base:
+         unit->dwarf_addr_offset = attr.u.val;
+         break;
+
+       case DW_AT_str_offsets_base:
+         unit->dwarf_str_offset = attr.u.val;
          break;
 
        default:
          break;
        }
     }
+
+  for (i = 0; i < str_count; ++i)
+    reread_attribute (unit, &str_addrp[i], &low_pc, &high_pc,
+                     &high_pc_relative, compunit_flag);
+
   if (high_pc_relative)
     high_pc += low_pc;
   if (high_pc != 0)
     {
-      if (!arange_add (unit, &unit->arange, low_pc, high_pc))
-       return NULL;
+      if (!arange_add (unit, &unit->arange, &unit->file->trie_root,
+                      low_pc, high_pc))
+       goto err_exit;
     }
 
   unit->first_child_die_ptr = info_ptr;
+
+  free (str_addrp);
   return unit;
+
+ err_exit:
+  unit->error = 1;
+  free (str_addrp);
+  return NULL;
 }
 
 /* Return TRUE if UNIT may contain the address given by ADDR.  When
@@ -3534,119 +4642,90 @@ parse_comp_unit (struct dwarf2_debug *stash,
    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)
+static bool
+comp_unit_may_contain_address (struct comp_unit *unit, bfd_vma addr)
 {
   struct arange *arange;
 
   if (unit->error)
-    return FALSE;
-
-  arange = &unit->arange;
-  do
-    {
-      if (addr >= arange->low && addr < arange->high)
-       return TRUE;
-      arange = arange->next;
-    }
-  while (arange);
+    return false;
 
-  return FALSE;
+  if (unit->arange.high == 0 /* No ranges have been computed yet.  */
+      || unit->line_table == NULL) /* The line info table has not been loaded.  */
+    return true;
+
+  for (arange = &unit->arange; arange != NULL; arange = arange->next)
+    if (addr >= arange->low && addr < arange->high)
+      return true;
+
+  return false;
 }
 
 /* If UNIT contains ADDR, set the output parameters to the values for
-   the line containing ADDR.  The output parameters, FILENAME_PTR,
-   FUNCTION_PTR, and LINENUMBER_PTR, are pointers to the objects
-   to be filled in.
+   the line containing ADDR and return TRUE.  Otherwise return FALSE.
+   The output parameters, FILENAME_PTR, FUNCTION_PTR, and
+   LINENUMBER_PTR, are pointers to the objects to be filled in.  */
 
-   Returns the range of addresses covered by the entry that was used
-   to fill in *LINENUMBER_PTR or 0 if it was not filled in.  */
-
-static bfd_vma
+static bool
 comp_unit_find_nearest_line (struct comp_unit *unit,
                             bfd_vma addr,
                             const char **filename_ptr,
                             struct funcinfo **function_ptr,
                             unsigned int *linenumber_ptr,
-                            unsigned int *discriminator_ptr,
-                            struct dwarf2_debug *stash)
+                            unsigned int *discriminator_ptr)
 {
-  bfd_boolean func_p;
-
-  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;
-       }
+  bool line_p, func_p;
 
-      if (unit->first_child_die_ptr < unit->end_ptr
-         && ! scan_unit_for_symbols (unit))
-       {
-         unit->error = 1;
-         return FALSE;
-       }
-    }
+  if (!comp_unit_maybe_decode_line_info (unit))
+    return false;
 
   *function_ptr = NULL;
   func_p = lookup_address_in_function_table (unit, addr, function_ptr);
   if (func_p && (*function_ptr)->tag == DW_TAG_inlined_subroutine)
-    stash->inliner_chain = *function_ptr;
+    unit->stash->inliner_chain = *function_ptr;
 
-  return lookup_address_in_line_info_table (unit->line_table, addr,
-                                           filename_ptr,
-                                           linenumber_ptr,
-                                           discriminator_ptr);
+  line_p = lookup_address_in_line_info_table (unit->line_table, addr,
+                                             filename_ptr,
+                                             linenumber_ptr,
+                                             discriminator_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)
+static bool
+comp_unit_maybe_decode_line_info (struct comp_unit *unit)
 {
   if (unit->error)
-    return FALSE;
+    return false;
 
   if (! unit->line_table)
     {
       if (! unit->stmtlist)
        {
          unit->error = 1;
-         return FALSE;
+         return false;
        }
 
-      unit->line_table = decode_line_info (unit, stash);
+      unit->line_table = decode_line_info (unit);
 
       if (! unit->line_table)
        {
          unit->error = 1;
-         return FALSE;
+         return false;
        }
 
       if (unit->first_child_die_ptr < unit->end_ptr
          && ! scan_unit_for_symbols (unit))
        {
          unit->error = 1;
-         return FALSE;
+         return false;
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 /* If UNIT contains SYM at ADDR, set the output parameters to the
@@ -3657,16 +4736,15 @@ comp_unit_maybe_decode_line_info (struct comp_unit *unit,
    Return TRUE if UNIT contains SYM, and no errors were encountered;
    FALSE otherwise.  */
 
-static bfd_boolean
+static bool
 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)
+                    unsigned int *linenumber_ptr)
 {
-  if (!comp_unit_maybe_decode_line_info (unit, stash))
-    return FALSE;
+  if (!comp_unit_maybe_decode_line_info (unit))
+    return false;
 
   if (sym->flags & BSF_FUNCTION)
     return lookup_symbol_in_function_table (unit, sym, addr,
@@ -3678,41 +4756,11 @@ comp_unit_find_line (struct comp_unit *unit,
                                          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
+static bool
 comp_unit_hash_info (struct dwarf2_debug *stash,
                     struct comp_unit *unit,
                     struct info_hash_table *funcinfo_hash_table,
@@ -3720,12 +4768,12 @@ comp_unit_hash_info (struct dwarf2_debug *stash,
 {
   struct funcinfo* each_func;
   struct varinfo* each_var;
-  bfd_boolean okay = TRUE;
+  bool okay = true;
 
   BFD_ASSERT (stash->info_hash_status != STASH_INFO_HASH_DISABLED);
 
-  if (!comp_unit_maybe_decode_line_info (unit, stash))
-    return FALSE;
+  if (!comp_unit_maybe_decode_line_info (unit))
+    return false;
 
   BFD_ASSERT (!unit->cached);
 
@@ -3745,11 +4793,11 @@ comp_unit_hash_info (struct dwarf2_debug *stash,
           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);
+                                      (void*) each_func, false);
     }
   unit->function_table = reverse_funcinfo_list (unit->function_table);
   if (!okay)
-    return FALSE;
+    return false;
 
   /* We do the same for variable infos.  */
   unit->variable_table = reverse_varinfo_list (unit->variable_table);
@@ -3758,18 +4806,18 @@ comp_unit_hash_info (struct dwarf2_debug *stash,
        each_var = each_var->prev_var)
     {
       /* Skip stack vars and vars with no files or names.  */
-      if (each_var->stack == 0
+      if (! each_var->stack
          && 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);
+                                      (void*) each_var, false);
     }
 
   unit->variable_table = reverse_varinfo_list (unit->variable_table);
-  unit->cached = TRUE;
+  unit->cached = true;
   return okay;
 }
 
@@ -3796,19 +4844,19 @@ find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections,
     {
       look = debug_sections[debug_info].uncompressed_name;
       msec = bfd_get_section_by_name (abfd, look);
-      if (msec != NULL)
+      /* Testing SEC_HAS_CONTENTS is an anti-fuzzer measure.  Of
+        course debug sections always have contents.  */
+      if (msec != NULL && (msec->flags & SEC_HAS_CONTENTS) != 0)
        return msec;
 
       look = debug_sections[debug_info].compressed_name;
-      if (look != NULL)
-       {
-         msec = bfd_get_section_by_name (abfd, look);
-         if (msec != NULL)
-           return msec;
-       }
+      msec = bfd_get_section_by_name (abfd, look);
+      if (msec != NULL && (msec->flags & SEC_HAS_CONTENTS) != 0)
+        return msec;
 
       for (msec = abfd->sections; msec != NULL; msec = msec->next)
-       if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO))
+       if ((msec->flags & SEC_HAS_CONTENTS) != 0
+           && startswith (msec->name, GNU_LINKONCE_INFO))
          return msec;
 
       return NULL;
@@ -3816,6 +4864,9 @@ find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections,
 
   for (msec = after_sec->next; msec != NULL; msec = msec->next)
     {
+      if ((msec->flags & SEC_HAS_CONTENTS) == 0)
+       continue;
+
       look = debug_sections[debug_info].uncompressed_name;
       if (strcmp (msec->name, look) == 0)
        return msec;
@@ -3824,7 +4875,7 @@ find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections,
       if (look != NULL && strcmp (msec->name, look) == 0)
        return msec;
 
-      if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO))
+      if (startswith (msec->name, GNU_LINKONCE_INFO))
        return msec;
     }
 
@@ -3855,6 +4906,41 @@ set_debug_vma (bfd *orig_bfd, bfd *debug_bfd)
     }
 }
 
+/* If the dwarf2 info was found in a separate debug file, return the
+   debug file section corresponding to the section in the original file
+   and the debug file symbols.  */
+
+static void
+_bfd_dwarf2_stash_syms (struct dwarf2_debug *stash, bfd *abfd,
+                       asection **sec, asymbol ***syms)
+{
+  if (stash->f.bfd_ptr != abfd)
+    {
+      asection *s, *d;
+
+      if (*sec == NULL)
+       {
+         *syms = stash->f.syms;
+         return;
+       }
+
+      for (s = abfd->sections, d = stash->f.bfd_ptr->sections;
+          s != NULL && d != NULL;
+          s = s->next, d = d->next)
+       {
+         if ((d->flags & SEC_DEBUGGING) != 0)
+           break;
+         if (s == *sec
+             && strcmp (s->name, d->name) == 0)
+           {
+             *sec = d;
+             *syms = stash->f.syms;
+             break;
+           }
+       }
+    }
+}
+
 /* Unset vmas for adjusted sections in STASH.  */
 
 static void
@@ -3866,7 +4952,7 @@ unset_sections (struct dwarf2_debug *stash)
   i = stash->adjusted_section_count;
   p = stash->adjusted_sections;
   for (; i > 0; i--, p++)
-    p->section->vma = 0;
+    p->section->vma = p->orig_vma;
 }
 
 /* Set VMAs for allocated and .debug_info sections in ORIG_BFD, a
@@ -3879,7 +4965,7 @@ unset_sections (struct dwarf2_debug *stash)
    logical section.  ??? We should probably do the same for other
    debug sections.  */
 
-static bfd_boolean
+static bool
 place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 {
   bfd *abfd;
@@ -3893,7 +4979,7 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
       p = stash->adjusted_sections;
       for (; i > 0; i--, p++)
        p->section->vma = p->adj_vma;
-      return TRUE;
+      return true;
     }
 
   debug_info_name = stash->debug_sections[debug_info].uncompressed_name;
@@ -3907,14 +4993,13 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
        {
          int is_debug_info;
 
-         if ((sect->output_section != NULL
-              && sect->output_section != sect
-              && (sect->flags & SEC_DEBUGGING) == 0)
-             || sect->vma != 0)
+         if (sect->output_section != NULL
+             && sect->output_section != sect
+             && (sect->flags & SEC_DEBUGGING) == 0)
            continue;
 
          is_debug_info = (strcmp (sect->name, debug_info_name) == 0
-                          || CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO));
+                          || startswith (sect->name, GNU_LINKONCE_INFO));
 
          if (!((sect->flags & SEC_ALLOC) != 0 && abfd == orig_bfd)
              && !is_debug_info)
@@ -3922,9 +5007,9 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 
          i++;
        }
-      if (abfd == stash->bfd_ptr)
+      if (abfd == stash->f.bfd_ptr)
        break;
-      abfd = stash->bfd_ptr;
+      abfd = stash->f.bfd_ptr;
     }
 
   if (i <= 1)
@@ -3932,11 +5017,11 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
   else
     {
       bfd_vma last_vma = 0, last_dwarf = 0;
-      bfd_size_type amt = i * sizeof (struct adjusted_section);
+      size_t amt = i * sizeof (struct adjusted_section);
 
       p = (struct adjusted_section *) bfd_malloc (amt);
       if (p == NULL)
-       return FALSE;
+       return false;
 
       stash->adjusted_sections = p;
       stash->adjusted_section_count = i;
@@ -3951,14 +5036,13 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
              bfd_size_type sz;
              int is_debug_info;
 
-             if ((sect->output_section != NULL
-                  && sect->output_section != sect
-                  && (sect->flags & SEC_DEBUGGING) == 0)
-                 || sect->vma != 0)
+             if (sect->output_section != NULL
+                 && sect->output_section != sect
+                 && (sect->flags & SEC_DEBUGGING) == 0)
                continue;
 
              is_debug_info = (strcmp (sect->name, debug_info_name) == 0
-                              || CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO));
+                              || startswith (sect->name, GNU_LINKONCE_INFO));
 
              if (!((sect->flags & SEC_ALLOC) != 0 && abfd == orig_bfd)
                  && !is_debug_info)
@@ -3966,37 +5050,30 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 
              sz = sect->rawsize ? sect->rawsize : sect->size;
 
-             if (is_debug_info)
-               {
-                 BFD_ASSERT (sect->alignment_power == 0);
-                 sect->vma = last_dwarf;
-                 last_dwarf += sz;
-               }
-             else
-               {
-                 /* 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 += sz;
-               }
-
              p->section = sect;
+             p->orig_vma = sect->vma;
+
+             bfd_vma *v = is_debug_info ? &last_dwarf : &last_vma;
+             /* Align the new address to the current section
+                alignment.  */
+             bfd_vma mask = -(bfd_vma) 1 << sect->alignment_power;
+             *v = (*v + ~mask) & mask;
+             sect->vma = *v;
+             *v += sz;
+
              p->adj_vma = sect->vma;
              p++;
            }
-         if (abfd == stash->bfd_ptr)
+         if (abfd == stash->f.bfd_ptr)
            break;
-         abfd = stash->bfd_ptr;
+         abfd = stash->f.bfd_ptr;
        }
     }
 
-  if (orig_bfd != stash->bfd_ptr)
-    set_debug_vma (orig_bfd, stash->bfd_ptr);
+  if (orig_bfd != stash->f.bfd_ptr)
+    set_debug_vma (orig_bfd, stash->f.bfd_ptr);
 
-  return TRUE;
+  return true;
 }
 
 /* Look up a funcinfo by name using the given info hash table.  If found,
@@ -4005,7 +5082,7 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
    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
+static bool
 info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
                           asymbol *sym,
                           bfd_vma addr,
@@ -4014,11 +5091,10 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
 {
   struct funcinfo* each_func;
   struct funcinfo* best_fit = NULL;
-  bfd_vma best_fit_len = 0;
+  bfd_vma best_fit_len = (bfd_vma) -1;
   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;
@@ -4029,11 +5105,9 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
           arange;
           arange = arange->next)
        {
-         if ((!each_func->sec || each_func->sec == sec)
-             && addr >= arange->low
+         if (addr >= arange->low
              && addr < arange->high
-             && (!best_fit
-                 || arange->high - arange->low < best_fit_len))
+             && arange->high - arange->low < best_fit_len)
            {
              best_fit = each_func;
              best_fit_len = arange->high - arange->low;
@@ -4043,13 +5117,12 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
 
   if (best_fit)
     {
-      best_fit->sec = sec;
       *filename_ptr = best_fit->file;
       *linenumber_ptr = best_fit->line;
-      return TRUE;
+      return true;
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Look up a varinfo by name using the given info hash table.  If found,
@@ -4058,53 +5131,50 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table,
    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
+static bool
 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;
+  const char *name = bfd_asymbol_name (sym);
 
   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))
+      if (each->addr == addr)
        {
-         each->sec = sec;
          *filename_ptr = each->file;
          *linenumber_ptr = each->line;
-         return TRUE;
+         return true;
        }
     }
 
-  return FALSE;
+  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
+static bool
 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->f.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;
+    each = stash->f.last_comp_unit;
 
   while (each)
     {
@@ -4112,13 +5182,13 @@ stash_maybe_update_info_hash_tables (struct dwarf2_debug *stash)
                                stash->varinfo_hash_table))
        {
          stash->info_hash_status = STASH_INFO_HASH_DISABLED;
-         return FALSE;
+         return false;
        }
       each = each->prev_unit;
     }
 
-  stash->hash_units_head = stash->all_comp_units;
-  return TRUE;
+  stash->hash_units_head = stash->f.all_comp_units;
+  return true;
 }
 
 /* Check consistency of info hash tables.  This is for debugging only.  */
@@ -4130,9 +5200,9 @@ stash_verify_info_hash_table (struct dwarf2_debug *stash)
   struct funcinfo *each_func;
   struct varinfo *each_var;
   struct info_list_node *node;
-  bfd_boolean found;
+  bool found;
 
-  for (each_unit = stash->all_comp_units;
+  for (each_unit = stash->f.all_comp_units;
        each_unit;
        each_unit = each_unit->next_unit)
     {
@@ -4145,7 +5215,7 @@ stash_verify_info_hash_table (struct dwarf2_debug *stash)
          node = lookup_info_hash_table (stash->funcinfo_hash_table,
                                         each_func->name);
          BFD_ASSERT (node);
-         found = FALSE;
+         found = false;
          while (node && !found)
            {
              found = node->info == each_func;
@@ -4163,7 +5233,7 @@ stash_verify_info_hash_table (struct dwarf2_debug *stash)
          node = lookup_info_hash_table (stash->varinfo_hash_table,
                                         each_var->name);
          BFD_ASSERT (node);
-         found = FALSE;
+         found = false;
          while (node && !found)
            {
              found = node->info == each_var;
@@ -4202,8 +5272,8 @@ stash_maybe_enable_info_hash_tables (bfd *abfd, struct dwarf2_debug *stash)
   /* 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;
+  if (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
@@ -4211,7 +5281,7 @@ stash_maybe_enable_info_hash_tables (bfd *abfd, struct dwarf2_debug *stash)
    TRUE and update the locations pointed to by filename_ptr and linenumber_ptr;
    otherwise it returns FALSE.  */
 
-static bfd_boolean
+static bool
 stash_find_line_fast (struct dwarf2_debug *stash,
                      asymbol *sym,
                      bfd_vma addr,
@@ -4229,25 +5299,28 @@ stash_find_line_fast (struct dwarf2_debug *stash,
 
 /* Save current section VMAs.  */
 
-static bfd_boolean
+static bool
 save_section_vma (const bfd *abfd, struct dwarf2_debug *stash)
 {
   asection *s;
   unsigned int i;
 
   if (abfd->section_count == 0)
-    return TRUE;
+    return true;
   stash->sec_vma = bfd_malloc (sizeof (*stash->sec_vma) * abfd->section_count);
   if (stash->sec_vma == NULL)
-    return FALSE;
-  for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next)
+    return false;
+  stash->sec_vma_count = abfd->section_count;
+  for (i = 0, s = abfd->sections;
+       s != NULL && i < abfd->section_count;
+       i++, s = s->next)
     {
       if (s->output_section != NULL)
        stash->sec_vma[i] = s->output_section->vma + s->output_offset;
       else
        stash->sec_vma[i] = s->vma;
     }
-  return TRUE;
+  return true;
 }
 
 /* Compare current section VMAs against those at the time the stash
@@ -4257,13 +5330,21 @@ save_section_vma (const bfd *abfd, struct dwarf2_debug *stash)
    sections, so the stashed section contents depend on symbol values,
    which in turn depend on section VMAs.  */
 
-static bfd_boolean
+static bool
 section_vma_same (const bfd *abfd, const struct dwarf2_debug *stash)
 {
   asection *s;
   unsigned int i;
 
-  for (i = 0, s = abfd->sections; i < abfd->section_count; i++, s = s->next)
+  /* PR 24334: If the number of sections in ABFD has changed between
+     when the stash was created and now, then we cannot trust the
+     stashed vma information.  */
+  if (abfd->section_count != stash->sec_vma_count)
+    return false;
+
+  for (i = 0, s = abfd->sections;
+       s != NULL && i < abfd->section_count;
+       i++, s = s->next)
     {
       bfd_vma vma;
 
@@ -4272,9 +5353,9 @@ section_vma_same (const bfd *abfd, const struct dwarf2_debug *stash)
       else
        vma = s->vma;
       if (vma != stash->sec_vma[i])
-       return FALSE;
+       return false;
     }
-  return TRUE;
+  return true;
 }
 
 /* Read debug information from DEBUG_BFD when DEBUG_BFD is specified.
@@ -4282,14 +5363,13 @@ section_vma_same (const bfd *abfd, const struct dwarf2_debug *stash)
    or its gnu_debuglink. The results will be stored in PINFO.
    The function returns TRUE iff debug information is ready.  */
 
-bfd_boolean
+bool
 _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
                              const struct dwarf_debug_section *debug_sections,
                              asymbol **symbols,
                              void **pinfo,
-                             bfd_boolean do_place)
+                             bool do_place)
 {
-  bfd_size_type amt = sizeof (struct dwarf2_debug);
   bfd_size_type total_size;
   asection *msec;
   struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
@@ -4297,35 +5377,52 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
   if (stash != NULL)
     {
       if (stash->orig_bfd == abfd
-          && section_vma_same (abfd, stash))
-        {
-          /* Check that we did previously find some debug information
-             before attempting to make use of it.  */
-          if (stash->bfd_ptr != NULL)
-            {
-              if (do_place && !place_sections (abfd, stash))
-                return FALSE;
-              return TRUE;
-            }
-
-          return FALSE;
-        }
+         && section_vma_same (abfd, stash))
+       {
+         /* Check that we did previously find some debug information
+            before attempting to make use of it.  */
+         if (stash->f.dwarf_info_size != 0)
+           {
+             if (do_place && !place_sections (abfd, stash))
+               return false;
+             return true;
+           }
+
+         return false;
+       }
       _bfd_dwarf2_cleanup_debug_info (abfd, pinfo);
-      memset (stash, 0, amt);
+      memset (stash, 0, sizeof (*stash));
     }
   else
     {
-      stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt);
+      stash = (struct dwarf2_debug *) bfd_zalloc (abfd, sizeof (*stash));
       if (! stash)
-       return FALSE;
+       return false;
+      *pinfo = stash;
     }
   stash->orig_bfd = abfd;
   stash->debug_sections = debug_sections;
-  stash->syms = symbols;
+  stash->f.syms = symbols;
   if (!save_section_vma (abfd, stash))
-    return FALSE;
+    return false;
+
+  stash->f.abbrev_offsets = htab_create_alloc (10, hash_abbrev, eq_abbrev,
+                                              del_abbrev, calloc, free);
+  if (!stash->f.abbrev_offsets)
+    return false;
+
+  stash->alt.abbrev_offsets = htab_create_alloc (10, hash_abbrev, eq_abbrev,
+                                                del_abbrev, calloc, free);
+  if (!stash->alt.abbrev_offsets)
+    return false;
+
+  stash->f.trie_root = alloc_trie_leaf (abfd);
+  if (!stash->f.trie_root)
+    return false;
 
-  *pinfo = stash;
+  stash->alt.trie_root = alloc_trie_leaf (abfd);
+  if (!stash->alt.trie_root)
+    return false;
 
   if (debug_bfd == NULL)
     debug_bfd = abfd;
@@ -4344,43 +5441,42 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
           Note that at this point the stash has been allocated, but
           contains zeros.  This lets future calls to this function
           fail more quickly.  */
-       return FALSE;
+       return false;
+
+      debug_bfd = bfd_openr (debug_filename, NULL);
+      free (debug_filename);
+      if (debug_bfd == NULL)
+       /* FIXME: Should we report our failure to follow the debuglink ?  */
+       return false;
 
       /* Set BFD_DECOMPRESS to decompress debug sections.  */
-      if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
-         || !(debug_bfd->flags |= BFD_DECOMPRESS,
-              bfd_check_format (debug_bfd, bfd_object))
+      debug_bfd->flags |= BFD_DECOMPRESS;
+      if (!bfd_check_format (debug_bfd, bfd_object)
          || (msec = find_debug_info (debug_bfd,
                                      debug_sections, NULL)) == NULL
          || !bfd_generic_link_read_symbols (debug_bfd))
        {
-         if (debug_bfd)
-           bfd_close (debug_bfd);
-         /* FIXME: Should we report our failure to follow the debuglink ?  */
-         free (debug_filename);
-         return FALSE;
+         bfd_close (debug_bfd);
+         return false;
        }
 
       symbols = bfd_get_outsymbols (debug_bfd);
-      stash->syms = symbols;
-      stash->close_on_cleanup = TRUE;
+      stash->f.syms = symbols;
+      stash->close_on_cleanup = true;
     }
-  stash->bfd_ptr = debug_bfd;
+  stash->f.bfd_ptr = debug_bfd;
 
   if (do_place
       && !place_sections (abfd, stash))
-    return FALSE;
+    return false;
 
   /* 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
+     there's more than one, try case two: 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.  */
+     reallocing the data as we add sections to the stash.)  */
 
   if (! find_debug_info (debug_bfd, debug_sections, msec))
     {
@@ -4388,8 +5484,8 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
       total_size = msec->size;
       if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
                          symbols, 0,
-                         &stash->info_ptr_memory, &total_size))
-       return FALSE;
+                         &stash->f.dwarf_info_buffer, &total_size))
+       goto restore_vma;
     }
   else
     {
@@ -4397,11 +5493,21 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
       for (total_size = 0;
           msec;
           msec = find_debug_info (debug_bfd, debug_sections, msec))
-       total_size += msec->size;
+       {
+         if (_bfd_section_size_insane (debug_bfd, msec))
+           goto restore_vma;
+         /* Catch PR25070 testcase overflowing size calculation here.  */
+         if (total_size + msec->size < total_size)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             goto restore_vma;
+           }
+         total_size += msec->size;
+       }
 
-      stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
-      if (stash->info_ptr_memory == NULL)
-       return FALSE;
+      stash->f.dwarf_info_buffer = (bfd_byte *) bfd_malloc (total_size);
+      if (stash->f.dwarf_info_buffer == NULL)
+       goto restore_vma;
 
       total_size = 0;
       for (msec = find_debug_info (debug_bfd, debug_sections, NULL);
@@ -4415,19 +5521,130 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
            continue;
 
          if (!(bfd_simple_get_relocated_section_contents
-               (debug_bfd, msec, stash->info_ptr_memory + total_size,
+               (debug_bfd, msec, stash->f.dwarf_info_buffer + total_size,
                 symbols)))
-           return FALSE;
+           goto restore_vma;
 
          total_size += size;
        }
     }
 
-  stash->info_ptr = stash->info_ptr_memory;
-  stash->info_ptr_end = stash->info_ptr + total_size;
-  stash->sec = find_debug_info (debug_bfd, debug_sections, NULL);
-  stash->sec_info_ptr = stash->info_ptr;
-  return TRUE;
+  stash->f.info_ptr = stash->f.dwarf_info_buffer;
+  stash->f.dwarf_info_size = total_size;
+  return true;
+
+ restore_vma:
+  unset_sections (stash);
+  return false;
+}
+
+/* Parse the next DWARF2 compilation unit at FILE->INFO_PTR.  */
+
+static struct comp_unit *
+stash_comp_unit (struct dwarf2_debug *stash, struct dwarf2_debug_file *file)
+{
+  bfd_size_type length;
+  unsigned int offset_size;
+  bfd_byte *info_ptr_unit = file->info_ptr;
+  bfd_byte *info_ptr_end = file->dwarf_info_buffer + file->dwarf_info_size;
+
+  if (file->info_ptr >= info_ptr_end)
+    return NULL;
+
+  length = read_4_bytes (file->bfd_ptr, &file->info_ptr, info_ptr_end);
+  /* 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 (file->bfd_ptr, &file->info_ptr, info_ptr_end);
+    }
+  /* A zero length is the IRIX way of indicating 64-bit offsets,
+     mostly because the 64-bit length will generally fit in 32
+     bits, and the endianness helps.  */
+  else if (length == 0)
+    {
+      offset_size = 8;
+      length = read_4_bytes (file->bfd_ptr, &file->info_ptr, info_ptr_end);
+    }
+  /* 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
+    offset_size = 4;
+
+  if (length != 0
+      && length <= (size_t) (info_ptr_end - file->info_ptr))
+    {
+      struct comp_unit *each = parse_comp_unit (stash, file,
+                                               file->info_ptr, length,
+                                               info_ptr_unit, offset_size);
+      if (each)
+       {
+         if (file->comp_unit_tree == NULL)
+           file->comp_unit_tree
+             = splay_tree_new (splay_tree_compare_addr_range,
+                               splay_tree_free_addr_range, NULL);
+
+         struct addr_range *r
+           = (struct addr_range *)bfd_malloc (sizeof (struct addr_range));
+         r->start = each->info_ptr_unit;
+         r->end = each->end_ptr;
+         splay_tree_node v = splay_tree_lookup (file->comp_unit_tree,
+                                                (splay_tree_key)r);
+         if (v != NULL || r->end <= r->start)
+           abort ();
+         splay_tree_insert (file->comp_unit_tree, (splay_tree_key)r,
+                            (splay_tree_value)each);
+
+         if (file->all_comp_units)
+           file->all_comp_units->prev_unit = each;
+         else
+           file->last_comp_unit = each;
+
+         each->next_unit = file->all_comp_units;
+         file->all_comp_units = each;
+
+         if (each->arange.high == 0)
+           {
+             each->next_unit_without_ranges = file->all_comp_units_without_ranges;
+             file->all_comp_units_without_ranges = each->next_unit_without_ranges;
+           }
+
+         file->info_ptr += length;
+         return each;
+       }
+    }
+
+  /* Don't trust any of the DWARF info after a corrupted length or
+     parse error.  */
+  file->info_ptr = info_ptr_end;
+  return NULL;
+}
+
+/* Hash function for an asymbol.  */
+
+static hashval_t
+hash_asymbol (const void *sym)
+{
+  const asymbol *asym = sym;
+  return htab_hash_string (asym->name);
+}
+
+/* Equality function for asymbols.  */
+
+static int
+eq_asymbol (const void *a, const void *b)
+{
+  const asymbol *sa = a;
+  const asymbol *sb = b;
+  return strcmp (sa->name, sb->name) == 0;
 }
 
 /* Scan the debug information in PINFO looking for a DW_TAG_subprogram
@@ -4440,60 +5657,60 @@ _bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo)
 {
   struct dwarf2_debug *stash;
   struct comp_unit * unit;
+  htab_t sym_hash;
+  bfd_signed_vma result = 0;
+  asymbol ** psym;
 
   stash = (struct dwarf2_debug *) *pinfo;
 
-  if (stash == NULL)
+  if (stash == NULL || symbols == NULL)
     return 0;
 
-  for (unit = stash->all_comp_units; unit; unit = unit->next_unit)
+  sym_hash = htab_create_alloc (10, hash_asymbol, eq_asymbol,
+                               NULL, xcalloc, free);
+  for (psym = symbols; * psym != NULL; psym++)
     {
-      struct funcinfo * func;
+      asymbol * sym = * psym;
 
-      if (unit->function_table == NULL)
+      if (sym->flags & BSF_FUNCTION && sym->section != NULL)
        {
-         if (unit->line_table == NULL)
-           unit->line_table = decode_line_info (unit, stash);
-         if (unit->line_table != NULL)
-           scan_unit_for_symbols (unit);
+         void **slot = htab_find_slot (sym_hash, sym, INSERT);
+         *slot = sym;
        }
+    }
+
+  for (unit = stash->f.all_comp_units; unit; unit = unit->next_unit)
+    {
+      struct funcinfo * func;
+
+      comp_unit_maybe_decode_line_info (unit);
 
       for (func = unit->function_table; func != NULL; func = func->prev_func)
        if (func->name && func->arange.low)
          {
-           asymbol ** psym;
+           asymbol search, *sym;
 
-           /* FIXME: Do we need to scan the aranges looking for the lowest pc value ?  */
+           /* FIXME: Do we need to scan the aranges looking for the
+              lowest pc value?  */
 
-           for (psym = symbols; * psym != NULL; psym++)
+           search.name = func->name;
+           sym = htab_find (sym_hash, &search);
+           if (sym != NULL)
              {
-               asymbol * sym = * psym;
-
-               if (sym->flags & BSF_FUNCTION
-                   && sym->section != NULL
-                   && strcmp (sym->name, func->name) == 0)
-                 return ((bfd_signed_vma) func->arange.low) -
-                   ((bfd_signed_vma) (sym->value + sym->section->vma));
+               result = func->arange.low - (sym->value + sym->section->vma);
+               goto done;
              }
          }
     }
 
-  return 0;
+ done:
+  htab_delete (sym_hash);
+  return result;
 }
 
-/* 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.
-   DEBUG_SECTIONS contains the name of the dwarf debug sections.
-   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.  */
+/* See _bfd_dwarf2_find_nearest_line_with_alt.  */
 
-bfd_boolean
+int
 _bfd_dwarf2_find_nearest_line (bfd *abfd,
                               asymbol **symbols,
                               asymbol *symbol,
@@ -4504,8 +5721,44 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                               unsigned int *linenumber_ptr,
                               unsigned int *discriminator_ptr,
                               const struct dwarf_debug_section *debug_sections,
-                              unsigned int addr_size,
                               void **pinfo)
+{
+  return _bfd_dwarf2_find_nearest_line_with_alt
+    (abfd, NULL, symbols, symbol, section, offset, filename_ptr,
+     functionname_ptr, linenumber_ptr, discriminator_ptr, debug_sections,
+     pinfo);
+}
+
+/* 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 1 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.
+   Returns 2 if partial information from _bfd_elf_find_function is
+   returned (function and maybe file) by looking at symbols.  DWARF2
+   info is present but not regarding the requested code location.
+   Returns 0 otherwise.
+   SYMBOLS contains the symbol table for ABFD.
+   DEBUG_SECTIONS contains the name of the dwarf debug sections.
+   If ALT_FILENAME is given, attempt to open the file and use it
+   as the .gnu_debugaltlink file. Otherwise this file will be
+   searched for when needed.  */
+
+int
+_bfd_dwarf2_find_nearest_line_with_alt
+  (bfd *abfd,
+   const char *alt_filename,
+   asymbol **symbols,
+   asymbol *symbol,
+   asection *section,
+   bfd_vma offset,
+   const char **filename_ptr,
+   const char **functionname_ptr,
+   unsigned int *linenumber_ptr,
+   unsigned int *discriminator_ptr,
+   const struct dwarf_debug_section *debug_sections,
+   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,
@@ -4520,8 +5773,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   bfd_vma addr;
   struct comp_unit* each;
   struct funcinfo *function = NULL;
-  bfd_boolean found = FALSE;
-  bfd_boolean do_line;
+  int found = false;
+  bool do_line;
 
   *filename_ptr = NULL;
   if (functionname_ptr != NULL)
@@ -4533,15 +5786,32 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   if (! _bfd_dwarf2_slurp_debug_info (abfd, NULL, debug_sections,
                                      symbols, pinfo,
                                      (abfd->flags & (EXEC_P | DYNAMIC)) == 0))
-    return FALSE;
+    return false;
 
   stash = (struct dwarf2_debug *) *pinfo;
 
+  if (stash->alt.bfd_ptr == NULL && alt_filename != NULL)
+    {
+      bfd *alt_bfd = bfd_openr (alt_filename, NULL);
+
+      if (alt_bfd == NULL)
+       /* bfd_openr will have set the bfd_error.  */
+       return false;
+      if (!bfd_check_format (alt_bfd, bfd_object))
+       {
+         bfd_set_error (bfd_error_wrong_format);
+         bfd_close (alt_bfd);
+         return false;
+       }
+
+      stash->alt.bfd_ptr = alt_bfd;
+    }
+
   do_line = symbol != NULL;
   if (do_line)
     {
       BFD_ASSERT (section == NULL && offset == 0 && functionname_ptr == NULL);
-      section = bfd_get_section (symbol);
+      section = bfd_asymbol_section (symbol);
       addr = symbol->value;
     }
   else
@@ -4550,18 +5820,18 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
       addr = offset;
 
       /* If we have no SYMBOL but the section we're looking at is not a
-         code section, then take a look through the list of symbols to see
-         if we have a symbol at the address we're looking for.  If we do
-         then use this to look up line information.  This will allow us to
-         give file and line results for data symbols.  We exclude code
-         symbols here, if we look up a function symbol and then look up the
-         line information we'll actually return the line number for the
-         opening '{' rather than the function definition line.  This is
-         because looking up by symbol uses the line table, in which the
-         first line for a function is usually the opening '{', while
-         looking up the function by section + offset uses the
-         DW_AT_decl_line from the function DW_TAG_subprogram for the line,
-         which will be the line of the function name.  */
+        code section, then take a look through the list of symbols to see
+        if we have a symbol at the address we're looking for.  If we do
+        then use this to look up line information.  This will allow us to
+        give file and line results for data symbols.  We exclude code
+        symbols here, if we look up a function symbol and then look up the
+        line information we'll actually return the line number for the
+        opening '{' rather than the function definition line.  This is
+        because looking up by symbol uses the line table, in which the
+        first line for a function is usually the opening '{', while
+        looking up the function by section + offset uses the
+        DW_AT_decl_line from the function DW_TAG_subprogram for the line,
+        which will be the line of the function name.  */
       if (symbols != NULL && (section->flags & SEC_CODE) == 0)
        {
          asymbol **tmp;
@@ -4573,11 +5843,11 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                && ((*tmp)->flags & BSF_SECTION_SYM) == 0)
              {
                symbol = *tmp;
-               do_line = TRUE;
-                /* For local symbols, keep going in the hope we find a
-                   global.  */
-                if ((symbol->flags & BSF_GLOBAL) != 0)
-                  break;
+               do_line = true;
+               /* For local symbols, keep going in the hope we find a
+                  global.  */
+               if ((symbol->flags & BSF_GLOBAL) != 0)
+                 break;
              }
        }
     }
@@ -4589,8 +5859,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
 
   /* 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;
+  if (! stash->f.info_ptr)
+    return false;
 
   stash->inliner_chain = NULL;
 
@@ -4610,230 +5880,158 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
 
       if (stash->info_hash_status == STASH_INFO_HASH_ON)
        {
-         found = stash_find_line_fast (stash, symbol, addr, filename_ptr,
-                                       linenumber_ptr);
+         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
-               || each->arange.high == 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
-    {
-      bfd_vma min_range = (bfd_vma) -1;
-      const char * local_filename = NULL;
-      struct funcinfo *local_function = NULL;
-      unsigned int local_linenumber = 0;
-      unsigned int local_discriminator = 0;
-
-      for (each = stash->all_comp_units; each; each = each->next_unit)
-       {
-         bfd_vma range = (bfd_vma) -1;
-
-         found = ((each->arange.high == 0
-                   || comp_unit_contains_address (each, addr))
-                  && (range = comp_unit_find_nearest_line (each, addr,
-                                                           & local_filename,
-                                                           & local_function,
-                                                           & local_linenumber,
-                                                           & local_discriminator,
-                                                           stash)) != 0);
-         if (found)
-           {
-             /* PRs 15935 15994: Bogus debug information may have provided us
-                with an erroneous match.  We attempt to counter this by
-                selecting the match that has the smallest address range
-                associated with it.  (We are assuming that corrupt debug info
-                will tend to result in extra large address ranges rather than
-                extra small ranges).
-
-                This does mean that we scan through all of the CUs associated
-                with the bfd each time this function is called.  But this does
-                have the benefit of producing consistent results every time the
-                function is called.  */
-             if (range <= min_range)
-               {
-                 if (filename_ptr && local_filename)
-                   * filename_ptr = local_filename;
-                 if (local_function)
-                   function = local_function;
-                 if (discriminator_ptr && local_discriminator)
-                   * discriminator_ptr = local_discriminator;
-                 if (local_linenumber)
-                   * linenumber_ptr = local_linenumber;
-                 min_range = range;
-               }
-           }
-       }
 
-      if (* linenumber_ptr)
-       {
-         found = TRUE;
-         goto done;
-       }
+      /* Check the previously read comp. units first.  */
+      for (each = stash->f.all_comp_units; each; each = each->next_unit)
+       if ((symbol->flags & BSF_FUNCTION) == 0
+           || comp_unit_may_contain_address (each, addr))
+         {
+           found = comp_unit_find_line (each, symbol, addr, filename_ptr,
+                                        linenumber_ptr);
+           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)
+  else
     {
-      bfd_vma length;
-      unsigned int offset_size = addr_size;
-      bfd_byte *info_ptr_unit = stash->info_ptr;
+      struct trie_node *trie = stash->f.trie_root;
+      unsigned int bits = VMA_BITS - 8;
+      struct comp_unit **prev_each;
 
-      length = read_4_bytes (stash->bfd_ptr, stash->info_ptr, stash->info_ptr_end);
-      /* 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 (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
-         stash->info_ptr += 12;
-       }
-      /* A zero length is the IRIX way of indicating 64-bit offsets,
-        mostly because the 64-bit length will generally fit in 32
-        bits, and the endianness helps.  */
-      else if (length == 0)
+      /* Traverse interior nodes until we get to a leaf.  */
+      while (trie && trie->num_room_in_leaf == 0)
        {
-         offset_size = 8;
-         length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4, stash->info_ptr_end);
-         stash->info_ptr += 8;
+         int ch = (addr >> bits) & 0xff;
+         trie = ((struct trie_interior *) trie)->children[ch];
+         bits -= 8;
        }
-      /* 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)
-       {
-         offset_size = 4;
-         stash->info_ptr += 4;
-       }
-      else
-       stash->info_ptr += 4;
 
-      if (length > 0)
+      if (trie)
        {
-         bfd_byte * new_ptr;
-
-         /* PR 21151  */
-         if (stash->info_ptr + length > stash->info_ptr_end)
-           return FALSE;
+         const struct trie_leaf *leaf = (struct trie_leaf *) trie;
+         unsigned int i;
 
-         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;
+         for (i = 0; i < leaf->num_stored_in_leaf; ++i)
+           leaf->ranges[i].unit->mark = false;
 
-         new_ptr = stash->info_ptr + length;
-         /* PR 17512: file: 1500698c.  */
-         if (new_ptr < stash->info_ptr)
+         for (i = 0; i < leaf->num_stored_in_leaf; ++i)
            {
-             /* A corrupt length value - do not trust the info any more.  */
-             found = FALSE;
-             break;
-           }
-         else
-           stash->info_ptr = new_ptr;
+             struct comp_unit *unit = leaf->ranges[i].unit;
+             if (unit->mark
+                 || addr < leaf->ranges[i].low_pc
+                 || addr >= leaf->ranges[i].high_pc)
+               continue;
+             unit->mark = true;
+
+             found = comp_unit_find_nearest_line (unit, addr,
+                                                  filename_ptr,
+                                                  &function,
+                                                  linenumber_ptr,
+                                                  discriminator_ptr);
+             if (found)
+               goto done;
+          }
+       }
 
-         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,
-                                                    &function,
-                                                    linenumber_ptr,
-                                                    discriminator_ptr,
-                                                    stash) != 0);
-
-         if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
-             == stash->sec->size)
+      /* Also scan through all compilation units without any ranges,
+         taking them out of the list if they have acquired any since
+        last time.  */
+      prev_each = &stash->f.all_comp_units_without_ranges;
+      for (each = *prev_each; each; each = each->next_unit_without_ranges)
+        {
+         if (each->arange.high != 0)
            {
-             stash->sec = find_debug_info (stash->bfd_ptr, debug_sections,
-                                           stash->sec);
-             stash->sec_info_ptr = stash->info_ptr;
+             *prev_each = each->next_unit_without_ranges;
+             continue;
            }
 
+         found = comp_unit_find_nearest_line (each, addr,
+                                              filename_ptr,
+                                              &function,
+                                              linenumber_ptr,
+                                              discriminator_ptr);
          if (found)
            goto done;
+         prev_each = &each->next_unit_without_ranges;
        }
     }
 
+  /* Read each remaining comp. units checking each as they are read.  */
+  while ((each = stash_comp_unit (stash, &stash->f)) != NULL)
+    {
+      /* 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
+                 || comp_unit_may_contain_address (each, addr))
+                && comp_unit_find_line (each, symbol, addr,
+                                        filename_ptr, linenumber_ptr));
+      else
+       found = (comp_unit_may_contain_address (each, addr)
+                && comp_unit_find_nearest_line (each, addr,
+                                                filename_ptr,
+                                                &function,
+                                                linenumber_ptr,
+                                                discriminator_ptr));
+
+      if (found)
+       break;
+    }
+
  done:
-  if (function)
+  if (functionname_ptr && function && function->is_linkage)
+    {
+      *functionname_ptr = function->name;
+      if (!found)
+        found = 2;
+    }
+  else if (functionname_ptr
+          && (!*functionname_ptr
+              || (function && !function->is_linkage)))
     {
-      if (!function->is_linkage)
+      asymbol *fun;
+      asymbol **syms = symbols;
+      asection *sec = section;
+
+      _bfd_dwarf2_stash_syms (stash, abfd, &sec, &syms);
+      fun = _bfd_elf_find_function (abfd, syms, sec, offset,
+                                   *filename_ptr ? NULL : filename_ptr,
+                                   functionname_ptr);
+
+      if (!found && fun != NULL)
+       found = 2;
+
+      if (function && !function->is_linkage)
        {
-         asymbol *fun;
          bfd_vma sec_vma;
 
-         fun = _bfd_elf_find_function (abfd, symbols, section, offset,
-                                       *filename_ptr ? NULL : filename_ptr,
-                                       functionname_ptr);
          sec_vma = section->vma;
          if (section->output_section != NULL)
            sec_vma = section->output_section->vma + section->output_offset;
-         if (fun != NULL
-             && fun->value + sec_vma == function->arange.low)
+         if (fun == NULL)
+           *functionname_ptr = function->name;
+         else if (fun->value + sec_vma == function->arange.low)
            function->name = *functionname_ptr;
          /* Even if we didn't find a linkage name, say that we have
             to stop a repeated search of symbols.  */
-         function->is_linkage = TRUE;
+         function->is_linkage = true;
        }
-      *functionname_ptr = function->name;
     }
-  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
-    unset_sections (stash);
+
+  unset_sections (stash);
 
   return found;
 }
 
-bfd_boolean
+bool
 _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
                               const char **filename_ptr,
                               const char **functionname_ptr,
@@ -4853,11 +6051,11 @@ _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED,
          *functionname_ptr = func->caller_func->name;
          *linenumber_ptr = func->caller_line;
          stash->inliner_chain = func->caller_func;
-         return TRUE;
+         return true;
        }
     }
 
-  return FALSE;
+  return false;
 }
 
 void
@@ -4865,92 +6063,75 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
 {
   struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
   struct comp_unit *each;
+  struct dwarf2_debug_file *file;
 
   if (abfd == NULL || stash == NULL)
     return;
 
-  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;
+  if (stash->varinfo_hash_table)
+    bfd_hash_table_free (&stash->varinfo_hash_table->base);
+  if (stash->funcinfo_hash_table)
+    bfd_hash_table_free (&stash->funcinfo_hash_table->base);
 
-      for (i = 0; i < ABBREV_HASH_SIZE; i++)
+  file = &stash->f;
+  while (1)
+    {
+      for (each = file->all_comp_units; each; each = each->next_unit)
        {
-         struct abbrev_info *abbrev = abbrevs[i];
+         struct funcinfo *function_table = each->function_table;
+         struct varinfo *variable_table = each->variable_table;
 
-         while (abbrev)
+         if (each->line_table && each->line_table != file->line_table)
            {
-             free (abbrev->attrs);
-             abbrev = abbrev->next;
+             free (each->line_table->files);
+             free (each->line_table->dirs);
            }
-       }
 
-      if (each->line_table)
-       {
-         free (each->line_table->dirs);
-         free (each->line_table->files);
-       }
+         free (each->lookup_funcinfo_table);
+         each->lookup_funcinfo_table = NULL;
 
-      while (function_table)
-       {
-         if (function_table->file)
+         while (function_table)
            {
              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;
            }
-         function_table = function_table->prev_func;
-       }
-
-      if (each->lookup_funcinfo_table)
-       {
-         free (each->lookup_funcinfo_table);
-         each->lookup_funcinfo_table = NULL;
-       }
 
-      while (variable_table)
-       {
-         if (variable_table->file)
+         while (variable_table)
            {
              free (variable_table->file);
              variable_table->file = NULL;
+             variable_table = variable_table->prev_var;
            }
+       }
 
-         variable_table = variable_table->prev_var;
+      if (file->line_table)
+       {
+         free (file->line_table->files);
+         free (file->line_table->dirs);
        }
+      htab_delete (file->abbrev_offsets);
+      if (file->comp_unit_tree != NULL)
+       splay_tree_delete (file->comp_unit_tree);
+
+      free (file->dwarf_line_str_buffer);
+      free (file->dwarf_str_buffer);
+      free (file->dwarf_ranges_buffer);
+      free (file->dwarf_line_buffer);
+      free (file->dwarf_abbrev_buffer);
+      free (file->dwarf_info_buffer);
+      if (file == &stash->alt)
+       break;
+      file = &stash->alt;
     }
-
-  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_line_str_buffer)
-    free (stash->dwarf_line_str_buffer);
-  if (stash->dwarf_ranges_buffer)
-    free (stash->dwarf_ranges_buffer);
-  if (stash->info_ptr_memory)
-    free (stash->info_ptr_memory);
+  free (stash->sec_vma);
+  free (stash->adjusted_sections);
   if (stash->close_on_cleanup)
-    bfd_close (stash->bfd_ptr);
-  if (stash->alt_dwarf_str_buffer)
-    free (stash->alt_dwarf_str_buffer);
-  if (stash->alt_dwarf_info_buffer)
-    free (stash->alt_dwarf_info_buffer);
-  if (stash->sec_vma)
-    free (stash->sec_vma);
-  if (stash->adjusted_sections)
-    free (stash->adjusted_sections);
-  if (stash->alt_bfd_ptr)
-    bfd_close (stash->alt_bfd_ptr);
+    bfd_close (stash->f.bfd_ptr);
+  if (stash->alt.bfd_ptr)
+    bfd_close (stash->alt.bfd_ptr);
 }
 
 /* Find the function to a particular section and offset,