This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 09/12] dwz -m support


Here is a new version of the 'dwz -m' patch.


This patch does all the actual work of supporting 'dwz -m'.

The .dwz file is referenced by a new .gnu_debugaltlink section.
if this section exists, we read its contents to find the .dwz file.

The .dwz BFDs are shared by all objfiles referring to them.  It would
be nice if we could go a step further and also share the data that is
read out of them (partial symbols and such), but this would be quite
hard at present.

For the main debuginfo reading, the work is in supporting the new
forms.

DW_FORM_GNU_ref_alt is like DW_FORM_ref, but it refers to an offset in
the .dwz file, not in the main file.

DW_FORM_GNU_strp_alt is like DW_FORM_strp, but it refers to a string
in the .dwz file, not in the main file.

Much of the patch is just teaching various code about these forms.
This is made much simpler due to the Fission patches -- thanks Doug.
There are some minor fixes for latent Fission bugs buried in here; for
example, I think there were a couple of places that were previously
referencing the wrong abbrev section.

The .dwz approach also introduces new DW_MACRO opcodes.  Dealing with
these is much more localized.

	* dwarf2read.c (struct dwarf2_per_objfile) <dwz_file>: New field.
	(struct dwarf2_per_cu_data) <length>: No longer bitfield.
	<is_dwz>: New field.
	(struct dwz_file): New.
	(struct partial_die_info) <is_dwz, spec_is_dwz>: New fields.
	(locate_dwz_sections, dwarf2_get_dwz_file)
	(get_abbrev_section_for_cu): New functions.
	(error_check_comp_unit_head, read_and_check_comp_unit_head)
	(read_and_check_type_unit_head): Add abbrev_section argument.
	(create_debug_types_hash_table): Update.
	(init_cutu_and_read_dies): Use proper abbrev section.
	(init_cutu_and_read_dies_no_follow): Likewise.
	(set_partial_user): Do nothing if PST==NULL.
	(read_comp_units_from_section): New function.
	(create_all_comp_units): Use it.
	(scan_partial_symbols, partial_die_parent_scope): Update.
	(skip_one_die): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
	(process_imported_unit_die, read_partial_die): Handle .dwz files.
	(find_partial_die): Add offset_in_dwz argument.  Update.
	(guess_partial_die_structure_name, fixup_partial_die): Update.
	(read_attribute_value): Handle DW_FORM_GNU_ref_alt,
	DW_FORM_GNU_strp_alt.
	(read_indirect_string_from_dwz): New function.
	(dwarf2_const_value_attr): Handle DW_FORM_GNU_strp_alt.
	(dump_die_shallow): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
	(is_ref_attr): Handle DW_FORM_GNU_ref_alt.
	(follow_die_offset): Add offset_in_dwz argument.
	(follow_die_ref, dwarf2_fetch_die_location_block): Update.
	(skip_form_bytes): Handle DW_FORM_GNU_strp_alt.
	(dwarf_decode_macro_bytes): Add section_is_dwz argument.
	Handle new macro forms.
	(dwarf_decode_macros): Update.
	(dwarf2_find_containing_comp_unit): Add offset_in_dwz argument.
	(dwarf2_per_objfile_free): Unref dwz_bfd, if it exists
	(lookup_die_type): Handle DW_FORM_GNU_ref_alt.
	(create_debug_types_hash_table): Use correct abbrev section.
	(get_debug_line_section): New function.
	(dwarf_decode_line_header, dwarf_decode_lines_1): Use it.
---
 gdb/dwarf2read.c |  514 +++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 429 insertions(+), 85 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2863e49..571b000 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -185,6 +185,10 @@ struct dwarf2_per_objfile
      This is NULL if the table hasn't been allocated yet.  */
   htab_t dwo_files;
 
+  /* The shared '.dwz' file, if one exists.  This is used when the
+     original data was compressed using 'dwz -m'.  */
+  struct dwz_file *dwz_file;
+
   /* A flag indicating wether this objfile has a section loaded at a
      VMA of 0.  */
   int has_section_at_zero;
@@ -442,15 +446,13 @@ struct dwarf2_cu
 
 struct dwarf2_per_cu_data
 {
-  /* The start offset and length of this compilation unit.  2**29-1
-     bytes should suffice to store the length of any compilation unit
-     - if it doesn't, GDB will fall over anyway.
+  /* The start offset and length of this compilation unit.
      NOTE: Unlike comp_unit_head.length, this length includes
      initial_length_size.
      If the DIE refers to a DWO file, this is always of the original die,
      not the DWO file.  */
   sect_offset offset;
-  unsigned int length : 29;
+  unsigned int length;
 
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
@@ -465,6 +467,9 @@ struct dwarf2_per_cu_data
   /* Non-zero if this CU is from .debug_types.  */
   unsigned int is_debug_types : 1;
 
+  /* Non-zero if this CU is from the .dwz file.  */
+  unsigned int is_dwz : 1;
+
   /* The section this CU/TU lives in.
      If the DIE refers to a DWO file, this is always the original die,
      not the DWO file.  */
@@ -579,6 +584,21 @@ struct dwo_file
   htab_t tus;
 };
 
+/* This represents a '.dwz' file.  */
+
+struct dwz_file
+{
+  /* A dwz file can only contain a few sections.  */
+  struct dwarf2_section_info abbrev;
+  struct dwarf2_section_info info;
+  struct dwarf2_section_info str;
+  struct dwarf2_section_info line;
+  struct dwarf2_section_info macro;
+
+  /* The dwz's BFD.  */
+  bfd *dwz_bfd;
+};
+
 /* Struct used to pass misc. parameters to read_die_and_children, et
    al.  which are used for both .debug_info and .debug_types dies.
    All parameters here are unchanging for the life of the call.  This
@@ -692,6 +712,12 @@ struct partial_die_info
     /* Flag set if fixup_partial_die has been called on this die.  */
     unsigned int fixup_called : 1;
 
+    /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt.  */
+    unsigned int is_dwz : 1;
+
+    /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt.  */
+    unsigned int spec_is_dwz : 1;
+
     /* The name of this DIE.  Normally the value of DW_AT_name, but
        sometimes a default name for unnamed DIEs.  */
     char *name;
@@ -1052,7 +1078,7 @@ static gdb_byte *read_partial_die (const struct die_reader_specs *,
 				   unsigned int,
 				   gdb_byte *);
 
-static struct partial_die_info *find_partial_die (sect_offset,
+static struct partial_die_info *find_partial_die (sect_offset, int,
 						  struct dwarf2_cu *);
 
 static void fixup_partial_die (struct partial_die_info *,
@@ -1094,6 +1120,8 @@ static char *read_indirect_string (bfd *, gdb_byte *,
                                    const struct comp_unit_head *,
                                    unsigned int *);
 
+static char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
+
 static ULONGEST read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
 
 static LONGEST read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
@@ -1357,7 +1385,7 @@ static hashval_t partial_die_hash (const void *item);
 static int partial_die_eq (const void *item_lhs, const void *item_rhs);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
-  (sect_offset offset, struct objfile *objfile);
+  (sect_offset offset, unsigned int offset_in_dwz, struct objfile *objfile);
 
 static void init_one_comp_unit (struct dwarf2_cu *cu,
 				struct dwarf2_per_cu_data *per_cu);
@@ -1419,7 +1447,8 @@ static char *file_full_name (int file, struct line_header *lh,
 
 static gdb_byte *read_and_check_comp_unit_head
   (struct comp_unit_head *header,
-   struct dwarf2_section_info *section, gdb_byte *info_ptr,
+   struct dwarf2_section_info *section,
+   struct dwarf2_section_info *abbrev_section, gdb_byte *info_ptr,
    int is_debug_types_section);
 
 static void init_cutu_and_read_dies
@@ -1735,6 +1764,106 @@ dwarf2_get_section_info (struct objfile *objfile,
   *sizep = info->size;
 }
 
+/* A helper function to find the sections for a .dwz file.  */
+
+static void
+locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
+{
+  struct dwz_file *dwz_file = arg;
+
+  /* Note that we only support the standard ELF names, because .dwz
+     is ELF-only (at the time of writing).  */
+  if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev))
+    {
+      dwz_file->abbrev.asection = sectp;
+      dwz_file->abbrev.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
+    {
+      dwz_file->info.asection = sectp;
+      dwz_file->info.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
+    {
+      dwz_file->str.asection = sectp;
+      dwz_file->str.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
+    {
+      dwz_file->line.asection = sectp;
+      dwz_file->line.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
+    {
+      dwz_file->macro.asection = sectp;
+      dwz_file->macro.size = bfd_get_section_size (sectp);
+    }
+}
+
+/* Open the separate '.dwz' debug file, if needed.  Error if the file
+   cannot be found.  */
+
+static struct dwz_file *
+dwarf2_get_dwz_file (void)
+{
+  bfd *abfd, *dwz_bfd;
+  asection *section;
+  gdb_byte *data;
+  struct cleanup *cleanup;
+  const char *filename;
+  struct dwz_file *result;
+
+  if (dwarf2_per_objfile->dwz_file != NULL)
+    return dwarf2_per_objfile->dwz_file;
+
+  abfd = dwarf2_per_objfile->objfile->obfd;
+  section = bfd_get_section_by_name (abfd, ".gnu_debugaltlink");
+  if (section == NULL)
+    error (_("could not find '.gnu_debugaltlink' section"));
+  if (!bfd_malloc_and_get_section (abfd, section, &data))
+    error (_("could not read '.gnu_debugaltlink' section: %s"),
+	   bfd_errmsg (bfd_get_error ()));
+  cleanup = make_cleanup (xfree, data);
+
+  filename = data;
+  if (!IS_ABSOLUTE_PATH (filename))
+    {
+      char *abs = gdb_realpath (dwarf2_per_objfile->objfile->name);
+      char *rel;
+
+      make_cleanup (xfree, abs);
+      abs = ldirname (abs);
+      make_cleanup (xfree, abs);
+
+      rel = concat (abs, SLASH_STRING, filename, (char *) NULL);
+      make_cleanup (xfree, rel);
+      filename = rel;
+    }
+
+  /* The format is just a NUL-terminated file name, followed by the
+     build-id.  For now, though, we ignore the build-id.  */
+  dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  if (dwz_bfd == NULL)
+    error (_("could not read '%s': %s"), filename,
+	   bfd_errmsg (bfd_get_error ()));
+
+  if (!bfd_check_format (dwz_bfd, bfd_object))
+    {
+      gdb_bfd_unref (dwz_bfd);
+      error (_("file '%s' was not usable: %s"), filename,
+	     bfd_errmsg (bfd_get_error ()));
+    }
+
+  result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
+			   struct dwz_file);
+  result->dwz_bfd = dwz_bfd;
+
+  bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
+
+  do_cleanups (cleanup);
+
+  return result;
+}
 
 /* DWARF quick_symbols_functions support.  */
 
@@ -3160,13 +3289,30 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   return info_ptr;
 }
 
+/* Helper function that returns the proper abbrev section for
+   THIS_CU.  */
+
+static struct dwarf2_section_info *
+get_abbrev_section_for_cu (struct dwarf2_per_cu_data *this_cu)
+{
+  struct dwarf2_section_info *abbrev;
+
+  if (this_cu->is_dwz)
+    abbrev = &dwarf2_get_dwz_file ()->abbrev;
+  else
+    abbrev = &dwarf2_per_objfile->abbrev;
+
+  return abbrev;
+}
+
 /* Subroutine of read_and_check_comp_unit_head and
    read_and_check_type_unit_head to simplify them.
    Perform various error checking on the header.  */
 
 static void
 error_check_comp_unit_head (struct comp_unit_head *header,
-			    struct dwarf2_section_info *section)
+			    struct dwarf2_section_info *section,
+			    struct dwarf2_section_info *abbrev_section)
 {
   bfd *abfd = section->asection->owner;
   const char *filename = bfd_get_filename (abfd);
@@ -3177,8 +3323,7 @@ error_check_comp_unit_head (struct comp_unit_head *header,
 	   filename);
 
   if (header->abbrev_offset.sect_off
-      >= dwarf2_section_size (dwarf2_per_objfile->objfile,
-			      &dwarf2_per_objfile->abbrev))
+      >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
     error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
 	   "(offset 0x%lx + 6) [in module %s]"),
 	   (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
@@ -3202,6 +3347,7 @@ error_check_comp_unit_head (struct comp_unit_head *header,
 static gdb_byte *
 read_and_check_comp_unit_head (struct comp_unit_head *header,
 			       struct dwarf2_section_info *section,
+			       struct dwarf2_section_info *abbrev_section,
 			       gdb_byte *info_ptr,
 			       int is_debug_types_section)
 {
@@ -3219,7 +3365,7 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
 
   header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
 
-  error_check_comp_unit_head (header, section);
+  error_check_comp_unit_head (header, section, abbrev_section);
 
   return info_ptr;
 }
@@ -3230,6 +3376,7 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
 static gdb_byte *
 read_and_check_type_unit_head (struct comp_unit_head *header,
 			       struct dwarf2_section_info *section,
+			       struct dwarf2_section_info *abbrev_section,
 			       gdb_byte *info_ptr,
 			       ULONGEST *signature,
 			       cu_offset *type_offset_in_tu)
@@ -3253,7 +3400,7 @@ read_and_check_type_unit_head (struct comp_unit_head *header,
 
   header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
 
-  error_check_comp_unit_head (header, section);
+  error_check_comp_unit_head (header, section, abbrev_section);
 
   return info_ptr;
 }
@@ -3384,6 +3531,7 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
     {
       bfd *abfd;
       gdb_byte *info_ptr, *end_ptr;
+      struct dwarf2_section_info *abbrev_section;
 
       dwarf2_read_section (objfile, section);
       info_ptr = section->buffer;
@@ -3395,6 +3543,11 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
 	 not present, in which case section->asection will be NULL.  */
       abfd = section->asection->owner;
 
+      if (dwo_file)
+	abbrev_section = &dwo_file->sections.abbrev;
+      else
+	abbrev_section = &dwarf2_per_objfile->abbrev;
+
       if (types_htab == NULL)
 	{
 	  if (dwo_file)
@@ -3429,7 +3582,8 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
 	  /* We need to read the type's signature in order to build the hash
 	     table, but we don't need anything else just yet.  */
 
-	  ptr = read_and_check_type_unit_head (&header, section, ptr,
+	  ptr = read_and_check_type_unit_head (&header, section,
+					       abbrev_section, ptr,
 					       &signature, &type_offset_in_tu);
 
 	  length = header.initial_length_size + header.length;
@@ -3641,6 +3795,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   struct attribute *attr;
   struct cleanup *cleanups, *free_cu_cleanup = NULL;
   struct signatured_type *sig_type = NULL;
+  struct dwarf2_section_info *abbrev;
 
   if (use_existing_cu)
     gdb_assert (keep);
@@ -3652,6 +3807,8 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
 
   begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
 
+  abbrev = get_abbrev_section_for_cu (this_cu);
+
   if (use_existing_cu && this_cu->cu != NULL)
     {
       cu = this_cu->cu;
@@ -3673,7 +3830,8 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
 	  ULONGEST signature;
 
 	  info_ptr = read_and_check_type_unit_head (&cu->header,
-						    section, info_ptr,
+						    section, abbrev,
+						    info_ptr,
 						    &signature, NULL);
 
 	  /* There's no way to get from PER_CU to its containing
@@ -3695,8 +3853,12 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
 	}
       else
 	{
+	  struct dwarf2_section_info *abbrev;
+
+	  abbrev = get_abbrev_section_for_cu (this_cu);
 	  info_ptr = read_and_check_comp_unit_head (&cu->header,
-						    section, info_ptr, 0);
+						    section, abbrev,
+						    info_ptr, 0);
 
 	  gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
 	  gdb_assert (this_cu->length
@@ -3715,7 +3877,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   /* Read the abbrevs for this compilation unit into a table.  */
   if (cu->dwarf2_abbrevs == NULL)
     {
-      dwarf2_read_abbrevs (cu, &dwarf2_per_objfile->abbrev);
+      dwarf2_read_abbrevs (cu, abbrev);
       make_cleanup (dwarf2_free_abbrev_table, cu);
     }
 
@@ -3811,9 +3973,12 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
       if (this_cu->is_debug_types)
 	{
 	  ULONGEST signature;
+	  struct dwarf2_section_info *abbrev
+	    = &dwo_unit->dwo_file->sections.abbrev;
 
 	  info_ptr = read_and_check_type_unit_head (&cu->header,
-						    section, info_ptr,
+						    section, abbrev,
+						    info_ptr,
 						    &signature, NULL);
 	  gdb_assert (sig_type->signature == signature);
 	  gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
@@ -3827,8 +3992,12 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
 	}
       else
 	{
+	  struct dwarf2_section_info *abbrev
+	    = &dwo_unit->dwo_file->sections.abbrev;
+
 	  info_ptr = read_and_check_comp_unit_head (&cu->header,
-						    section, info_ptr, 0);
+						    section, abbrev,
+						    info_ptr, 0);
 	  gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
 	  gdb_assert (dwo_unit->length
 		      == cu->header.length + cu->header.initial_length_size);
@@ -3938,7 +4107,8 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   cleanups = make_cleanup (free_stack_comp_unit, &cu);
 
   begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
-  info_ptr = read_and_check_comp_unit_head (&cu.header, section, info_ptr,
+  info_ptr = read_and_check_comp_unit_head (&cu.header, section,
+					    abbrev_section, info_ptr,
 					    this_cu->is_debug_types);
 
   this_cu->length = cu.header.length + cu.header.initial_length_size;
@@ -3977,7 +4147,7 @@ init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
 				void *data)
 {
   init_cutu_and_read_dies_no_follow (this_cu,
-				     &dwarf2_per_objfile->abbrev,
+				     get_abbrev_section_for_cu (this_cu),
 				     NULL,
 				     die_reader_func, data);
 }
@@ -4210,6 +4380,9 @@ set_partial_user (struct objfile *objfile)
       struct partial_symtab *pst = per_cu->v.psymtab;
       int j;
 
+      if (pst == NULL)
+	continue;
+
       for (j = 0; j < pst->number_of_dependencies; ++j)
 	{
 	  /* Set the 'user' field only if it is not already set.  */
@@ -4293,38 +4466,32 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
   init_cutu_and_read_dies (this_cu, 1, 1, load_partial_comp_unit_reader, NULL);
 }
 
-/* Create a list of all compilation units in OBJFILE.
-   This is only done for -readnow and building partial symtabs.  */
-
 static void
-create_all_comp_units (struct objfile *objfile)
+read_comp_units_from_section (struct objfile *objfile,
+			      struct dwarf2_section_info *section,
+			      unsigned int is_dwz,
+			      int *n_allocated,
+			      int *n_comp_units,
+			      struct dwarf2_per_cu_data ***all_comp_units)
 {
-  int n_allocated;
-  int n_comp_units;
-  struct dwarf2_per_cu_data **all_comp_units;
   gdb_byte *info_ptr;
+  bfd *abfd = section->asection->owner;
 
-  dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
-  info_ptr = dwarf2_per_objfile->info.buffer;
+  dwarf2_read_section (objfile, section);
 
-  n_comp_units = 0;
-  n_allocated = 10;
-  all_comp_units = xmalloc (n_allocated
-			    * sizeof (struct dwarf2_per_cu_data *));
+  info_ptr = section->buffer;
 
-  while (info_ptr < dwarf2_per_objfile->info.buffer
-	 + dwarf2_per_objfile->info.size)
+  while (info_ptr < section->buffer + section->size)
     {
       unsigned int length, initial_length_size;
       struct dwarf2_per_cu_data *this_cu;
       sect_offset offset;
 
-      offset.sect_off = info_ptr - dwarf2_per_objfile->info.buffer;
+      offset.sect_off = info_ptr - section->buffer;
 
       /* Read just enough information to find out where the next
 	 compilation unit is.  */
-      length = read_initial_length (objfile->obfd, info_ptr,
-				    &initial_length_size);
+      length = read_initial_length (abfd, info_ptr, &initial_length_size);
 
       /* Save the compilation unit for later lookup.  */
       this_cu = obstack_alloc (&objfile->objfile_obstack,
@@ -4332,20 +4499,50 @@ create_all_comp_units (struct objfile *objfile)
       memset (this_cu, 0, sizeof (*this_cu));
       this_cu->offset = offset;
       this_cu->length = length + initial_length_size;
+      this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
-      this_cu->info_or_types_section = &dwarf2_per_objfile->info;
+      this_cu->info_or_types_section = section;
 
-      if (n_comp_units == n_allocated)
+      if (*n_comp_units == *n_allocated)
 	{
-	  n_allocated *= 2;
-	  all_comp_units = xrealloc (all_comp_units,
-				     n_allocated
-				     * sizeof (struct dwarf2_per_cu_data *));
+	  *n_allocated *= 2;
+	  *all_comp_units = xrealloc (*all_comp_units,
+				      *n_allocated
+				      * sizeof (struct dwarf2_per_cu_data *));
 	}
-      all_comp_units[n_comp_units++] = this_cu;
+      (*all_comp_units)[*n_comp_units] = this_cu;
+      ++*n_comp_units;
 
       info_ptr = info_ptr + this_cu->length;
     }
+}
+
+/* Create a list of all compilation units in OBJFILE.
+   This is only done for -readnow and building partial symtabs.  */
+
+static void
+create_all_comp_units (struct objfile *objfile)
+{
+  int n_allocated;
+  int n_comp_units;
+  struct dwarf2_per_cu_data **all_comp_units;
+
+  n_comp_units = 0;
+  n_allocated = 10;
+  all_comp_units = xmalloc (n_allocated
+			    * sizeof (struct dwarf2_per_cu_data *));
+
+  read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0,
+				&n_allocated, &n_comp_units, &all_comp_units);
+
+  if (bfd_get_section_by_name (objfile->obfd, ".gnu_debugaltlink") != NULL)
+    {
+      struct dwz_file *dwz = dwarf2_get_dwz_file ();
+
+      read_comp_units_from_section (objfile, &dwz->info, 1,
+				    &n_allocated, &n_comp_units,
+				    &all_comp_units);
+    }
 
   dwarf2_per_objfile->all_comp_units
     = obstack_alloc (&objfile->objfile_obstack,
@@ -4430,6 +4627,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
 		struct dwarf2_per_cu_data *per_cu;
 
 		per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
+							   pdi->is_dwz,
 							   cu->objfile);
 
 		/* Go read the partial unit, if needed.  */
@@ -4487,7 +4685,8 @@ partial_die_parent_scope (struct partial_die_info *pdi,
 
   real_pdi = pdi;
   while (real_pdi->has_specification)
-    real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+    real_pdi = find_partial_die (real_pdi->spec_offset,
+				 real_pdi->spec_is_dwz, cu);
 
   parent = real_pdi->die_parent;
   if (parent == NULL)
@@ -4987,6 +5186,9 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
 	  else
 	    info_ptr += cu->header.offset_size;
 	  break;
+	case DW_FORM_GNU_ref_alt:
+	  info_ptr += cu->header.offset_size;
+	  break;
 	case DW_FORM_addr:
 	  info_ptr += cu->header.addr_size;
 	  break;
@@ -5016,6 +5218,7 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
 	  break;
 	case DW_FORM_sec_offset:
 	case DW_FORM_strp:
+	case DW_FORM_GNU_strp_alt:
 	  info_ptr += cu->header.offset_size;
 	  break;
 	case DW_FORM_exprloc:
@@ -5660,9 +5863,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_per_cu_data *per_cu;
       struct symtab *imported_symtab;
       sect_offset offset;
+      int is_dwz;
 
       offset = dwarf2_get_ref_die_offset (attr);
-      per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+      is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
+      per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
 
       /* Queue the unit, if needed.  */
       if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@@ -11189,6 +11394,8 @@ read_partial_die (const struct die_reader_specs *reader,
 	case DW_AT_extension:
 	  part_die->has_specification = 1;
 	  part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
+	  part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+				   || cu->per_cu->is_dwz);
 	  break;
 	case DW_AT_sibling:
 	  /* Ignore absolute siblings, they might point outside of
@@ -11235,7 +11442,11 @@ read_partial_die (const struct die_reader_specs *reader,
 
 	case DW_AT_import:
 	  if (part_die->tag == DW_TAG_imported_unit)
-	    part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+	    {
+	      part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+	      part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+				  || cu->per_cu->is_dwz);
+	    }
 	  break;
 
 	default:
@@ -11306,13 +11517,14 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
    DW_FORM_ref_sig8).  */
 
 static struct partial_die_info *
-find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
+find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
 
-  if (offset_in_cu_p (&cu->header, offset))
+  if (offset_in_dwz == cu->per_cu->is_dwz
+      && offset_in_cu_p (&cu->header, offset))
     {
       pd = find_partial_die_in_comp_unit (offset, cu);
       if (pd != NULL)
@@ -11331,7 +11543,8 @@ find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
 		 (long) cu->header.offset.sect_off, (long) offset.sect_off,
 		 bfd_get_filename (objfile->obfd));
 	}
-      per_cu = dwarf2_find_containing_comp_unit (offset, objfile);
+      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+						 objfile);
 
       if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
 	load_partial_comp_unit (per_cu);
@@ -11389,7 +11602,8 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
 
   real_pdi = struct_pdi;
   while (real_pdi->has_specification)
-    real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+    real_pdi = find_partial_die (real_pdi->spec_offset,
+				 real_pdi->spec_is_dwz, cu);
 
   if (real_pdi->die_parent != NULL)
     return;
@@ -11437,7 +11651,8 @@ fixup_partial_die (struct partial_die_info *part_die,
     {
       struct partial_die_info *spec_die;
 
-      spec_die = find_partial_die (part_die->spec_offset, cu);
+      spec_die = find_partial_die (part_die->spec_offset,
+				   part_die->spec_is_dwz, cu);
 
       fixup_partial_die (spec_die, cu);
 
@@ -11525,6 +11740,10 @@ read_attribute_value (const struct die_reader_specs *reader,
 				       &cu->header, &bytes_read);
       info_ptr += bytes_read;
       break;
+    case DW_FORM_GNU_ref_alt:
+      DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+      info_ptr += bytes_read;
+      break;
     case DW_FORM_addr:
       DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
       info_ptr += bytes_read;
@@ -11567,10 +11786,25 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     case DW_FORM_strp:
-      DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
-					       &bytes_read);
-      DW_STRING_IS_CANONICAL (attr) = 0;
-      info_ptr += bytes_read;
+      if (!cu->per_cu->is_dwz)
+	{
+	  DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
+						   &bytes_read);
+	  DW_STRING_IS_CANONICAL (attr) = 0;
+	  info_ptr += bytes_read;
+	  break;
+	}
+      /* FALLTHROUGH */
+    case DW_FORM_GNU_strp_alt:
+      {
+	struct dwz_file *dwz = dwarf2_get_dwz_file ();
+	LONGEST str_offset = read_offset (abfd, info_ptr, cu_header,
+					  &bytes_read);
+
+	DW_STRING (attr) = read_indirect_string_from_dwz (dwz, str_offset);
+	DW_STRING_IS_CANONICAL (attr) = 0;
+	info_ptr += bytes_read;
+      }
       break;
     case DW_FORM_exprloc:
     case DW_FORM_block:
@@ -11682,6 +11916,10 @@ read_attribute_value (const struct die_reader_specs *reader,
 	     bfd_get_filename (abfd));
     }
 
+  /* Super hack.  */
+  if (cu->per_cu->is_dwz && is_ref_attr (attr))
+    attr->form = DW_FORM_GNU_ref_alt;
+
   /* We have seen instances where the compiler tried to emit a byte
      size attribute of -1 which ended up being encoded as an unsigned
      0xffffffff.  Although 0xffffffff is technically a valid size value,
@@ -11978,6 +12216,30 @@ read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
   return (char *) (dwarf2_per_objfile->str.buffer + str_offset);
 }
 
+/* Read a string at offset STR_OFFSET in the .debug_str section from
+   the .dwz file DWZ.  Throw an error if the offset is too large.  If
+   the string consists of a single NUL byte, return NULL; otherwise
+   return a pointer to the string.  */
+
+static char *
+read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset)
+{
+  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwz->str);
+
+  if (dwz->str.buffer == NULL)
+    error (_("DW_FORM_GNU_strp_alt used without .debug_str "
+	     "section [in module %s]"),
+	   bfd_get_filename (dwz->dwz_bfd));
+  if (str_offset >= dwz->str.size)
+    error (_("DW_FORM_GNU_strp_alt pointing outside of "
+	     ".debug_str section [in module %s]"),
+	   bfd_get_filename (dwz->dwz_bfd));
+  gdb_assert (HOST_CHAR_BIT == 8);
+  if (dwz->str.buffer[str_offset] == '\0')
+    return NULL;
+  return (char *) (dwz->str.buffer + str_offset);
+}
+
 static char *
 read_indirect_string (bfd *abfd, gdb_byte *buf,
 		      const struct comp_unit_head *cu_header,
@@ -12450,6 +12712,30 @@ add_file_name (struct line_header *lh,
   fe->symtab = NULL;
 }
 
+/* A convenience function to find the proper .debug_line section for a
+   CU.  */
+
+static struct dwarf2_section_info *
+get_debug_line_section (struct dwarf2_cu *cu)
+{
+  struct dwarf2_section_info *section;
+
+  /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
+     DWO file.  */
+  if (cu->dwo_unit && cu->per_cu->is_debug_types)
+    section = &cu->dwo_unit->dwo_file->sections.line;
+  else if (cu->per_cu->is_dwz)
+    {
+      struct dwz_file *dwz = dwarf2_get_dwz_file ();
+
+      section = &dwz->line;
+    }
+  else
+    section = &dwarf2_per_objfile->line;
+
+  return section;
+}
+
 /* Read the statement program header starting at OFFSET in
    .debug_line, or .debug_line.dwo.  Return a pointer
    to a struct line_header, allocated using xmalloc.
@@ -12470,13 +12756,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   struct dwarf2_section_info *section;
   bfd *abfd;
 
-  /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
-     DWO file.  */
-  if (cu->dwo_unit && cu->per_cu->is_debug_types)
-    section = &cu->dwo_unit->dwo_file->sections.line;
-  else
-    section = &dwarf2_per_objfile->line;
-
+  section = get_debug_line_section (cu);
   dwarf2_read_section (dwarf2_per_objfile->objfile, section);
   if (section->buffer == NULL)
     {
@@ -12801,7 +13081,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
 			 GCd by the linker.  Ignore it.  PR gdb/12528 */
 
 		      long line_offset
-			= line_ptr - dwarf2_per_objfile->line.buffer;
+			= line_ptr - get_debug_line_section (cu)->buffer;
 
 		      complaint (&symfile_complaints,
 				 _(".debug_line address at offset 0x%lx is 0 "
@@ -13630,6 +13910,7 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
     case DW_FORM_string:
     case DW_FORM_strp:
     case DW_FORM_GNU_str_index:
+    case DW_FORM_GNU_strp_alt:
       /* DW_STRING is already allocated on the objfile obstack, point
 	 directly to it.  */
       *bytes = (gdb_byte *) DW_STRING (attr);
@@ -13816,7 +14097,15 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
 
   /* First see if we have it cached.  */
 
-  if (is_ref_attr (attr))
+  if (attr->form == DW_FORM_GNU_ref_alt)
+    {
+      struct dwarf2_per_cu_data *per_cu;
+      sect_offset offset = dwarf2_get_ref_die_offset (attr);
+
+      per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
+      this_type = get_die_type_at_offset (offset, per_cu);
+    }
+  else if (is_ref_attr (attr))
     {
       sect_offset offset = dwarf2_get_ref_die_offset (attr);
 
@@ -14589,6 +14878,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 	  fprintf_unfiltered (f, "ref address: ");
 	  fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
 	  break;
+	case DW_FORM_GNU_ref_alt:
+	  fprintf_unfiltered (f, "alt ref address: ");
+	  fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
+	  break;
 	case DW_FORM_ref1:
 	case DW_FORM_ref2:
 	case DW_FORM_ref4:
@@ -14620,6 +14913,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 	case DW_FORM_string:
 	case DW_FORM_strp:
 	case DW_FORM_GNU_str_index:
+	case DW_FORM_GNU_strp_alt:
 	  fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
 		   DW_STRING (&die->attrs[i])
 		   ? DW_STRING (&die->attrs[i]) : "",
@@ -14723,6 +15017,7 @@ is_ref_attr (struct attribute *attr)
     case DW_FORM_ref4:
     case DW_FORM_ref8:
     case DW_FORM_ref_udata:
+    case DW_FORM_GNU_ref_alt:
       return 1;
     default:
       return 0;
@@ -14842,7 +15137,8 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
    Returns NULL if OFFSET is invalid.  */
 
 static struct die_info *
-follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
+follow_die_offset (sect_offset offset, int offset_in_dwz,
+		   struct dwarf2_cu **ref_cu)
 {
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
@@ -14859,11 +15155,13 @@ follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
       if (! offset_in_cu_p (&cu->header, offset))
 	return NULL;
     }
-  else if (! offset_in_cu_p (&cu->header, offset))
+  else if (offset_in_dwz != cu->per_cu->is_dwz
+	   || ! offset_in_cu_p (&cu->header, offset))
     {
       struct dwarf2_per_cu_data *per_cu;
 
-      per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+						 cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
       if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@@ -14895,7 +15193,10 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
   struct dwarf2_cu *cu = *ref_cu;
   struct die_info *die;
 
-  die = follow_die_offset (offset, ref_cu);
+  die = follow_die_offset (offset,
+			   (attr->form == DW_FORM_GNU_ref_alt
+			    || cu->per_cu->is_dwz),
+			   ref_cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
 	   "at 0x%x [in module %s]"),
@@ -14926,7 +15227,7 @@ dwarf2_fetch_die_location_block (cu_offset offset_in_cu,
     load_cu (per_cu);
   cu = per_cu->cu;
 
-  die = follow_die_offset (offset, &cu);
+  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
 	   offset.sect_off, per_cu->objfile->name);
@@ -15735,6 +16036,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
 
     case DW_FORM_sec_offset:
     case DW_FORM_strp:
+    case DW_FORM_GNU_strp_alt:
       bytes += offset_size;
       break;
 
@@ -15890,7 +16192,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
 			  struct macro_source_file *current_file,
 			  struct line_header *lh, char *comp_dir,
 			  struct dwarf2_section_info *section,
-			  int section_is_gnu,
+			  int section_is_gnu, int section_is_dwz,
 			  unsigned int offset_size,
 			  struct objfile *objfile,
 			  htab_t include_hash)
@@ -15941,6 +16243,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
         case DW_MACRO_GNU_undef:
 	case DW_MACRO_GNU_define_indirect:
 	case DW_MACRO_GNU_undef_indirect:
+	case DW_MACRO_GNU_define_indirect_alt:
+	case DW_MACRO_GNU_undef_indirect_alt:
           {
             unsigned int bytes_read;
             int line;
@@ -15963,11 +16267,20 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
 		str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
 		mac_ptr += offset_size;
 
-		body = read_indirect_string_at_offset (abfd, str_offset);
+		if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
+		    || macinfo_type == DW_MACRO_GNU_undef_indirect_alt)
+		  {
+		    struct dwz_file *dwz = dwarf2_get_dwz_file ();
+
+		    body = read_indirect_string_from_dwz (dwz, str_offset);
+		  }
+		else
+		  body = read_indirect_string_at_offset (abfd, str_offset);
 	      }
 
 	    is_define = (macinfo_type == DW_MACRO_GNU_define
-			 || macinfo_type == DW_MACRO_GNU_define_indirect);
+			 || macinfo_type == DW_MACRO_GNU_define_indirect
+			 || macinfo_type == DW_MACRO_GNU_define_indirect_alt);
             if (! current_file)
 	      {
 		/* DWARF violation as no main source is present.  */
@@ -15991,7 +16304,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
 	    else
 	      {
 		gdb_assert (macinfo_type == DW_MACRO_GNU_undef
-			    || macinfo_type == DW_MACRO_GNU_undef_indirect);
+			    || macinfo_type == DW_MACRO_GNU_undef_indirect
+			    || macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
 		macro_undef (current_file, line, body);
 	      }
           }
@@ -16066,6 +16380,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
           break;
 
 	case DW_MACRO_GNU_transparent_include:
+	case DW_MACRO_GNU_transparent_include_alt:
 	  {
 	    LONGEST offset;
 	    void **slot;
@@ -16084,13 +16399,32 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
 	      }
 	    else
 	      {
+		bfd *include_bfd = abfd;
+		struct dwarf2_section_info *include_section = section;
+		struct dwarf2_section_info alt_section;
+		gdb_byte *include_mac_end = mac_end;
+		int is_dwz = section_is_dwz;
+
 		*slot = mac_ptr;
 
-		dwarf_decode_macro_bytes (abfd,
-					  section->buffer + offset,
-					  mac_end, current_file,
+		if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
+		  {
+		    struct dwz_file *dwz = dwarf2_get_dwz_file ();
+
+		    dwarf2_read_section (dwarf2_per_objfile->objfile,
+					 &dwz->macro);
+
+		    include_bfd = dwz->macro.asection->owner;
+		    include_section = &dwz->macro;
+		    include_mac_end = dwz->macro.buffer + dwz->macro.size;
+		    is_dwz = 1;
+		  }
+
+		dwarf_decode_macro_bytes (include_bfd,
+					  include_section->buffer + offset,
+					  include_mac_end, current_file,
 					  lh, comp_dir,
-					  section, section_is_gnu,
+					  section, section_is_gnu, is_dwz,
 					  offset_size, objfile, include_hash);
 
 		htab_remove_elt (include_hash, mac_ptr);
@@ -16280,7 +16614,8 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
   slot = htab_find_slot (include_hash, mac_ptr, INSERT);
   *slot = mac_ptr;
   dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
-			    current_file, lh, comp_dir, section, section_is_gnu,
+			    current_file, lh, comp_dir, section,
+			    section_is_gnu, 0,
 			    offset_size, objfile, include_hash);
   do_cleanups (cleanup);
 }
@@ -16539,28 +16874,34 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
 
 static struct dwarf2_per_cu_data *
 dwarf2_find_containing_comp_unit (sect_offset offset,
+				  unsigned int offset_in_dwz,
 				  struct objfile *objfile)
 {
   struct dwarf2_per_cu_data *this_cu;
   int low, high;
+  const sect_offset *cu_off;
 
   low = 0;
   high = dwarf2_per_objfile->n_comp_units - 1;
   while (high > low)
     {
+      struct dwarf2_per_cu_data *mid_cu;
       int mid = low + (high - low) / 2;
 
-      if (dwarf2_per_objfile->all_comp_units[mid]->offset.sect_off
-	  >= offset.sect_off)
+      mid_cu = dwarf2_per_objfile->all_comp_units[mid];
+      cu_off = &mid_cu->offset;
+      if (mid_cu->is_dwz >= offset_in_dwz
+	  && cu_off->sect_off >= offset.sect_off)
 	high = mid;
       else
 	low = mid + 1;
     }
   gdb_assert (low == high);
-  if (dwarf2_per_objfile->all_comp_units[low]->offset.sect_off
-      > offset.sect_off)
+  this_cu = dwarf2_per_objfile->all_comp_units[low];
+  cu_off = &this_cu->offset;
+  if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off)
     {
-      if (low == 0)
+      if (low == 0 || this_cu->is_dwz != offset_in_dwz)
 	error (_("Dwarf Error: could not find partial DIE containing "
 	       "offset 0x%lx [in module %s]"),
 	       (long) offset.sect_off, bfd_get_filename (objfile->obfd));
@@ -17018,6 +17359,9 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
 
   if (data->dwo_files)
     free_dwo_files (data->dwo_files, objfile);
+
+  if (data->dwz_file && data->dwz_file->dwz_bfd)
+    gdb_bfd_unref (data->dwz_file->dwz_bfd);
 }
 
 
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]