Blob Blame History Raw
diff -rup binutils.orig/bfd/dwarf2.c binutils-2.33.1/bfd/dwarf2.c
--- binutils.orig/bfd/dwarf2.c	2020-01-02 17:07:57.530373027 +0000
+++ binutils-2.33.1/bfd/dwarf2.c	2020-01-02 17:11:21.510870042 +0000
@@ -1,5 +1,5 @@
 /* DWARF 2 support.
-   Copyright (C) 1994-2019 Free Software Foundation, Inc.
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
 
    Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
    (gavin@cygnus.com).
@@ -82,55 +82,23 @@ struct adjusted_section
   bfd_vma adj_vma;
 };
 
-struct dwarf2_debug
+struct dwarf2_debug_file
 {
-  /* A list of all previously read comp_units.  */
-  struct comp_unit *all_comp_units;
-
-  /* Last comp unit in list above.  */
-  struct comp_unit *last_comp_unit;
+  /* The actual bfd from which debug info was loaded.  Might be
+     different to orig_bfd because of gnu_debuglink sections.  */
+  bfd *bfd_ptr;
 
-  /* Names of the debug sections.  */
-  const struct dwarf_debug_section *debug_sections;
+  /* Pointer to the symbol table.  */
+  asymbol **syms;
 
-  /* 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.  */
+  /* The current info pointer for the .debug_info section being parsed.  */
   bfd_byte *info_ptr;
 
-  /* Pointer to the end of the .debug_info section memory buffer.  */
-  bfd_byte *info_ptr_end;
+  /* A pointer to the memory block allocated for .debug_info sections.  */
+  bfd_byte *dwarf_info_buffer;
 
-  /* 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;
-
-  /* Pointer to the bfd, section and address of the beginning of the
-     section.  The bfd might be different than expected because of
-     gnu_debuglink sections.  */
-  bfd *bfd_ptr;
-  asection *sec;
-  bfd_byte *sec_info_ptr;
-
-  /* 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;
+  /* 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;
@@ -162,6 +130,33 @@ struct dwarf2_debug
   /* Length of the loaded .debug_ranges section.  */
   bfd_size_type dwarf_ranges_size;
 
+  /* A list of all previously read comp_units.  */
+  struct comp_unit *all_comp_units;
+
+  /* Last comp unit in list above.  */
+  struct comp_unit *last_comp_unit;
+
+  /* Line table at line_offset zero.  */
+  struct line_info_table *line_table;
+
+  /* Hash table to map offsets to decoded abbrevs.  */
+  htab_t abbrev_offsets;
+};
+
+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
@@ -276,8 +271,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;
@@ -706,6 +702,7 @@ read_indirect_string (struct comp_unit *
 {
   bfd_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)
@@ -722,13 +719,11 @@ read_indirect_string (struct comp_unit *
   *bytes_read_ptr = unit->offset_size;
 
   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;
@@ -744,6 +739,7 @@ read_indirect_line_string (struct comp_u
 {
   bfd_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)
@@ -760,14 +756,12 @@ read_indirect_line_string (struct comp_u
   *bytes_read_ptr = unit->offset_size;
 
   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;
@@ -800,7 +794,7 @@ read_alt_indirect_string (struct comp_un
 
   *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);
@@ -819,20 +813,17 @@ read_alt_indirect_string (struct comp_un
 	  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;
 
@@ -849,13 +840,13 @@ read_alt_indirect_ref (struct comp_unit
 {
   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);
 
       if (debug_filename == NULL)
-	return FALSE;
+	return NULL;
 
       debug_bfd = bfd_openr (debug_filename, NULL);
       free (debug_filename);
@@ -868,20 +859,17 @@ read_alt_indirect_ref (struct comp_unit
 	  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
@@ -947,13 +935,59 @@ lookup_abbrev (unsigned int number, stru
   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, bfd_uint64_t offset, struct dwarf2_debug *stash,
+	      struct dwarf2_debug_file *file)
 {
   struct abbrev_info **abbrevs;
   bfd_byte *abbrev_ptr;
@@ -962,13 +996,22 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
   unsigned int abbrev_number, bytes_read, abbrev_name;
   unsigned int abbrev_form, hash_number;
   bfd_size_type 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;
@@ -976,8 +1019,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
   if (abbrevs == NULL)
     return NULL;
 
-  abbrev_ptr = stash->dwarf_abbrev_buffer + offset;
-  abbrev_end = stash->dwarf_abbrev_buffer + stash->dwarf_abbrev_size;
+  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, &bytes_read,
 					 FALSE, abbrev_end);
   abbrev_ptr += bytes_read;
@@ -988,7 +1031,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
       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;
@@ -1030,21 +1073,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
 	      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;
 	    }
 
@@ -1068,8 +1097,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
 	 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);
@@ -1078,7 +1107,31 @@ read_abbrevs (bfd *abfd, bfd_uint64_t of
 	break;
     }
 
+  *slot = bfd_malloc (sizeof ent);
+  if (!*slot)
+    goto fail;
+  ent.abbrevs = abbrevs;
+  memcpy (*slot, &ent, sizeof ent);
   return abbrevs;
+
+ fail:
+  if (abbrevs != 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;
+	    }
+	}
+      free (abbrevs);
+    }
+  return NULL;
 }
 
 /* Returns true if the form is one which has a string value.  */
@@ -1413,6 +1466,8 @@ struct lookup_funcinfo
      The highest address of all prior functions after the lookup table is
      sorted, which is used for binary search.  */
   bfd_vma		high_addr;
+  /* Index of this function, used to ensure qsort is stable.  */
+  unsigned int idx;
 };
 
 struct varinfo
@@ -1713,6 +1768,11 @@ compare_sequences (const void* a, const
   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;
 }
 
@@ -1739,12 +1799,14 @@ build_line_info_table (struct line_info_
   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;
 
   /* 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;
 
@@ -1754,10 +1816,6 @@ build_line_info_table (struct line_info_
     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;
 }
 
@@ -1793,7 +1851,7 @@ sort_line_sequences (struct line_info_ta
       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);
     }
@@ -2020,9 +2078,11 @@ read_formatted_entries (struct comp_unit
 /* 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;
@@ -2033,39 +2093,24 @@ decode_line_info (struct comp_unit *unit
   unsigned int exop_len;
   bfd_size_type 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 (%" PRId64 ")"),
-	 (int64_t) stash->dwarf_line_size);
+	 (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);
@@ -2192,6 +2237,24 @@ decode_line_info (struct comp_unit *unit
       line_ptr += 1;
     }
 
+  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)
     {
       /* Read directory table.  */
@@ -2391,16 +2454,16 @@ decode_line_info (struct comp_unit *unit
 	      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);
+		filenum = _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);
+		filename = concat_filename (table, filenum);
 		break;
 	      }
 	    case DW_LNS_set_column:
@@ -2449,6 +2512,8 @@ decode_line_info (struct comp_unit *unit
 	free (filename);
     }
 
+  if (unit->line_offset == 0)
+    file->line_table = table;
   if (sort_line_sequences (table))
     return table;
 
@@ -2544,12 +2609,12 @@ fail:
 static bfd_boolean
 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);
 }
 
 /* Function table functions.  */
@@ -2569,6 +2634,10 @@ compare_lookup_funcinfos (const void * a
   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;
 }
 
@@ -2598,6 +2667,7 @@ build_lookup_funcinfo_table (struct comp
     {
       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;
@@ -2807,21 +2877,21 @@ lookup_symbol_in_variable_table (struct
   return FALSE;
 }
 
-static struct comp_unit *stash_comp_unit (struct dwarf2_debug *);
-static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *,
-						     struct dwarf2_debug *);
+static struct comp_unit *stash_comp_unit (struct dwarf2_debug *,
+					  struct dwarf2_debug_file *);
+static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *);
 
 static bfd_boolean
-find_abstract_instance (struct comp_unit *   unit,
-			struct attribute *   attr_ptr,
-			unsigned int         recur_count,
-			const char **        pname,
-			bfd_boolean *        is_linkage,
-			char **              filename_ptr,
-			int *                linenumber_ptr)
+find_abstract_instance (struct comp_unit *unit,
+			struct attribute *attr_ptr,
+			unsigned int recur_count,
+			const char **pname,
+			bfd_boolean *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;
   struct abbrev_info *abbrev;
@@ -2832,7 +2902,7 @@ find_abstract_instance (struct comp_unit
   if (recur_count == 100)
     {
       _bfd_error_handler
-       (_("DWARF error: abstract instance recursion detected"));
+	(_("DWARF error: abstract instance recursion detected"));
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -2854,12 +2924,12 @@ find_abstract_instance (struct comp_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)
 	return TRUE;
@@ -2871,14 +2941,38 @@ find_abstract_instance (struct comp_unit
 	  return FALSE;
 	}
       info_ptr += die_ref;
+    }
+  else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
+    {
+      bfd_boolean 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;
 
 	  for (u = unit->prev_unit; u != NULL; u = u->prev_unit)
 	    if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
@@ -2889,15 +2983,27 @@ find_abstract_instance (struct comp_unit
 	      if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
 		break;
 
-	  while (u == NULL)
-	    {
-	      u = stash_comp_unit (unit->stash);
-	      if (u == NULL)
-		break;
-	      if (info_ptr >= u->info_ptr_unit && info_ptr < u->end_ptr)
-		break;
-	      u = NULL;
-	    }
+	  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;
+	      }
+
+	  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)
 	    {
@@ -2911,23 +3017,6 @@ find_abstract_instance (struct comp_unit
 	  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 %" 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);
-
-      /* 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
@@ -2970,7 +3059,6 @@ find_abstract_instance (struct comp_unit
 					 info_ptr, info_ptr_end);
 	      if (info_ptr == NULL)
 		break;
-
 	      switch (attr.name)
 		{
 		case DW_AT_name:
@@ -3000,7 +3088,7 @@ find_abstract_instance (struct comp_unit
 		    }
 		  break;
 		case DW_AT_decl_file:
-		  if (!comp_unit_maybe_decode_line_info (unit, unit->stash))
+		  if (!comp_unit_maybe_decode_line_info (unit))
 		    return FALSE;
 		  *filename_ptr = concat_filename (unit->line_table,
 						   attr.u.val);
@@ -3026,16 +3114,16 @@ read_rangelist (struct comp_unit *unit,
   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;
     }
 
-  ranges_ptr = unit->stash->dwarf_ranges_buffer + offset;
-  if (ranges_ptr < unit->stash->dwarf_ranges_buffer)
+  ranges_ptr = unit->file->dwarf_ranges_buffer + offset;
+  if (ranges_ptr < unit->file->dwarf_ranges_buffer)
     return FALSE;
-  ranges_end = unit->stash->dwarf_ranges_buffer + unit->stash->dwarf_ranges_size;
+  ranges_end = unit->file->dwarf_ranges_buffer + unit->file->dwarf_ranges_size;
 
   for (;;)
     {
@@ -3365,6 +3453,8 @@ scan_unit_for_symbols (struct comp_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)
@@ -3378,12 +3468,11 @@ parse_comp_unit (struct dwarf2_debug *st
   unsigned int abbrev_number, bytes_read, 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;
   bfd_vma low_pc = 0;
   bfd_vma high_pc = 0;
-  bfd *abfd = stash->bfd_ptr;
+  bfd *abfd = file->bfd_ptr;
   bfd_boolean high_pc_relative = FALSE;
   enum dwarf_unit_type unit_type;
 
@@ -3460,7 +3549,7 @@ parse_comp_unit (struct dwarf2_debug *st
     }
 
   /* 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;
 
@@ -3496,6 +3585,7 @@ parse_comp_unit (struct dwarf2_debug *st
   unit->abbrevs = abbrevs;
   unit->end_ptr = end_ptr;
   unit->stash = stash;
+  unit->file = file;
   unit->info_ptr_unit = info_ptr_unit;
 
   for (i = 0; i < abbrev->num_attrs; ++i)
@@ -3622,18 +3712,17 @@ comp_unit_find_nearest_line (struct comp
 			     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 (!comp_unit_maybe_decode_line_info (unit, stash))
+  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,
@@ -3646,8 +3735,7 @@ comp_unit_find_nearest_line (struct comp
    FALSE otherwise.  */
 
 static bfd_boolean
-comp_unit_maybe_decode_line_info (struct comp_unit *unit,
-				  struct dwarf2_debug *stash)
+comp_unit_maybe_decode_line_info (struct comp_unit *unit)
 {
   if (unit->error)
     return FALSE;
@@ -3660,7 +3748,7 @@ comp_unit_maybe_decode_line_info (struct
 	  return FALSE;
 	}
 
-      unit->line_table = decode_line_info (unit, stash);
+      unit->line_table = decode_line_info (unit);
 
       if (! unit->line_table)
 	{
@@ -3692,10 +3780,9 @@ comp_unit_find_line (struct comp_unit *u
 		     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))
+  if (!comp_unit_maybe_decode_line_info (unit))
     return FALSE;
 
   if (sym->flags & BSF_FUNCTION)
@@ -3754,7 +3841,7 @@ comp_unit_hash_info (struct dwarf2_debug
 
   BFD_ASSERT (stash->info_hash_status != STASH_INFO_HASH_DISABLED);
 
-  if (!comp_unit_maybe_decode_line_info (unit, stash))
+  if (!comp_unit_maybe_decode_line_info (unit))
     return FALSE;
 
   BFD_ASSERT (!unit->cached);
@@ -3885,6 +3972,41 @@ set_debug_vma (bfd *orig_bfd, bfd *debug
     }
 }
 
+/* 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
@@ -3952,9 +4074,9 @@ place_sections (bfd *orig_bfd, struct dw
 
 	  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)
@@ -4017,14 +4139,14 @@ place_sections (bfd *orig_bfd, struct dw
 	      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;
 }
@@ -4128,13 +4250,13 @@ stash_maybe_update_info_hash_tables (str
   struct comp_unit *each;
 
   /* Exit if hash tables are up-to-date.  */
-  if (stash->all_comp_units == stash->hash_units_head)
+  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)
     {
@@ -4147,7 +4269,7 @@ stash_maybe_update_info_hash_tables (str
       each = each->prev_unit;
     }
 
-  stash->hash_units_head = stash->all_comp_units;
+  stash->hash_units_head = stash->f.all_comp_units;
   return TRUE;
 }
 
@@ -4162,7 +4284,7 @@ stash_verify_info_hash_table (struct dwa
   struct info_list_node *node;
   bfd_boolean found;
 
-  for (each_unit = stash->all_comp_units;
+  for (each_unit = stash->f.all_comp_units;
        each_unit;
        each_unit = each_unit->next_unit)
     {
@@ -4232,8 +4354,8 @@ stash_maybe_enable_info_hash_tables (bfd
   /* 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
@@ -4342,7 +4464,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
 	{
 	  /* Check that we did previously find some debug information
 	     before attempting to make use of it.  */
-	  if (stash->bfd_ptr != NULL)
+	  if (stash->f.bfd_ptr != NULL)
 	    {
 	      if (do_place && !place_sections (abfd, stash))
 		return FALSE;
@@ -4362,10 +4484,20 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
     }
   stash->orig_bfd = abfd;
   stash->debug_sections = debug_sections;
-  stash->syms = symbols;
+  stash->f.syms = symbols;
   if (!save_section_vma (abfd, stash))
     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;
+
   *pinfo = stash;
 
   if (debug_bfd == NULL)
@@ -4405,10 +4537,10 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
 	}
 
       symbols = bfd_get_outsymbols (debug_bfd);
-      stash->syms = symbols;
+      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))
@@ -4431,7 +4563,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
       total_size = msec->size;
       if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
 			  symbols, 0,
-			  &stash->info_ptr_memory, &total_size))
+			  &stash->f.dwarf_info_buffer, &total_size))
 	return FALSE;
     }
   else
@@ -4440,19 +4572,19 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
       for (total_size = 0;
 	   msec;
 	   msec = find_debug_info (debug_bfd, debug_sections, msec))
-       {
-         /* Catch PR25070 testcase overflowing size calculation here.  */
-         if (total_size + msec->size < total_size
-             || total_size + msec->size < msec->size)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             return FALSE;
-           }
-         total_size += msec->size;
-       }
+	{
+	  /* Catch PR25070 testcase overflowing size calculation here.  */
+	  if (total_size + msec->size < total_size
+	      || total_size + msec->size < msec->size)
+	    {
+	      bfd_set_error (bfd_error_no_memory);
+	      return FALSE;
+	    }
+	  total_size += msec->size;
+	}
 
-      stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
-      if (stash->info_ptr_memory == NULL)
+      stash->f.dwarf_info_buffer = (bfd_byte *) bfd_malloc (total_size);
+      if (stash->f.dwarf_info_buffer == NULL)
 	return FALSE;
 
       total_size = 0;
@@ -4467,7 +4599,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
 	    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;
 
@@ -4475,35 +4607,33 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd,
 	}
     }
 
-  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;
+  stash->f.info_ptr = stash->f.dwarf_info_buffer;
+  stash->f.dwarf_info_size = total_size;
   return TRUE;
 }
 
-/* Parse the next DWARF2 compilation unit at STASH->INFO_PTR.  */
+/* Parse the next DWARF2 compilation unit at FILE->INFO_PTR.  */
 
 static struct comp_unit *
-stash_comp_unit (struct dwarf2_debug *stash)
+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 = stash->info_ptr;
+  bfd_byte *info_ptr_unit = file->info_ptr;
+  bfd_byte *info_ptr_end = file->dwarf_info_buffer + file->dwarf_info_size;
 
-  if (stash->info_ptr >= stash->info_ptr_end)
+  if (file->info_ptr >= info_ptr_end)
     return NULL;
 
-  length = read_4_bytes (stash->bfd_ptr, stash->info_ptr,
-			 stash->info_ptr_end);
+  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 (stash->bfd_ptr, stash->info_ptr + 4,
-			     stash->info_ptr_end);
-      stash->info_ptr += 12;
+      length = read_8_bytes (file->bfd_ptr, file->info_ptr + 4,
+			     info_ptr_end);
+      file->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
@@ -4511,9 +4641,9 @@ stash_comp_unit (struct dwarf2_debug *st
   else if (length == 0)
     {
       offset_size = 8;
-      length = read_4_bytes (stash->bfd_ptr, stash->info_ptr + 4,
-			     stash->info_ptr_end);
-      stash->info_ptr += 8;
+      length = read_4_bytes (file->bfd_ptr, file->info_ptr + 4,
+			     info_ptr_end);
+      file->info_ptr += 8;
     }
   /* In the absence of the hints above, we assume 32-bit DWARF2
      offsets even for targets with 64-bit addresses, because:
@@ -4527,42 +4657,34 @@ stash_comp_unit (struct dwarf2_debug *st
   else
     {
       offset_size = 4;
-      stash->info_ptr += 4;
+      file->info_ptr += 4;
     }
 
   if (length != 0
-      && stash->info_ptr + length <= stash->info_ptr_end
-      && stash->info_ptr + length > stash->info_ptr)
+      && file->info_ptr + length <= info_ptr_end
+      && file->info_ptr + length > file->info_ptr)
     {
-      struct comp_unit *each = parse_comp_unit (stash, length, info_ptr_unit,
-						offset_size);
+      struct comp_unit *each = parse_comp_unit (stash, file,
+						file->info_ptr, length,
+						info_ptr_unit, offset_size);
       if (each)
 	{
-	  if (stash->all_comp_units)
-	    stash->all_comp_units->prev_unit = each;
+	  if (file->all_comp_units)
+	    file->all_comp_units->prev_unit = each;
 	  else
-	    stash->last_comp_unit = each;
+	    file->last_comp_unit = each;
 
-	  each->next_unit = stash->all_comp_units;
-	  stash->all_comp_units = each;
+	  each->next_unit = file->all_comp_units;
+	  file->all_comp_units = each;
 
-	  stash->info_ptr += length;
-
-	  if ((bfd_size_type) (stash->info_ptr - stash->sec_info_ptr)
-	      == stash->sec->size)
-	    {
-	      stash->sec = find_debug_info (stash->bfd_ptr,
-					    stash->debug_sections,
-					    stash->sec);
-	      stash->sec_info_ptr = stash->info_ptr;
-	    }
+	  file->info_ptr += length;
 	  return each;
 	}
     }
 
   /* Don't trust any of the DWARF info after a corrupted length or
      parse error.  */
-  stash->info_ptr = stash->info_ptr_end;
+  file->info_ptr = info_ptr_end;
   return NULL;
 }
 
@@ -4617,11 +4739,11 @@ _bfd_dwarf2_find_symbol_bias (asymbol **
 	}
     }
 
-  for (unit = stash->all_comp_units; unit; unit = unit->next_unit)
+  for (unit = stash->f.all_comp_units; unit; unit = unit->next_unit)
     {
       struct funcinfo * func;
 
-      comp_unit_maybe_decode_line_info (unit, stash);
+      comp_unit_maybe_decode_line_info (unit);
 
       for (func = unit->function_table; func != NULL; func = func->prev_func)
 	if (func->name && func->arange.low)
@@ -4649,15 +4771,17 @@ _bfd_dwarf2_find_symbol_bias (asymbol **
 /* 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
+   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.
-   field and in the abbreviation offset, or zero to indicate that the
-   default value should be used.  */
+   DEBUG_SECTIONS contains the name of the dwarf debug sections.  */
 
-bfd_boolean
+int
 _bfd_dwarf2_find_nearest_line (bfd *abfd,
 			       asymbol **symbols,
 			       asymbol *symbol,
@@ -4683,7 +4807,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
   bfd_vma addr;
   struct comp_unit* each;
   struct funcinfo *function = NULL;
-  bfd_boolean found = FALSE;
+  int found = FALSE;
   bfd_boolean do_line;
 
   *filename_ptr = NULL;
@@ -4752,7 +4876,7 @@ _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)
+  if (! stash->f.info_ptr)
     return FALSE;
 
   stash->inliner_chain = NULL;
@@ -4781,13 +4905,13 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
       else
 	{
 	  /* Check the previously read comp. units first.  */
-	  for (each = stash->all_comp_units; each; each = each->next_unit)
+	  for (each = stash->f.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);
+					     linenumber_ptr);
 		if (found)
 		  goto done;
 	      }
@@ -4801,18 +4925,16 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
       unsigned int local_linenumber = 0;
       unsigned int local_discriminator = 0;
 
-      for (each = stash->all_comp_units; each; each = each->next_unit)
+      for (each = stash->f.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);
+		   && (range = (comp_unit_find_nearest_line
+				(each, addr, &local_filename,
+				 &local_function, &local_linenumber,
+				 &local_discriminator))) != 0);
 	  if (found)
 	    {
 	      /* PRs 15935 15994: Bogus debug information may have provided us
@@ -4849,7 +4971,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
     }
 
   /* Read each remaining comp. units checking each as they are read.  */
-  while ((each = stash_comp_unit (stash)) != NULL)
+  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.,
@@ -4861,9 +4983,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 		  || each->arange.high == 0
 		  || comp_unit_contains_address (each, addr))
 		 && comp_unit_find_line (each, symbol, addr,
-					 filename_ptr,
-					 linenumber_ptr,
-					 stash));
+					 filename_ptr, linenumber_ptr));
       else
 	found = ((each->arange.high == 0
 		  || comp_unit_contains_address (each, addr))
@@ -4871,24 +4991,35 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 						 filename_ptr,
 						 &function,
 						 linenumber_ptr,
-						 discriminator_ptr,
-						 stash) != 0);
+						 discriminator_ptr) != 0);
 
       if (found)
 	break;
     }
 
  done:
-  if (function)
-    {
-      if (!function->is_linkage)
+  if (functionname_ptr && function && function->is_linkage)
+    *functionname_ptr = function->name;
+  else if (functionname_ptr
+	   && (!*functionname_ptr
+	       || (function && !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;
@@ -4899,8 +5030,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 	     to stop a repeated search of symbols.  */
 	  function->is_linkage = TRUE;
 	}
-      *functionname_ptr = function->name;
     }
+
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
     unset_sections (stash);
 
@@ -4939,96 +5070,85 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abf
 {
   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);
-	}
+	  if (each->lookup_funcinfo_table)
+	    {
+	      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->file)
+		{
+		  free (function_table->file);
+		  function_table->file = NULL;
+		}
+	      if (function_table->caller_file)
+		{
+		  free (function_table->caller_file);
+		  function_table->caller_file = NULL;
+		}
+	      function_table = function_table->prev_func;
 	    }
 
-	  if (function_table->caller_file)
+	  while (variable_table)
 	    {
-	      free (function_table->caller_file);
-	      function_table->caller_file = NULL;
+	      if (variable_table->file)
+		{
+		  free (variable_table->file);
+		  variable_table->file = NULL;
+		}
+	      variable_table = variable_table->prev_var;
 	    }
-	  function_table = function_table->prev_func;
 	}
 
-      if (each->lookup_funcinfo_table)
+      if (file->line_table)
 	{
-	  free (each->lookup_funcinfo_table);
-	  each->lookup_funcinfo_table = NULL;
+	  free (file->line_table->files);
+	  free (file->line_table->dirs);
 	}
+      htab_delete (file->abbrev_offsets);
 
-      while (variable_table)
-	{
-	  if (variable_table->file)
-	    {
-	      free (variable_table->file);
-	      variable_table->file = NULL;
-	    }
-
-	  variable_table = variable_table->prev_var;
-	}
+      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->funcinfo_hash_table)
-    bfd_hash_table_free (&stash->funcinfo_hash_table->base);
-  if (stash->varinfo_hash_table)
-    bfd_hash_table_free (&stash->varinfo_hash_table->base);
-  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,