Handle unaligned mapping of .gdb_index
[deliverable/binutils-gdb.git] / gdb / dwarf2 / read.c
index 19131da0b1d33141a025ea45f96dc72cc15b6a09..40aeb298c14d70279413c90d33539ab7dac45310 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2020 Free Software Foundation, Inc.
+   Copyright (C) 1994-2021 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -40,7 +40,9 @@
 #include "dwarf2/dwz.h"
 #include "dwarf2/macro.h"
 #include "dwarf2/die.h"
+#include "dwarf2/sect-names.h"
 #include "dwarf2/stringify.h"
+#include "dwarf2/public.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
 #include "rust-lang.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
-#include "debuginfod-support.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
    This is in contrast to the low level DIE reading of dwarf_die_debug.  */
 static unsigned int dwarf_read_debug = 0;
 
+/* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 1.  */
+
+#define dwarf_read_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (dwarf_read_debug >= 1, "dwarf-read", fmt, \
+                             ##__VA_ARGS__)
+
+/* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 2.  */
+
+#define dwarf_read_debug_printf_v(fmt, ...) \
+  debug_prefixed_printf_cond (dwarf_read_debug >= 2, "dwarf-read", fmt, \
+                             ##__VA_ARGS__)
+
 /* When non-zero, dump DIEs after they are read in.  */
 static unsigned int dwarf_die_debug = 0;
 
@@ -210,17 +223,50 @@ protected:
   ~mapped_index_base() = default;
 };
 
+/* This is a view into the index that converts from bytes to an
+   offset_type, and allows indexing.  Unaligned bytes are specifically
+   allowed here, and handled via unpacking.  */
+
+class offset_view
+{
+public:
+  offset_view () = default;
+
+  explicit offset_view (gdb::array_view<const gdb_byte> bytes)
+    : m_bytes (bytes)
+  {
+  }
+
+  /* Extract the INDEXth offset_type from the array.  */
+  offset_type operator[] (size_t index) const
+  {
+    const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)];
+    return (offset_type) extract_unsigned_integer (bytes,
+                                                  sizeof (offset_type),
+                                                  BFD_ENDIAN_LITTLE);
+  }
+
+  /* Return the number of offset_types in this array.  */
+  size_t size () const
+  {
+    return m_bytes.size () / sizeof (offset_type);
+  }
+
+  /* Return true if this view is empty.  */
+  bool empty () const
+  {
+    return m_bytes.empty ();
+  }
+
+private:
+  /* The underlying bytes.  */
+  gdb::array_view<const gdb_byte> m_bytes;
+};
+
 /* A description of the mapped index.  The file format is described in
    a comment by the code that writes the index.  */
 struct mapped_index final : public mapped_index_base
 {
-  /* A slot/bucket in the symbol table hash.  */
-  struct symbol_table_slot
-  {
-    const offset_type name;
-    const offset_type vec;
-  };
-
   /* Index data format version.  */
   int version = 0;
 
@@ -228,25 +274,42 @@ struct mapped_index final : public mapped_index_base
   gdb::array_view<const gdb_byte> address_table;
 
   /* The symbol table, implemented as a hash table.  */
-  gdb::array_view<symbol_table_slot> symbol_table;
+  offset_view symbol_table;
 
   /* A pointer to the constant pool.  */
-  const char *constant_pool = nullptr;
+  gdb::array_view<const gdb_byte> constant_pool;
+
+  /* Return the index into the constant pool of the name of the IDXth
+     symbol in the symbol table.  */
+  offset_type symbol_name_index (offset_type idx) const
+  {
+    return symbol_table[2 * idx];
+  }
+
+  /* Return the index into the constant pool of the CU vector of the
+     IDXth symbol in the symbol table.  */
+  offset_type symbol_vec_index (offset_type idx) const
+  {
+    return symbol_table[2 * idx + 1];
+  }
 
   bool symbol_name_slot_invalid (offset_type idx) const override
   {
-    const auto &bucket = this->symbol_table[idx];
-    return bucket.name == 0 && bucket.vec == 0;
+    return (symbol_name_index (idx) == 0
+           && symbol_vec_index (idx) == 0);
   }
 
   /* Convenience method to get at the name of the symbol at IDX in the
      symbol table.  */
   const char *symbol_name_at
     (offset_type idx, dwarf2_per_objfile *per_objfile) const override
-  { return this->constant_pool + MAYBE_SWAP (this->symbol_table[idx].name); }
+  {
+    return (const char *) (this->constant_pool.data ()
+                          + symbol_name_index (idx));
+  }
 
   size_t symbol_name_count () const override
-  { return this->symbol_table.size (); }
+  { return this->symbol_table.size () / 2; }
 };
 
 /* A description of the mapped .debug_names.
@@ -311,7 +374,7 @@ get_dwarf2_per_objfile (struct objfile *objfile)
 /* Note that if the debugging section has been compressed, it might
    have a name like .zdebug_info.  */
 
-static const struct dwarf2_debug_sections dwarf2_elf_names =
+const struct dwarf2_debug_sections dwarf2_elf_names =
 {
   { ".debug_info", ".zdebug_info" },
   { ".debug_abbrev", ".zdebug_abbrev" },
@@ -539,16 +602,41 @@ public:
      Note this value comes from the Fission stub CU/TU's DIE.  */
   gdb::optional<ULONGEST> addr_base;
 
-  /* The DW_AT_rnglists_base attribute if present.
-     Note this value comes from the Fission stub CU/TU's DIE.
-     Also note that the value is zero in the non-DWO case so this value can
-     be used without needing to know whether DWO files are in use or not.
-     N.B. This does not apply to DW_AT_ranges appearing in
-     DW_TAG_compile_unit dies.  This is a bit of a wart, consider if ever
-     DW_AT_ranges appeared in the DW_TAG_compile_unit of DWO DIEs: then
-     DW_AT_rnglists_base *would* have to be applied, and we'd have to care
-     whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
-  ULONGEST ranges_base = 0;
+  /* The DW_AT_GNU_ranges_base attribute, if present.
+
+     This is only relevant in the context of pre-DWARF 5 split units.  In this
+     context, there is a .debug_ranges section in the linked executable,
+     containing all the ranges data for all the compilation units.  Each
+     skeleton/stub unit has (if needed) a DW_AT_GNU_ranges_base attribute that
+     indicates the base of its contribution to that section.  The DW_AT_ranges
+     attributes in the split-unit are of the form DW_FORM_sec_offset and point
+     into the .debug_ranges section of the linked file.  However, they are not
+     "true" DW_FORM_sec_offset, because they are relative to the base of their
+     compilation unit's contribution, rather than relative to the beginning of
+     the section.  The DW_AT_GNU_ranges_base value must be added to it to make
+     it relative to the beginning of the section.
+
+     Note that the value is zero when we are not in a pre-DWARF 5 split-unit
+     case, so this value can be added without needing to know whether we are in
+     this case or not.
+
+     N.B. If a DW_AT_ranges attribute is found on the DW_TAG_compile_unit in the
+     skeleton/stub, it must not have the base added, as it already points to the
+     right place.  And since the DW_TAG_compile_unit DIE in the split-unit can't
+     have a DW_AT_ranges attribute, we can use the
+
+       die->tag != DW_AT_compile_unit
+
+     to determine whether the base should be added or not.  */
+  ULONGEST gnu_ranges_base = 0;
+
+  /* The DW_AT_rnglists_base attribute, if present.
+
+     This is used when processing attributes of form DW_FORM_rnglistx in
+     non-split units.  Attributes of this form found in a split unit don't
+     use it, as split-unit files have their own non-shared .debug_rnglists.dwo
+     section.  */
+  ULONGEST rnglists_base = 0;
 
   /* The DW_AT_loclists_base attribute if present.  */
   ULONGEST loclist_base = 0;
@@ -918,7 +1006,7 @@ struct dwp_file
 struct die_reader_specs
 {
   /* The bfd of die_section.  */
-  bfdabfd;
+  bfd *abfd;
 
   /* The CU of the DIE we are parsing.  */
   struct dwarf2_cu *cu;
@@ -987,7 +1075,7 @@ private:
    need this much information.  */
 struct partial_die_info : public allocate_on_obstack
   {
-    partial_die_info (sect_offset sect_off, struct abbrev_info *abbrev);
+    partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev);
 
     /* Disable assign but still keep copy ctor, which is needed
        load_partial_dies.   */
@@ -1303,7 +1391,8 @@ static const struct cu_partial_die_info find_partial_die (sect_offset, int,
                                                          struct dwarf2_cu *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
-                                      struct attribute *, struct attr_abbrev *,
+                                      struct attribute *,
+                                      const struct attr_abbrev *,
                                       const gdb_byte *);
 
 static void read_attribute_reprocess (const struct die_reader_specs *reader,
@@ -1337,12 +1426,12 @@ static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
                                      struct dwarf2_cu *);
 
 static const char *dwarf2_string_attr (struct die_info *die, unsigned int name,
-                                       struct dwarf2_cu *cu);
+                                      struct dwarf2_cu *cu);
 
 static const char *dwarf2_dwo_name (struct die_info *die, struct dwarf2_cu *cu);
 
 static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
-                               struct dwarf2_cu *cu);
+                              struct dwarf2_cu *cu);
 
 static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
 
@@ -1373,6 +1462,9 @@ static void dwarf2_const_value_attr (const struct attribute *attr,
                                     const gdb_byte **bytes,
                                     struct dwarf2_locexpr_baton **baton);
 
+static struct type *read_subrange_index_type (struct die_info *die,
+                                             struct dwarf2_cu *cu);
+
 static struct type *die_type (struct die_info *, struct dwarf2_cu *);
 
 static int need_gnat_info (struct dwarf2_cu *);
@@ -1446,7 +1538,7 @@ static void get_scope_pc_bounds (struct die_info *,
                                 struct dwarf2_cu *);
 
 static void dwarf2_record_block_ranges (struct die_info *, struct block *,
-                                        CORE_ADDR, struct dwarf2_cu *);
+                                       CORE_ADDR, struct dwarf2_cu *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
                              struct dwarf2_cu *);
@@ -1583,7 +1675,7 @@ static void dwarf2_symbol_mark_computed (const struct attribute *attr,
 
 static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
                                     const gdb_byte *info_ptr,
-                                    struct abbrev_info *abbrev);
+                                    const struct abbrev_info *abbrev);
 
 static hashval_t partial_die_hash (const void *item);
 
@@ -1598,7 +1690,7 @@ static void prepare_one_comp_unit (struct dwarf2_cu *cu,
                                   enum language pretend_language);
 
 static struct type *set_die_type (struct die_info *, struct type *,
-                                 struct dwarf2_cu *);
+                                 struct dwarf2_cu *, bool = false);
 
 static void create_all_comp_units (dwarf2_per_objfile *per_objfile);
 
@@ -1644,15 +1736,18 @@ public:
   explicit dwarf2_queue_guard (dwarf2_per_objfile *per_objfile)
     : m_per_objfile (per_objfile)
   {
+    gdb_assert (!m_per_objfile->per_bfd->queue.has_value ());
+
+    m_per_objfile->per_bfd->queue.emplace ();
   }
 
   /* Free any entries remaining on the queue.  There should only be
      entries left if we hit an error while processing the dwarf.  */
   ~dwarf2_queue_guard ()
   {
-    /* Ensure that no memory is allocated by the queue.  */
-    std::queue<dwarf2_queue_item> empty;
-    std::swap (m_per_objfile->per_bfd->queue, empty);
+    gdb_assert (m_per_objfile->per_bfd->queue.has_value ());
+
+    m_per_objfile->per_bfd->queue.reset ();
   }
 
   DISABLE_COPY_AND_ASSIGN (dwarf2_queue_guard);
@@ -1821,6 +1916,8 @@ dwarf2_per_bfd::~dwarf2_per_bfd ()
 void
 dwarf2_per_objfile::remove_all_cus ()
 {
+  gdb_assert (!this->per_bfd->queue.has_value ());
+
   for (auto pair : m_dwarf2_cus)
     delete pair.second;
 
@@ -1892,7 +1989,7 @@ dwarf2_per_objfile::set_symtab (const dwarf2_per_cu_data *per_cu,
 
 int
 dwarf2_has_info (struct objfile *objfile,
-                 const struct dwarf2_debug_sections *names,
+                const struct dwarf2_debug_sections *names,
                 bool can_copy)
 {
   if (objfile->flags & OBJF_READNEVER)
@@ -1904,11 +2001,14 @@ dwarf2_has_info (struct objfile *objfile,
     {
       dwarf2_per_bfd *per_bfd;
 
-      /* We can share a "dwarf2_per_bfd" with other objfiles if the BFD
-         doesn't require relocations and if there aren't partial symbols
-        from some other reader.  */
-      if (!objfile_has_partial_symbols (objfile)
-         && !gdb_bfd_requires_relocations (objfile->obfd))
+      /* We can share a "dwarf2_per_bfd" with other objfiles if the
+        BFD doesn't require relocations.
+
+        We don't share with objfiles for which -readnow was requested,
+        because it would complicate things when loading the same BFD with
+        -readnow and then without -readnow.  */
+      if (!gdb_bfd_requires_relocations (objfile->obfd)
+         && (objfile->flags & OBJF_READNOW) == 0)
        {
          /* See if one has been created for this BFD yet.  */
          per_bfd = dwarf2_per_bfd_bfd_data_key.get (objfile->obfd);
@@ -1936,22 +2036,6 @@ dwarf2_has_info (struct objfile *objfile,
          && per_objfile->per_bfd->abbrev.s.section != NULL);
 }
 
-/* When loading sections, we look either for uncompressed section or for
-   compressed section names.  */
-
-static int
-section_is_p (const char *section_name,
-              const struct dwarf2_section_names *names)
-{
-  if (names->normal != NULL
-      && strcmp (section_name, names->normal) == 0)
-    return 1;
-  if (names->compressed != NULL
-      && strcmp (section_name, names->compressed) == 0)
-    return 1;
-  return 0;
-}
-
 /* See declaration.  */
 
 void
@@ -1972,82 +2056,82 @@ dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp,
               bfd_section_name (sectp), phex_nz (size, sizeof (size)),
               bfd_get_filename (abfd));
     }
-  else if (section_is_p (sectp->name, &names.info))
+  else if (names.info.matches (sectp->name))
     {
       this->info.s.section = sectp;
       this->info.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.abbrev))
+  else if (names.abbrev.matches (sectp->name))
     {
       this->abbrev.s.section = sectp;
       this->abbrev.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.line))
+  else if (names.line.matches (sectp->name))
     {
       this->line.s.section = sectp;
       this->line.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.loc))
+  else if (names.loc.matches (sectp->name))
     {
       this->loc.s.section = sectp;
       this->loc.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.loclists))
+  else if (names.loclists.matches (sectp->name))
     {
       this->loclists.s.section = sectp;
       this->loclists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.macinfo))
+  else if (names.macinfo.matches (sectp->name))
     {
       this->macinfo.s.section = sectp;
       this->macinfo.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.macro))
+  else if (names.macro.matches (sectp->name))
     {
       this->macro.s.section = sectp;
       this->macro.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.str))
+  else if (names.str.matches (sectp->name))
     {
       this->str.s.section = sectp;
       this->str.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.str_offsets))
+  else if (names.str_offsets.matches (sectp->name))
     {
       this->str_offsets.s.section = sectp;
       this->str_offsets.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.line_str))
+  else if (names.line_str.matches (sectp->name))
     {
       this->line_str.s.section = sectp;
       this->line_str.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.addr))
+  else if (names.addr.matches (sectp->name))
     {
       this->addr.s.section = sectp;
       this->addr.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.frame))
+  else if (names.frame.matches (sectp->name))
     {
       this->frame.s.section = sectp;
       this->frame.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.eh_frame))
+  else if (names.eh_frame.matches (sectp->name))
     {
       this->eh_frame.s.section = sectp;
       this->eh_frame.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.ranges))
+  else if (names.ranges.matches (sectp->name))
     {
       this->ranges.s.section = sectp;
       this->ranges.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.rnglists))
+  else if (names.rnglists.matches (sectp->name))
     {
       this->rnglists.s.section = sectp;
       this->rnglists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.types))
+  else if (names.types.matches (sectp->name))
     {
       struct dwarf2_section_info type_section;
 
@@ -2057,17 +2141,17 @@ dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp,
 
       this->types.push_back (type_section);
     }
-  else if (section_is_p (sectp->name, &names.gdb_index))
+  else if (names.gdb_index.matches (sectp->name))
     {
       this->gdb_index.s.section = sectp;
       this->gdb_index.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.debug_names))
+  else if (names.debug_names.matches (sectp->name))
     {
       this->debug_names.s.section = sectp;
       this->debug_names.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names.debug_aranges))
+  else if (names.debug_aranges.matches (sectp->name))
     {
       this->debug_aranges.s.section = sectp;
       this->debug_aranges.size = bfd_section_size (sectp);
@@ -2083,9 +2167,9 @@ dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp,
 
 void
 dwarf2_get_section_info (struct objfile *objfile,
-                         enum dwarf2_section_enum sect,
-                         asection **sectp, const gdb_byte **bufp,
-                         bfd_size_type *sizep)
+                        enum dwarf2_section_enum sect,
+                        asection **sectp, const gdb_byte **bufp,
+                        bfd_size_type *sizep)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   struct dwarf2_section_info *info;
@@ -2118,142 +2202,8 @@ 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, dwz_file *dwz_file)
-{
-  /* 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.s.section = sectp;
-      dwz_file->abbrev.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
-    {
-      dwz_file->info.s.section = sectp;
-      dwz_file->info.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
-    {
-      dwz_file->str.s.section = sectp;
-      dwz_file->str.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
-    {
-      dwz_file->line.s.section = sectp;
-      dwz_file->line.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
-    {
-      dwz_file->macro.s.section = sectp;
-      dwz_file->macro.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index))
-    {
-      dwz_file->gdb_index.s.section = sectp;
-      dwz_file->gdb_index.size = bfd_section_size (sectp);
-    }
-  else if (section_is_p (sectp->name, &dwarf2_elf_names.debug_names))
-    {
-      dwz_file->debug_names.s.section = sectp;
-      dwz_file->debug_names.size = bfd_section_size (sectp);
-    }
-}
-
-/* See dwarf2read.h.  */
-
-struct dwz_file *
-dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd)
-{
-  const char *filename;
-  bfd_size_type buildid_len_arg;
-  size_t buildid_len;
-  bfd_byte *buildid;
-
-  if (per_bfd->dwz_file != NULL)
-    return per_bfd->dwz_file.get ();
-
-  bfd_set_error (bfd_error_no_error);
-  gdb::unique_xmalloc_ptr<char> data
-    (bfd_get_alt_debug_link_info (per_bfd->obfd,
-                                 &buildid_len_arg, &buildid));
-  if (data == NULL)
-    {
-      if (bfd_get_error () == bfd_error_no_error)
-       return NULL;
-      error (_("could not read '.gnu_debugaltlink' section: %s"),
-            bfd_errmsg (bfd_get_error ()));
-    }
-
-  gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
-
-  buildid_len = (size_t) buildid_len_arg;
-
-  filename = data.get ();
-
-  std::string abs_storage;
-  if (!IS_ABSOLUTE_PATH (filename))
-    {
-      gdb::unique_xmalloc_ptr<char> abs
-       = gdb_realpath (bfd_get_filename (per_bfd->obfd));
-
-      abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
-      filename = abs_storage.c_str ();
-    }
-
-  /* First try the file name given in the section.  If that doesn't
-     work, try to use the build-id instead.  */
-  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget));
-  if (dwz_bfd != NULL)
-    {
-      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
-       dwz_bfd.reset (nullptr);
-    }
-
-  if (dwz_bfd == NULL)
-    dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
-
-  if (dwz_bfd == nullptr)
-    {
-      gdb::unique_xmalloc_ptr<char> alt_filename;
-      const char *origname = bfd_get_filename (per_bfd->obfd);
-
-      scoped_fd fd (debuginfod_debuginfo_query (buildid,
-                                               buildid_len,
-                                               origname,
-                                               &alt_filename));
-
-      if (fd.get () >= 0)
-       {
-         /* File successfully retrieved from server.  */
-         dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget);
-
-         if (dwz_bfd == nullptr)
-           warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
-                    alt_filename.get ());
-         else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
-           dwz_bfd.reset (nullptr);
-       }
-    }
-
-  if (dwz_bfd == NULL)
-    error (_("could not find '.gnu_debugaltlink' file for %s"),
-          bfd_get_filename (per_bfd->obfd));
-
-  std::unique_ptr<struct dwz_file> result
-    (new struct dwz_file (std::move (dwz_bfd)));
-
-  for (asection *sec : gdb_bfd_sections (result->dwz_bfd))
-    locate_dwz_sections (result->dwz_bfd.get (), sec, result.get ());
-
-  gdb_bfd_record_inclusion (per_bfd->obfd, result->dwz_bfd.get ());
-  per_bfd->dwz_file = std::move (result);
-  return per_bfd->dwz_file.get ();
-}
 \f
-/* DWARF quick_symbols_functions support.  */
+/* DWARF quick_symbol_functions support.  */
 
 /* TUs can share .debug_line entries, and there can be a lot more TUs than
    unique line tables, so we maintain a separate table of all .debug_line
@@ -2296,6 +2246,122 @@ struct dwarf2_per_cu_quick_data
   unsigned int no_file_data : 1;
 };
 
+/* A subclass of psymbol_functions that arranges to read the DWARF
+   partial symbols when needed.  */
+struct lazy_dwarf_reader : public psymbol_functions
+{
+  using psymbol_functions::psymbol_functions;
+
+  bool can_lazily_read_symbols () override
+  {
+    return true;
+  }
+
+  void read_partial_symbols (struct objfile *objfile) override
+  {
+    if (dwarf2_has_info (objfile, nullptr))
+      dwarf2_build_psymtabs (objfile, this);
+  }
+};
+
+static quick_symbol_functions_up
+make_lazy_dwarf_reader ()
+{
+  return quick_symbol_functions_up (new lazy_dwarf_reader);
+}
+
+struct dwarf2_base_index_functions : public quick_symbol_functions
+{
+  bool has_symbols (struct objfile *objfile) override;
+
+  struct symtab *find_last_source_symtab (struct objfile *objfile) override;
+
+  void forget_cached_source_info (struct objfile *objfile) override;
+
+  enum language lookup_global_symbol_language (struct objfile *objfile,
+                                              const char *name,
+                                              domain_enum domain,
+                                              bool *symbol_found_p) override
+  {
+    *symbol_found_p = false;
+    return language_unknown;
+  }
+
+  void print_stats (struct objfile *objfile, bool print_bcache) override;
+
+  void expand_all_symtabs (struct objfile *objfile) override;
+
+  struct compunit_symtab *find_pc_sect_compunit_symtab
+    (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+     CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
+
+  struct compunit_symtab *find_compunit_symtab_by_address
+    (struct objfile *objfile, CORE_ADDR address) override
+  {
+    return nullptr;
+  }
+
+  void map_symbol_filenames (struct objfile *objfile,
+                            gdb::function_view<symbol_filename_ftype> fun,
+                            bool need_fullname) override;
+};
+
+struct dwarf2_gdb_index : public dwarf2_base_index_functions
+{
+  void dump (struct objfile *objfile) override;
+
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
+
+  bool expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind) override;
+};
+
+struct dwarf2_debug_names_index : public dwarf2_base_index_functions
+{
+  void dump (struct objfile *objfile) override;
+
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
+
+  bool expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind) override;
+};
+
+static quick_symbol_functions_up
+make_dwarf_gdb_index ()
+{
+  return quick_symbol_functions_up (new dwarf2_gdb_index);
+}
+
+static quick_symbol_functions_up
+make_dwarf_debug_names ()
+{
+  return quick_symbol_functions_up (new dwarf2_debug_names_index);
+}
+
 /* Utility hash function for a stmt_list_hash.  */
 
 static hashval_t
@@ -2398,7 +2464,7 @@ load_cu (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
   return cu;
 }
 
-/* Read in the symbols for PER_CU in the context of DWARF"_PER_OBJFILE.  */
+/* Read in the symbols for PER_CU in the context of PER_OBJFILE.  */
 
 static void
 dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
@@ -2409,30 +2475,32 @@ dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
   if (per_cu->type_unit_group_p ())
     return;
 
-  /* The destructor of dwarf2_queue_guard frees any entries left on
-     the queue.  After this point we're guaranteed to leave this function
-     with the dwarf queue empty.  */
-  dwarf2_queue_guard q_guard (dwarf2_per_objfile);
-
-  if (!per_objfile->symtab_set_p (per_cu))
-    {
-      queue_comp_unit (per_cu, per_objfile, language_minimal);
-      dwarf2_cu *cu = load_cu (per_cu, per_objfile, skip_partial);
+  {
+    /* The destructor of dwarf2_queue_guard frees any entries left on
+       the queue.  After this point we're guaranteed to leave this function
+       with the dwarf queue empty.  */
+    dwarf2_queue_guard q_guard (per_objfile);
 
-      /* If we just loaded a CU from a DWO, and we're working with an index
-        that may badly handle TUs, load all the TUs in that DWO as well.
-        http://sourceware.org/bugzilla/show_bug.cgi?id=15021  */
-      if (!per_cu->is_debug_types
-         && cu != NULL
-         && cu->dwo_unit != NULL
-         && per_objfile->per_bfd->index_table != NULL
-         && per_objfile->per_bfd->index_table->version <= 7
-         /* DWP files aren't supported yet.  */
-         && get_dwp_file (per_objfile) == NULL)
-       queue_and_load_all_dwo_tus (cu);
-    }
+    if (!per_objfile->symtab_set_p (per_cu))
+      {
+       queue_comp_unit (per_cu, per_objfile, language_minimal);
+       dwarf2_cu *cu = load_cu (per_cu, per_objfile, skip_partial);
+
+       /* If we just loaded a CU from a DWO, and we're working with an index
+          that may badly handle TUs, load all the TUs in that DWO as well.
+          http://sourceware.org/bugzilla/show_bug.cgi?id=15021  */
+       if (!per_cu->is_debug_types
+           && cu != NULL
+           && cu->dwo_unit != NULL
+           && per_objfile->per_bfd->index_table != NULL
+           && per_objfile->per_bfd->index_table->version <= 7
+           /* DWP files aren't supported yet.  */
+           && get_dwp_file (per_objfile) == NULL)
+         queue_and_load_all_dwo_tus (cu);
+      }
 
-  process_queue (per_objfile);
+    process_queue (per_objfile);
+  }
 
   /* Age the cache, releasing compilation units that have not
      been used recently.  */
@@ -2688,13 +2756,14 @@ create_signatured_type_table_from_debug_names
 }
 
 /* Read the address map data from the mapped index, and use it to
-   populate the objfile's psymtabs_addrmap.  */
+   populate the psymtabs_addrmap.  */
 
 static void
 create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                           struct mapped_index *index)
 {
   struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const gdb_byte *iter, *end;
   struct addrmap *mutable_map;
@@ -2726,7 +2795,7 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
          continue;
        }
 
-      if (cu_index >= per_objfile->per_bfd->all_comp_units.size ())
+      if (cu_index >= per_bfd->all_comp_units.size ())
        {
          complaint (_(".gdb_index address table has invalid CU number %u"),
                     (unsigned) cu_index);
@@ -2736,15 +2805,15 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
       lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr;
       hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr;
       addrmap_set_empty (mutable_map, lo, hi - 1,
-                        per_objfile->per_bfd->get_cu (cu_index));
+                        per_bfd->get_cu (cu_index));
     }
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (mutable_map, objfile->partial_symtabs->obstack ());
+  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                &per_bfd->obstack);
 }
 
 /* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the objfile's psymtabs_addrmap.  */
+   populate the psymtabs_addrmap.  */
 
 static void
 create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
@@ -2754,6 +2823,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   auto_obstack temp_obstack;
   addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
@@ -2762,7 +2832,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
     debug_info_offset_to_per_cu;
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (dwarf2_per_cu_data *per_cu : per_bfd->all_comp_units)
     {
       const auto insertpair
        = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu);
@@ -2796,7 +2866,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
       if (addr + entry_length > section->buffer + section->size)
        {
          warning (_("Section .debug_aranges in %s entry at offset %s "
-                    "length %s exceeds section length %s, "
+                    "length %s exceeds section length %s, "
                     "ignoring .debug_aranges."),
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
@@ -2857,11 +2927,11 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
        }
 
       /* Must pad to an alignment boundary that is twice the address
-         size.  It is undocumented by the DWARF standard but GCC does
-         use it.  */
+        size.  It is undocumented by the DWARF standard but GCC does
+        use it.  */
       for (size_t padding = ((-(addr - section->buffer))
                             & (2 * address_size - 1));
-           padding > 0; padding--)
+          padding > 0; padding--)
        if (*addr++ != 0)
          {
            warning (_("Section .debug_aranges in %s entry at offset %s "
@@ -2890,7 +2960,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
          addr += address_size;
          if (start == 0 && length == 0)
            break;
-         if (start == 0 && !per_objfile->per_bfd->has_section_at_zero)
+         if (start == 0 && !per_bfd->has_section_at_zero)
            {
              /* Symbol was eliminated due to a COMDAT group.  */
              continue;
@@ -2904,70 +2974,8 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
        }
     }
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (mutable_map, objfile->partial_symtabs->obstack ());
-}
-
-/* Find a slot in the mapped index INDEX for the object named NAME.
-   If NAME is found, set *VEC_OUT to point to the CU vector in the
-   constant pool and return true.  If NAME cannot be found, return
-   false.  */
-
-static bool
-find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
-                         offset_type **vec_out)
-{
-  offset_type hash;
-  offset_type slot, step;
-  int (*cmp) (const char *, const char *);
-
-  gdb::unique_xmalloc_ptr<char> without_params;
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran
-      || current_language->la_language == language_d)
-    {
-      /* NAME is already canonical.  Drop any qualifiers as .gdb_index does
-        not contain any.  */
-
-      if (strchr (name, '(') != NULL)
-       {
-         without_params = cp_remove_params (name);
-
-         if (without_params != NULL)
-           name = without_params.get ();
-       }
-    }
-
-  /* Index version 4 did not support case insensitive searches.  But the
-     indices for case insensitive languages are built in lowercase, therefore
-     simulate our NAME being searched is also lowercased.  */
-  hash = mapped_index_string_hash ((index->version == 4
-                                    && case_sensitivity == case_sensitive_off
-                                   ? 5 : index->version),
-                                  name);
-
-  slot = hash & (index->symbol_table.size () - 1);
-  step = ((hash * 17) & (index->symbol_table.size () - 1)) | 1;
-  cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
-
-  for (;;)
-    {
-      const char *str;
-
-      const auto &bucket = index->symbol_table[slot];
-      if (bucket.name == 0 && bucket.vec == 0)
-       return false;
-
-      str = index->constant_pool + MAYBE_SWAP (bucket.name);
-      if (!cmp (name, str))
-       {
-         *vec_out = (offset_type *) (index->constant_pool
-                                     + MAYBE_SWAP (bucket.vec));
-         return true;
-       }
-
-      slot = (slot + step) & (index->symbol_table.size () - 1);
-    }
+  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                &per_bfd->obstack);
 }
 
 /* A helper function that reads the .gdb_index from BUFFER and fills
@@ -2992,9 +3000,10 @@ read_gdb_index_from_buffer (const char *filename,
                            offset_type *types_list_elements)
 {
   const gdb_byte *addr = &buffer[0];
+  offset_view metadata (buffer);
 
   /* Version check.  */
-  offset_type version = MAYBE_SWAP (*(offset_type *) addr);
+  offset_type version = metadata[0];
   /* Versions earlier than 3 emitted every copy of a psymbol.  This
      causes the index to behave very poorly for certain requests.  Version 3
      contained incomplete addrmap.  So, it seems better to just ignore such
@@ -3047,35 +3056,29 @@ to use the section anyway."),
 
   map->version = version;
 
-  offset_type *metadata = (offset_type *) (addr + sizeof (offset_type));
-
-  int i = 0;
-  *cu_list = addr + MAYBE_SWAP (metadata[i]);
-  *cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i]))
-                      / 8);
+  int i = 1;
+  *cu_list = addr + metadata[i];
+  *cu_list_elements = (metadata[i + 1] - metadata[i]) / 8;
   ++i;
 
-  *types_list = addr + MAYBE_SWAP (metadata[i]);
-  *types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
-                          - MAYBE_SWAP (metadata[i]))
-                         / 8);
+  *types_list = addr + metadata[i];
+  *types_list_elements = (metadata[i + 1] - metadata[i]) / 8;
   ++i;
 
-  const gdb_byte *address_table = addr + MAYBE_SWAP (metadata[i]);
-  const gdb_byte *address_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  const gdb_byte *address_table = addr + metadata[i];
+  const gdb_byte *address_table_end = addr + metadata[i + 1];
   map->address_table
     = gdb::array_view<const gdb_byte> (address_table, address_table_end);
   ++i;
 
-  const gdb_byte *symbol_table = addr + MAYBE_SWAP (metadata[i]);
-  const gdb_byte *symbol_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  const gdb_byte *symbol_table = addr + metadata[i];
+  const gdb_byte *symbol_table_end = addr + metadata[i + 1];
   map->symbol_table
-    = gdb::array_view<mapped_index::symbol_table_slot>
-       ((mapped_index::symbol_table_slot *) symbol_table,
-       (mapped_index::symbol_table_slot *) symbol_table_end);
+    = offset_view (gdb::array_view<const gdb_byte> (symbol_table,
+                                                   symbol_table_end));
 
   ++i;
-  map->constant_pool = (char *) (addr + MAYBE_SWAP (metadata[i]));
+  map->constant_pool = buffer.slice (metadata[i]);
 
   return 1;
 }
@@ -3172,11 +3175,6 @@ dwarf2_read_gdb_index
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
-  /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
-     objfiles using the same BFD.  */
-  gdb_assert (per_bfd->partial_symtabs == nullptr);
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
-
   return 1;
 }
 
@@ -3184,7 +3182,6 @@ dwarf2_read_gdb_index
 
 static void
 dw2_get_file_names_reader (const struct die_reader_specs *reader,
-                          const gdb_byte *info_ptr,
                           struct die_info *comp_unit_die)
 {
   struct dwarf2_cu *cu = reader->cu;
@@ -3284,7 +3281,7 @@ dw2_get_file_names (dwarf2_per_cu_data *this_cu,
 
   cutu_reader reader (this_cu, per_objfile);
   if (!reader.dummy_p)
-    dw2_get_file_names_reader (&reader, reader.info_ptr, reader.comp_unit_die);
+    dw2_get_file_names_reader (&reader, reader.comp_unit_die);
 
   if (this_cu->v.quick->no_file_data)
     return NULL;
@@ -3308,8 +3305,8 @@ dw2_get_real_path (dwarf2_per_objfile *per_objfile,
   return qfn->real_names[index];
 }
 
-static struct symtab *
-dw2_find_last_source_symtab (struct objfile *objfile)
+struct symtab *
+dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   dwarf2_per_cu_data *dwarf_cu = per_objfile->per_bfd->all_comp_units.back ();
@@ -3342,8 +3339,9 @@ dw2_free_cached_file_names (void **slot, void *info)
   return 1;
 }
 
-static void
-dw2_forget_cached_source_info (struct objfile *objfile)
+void
+dwarf2_base_index_functions::forget_cached_source_info
+     (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -3351,100 +3349,6 @@ dw2_forget_cached_source_info (struct objfile *objfile)
                          dw2_free_cached_file_names, NULL);
 }
 
-/* Helper function for dw2_map_symtabs_matching_filename that expands
-   the symtabs and calls the iterator.  */
-
-static int
-dw2_map_expand_apply (struct objfile *objfile,
-                     struct dwarf2_per_cu_data *per_cu,
-                     const char *name, const char *real_path,
-                     gdb::function_view<bool (symtab *)> callback)
-{
-  struct compunit_symtab *last_made = objfile->compunit_symtabs;
-
-  /* Don't visit already-expanded CUs.  */
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  if (per_objfile->symtab_set_p (per_cu))
-    return 0;
-
-  /* This may expand more than one symtab, and we want to iterate over
-     all of them.  */
-  dw2_instantiate_symtab (per_cu, per_objfile, false);
-
-  return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs,
-                                   last_made, callback);
-}
-
-/* Implementation of the map_symtabs_matching_filename method.  */
-
-static bool
-dw2_map_symtabs_matching_filename
-  (struct objfile *objfile, const char *name, const char *real_path,
-   gdb::function_view<bool (symtab *)> callback)
-{
-  const char *name_basename = lbasename (name);
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* The rule is CUs specify all the files, including those used by
-     any TU, so there's no need to scan TUs here.  */
-
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu))
-       continue;
-
-      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
-      if (file_data == NULL)
-       continue;
-
-      for (int j = 0; j < file_data->num_file_names; ++j)
-       {
-         const char *this_name = file_data->file_names[j];
-         const char *this_real_name;
-
-         if (compare_filenames_for_search (this_name, name))
-           {
-             if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback))
-               return true;
-             continue;
-           }
-
-         /* Before we invoke realpath, which can get expensive when many
-            files are involved, do a quick comparison of the basenames.  */
-         if (! basenames_may_differ
-             && FILENAME_CMP (lbasename (this_name), name_basename) != 0)
-           continue;
-
-         this_real_name = dw2_get_real_path (per_objfile, file_data, j);
-         if (compare_filenames_for_search (this_real_name, name))
-           {
-             if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback))
-               return true;
-             continue;
-           }
-
-         if (real_path != NULL)
-           {
-             gdb_assert (IS_ABSOLUTE_PATH (real_path));
-             gdb_assert (IS_ABSOLUTE_PATH (name));
-             if (this_real_name != NULL
-                 && FILENAME_CMP (real_path, this_real_name) == 0)
-               {
-                 if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                           callback))
-                   return true;
-                 continue;
-               }
-           }
-       }
-    }
-
-  return false;
-}
-
 /* Struct used to manage iterating over all CUs looking for a symbol.  */
 
 struct dw2_symtab_iterator
@@ -3458,7 +3362,7 @@ struct dw2_symtab_iterator
   domain_enum domain;
   /* The list of CUs from the index entry of the symbol,
      or NULL if not found.  */
-  offset_type *vec;
+  offset_view vec;
   /* The next element in VEC to look at.  */
   int next;
   /* The number of elements in VEC, or zero if there is no match.  */
@@ -3470,52 +3374,21 @@ struct dw2_symtab_iterator
   int global_seen;
 };
 
-/* Initialize the index symtab iterator ITER, common part.  */
+/* Initialize the index symtab iterator ITER, offset_type NAMEI variant.  */
 
 static void
-dw2_symtab_iter_init_common (struct dw2_symtab_iterator *iter,
-                            dwarf2_per_objfile *per_objfile,
-                            gdb::optional<block_enum> block_index,
-                            domain_enum domain)
+dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
+                     dwarf2_per_objfile *per_objfile,
+                     gdb::optional<block_enum> block_index,
+                     domain_enum domain, offset_type namei)
 {
   iter->per_objfile = per_objfile;
   iter->block_index = block_index;
   iter->domain = domain;
   iter->next = 0;
   iter->global_seen = 0;
-  iter->vec = NULL;
+  iter->vec = {};
   iter->length = 0;
-}
-
-/* Initialize the index symtab iterator ITER, const char *NAME variant.  */
-
-static void
-dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
-                     dwarf2_per_objfile *per_objfile,
-                     gdb::optional<block_enum> block_index,
-                     domain_enum domain,
-                     const char *name)
-{
-  dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
-
-  mapped_index *index = per_objfile->per_bfd->index_table.get ();
-  /* index is NULL if OBJF_READNOW.  */
-  if (index == NULL)
-    return;
-
-  if (find_slot_in_mapped_hash (index, name, &iter->vec))
-    iter->length = MAYBE_SWAP (*iter->vec);
-}
-
-/* Initialize the index symtab iterator ITER, offset_type NAMEI variant.  */
-
-static void
-dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
-                     dwarf2_per_objfile *per_objfile,
-                     gdb::optional<block_enum> block_index,
-                     domain_enum domain, offset_type namei)
-{
-  dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
 
   mapped_index *index = per_objfile->per_bfd->index_table.get ();
   /* index is NULL if OBJF_READNOW.  */
@@ -3523,11 +3396,10 @@ dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
     return;
 
   gdb_assert (!index->symbol_name_slot_invalid (namei));
-  const auto &bucket = index->symbol_table[namei];
+  offset_type vec_idx = index->symbol_vec_index (namei);
 
-  iter->vec = (offset_type *) (index->constant_pool
-                              + MAYBE_SWAP (bucket.vec));
-  iter->length = MAYBE_SWAP (*iter->vec);
+  iter->vec = offset_view (index->constant_pool.slice (vec_idx));
+  iter->length = iter->vec[0];
 }
 
 /* Return the next matching CU or NULL if there are no more.  */
@@ -3539,8 +3411,7 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
 
   for ( ; iter->next < iter->length; ++iter->next)
     {
-      offset_type cu_index_and_attrs =
-       MAYBE_SWAP (iter->vec[iter->next + 1]);
+      offset_type cu_index_and_attrs = iter->vec[iter->next + 1];
       offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
       gdb_index_symbol_kind symbol_kind =
        GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
@@ -3624,55 +3495,16 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
       return per_cu;
     }
 
-  return NULL;
-}
-
-static struct compunit_symtab *
-dw2_lookup_symbol (struct objfile *objfile, block_enum block_index,
-                  const char *name, domain_enum domain)
-{
-  struct compunit_symtab *stab_best = NULL;
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
-
-  struct dw2_symtab_iterator iter;
-  struct dwarf2_per_cu_data *per_cu;
-
-  dw2_symtab_iter_init (&iter, per_objfile, block_index, domain, name);
-
-  while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
-    {
-      struct symbol *sym, *with_opaque = NULL;
-      struct compunit_symtab *stab
-       = dw2_instantiate_symtab (per_cu, per_objfile, false);
-      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
-      const struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
-
-      sym = block_find_symbol (block, name, domain,
-                              block_find_non_opaque_type_preferred,
-                              &with_opaque);
-
-      /* Some caution must be observed with overloaded functions
-        and methods, since the index will not contain any overload
-        information (but NAME might contain it).  */
-
-      if (sym != NULL
-         && SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
-       return stab;
-      if (with_opaque != NULL
-         && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, lookup_name))
-       stab_best = stab;
-
-      /* Keep looking through other CUs.  */
-    }
-
-  return stab_best;
+  return NULL;
 }
 
-static void
-dw2_print_stats (struct objfile *objfile)
+void
+dwarf2_base_index_functions::print_stats (struct objfile *objfile,
+                                         bool print_bcache)
 {
+  if (print_bcache)
+    return;
+
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   int total = (per_objfile->per_bfd->all_comp_units.size ()
               + per_objfile->per_bfd->all_type_units.size ());
@@ -3694,8 +3526,8 @@ dw2_print_stats (struct objfile *objfile)
    One use is to verify .gdb_index has been loaded by the
    gdb.dwarf2/gdb-index.exp testcase.  */
 
-static void
-dw2_dump (struct objfile *objfile)
+void
+dwarf2_gdb_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -3711,24 +3543,8 @@ dw2_dump (struct objfile *objfile)
   printf_filtered ("\n");
 }
 
-static void
-dw2_expand_symtabs_for_function (struct objfile *objfile,
-                                const char *func_name)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  struct dw2_symtab_iterator iter;
-  struct dwarf2_per_cu_data *per_cu;
-
-  dw2_symtab_iter_init (&iter, per_objfile, {}, VAR_DOMAIN, func_name);
-
-  while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
-    dw2_instantiate_symtab (per_cu, per_objfile, false);
-
-}
-
-static void
-dw2_expand_all_symtabs (struct objfile *objfile)
+void
+dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   int total_units = (per_objfile->per_bfd->all_comp_units.size ()
@@ -3747,62 +3563,26 @@ dw2_expand_all_symtabs (struct objfile *objfile)
     }
 }
 
-static void
-dw2_expand_symtabs_with_fullname (struct objfile *objfile,
-                                 const char *fullname)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* We don't need to consider type units here.
-     This is only called for examining code, e.g. expand_line_sal.
-     There can be an order of magnitude (or more) more type units
-     than comp units, and we avoid them if we can.  */
-
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu))
-       continue;
-
-      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
-      if (file_data == NULL)
-       continue;
-
-      for (int j = 0; j < file_data->num_file_names; ++j)
-       {
-         const char *this_fullname = file_data->file_names[j];
-
-         if (filename_cmp (this_fullname, fullname) == 0)
-           {
-             dw2_instantiate_symtab (per_cu, per_objfile, false);
-             break;
-           }
-       }
-    }
-}
-
-static void
+static bool
 dw2_expand_symtabs_matching_symbol
   (mapped_index_base &index,
    const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   enum search_domain kind,
    gdb::function_view<bool (offset_type)> match_callback,
    dwarf2_per_objfile *per_objfile);
 
-static void
+static bool
 dw2_expand_symtabs_matching_one
   (dwarf2_per_cu_data *per_cu,
    dwarf2_per_objfile *per_objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify);
 
-static void
-dw2_map_matching_symbols
+void
+dwarf2_gdb_index::expand_matching_symbols
   (struct objfile *objfile,
    const lookup_name_info &name, domain_enum domain,
    int global,
-   gdb::function_view<symbol_found_callback_ftype> callback,
    symbol_compare_ftype *ordered_compare)
 {
   /* Used for Ada.  */
@@ -3822,7 +3602,7 @@ dw2_map_matching_symbols
          return ordered_compare (symname, match_name) == 0;
        };
 
-      dw2_expand_symtabs_matching_symbol (index, name, matcher, ALL_DOMAIN,
+      dw2_expand_symtabs_matching_symbol (index, name, matcher,
                                          [&] (offset_type namei)
       {
        struct dw2_symtab_iterator iter;
@@ -3841,18 +3621,6 @@ dw2_map_matching_symbols
       /* We have -readnow: no .gdb_index, but no partial symtabs either.  So,
         proceed assuming all symtabs have been read in.  */
     }
-
-  for (compunit_symtab *cust : objfile->compunits ())
-    {
-      const struct block *block;
-
-      if (cust == NULL)
-       continue;
-      block = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), block_kind);
-      if (!iterate_over_symbols_terminated (block, name,
-                                           domain, callback))
-       return;
-    }
 }
 
 /* Starting from a search name, return the string that finds the upper
@@ -4085,12 +3853,11 @@ mapped_index_base::build_name_components (dwarf2_per_objfile *per_objfile)
    symbol name that matches, calls MATCH_CALLBACK, passing it the
    symbol's index in the mapped_index_base symbol table.  */
 
-static void
+static bool
 dw2_expand_symtabs_matching_symbol
   (mapped_index_base &index,
    const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   enum search_domain kind,
    gdb::function_view<bool (offset_type)> match_callback,
    dwarf2_per_objfile *per_objfile)
 {
@@ -4134,7 +3901,7 @@ dw2_expand_symtabs_matching_symbol
        = lang->get_symbol_name_matcher (lookup_name_without_params);
 
       name_and_matcher key {
-         name_matcher,
+        name_matcher,
         lookup_name_without_params.language_lookup_name (lang_e)
       };
 
@@ -4171,12 +3938,16 @@ dw2_expand_symtabs_matching_symbol
 
   /* Finally call the callback, once per match.  */
   ULONGEST prev = -1;
+  bool result = true;
   for (offset_type idx : matches)
     {
       if (prev != idx)
        {
          if (!match_callback (idx))
-           break;
+           {
+             result = false;
+             break;
+           }
          prev = idx;
        }
     }
@@ -4184,6 +3955,8 @@ dw2_expand_symtabs_matching_symbol
   /* Above we use a type wider than idx's for 'prev', since 0 and
      (offset_type)-1 are both possible values.  */
   static_assert (sizeof (prev) > sizeof (offset_type), "");
+
+  return result;
 }
 
 #if GDB_SELF_TEST
@@ -4264,7 +4037,7 @@ check_match (const char *file, int line,
   auto expected_end = expected_list.end ();
 
   dw2_expand_symtabs_matching_symbol (mock_index, lookup_name,
-                                     NULL, ALL_DOMAIN,
+                                     nullptr,
                                      [&] (offset_type idx)
   {
     const char *matched_name = mock_index.symbol_name_at (idx, per_objfile);
@@ -4624,7 +4397,7 @@ run_test ()
    dw_expand_symtabs_matching_file_matcher), expand the CU and call
    EXPANSION_NOTIFY on it.  */
 
-static void
+static bool
 dw2_expand_symtabs_matching_one
   (dwarf2_per_cu_data *per_cu,
    dwarf2_per_objfile *per_objfile,
@@ -4640,31 +4413,32 @@ dw2_expand_symtabs_matching_one
       gdb_assert (symtab != nullptr);
 
       if (expansion_notify != NULL && symtab_was_null)
-       expansion_notify (symtab);
+       return expansion_notify (symtab);
     }
+  return true;
 }
 
 /* Helper for dw2_expand_matching symtabs.  Called on each symbol
    matched, to expand corresponding CUs that were marked.  IDX is the
    index of the symbol name that matched.  */
 
-static void
+static bool
 dw2_expand_marked_cus
   (dwarf2_per_objfile *per_objfile, offset_type idx,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   block_search_flags search_flags,
    search_domain kind)
 {
-  offset_type *vec, vec_len, vec_idx;
+  offset_type vec_len, vec_idx;
   bool global_seen = false;
   mapped_index &index = *per_objfile->per_bfd->index_table;
 
-  vec = (offset_type *) (index.constant_pool
-                        + MAYBE_SWAP (index.symbol_table[idx].vec));
-  vec_len = MAYBE_SWAP (vec[0]);
+  offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
+  vec_len = vec[0];
   for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
     {
-      offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
+      offset_type cu_index_and_attrs = vec[vec_idx + 1];
       /* This value is only valid for index versions >= 7.  */
       int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
       gdb_index_symbol_kind symbol_kind =
@@ -4692,6 +4466,17 @@ dw2_expand_marked_cus
       /* Only check the symbol's kind if it has one.  */
       if (attrs_valid)
        {
+         if (is_static)
+           {
+             if ((search_flags & SEARCH_STATIC_BLOCK) == 0)
+               continue;
+           }
+         else
+           {
+             if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
+               continue;
+           }
+
          switch (kind)
            {
            case VARIABLES_DOMAIN:
@@ -4725,9 +4510,12 @@ dw2_expand_marked_cus
        }
 
       dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cutu (cu_index);
-      dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                      expansion_notify);
+      if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
+                                           expansion_notify))
+       return false;
     }
+
+  return true;
 }
 
 /* If FILE_MATCHER is non-NULL, set all the
@@ -4807,20 +4595,22 @@ dw_expand_symtabs_matching_file_matcher
     }
 }
 
-static void
-dw2_expand_symtabs_matching
-  (struct objfile *objfile,
-   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info *lookup_name,
-   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
-   enum search_domain kind)
+bool
+dwarf2_gdb_index::expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
   /* index_table is NULL if OBJF_READNOW.  */
   if (!per_objfile->per_bfd->index_table)
-    return;
+    return true;
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
@@ -4830,22 +4620,28 @@ dw2_expand_symtabs_matching
        {
          QUIT;
 
-         dw2_expand_symtabs_matching_one (per_cu, per_objfile,
-                                          file_matcher, expansion_notify);
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
-      return;
+      return true;
     }
 
   mapped_index &index = *per_objfile->per_bfd->index_table;
 
-  dw2_expand_symtabs_matching_symbol (index, *lookup_name,
-                                     symbol_matcher,
-                                     kind, [&] (offset_type idx)
+  bool result
+    = dw2_expand_symtabs_matching_symbol (index, *lookup_name,
+                                         symbol_matcher,
+                                         [&] (offset_type idx)
     {
-      dw2_expand_marked_cus (per_objfile, idx, file_matcher, expansion_notify,
-                            kind);
+      if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
+                                 expansion_notify, search_flags, kind))
+       return false;
       return true;
     }, per_objfile);
+
+  return result;
 }
 
 /* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
@@ -4876,26 +4672,28 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
   return NULL;
 }
 
-static struct compunit_symtab *
-dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
-                                 struct bound_minimal_symbol msymbol,
-                                 CORE_ADDR pc,
-                                 struct obj_section *section,
-                                 int warn_if_readin)
+struct compunit_symtab *
+dwarf2_base_index_functions::find_pc_sect_compunit_symtab
+     (struct objfile *objfile,
+      struct bound_minimal_symbol msymbol,
+      CORE_ADDR pc,
+      struct obj_section *section,
+      int warn_if_readin)
 {
   struct dwarf2_per_cu_data *data;
   struct compunit_symtab *result;
 
-  if (!objfile->partial_symtabs->psymtabs_addrmap)
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_addrmap == nullptr)
     return NULL;
 
   CORE_ADDR baseaddr = objfile->text_section_offset ();
-  data = (struct dwarf2_per_cu_data *) addrmap_find
-    (objfile->partial_symtabs->psymtabs_addrmap, pc - baseaddr);
+  data = ((struct dwarf2_per_cu_data *)
+         addrmap_find (per_objfile->per_bfd->index_addrmap,
+                       pc - baseaddr));
   if (!data)
     return NULL;
 
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   if (warn_if_readin && per_objfile->symtab_set_p (data))
     warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
             paddress (objfile->arch (), pc));
@@ -4907,9 +4705,11 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
   return result;
 }
 
-static void
-dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
-                         void *data, int need_fullname)
+void
+dwarf2_base_index_functions::map_symbol_filenames
+     (struct objfile *objfile,
+      gdb::function_view<symbol_filename_ftype> fun,
+      bool need_fullname)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -4970,36 +4770,16 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
 
       if (need_fullname)
        this_real_name = gdb_realpath (filename);
-      (*fun) (filename, this_real_name.get (), data);
+      fun (filename, this_real_name.get ());
     });
 }
 
-static int
-dw2_has_symbols (struct objfile *objfile)
+bool
+dwarf2_base_index_functions::has_symbols (struct objfile *objfile)
 {
-  return 1;
+  return true;
 }
 
-const struct quick_symbol_functions dwarf2_gdb_index_functions =
-{
-  dw2_has_symbols,
-  dw2_find_last_source_symtab,
-  dw2_forget_cached_source_info,
-  dw2_map_symtabs_matching_filename,
-  dw2_lookup_symbol,
-  NULL,
-  dw2_print_stats,
-  dw2_dump,
-  dw2_expand_symtabs_for_function,
-  dw2_expand_all_symtabs,
-  dw2_expand_symtabs_with_fullname,
-  dw2_map_matching_symbols,
-  dw2_expand_symtabs_matching,
-  dw2_find_pc_sect_compunit_symtab,
-  NULL,
-  dw2_map_symbol_filenames
-};
-
 /* DWARF-5 debug_names reader.  */
 
 /* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
@@ -5200,21 +4980,24 @@ create_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
 {
   if (!map.augmentation_is_gdb)
     {
-    for (uint32_t i = 0; i < map.cu_count; ++i)
-      {
-       sect_offset sect_off
-         = (sect_offset) (extract_unsigned_integer
-                          (map.cu_table_reordered + i * map.offset_size,
-                           map.offset_size,
-                           map.dwarf5_byte_order));
-       /* We don't know the length of the CU, because the CU list in a
-          .debug_names index can be incomplete, so we can't use the start of
-          the next CU as end of this CU.  We create the CUs here with length 0,
-          and in cutu_reader::cutu_reader we'll fill in the actual length.  */
-       dwarf2_per_cu_data *per_cu
-         = create_cu_from_index_list (per_bfd, &section, is_dwz, sect_off, 0);
-       per_bfd->all_comp_units.push_back (per_cu);
-      }
+      for (uint32_t i = 0; i < map.cu_count; ++i)
+       {
+         sect_offset sect_off
+           = (sect_offset) (extract_unsigned_integer
+                            (map.cu_table_reordered + i * map.offset_size,
+                             map.offset_size,
+                             map.dwarf5_byte_order));
+         /* We don't know the length of the CU, because the CU list in a
+            .debug_names index can be incomplete, so we can't use the start
+            of the next CU as end of this CU.  We create the CUs here with
+            length 0, and in cutu_reader::cutu_reader we'll fill in the
+            actual length.  */
+         dwarf2_per_cu_data *per_cu
+           = create_cu_from_index_list (per_bfd, &section, is_dwz,
+                                        sect_off, 0);
+         per_bfd->all_comp_units.push_back (per_cu);
+       }
+      return;
     }
 
   sect_offset sect_off_prev;
@@ -5277,7 +5060,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   if (!read_debug_names_from_section (objfile, objfile_name (objfile),
-                                     &per_objfile->per_bfd->debug_names, *map))
+                                     &per_bfd->debug_names, *map))
     return false;
 
   /* Don't use the index if it's empty.  */
@@ -5319,12 +5102,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
   per_bfd->debug_names_table = std::move (map);
   per_bfd->using_index = 1;
   per_bfd->quick_file_names_table =
-    create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ());
-
-  /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
-     objfiles using the same BFD.  */
-  gdb_assert (per_bfd->partial_symtabs == nullptr);
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
+    create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
   return true;
 }
@@ -5336,7 +5114,7 @@ class dw2_debug_names_iterator
 {
 public:
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           gdb::optional<block_enum> block_index,
+                           block_search_flags block_index,
                            domain_enum domain,
                            const char *name, dwarf2_per_objfile *per_objfile)
     : m_map (map), m_block_index (block_index), m_domain (domain),
@@ -5345,15 +5123,18 @@ public:
   {}
 
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           search_domain search, uint32_t namei, dwarf2_per_objfile *per_objfile)
+                           search_domain search, uint32_t namei,
+                           dwarf2_per_objfile *per_objfile,
+                           domain_enum domain = UNDEF_DOMAIN)
     : m_map (map),
+      m_domain (domain),
       m_search (search),
       m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
       m_per_objfile (per_objfile)
   {}
 
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           block_enum block_index, domain_enum domain,
+                           block_search_flags block_index, domain_enum domain,
                            uint32_t namei, dwarf2_per_objfile *per_objfile)
     : m_map (map), m_block_index (block_index), m_domain (domain),
       m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
@@ -5374,9 +5155,9 @@ private:
   /* The internalized form of .debug_names.  */
   const mapped_debug_names &m_map;
 
-  /* If set, only look for symbols that match that block.  Valid values are
-     GLOBAL_BLOCK and STATIC_BLOCK.  */
-  const gdb::optional<block_enum> m_block_index;
+  /* Restrict the search to these blocks.  */
+  block_search_flags m_block_index = (SEARCH_GLOBAL_BLOCK
+                                     | SEARCH_STATIC_BLOCK);
 
   /* The kind of symbol we're looking for.  */
   const domain_enum m_domain = UNDEF_DOMAIN;
@@ -5579,7 +5360,7 @@ dw2_debug_names_iterator::next ()
        {
        case DW_IDX_compile_unit:
          /* Don't crash on bad data.  */
-         if (ull >= m_per_objfile->per_bfd->all_comp_units.size ())
+         if (ull >= per_bfd->all_comp_units.size ())
            {
              complaint (_(".debug_names entry has bad CU index %s"
                           " [in module %s]"),
@@ -5625,13 +5406,18 @@ dw2_debug_names_iterator::next ()
     goto again;
 
   /* Check static vs global.  */
-  if (symbol_linkage_ != symbol_linkage::unknown && m_block_index.has_value ())
+  if (symbol_linkage_ != symbol_linkage::unknown)
     {
-       const bool want_static = *m_block_index == STATIC_BLOCK;
-       const bool symbol_is_static =
-         symbol_linkage_ == symbol_linkage::static_;
-       if (want_static != symbol_is_static)
-         goto again;
+      if (symbol_linkage_ == symbol_linkage::static_)
+       {
+         if ((m_block_index & SEARCH_STATIC_BLOCK) == 0)
+           goto again;
+       }
+      else
+       {
+         if ((m_block_index & SEARCH_GLOBAL_BLOCK) == 0)
+           goto again;
+       }
     }
 
   /* Match dw2_symtab_iter_next, symbol_kind
@@ -5731,59 +5517,12 @@ dw2_debug_names_iterator::next ()
   return per_cu;
 }
 
-static struct compunit_symtab *
-dw2_debug_names_lookup_symbol (struct objfile *objfile, block_enum block_index,
-                              const char *name, domain_enum domain)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  const auto &mapp = per_objfile->per_bfd->debug_names_table;
-  if (!mapp)
-    {
-      /* index is NULL if OBJF_READNOW.  */
-      return NULL;
-    }
-  const auto &map = *mapp;
-
-  dw2_debug_names_iterator iter (map, block_index, domain, name, per_objfile);
-
-  struct compunit_symtab *stab_best = NULL;
-  struct dwarf2_per_cu_data *per_cu;
-  while ((per_cu = iter.next ()) != NULL)
-    {
-      struct symbol *sym, *with_opaque = NULL;
-      compunit_symtab *stab
-       = dw2_instantiate_symtab (per_cu, per_objfile, false);
-      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
-      const struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
-
-      sym = block_find_symbol (block, name, domain,
-                              block_find_non_opaque_type_preferred,
-                              &with_opaque);
-
-      /* Some caution must be observed with overloaded functions and
-        methods, since the index will not contain any overload
-        information (but NAME might contain it).  */
-
-      if (sym != NULL
-         && strcmp_iw (sym->search_name (), name) == 0)
-       return stab;
-      if (with_opaque != NULL
-         && strcmp_iw (with_opaque->search_name (), name) == 0)
-       stab_best = stab;
-
-      /* Keep looking through other CUs.  */
-    }
-
-  return stab_best;
-}
-
 /* This dumps minimal information about .debug_names.  It is called
    via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
    uses this to verify that .debug_names has been loaded.  */
 
-static void
-dw2_debug_names_dump (struct objfile *objfile)
+void
+dwarf2_debug_names_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -5796,32 +5535,11 @@ dw2_debug_names_dump (struct objfile *objfile)
   printf_filtered ("\n");
 }
 
-static void
-dw2_debug_names_expand_symtabs_for_function (struct objfile *objfile,
-                                            const char *func_name)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* per_objfile->per_bfd->debug_names_table is NULL if OBJF_READNOW.  */
-  if (per_objfile->per_bfd->debug_names_table)
-    {
-      const mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
-
-      dw2_debug_names_iterator iter (map, {}, VAR_DOMAIN, func_name,
-                                    per_objfile);
-
-      struct dwarf2_per_cu_data *per_cu;
-      while ((per_cu = iter.next ()) != NULL)
-       dw2_instantiate_symtab (per_cu, per_objfile, false);
-    }
-}
-
-static void
-dw2_debug_names_map_matching_symbols
+void
+dwarf2_debug_names_index::expand_matching_symbols
   (struct objfile *objfile,
    const lookup_name_info &name, domain_enum domain,
    int global,
-   gdb::function_view<symbol_found_callback_ftype> callback,
    symbol_compare_ftype *ordered_compare)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
@@ -5831,7 +5549,8 @@ dw2_debug_names_map_matching_symbols
     return;
 
   mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
-  const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
+  const block_search_flags block_flags
+    = global ? SEARCH_GLOBAL_BLOCK : SEARCH_STATIC_BLOCK;
 
   const char *match_name = name.ada ().lookup_name ().c_str ();
   auto matcher = [&] (const char *symname)
@@ -5841,12 +5560,12 @@ dw2_debug_names_map_matching_symbols
       return ordered_compare (symname, match_name) == 0;
     };
 
-  dw2_expand_symtabs_matching_symbol (map, name, matcher, ALL_DOMAIN,
+  dw2_expand_symtabs_matching_symbol (map, name, matcher,
                                      [&] (offset_type namei)
     {
       /* The name was matched, now expand corresponding CUs that were
         marked.  */
-      dw2_debug_names_iterator iter (map, block_kind, domain, namei,
+      dw2_debug_names_iterator iter (map, block_flags, domain, namei,
                                     per_objfile);
 
       struct dwarf2_per_cu_data *per_cu;
@@ -5855,39 +5574,24 @@ dw2_debug_names_map_matching_symbols
                                         nullptr);
       return true;
     }, per_objfile);
-
-  /* It's a shame we couldn't do this inside the
-     dw2_expand_symtabs_matching_symbol callback, but that skips CUs
-     that have already been expanded.  Instead, this loop matches what
-     the psymtab code does.  */
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      compunit_symtab *symtab = per_objfile->get_symtab (per_cu);
-      if (symtab != nullptr)
-       {
-         const struct block *block
-           = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (symtab), block_kind);
-         if (!iterate_over_symbols_terminated (block, name,
-                                               domain, callback))
-           break;
-       }
-    }
 }
 
-static void
-dw2_debug_names_expand_symtabs_matching
+bool
+dwarf2_debug_names_index::expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    const lookup_name_info *lookup_name,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   block_search_flags search_flags,
+   domain_enum domain,
    enum search_domain kind)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
   /* debug_names_table is NULL if OBJF_READNOW.  */
   if (!per_objfile->per_bfd->debug_names_table)
-    return;
+    return true;
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
@@ -5897,49 +5601,36 @@ dw2_debug_names_expand_symtabs_matching
        {
          QUIT;
 
-         dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                          expansion_notify);
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
-      return;
+      return true;
     }
 
   mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
 
-  dw2_expand_symtabs_matching_symbol (map, *lookup_name,
-                                     symbol_matcher,
-                                     kind, [&] (offset_type namei)
+  bool result
+    = dw2_expand_symtabs_matching_symbol (map, *lookup_name,
+                                         symbol_matcher,
+                                         [&] (offset_type namei)
     {
       /* The name was matched, now expand corresponding CUs that were
         marked.  */
-      dw2_debug_names_iterator iter (map, kind, namei, per_objfile);
+      dw2_debug_names_iterator iter (map, kind, namei, per_objfile, domain);
 
       struct dwarf2_per_cu_data *per_cu;
       while ((per_cu = iter.next ()) != NULL)
-       dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                        expansion_notify);
+       if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                             file_matcher,
+                                             expansion_notify))
+         return false;
       return true;
     }, per_objfile);
-}
 
-const struct quick_symbol_functions dwarf2_debug_names_functions =
-{
-  dw2_has_symbols,
-  dw2_find_last_source_symtab,
-  dw2_forget_cached_source_info,
-  dw2_map_symtabs_matching_filename,
-  dw2_debug_names_lookup_symbol,
-  NULL,
-  dw2_print_stats,
-  dw2_debug_names_dump,
-  dw2_debug_names_expand_symtabs_for_function,
-  dw2_expand_all_symtabs,
-  dw2_expand_symtabs_with_fullname,
-  dw2_debug_names_map_matching_symbols,
-  dw2_debug_names_expand_symtabs_matching,
-  dw2_find_pc_sect_compunit_symtab,
-  NULL,
-  dw2_map_symbol_filenames
-};
+  return result;
+}
 
 /* Get the content of the .gdb_index section of OBJ.  SECTION_OWNER should point
    to either a dwarf2_per_bfd or dwz_file object.  */
@@ -5995,27 +5686,32 @@ get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz)
   return global_index_cache.lookup_gdb_index (build_id, &dwz->index_cache_res);
 }
 
-/* See symfile.h.  */
+/* See dwarf2/public.h.  */
 
-bool
-dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
+void
+dwarf2_initialize_objfile (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
+  dwarf_read_debug_printf ("called");
+
   /* If we're about to read full symbols, don't bother with the
      indices.  In this case we also don't care if some other debug
      format is making psymtabs, because they are all about to be
      expanded anyway.  */
   if ((objfile->flags & OBJF_READNOW))
     {
+      dwarf_read_debug_printf ("readnow requested");
+
       /* When using READNOW, the using_index flag (set below) indicates that
         PER_BFD was already initialized, when we loaded some other objfile.  */
       if (per_bfd->using_index)
        {
-         *index_kind = dw_index_kind::GDB_INDEX;
+         dwarf_read_debug_printf ("using_index already set");
          per_objfile->resize_symtabs ();
-         return true;
+         objfile->qf.push_front (make_dwarf_gdb_index ());
+         return;
        }
 
       per_bfd->using_index = 1;
@@ -6034,31 +5730,31 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
                                            struct dwarf2_per_cu_quick_data);
        }
 
-      /* Return 1 so that gdb sees the "quick" functions.  However,
-        these functions will be no-ops because we will have expanded
-        all symtabs.  */
-      *index_kind = dw_index_kind::GDB_INDEX;
-      return true;
+      /* Arrange for gdb to see the "quick" functions.  However, these
+        functions will be no-ops because we will have expanded all
+        symtabs.  */
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* Was a debug names index already read when we processed an objfile sharing
      PER_BFD?  */
   if (per_bfd->debug_names_table != nullptr)
     {
-      *index_kind = dw_index_kind::DEBUG_NAMES;
-      per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
+      dwarf_read_debug_printf ("re-using shared debug names table");
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_debug_names ());
+      return;
     }
 
   /* Was a GDB index already read when we processed an objfile sharing
      PER_BFD?  */
   if (per_bfd->index_table != nullptr)
     {
-      *index_kind = dw_index_kind::GDB_INDEX;
-      per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
+      dwarf_read_debug_printf ("re-using shared index table");
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* There might already be partial symtabs built for this BFD.  This happens
@@ -6067,22 +5763,28 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
      be completed in dwarf2_build_psymtabs, in the standard partial symtabs
      code path.  */
   if (per_bfd->partial_symtabs != nullptr)
-    return false;
+    {
+      dwarf_read_debug_printf ("re-using shared partial symtabs");
+      objfile->qf.push_front (make_lazy_dwarf_reader ());
+      return;
+    }
 
   if (dwarf2_read_debug_names (per_objfile))
     {
-      *index_kind = dw_index_kind::DEBUG_NAMES;
+      dwarf_read_debug_printf ("found debug names");
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_debug_names ());
+      return;
     }
 
   if (dwarf2_read_gdb_index (per_objfile,
                             get_gdb_index_contents_from_section<struct dwarf2_per_bfd>,
                             get_gdb_index_contents_from_section<dwz_file>))
     {
-      *index_kind = dw_index_kind::GDB_INDEX;
+      dwarf_read_debug_printf ("found gdb index from file");
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* ... otherwise, try to find the index in the index cache.  */
@@ -6090,14 +5792,15 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
                             get_gdb_index_contents_from_cache,
                             get_gdb_index_contents_from_cache_dwz))
     {
+      dwarf_read_debug_printf ("found gdb index from cache");
       global_index_cache.hit ();
-      *index_kind = dw_index_kind::GDB_INDEX;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   global_index_cache.miss ();
-  return false;
+  objfile->qf.push_front (make_lazy_dwarf_reader ());
 }
 
 \f
@@ -6105,7 +5808,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
 /* Build a partial symbol table.  */
 
 void
-dwarf2_build_psymtabs (struct objfile *objfile)
+dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
@@ -6114,17 +5817,37 @@ dwarf2_build_psymtabs (struct objfile *objfile)
     {
       /* Partial symbols were already read, so now we can simply
         attach them.  */
-      objfile->partial_symtabs = per_bfd->partial_symtabs;
+      if (psf == nullptr)
+       {
+         psf = new psymbol_functions (per_bfd->partial_symtabs);
+         objfile->qf.emplace_front (psf);
+       }
+      else
+       psf->set_partial_symtabs (per_bfd->partial_symtabs);
       per_objfile->resize_symtabs ();
       return;
     }
 
+  if (psf == nullptr)
+    {
+      psf = new psymbol_functions;
+      objfile->qf.emplace_front (psf);
+    }
+  const std::shared_ptr<psymtab_storage> &partial_symtabs
+    = psf->get_partial_symtabs ();
+
+  /* Set the local reference to partial symtabs, so that we don't try
+     to read them again if reading another objfile with the same BFD.
+     If we can't in fact share, this won't make a difference anyway as
+     the dwarf2_per_bfd object won't be shared.  */
+  per_bfd->partial_symtabs = partial_symtabs;
+
   try
     {
       /* This isn't really ideal: all the data we allocate on the
         objfile's obstack is still uselessly kept around.  However,
         freeing it seems unsafe.  */
-      psymtab_discarder psymtabs (objfile);
+      psymtab_discarder psymtabs (partial_symtabs.get ());
       dwarf2_build_psymtabs_hard (per_objfile);
       psymtabs.keep ();
 
@@ -6137,12 +5860,6 @@ dwarf2_build_psymtabs (struct objfile *objfile)
     {
       exception_print (gdb_stderr, except);
     }
-
-  /* Finish by setting the local reference to partial symtabs, so that
-     we don't try to read them again if reading another objfile with the same
-     BFD.  If we can't in fact share, this won't make a difference anyway as
-     the dwarf2_per_bfd object won't be shared.  */
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -6179,7 +5896,7 @@ get_abbrev_section_for_cu (struct dwarf2_per_cu_data *this_cu)
   dwarf2_per_bfd *per_bfd = this_cu->per_bfd;
 
   if (this_cu->is_dwz)
-    abbrev = &dwarf2_get_dwz_file (per_bfd)->abbrev;
+    abbrev = &dwarf2_get_dwz_file (per_bfd, true)->abbrev;
   else
     abbrev = &per_bfd->abbrev;
 
@@ -6218,8 +5935,10 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
 /* A partial symtab that is used only for include files.  */
 struct dwarf2_include_psymtab : public partial_symtab
 {
-  dwarf2_include_psymtab (const char *filename, struct objfile *objfile)
-    : partial_symtab (filename, objfile)
+  dwarf2_include_psymtab (const char *filename,
+                         psymtab_storage *partial_symtabs,
+                         objfile_per_bfd_storage *objfile_per_bfd)
+    : partial_symtab (filename, partial_symtabs, objfile_per_bfd)
   {
   }
 
@@ -6271,15 +5990,19 @@ private:
    partial symtab as being an include of PST.  */
 
 static void
-dwarf2_create_include_psymtab (const char *name, dwarf2_psymtab *pst,
-                               struct objfile *objfile)
+dwarf2_create_include_psymtab (dwarf2_per_bfd *per_bfd,
+                              const char *name,
+                              dwarf2_psymtab *pst,
+                              psymtab_storage *partial_symtabs,
+                              objfile_per_bfd_storage *objfile_per_bfd)
 {
-  dwarf2_include_psymtab *subpst = new dwarf2_include_psymtab (name, objfile);
+  dwarf2_include_psymtab *subpst
+    = new dwarf2_include_psymtab (name, partial_symtabs, objfile_per_bfd);
 
   if (!IS_ABSOLUTE_PATH (subpst->filename))
     subpst->dirname = pst->dirname;
 
-  subpst->dependencies = objfile->partial_symtabs->allocate_dependencies (1);
+  subpst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (1);
   subpst->dependencies[0] = pst;
   subpst->number_of_dependencies = 1;
 }
@@ -6373,10 +6096,9 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
                    ? &dwo_file->sections.abbrev
                    : &per_objfile->per_bfd->abbrev);
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
-                       section->get_name (),
-                       abbrev_section->get_file_name ());
+  dwarf_read_debug_printf ("Reading %s for %s",
+                          section->get_name (),
+                          abbrev_section->get_file_name ());
 
   section->read (objfile);
   info_ptr = section->buffer;
@@ -6488,10 +6210,9 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
        }
       *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
 
-      if (dwarf_read_debug > 1)
-       fprintf_unfiltered (gdb_stdlog, "  offset %s, signature %s\n",
-                           sect_offset_str (sect_off),
-                           hex_string (header.signature));
+      dwarf_read_debug_printf_v ("  offset %s, signature %s",
+                                sect_offset_str (sect_off),
+                                hex_string (header.signature));
 
       info_ptr += length;
     }
@@ -6861,10 +6582,17 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
 
       cu->addr_base = stub_comp_unit_die->addr_base ();
 
-      /* There should be a DW_AT_rnglists_base (DW_AT_GNU_ranges_base) attribute
-        here (if needed). We need the value before we can process
-        DW_AT_ranges.  */
-      cu->ranges_base = stub_comp_unit_die->ranges_base ();
+      /* There should be a DW_AT_GNU_ranges_base attribute here (if needed).
+         We need the value before we can process DW_AT_ranges values from the
+         DWO.  */
+      cu->gnu_ranges_base = stub_comp_unit_die->gnu_ranges_base ();
+
+      /* For DWARF5: record the DW_AT_rnglists_base value from the skeleton.  If
+         there are attributes of form DW_FORM_rnglistx in the skeleton, they'll
+         need the rnglists base.  Attributes of form DW_FORM_rnglistx in the
+         split unit don't use it, as the DWO has its own .debug_rnglists.dwo
+         section.  */
+      cu->rnglists_base = stub_comp_unit_die->rnglists_base ();
     }
   else if (stub_comp_dir != NULL)
     {
@@ -6923,9 +6651,9 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
       dwo_unit->length = cu->header.get_length ();
     }
 
+  dwo_abbrev_section->read (objfile);
   *result_dwo_abbrev_table
-    = abbrev_table::read (objfile, dwo_abbrev_section,
-                         cu->header.abbrev_sect_off);
+    = abbrev_table::read (dwo_abbrev_section, cu->header.abbrev_sect_off);
   init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file,
                      result_dwo_abbrev_table->get ());
 
@@ -7053,7 +6781,7 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
   else
     {
       /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
-         in per_objfile yet.  */
+        in per_objfile yet.  */
       gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
@@ -7144,7 +6872,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   else
     {
       /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
-         in per_objfile yet.  */
+        in per_objfile yet.  */
       gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
@@ -7213,9 +6941,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
   else
     {
+      abbrev_section->read (objfile);
       m_abbrev_table_holder
-       = abbrev_table::read (objfile, abbrev_section,
-                             cu->header.abbrev_sect_off);
+       = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
       abbrev_table = m_abbrev_table_holder.get ();
     }
 
@@ -7284,7 +7012,7 @@ cutu_reader::keep ()
   if (m_new_cu != NULL)
     {
       /* Save this dwarf2_cu in the per_objfile.  The per_objfile owns it
-         now.  */
+        now.  */
       dwarf2_per_objfile *per_objfile = m_new_cu->per_objfile;
       per_objfile->set_cu (m_this_cu, m_new_cu.release ());
     }
@@ -7357,9 +7085,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
       return;
     }
 
+  abbrev_section->read (objfile);
   m_abbrev_table_holder
-    = abbrev_table::read (objfile, abbrev_section,
-                         m_new_cu->header.abbrev_sect_off);
+    = abbrev_table::read (abbrev_section, m_new_cu->header.abbrev_sect_off);
 
   init_cu_die_reader (this, m_new_cu.get (), section, dwo_file,
                      m_abbrev_table_holder.get ());
@@ -7421,7 +7149,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
   struct dwarf2_per_cu_data *per_cu;
   struct type_unit_group *tu_group;
 
-  tu_group = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, type_unit_group);
+  tu_group = OBSTACK_ZALLOC (&per_bfd->obstack, type_unit_group);
   per_cu = &tu_group->per_cu;
   per_cu->per_bfd = per_bfd;
 
@@ -7521,10 +7249,9 @@ create_partial_symtab (dwarf2_per_cu_data *per_cu,
                       dwarf2_per_objfile *per_objfile,
                       const char *name)
 {
-  struct objfile *objfile = per_objfile->objfile;
-  dwarf2_psymtab *pst;
-
-  pst = new dwarf2_psymtab (name, objfile, per_cu);
+  dwarf2_psymtab *pst
+    = new dwarf2_psymtab (name, per_objfile->per_bfd->partial_symtabs.get (),
+                         per_objfile->objfile->per_bfd, per_cu);
 
   pst->psymtabs_addrmap_supported = true;
 
@@ -7544,6 +7271,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 {
   struct dwarf2_cu *cu = reader->cu;
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct objfile *objfile = per_objfile->objfile;
   struct gdbarch *gdbarch = objfile->arch ();
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
@@ -7594,7 +7322,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
           - baseaddr - 1);
       /* Store the contiguous range if it is not empty; it can be
         empty for CUs with no code.  */
-      addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+      addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                         low, high, pst);
     }
 
@@ -7645,7 +7373,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
         post-pass.  */
       pst->number_of_dependencies = len;
       pst->dependencies
-       = objfile->partial_symtabs->allocate_dependencies (len);
+       = per_bfd->partial_symtabs->allocate_dependencies (len);
       for (i = 0; i < len; ++i)
        {
          pst->dependencies[i]
@@ -7659,16 +7387,14 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
      and build a psymtab for each of them.  */
   dwarf2_build_include_psymtabs (cu, comp_unit_die, pst);
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "Psymtab for %s unit @%s: %s - %s"
-                       ", %d global, %d static syms\n",
-                       per_cu->is_debug_types ? "type" : "comp",
-                       sect_offset_str (per_cu->sect_off),
-                       paddress (gdbarch, pst->text_low (objfile)),
-                       paddress (gdbarch, pst->text_high (objfile)),
-                       (int) pst->global_psymbols.size (),
-                       (int) pst->static_psymbols.size ());
+  dwarf_read_debug_printf ("Psymtab for %s unit @%s: %s - %s"
+                          ", %d global, %d static syms",
+                          per_cu->is_debug_types ? "type" : "comp",
+                          sect_offset_str (per_cu->sect_off),
+                          paddress (gdbarch, pst->text_low (objfile)),
+                          paddress (gdbarch, pst->text_high (objfile)),
+                          (int) pst->global_psymbols.size (),
+                          (int) pst->static_psymbols.size ());
 }
 
 /* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
@@ -7697,8 +7423,14 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
     case DW_TAG_partial_unit:
       this_cu->unit_type = DW_UT_partial;
       break;
+    case DW_TAG_type_unit:
+      this_cu->unit_type = DW_UT_type;
+      break;
     default:
-      abort ();
+      error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"),
+            dwarf_tag_name (reader.comp_unit_die->tag),
+            sect_offset_str (reader.cu->per_cu->sect_off),
+            objfile_name (per_objfile->objfile));
     }
 
   if (reader.dummy_p)
@@ -7834,8 +7566,7 @@ build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
          [IWBN if DWO skeletons had DW_AT_stmt_list]
        call FUNC  */
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
+  dwarf_read_debug_printf ("Building type unit groups ...");
 
   /* Sort in a separate table to maintain the order of all_type_units
      for .gdb_index: TU indices directly index all_type_units.  */
@@ -7859,9 +7590,9 @@ build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
          || tu.abbrev_offset != abbrev_offset)
        {
          abbrev_offset = tu.abbrev_offset;
+         per_objfile->per_bfd->abbrev.read (per_objfile->objfile);
          abbrev_table =
-           abbrev_table::read (per_objfile->objfile,
-                               &per_objfile->per_bfd->abbrev, abbrev_offset);
+           abbrev_table::read (&per_objfile->per_bfd->abbrev, abbrev_offset);
          ++tu_stats->nr_uniq_abbrev_tables;
        }
 
@@ -7880,19 +7611,19 @@ print_tu_stats (dwarf2_per_objfile *per_objfile)
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
 
-  fprintf_unfiltered (gdb_stdlog, "Type unit statistics:\n");
-  fprintf_unfiltered (gdb_stdlog, "  %zu TUs\n",
-                     per_objfile->per_bfd->all_type_units.size ());
-  fprintf_unfiltered (gdb_stdlog, "  %d uniq abbrev tables\n",
-                     tu_stats->nr_uniq_abbrev_tables);
-  fprintf_unfiltered (gdb_stdlog, "  %d symtabs from stmt_list entries\n",
-                     tu_stats->nr_symtabs);
-  fprintf_unfiltered (gdb_stdlog, "  %d symtab sharers\n",
-                     tu_stats->nr_symtab_sharers);
-  fprintf_unfiltered (gdb_stdlog, "  %d type units without a stmt_list\n",
-                     tu_stats->nr_stmt_less_type_units);
-  fprintf_unfiltered (gdb_stdlog, "  %d all_type_units reallocs\n",
-                     tu_stats->nr_all_type_units_reallocs);
+  dwarf_read_debug_printf ("Type unit statistics:");
+  dwarf_read_debug_printf ("  %zu TUs",
+                          per_objfile->per_bfd->all_type_units.size ());
+  dwarf_read_debug_printf ("  %d uniq abbrev tables",
+                          tu_stats->nr_uniq_abbrev_tables);
+  dwarf_read_debug_printf ("  %d symtabs from stmt_list entries",
+                          tu_stats->nr_symtabs);
+  dwarf_read_debug_printf ("  %d symtab sharers",
+                          tu_stats->nr_symtab_sharers);
+  dwarf_read_debug_printf ("  %d type units without a stmt_list",
+                          tu_stats->nr_stmt_less_type_units);
+  dwarf_read_debug_printf ("  %d all_type_units reallocs",
+                          tu_stats->nr_all_type_units_reallocs);
 }
 
 /* Traversal function for build_type_psymtabs.  */
@@ -7901,7 +7632,7 @@ static int
 build_type_psymtab_dependencies (void **slot, void *info)
 {
   dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
-  struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
   struct dwarf2_per_cu_data *per_cu = &tu_group->per_cu;
   dwarf2_psymtab *pst = per_cu->v.psymtab;
@@ -7912,7 +7643,7 @@ build_type_psymtab_dependencies (void **slot, void *info)
   gdb_assert (per_cu->type_unit_group_p ());
 
   pst->number_of_dependencies = len;
-  pst->dependencies = objfile->partial_symtabs->allocate_dependencies (len);
+  pst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (len);
   for (i = 0; i < len; ++i)
     {
       struct signatured_type *iter = tu_group->tus->at (i);
@@ -8036,18 +7767,15 @@ static void
 dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
 {
   struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Building psymtabs of objfile %s ...\n",
-                         objfile_name (objfile));
-    }
+  dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
+                          objfile_name (objfile));
 
   scoped_restore restore_reading_psyms
-    = make_scoped_restore (&per_objfile->per_bfd->reading_partial_symbols,
-                          true);
+    = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
 
-  per_objfile->per_bfd->info.read (objfile);
+  per_bfd->info.read (objfile);
 
   /* Any cached compilation units will be linked by the per-objfile
      read_in_chain.  Make sure to free them when we're done.  */
@@ -8062,10 +7790,10 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   auto_obstack temp_obstack;
 
   scoped_restore save_psymtabs_addrmap
-    = make_scoped_restore (&objfile->partial_symtabs->psymtabs_addrmap,
+    = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
                           addrmap_create_mutable (&temp_obstack));
 
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (dwarf2_per_cu_data *per_cu : per_bfd->all_comp_units)
     {
       if (per_cu->v.psymtab != NULL)
        /* In case a forward DW_TAG_imported_unit has read the CU already.  */
@@ -8078,26 +7806,25 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   process_skeletonless_type_units (per_objfile);
 
   /* Now that all TUs have been processed we can fill in the dependencies.  */
-  if (per_objfile->per_bfd->type_unit_groups != NULL)
+  if (per_bfd->type_unit_groups != NULL)
     {
-      htab_traverse_noresize (per_objfile->per_bfd->type_unit_groups.get (),
+      htab_traverse_noresize (per_bfd->type_unit_groups.get (),
                              build_type_psymtab_dependencies, per_objfile);
     }
 
-  if (dwarf_read_debug)
+  if (dwarf_read_debug > 0)
     print_tu_stats (per_objfile);
 
   set_partial_user (per_objfile);
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (objfile->partial_symtabs->psymtabs_addrmap,
-                           objfile->partial_symtabs->obstack ());
+  per_bfd->partial_symtabs->psymtabs_addrmap
+    = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
+                           per_bfd->partial_symtabs->obstack ());
   /* At this point we want to keep the address map.  */
   save_psymtabs_addrmap.release ();
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
-                       objfile_name (objfile));
+  dwarf_read_debug_printf ("Done building psymtabs of %s",
+                          objfile_name (objfile));
 }
 
 /* Load the partial DIEs for a secondary CU into memory.
@@ -8134,10 +7861,9 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
   const gdb_byte *info_ptr;
   struct objfile *objfile = per_objfile->objfile;
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s for %s\n",
-                       section->get_name (),
-                       section->get_file_name ());
+  dwarf_read_debug_printf ("Reading %s for %s",
+                          section->get_name (),
+                          section->get_file_name ());
 
   section->read (objfile);
 
@@ -8259,9 +7985,9 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                add_partial_enumeration (pdi, cu);
              break;
            case DW_TAG_base_type:
-            case DW_TAG_subrange_type:
+           case DW_TAG_subrange_type:
              /* File scope base type definitions are added to the partial
-                symbol table.  */
+                symbol table.  */
              add_partial_symbol (pdi, cu);
              break;
            case DW_TAG_namespace:
@@ -8476,7 +8202,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
   partial_symbol psymbol;
   memset (&psymbol, 0, sizeof (psymbol));
   psymbol.ginfo.set_language (cu->language, &objfile->objfile_obstack);
-  psymbol.ginfo.section = -1;
+  psymbol.ginfo.set_section_index (-1);
 
   /* The code below indicates that the psymbol should be installed by
      setting this.  */
@@ -8494,10 +8220,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              && pdi->die_parent != NULL
              && pdi->die_parent->tag == DW_TAG_subprogram))
        {
-          /* Normally, only "external" DIEs are part of the global scope.
-             But in Ada and Fortran, we want to be able to access nested
-             procedures globally.  So all Ada and Fortran subprograms are
-             stored in the global scope.  */
+         /* Normally, only "external" DIEs are part of the global scope.
+            But in Ada and Fortran, we want to be able to access nested
+            procedures globally.  So all Ada and Fortran subprograms are
+            stored in the global scope.  */
          where = psymbol_placement::GLOBAL;
        }
       else
@@ -8505,7 +8231,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
       psymbol.domain = VAR_DOMAIN;
       psymbol.aclass = LOC_BLOCK;
-      psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+      psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
       psymbol.ginfo.value.address = addr;
 
       if (pdi->main_subprogram && actual_name != NULL)
@@ -8550,7 +8276,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
            {
              psymbol.domain = VAR_DOMAIN;
              psymbol.aclass = LOC_STATIC;
-             psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+             psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
              psymbol.ginfo.value.address = addr;
              where = psymbol_placement::GLOBAL;
            }
@@ -8566,12 +8292,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
          psymbol.domain = VAR_DOMAIN;
          psymbol.aclass = LOC_STATIC;
-         psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+         psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
          if (has_loc)
            psymbol.ginfo.value.address = addr;
          where = psymbol_placement::STATIC;
        }
       break;
+    case DW_TAG_array_type:
     case DW_TAG_typedef:
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
@@ -8587,8 +8314,8 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       break;
     case DW_TAG_module:
       /* With Fortran 77 there might be a "BLOCK DATA" module
-         available without any name.  If so, we skip the module as it
-         doesn't bring any value.  */
+        available without any name.  If so, we skip the module as it
+        doesn't bring any value.  */
       if (actual_name != nullptr)
        {
          psymbol.domain = MODULE_DOMAIN;
@@ -8602,10 +8329,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
     case DW_TAG_union_type:
     case DW_TAG_enumeration_type:
       /* Skip external references.  The DWARF standard says in the section
-         about "Structure, Union, and Class Type Entries": "An incomplete
-         structure, union or class type is represented by a structure,
-         union or class entry that does not have a byte size attribute
-         and that has a DW_AT_declaration attribute."  */
+        about "Structure, Union, and Class Type Entries": "An incomplete
+        structure, union or class type is represented by a structure,
+        union or class entry that does not have a byte size attribute
+        and that has a DW_AT_declaration attribute."  */
       if (!pdi->has_byte_size && pdi->is_declaration)
        return;
 
@@ -8640,7 +8367,9 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
                                            &objfile->objfile_obstack);
          psymbol.ginfo.set_linkage_name (pdi->linkage_name);
        }
-      cu->per_cu->v.psymtab->add_psymbol (psymbol, *where, objfile);
+      cu->per_cu->v.psymtab->add_psymbol
+       (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (),
+        objfile);
     }
 }
 
@@ -8699,14 +8428,15 @@ add_partial_subprogram (struct partial_die_info *pdi,
   if (pdi->tag == DW_TAG_subprogram || pdi->tag == DW_TAG_inlined_subroutine)
     {
       if (pdi->has_pc_info)
-        {
-          if (pdi->lowpc < *lowpc)
-            *lowpc = pdi->lowpc;
-          if (pdi->highpc > *highpc)
-            *highpc = pdi->highpc;
+       {
+         if (pdi->lowpc < *lowpc)
+           *lowpc = pdi->lowpc;
+         if (pdi->highpc > *highpc)
+           *highpc = pdi->highpc;
          if (set_addrmap)
            {
              struct objfile *objfile = cu->per_objfile->objfile;
+             dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
              struct gdbarch *gdbarch = objfile->arch ();
              CORE_ADDR baseaddr;
              CORE_ADDR this_highpc;
@@ -8721,21 +8451,21 @@ add_partial_subprogram (struct partial_die_info *pdi,
                = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                               pdi->highpc + baseaddr)
                   - baseaddr);
-             addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+             addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                                 this_lowpc, this_highpc - 1,
                                 cu->per_cu->v.psymtab);
            }
-        }
+       }
 
       if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined))
        {
-          if (!pdi->is_declaration)
+         if (!pdi->is_declaration)
            /* Ignore subprogram DIEs that do not have a name, they are
               illegal.  Do not emit a complaint at this point, we will
               do so when we convert this psymtab into a symtab.  */
            if (pdi->name (cu))
              add_partial_symbol (pdi, cu);
-        }
+       }
     }
 
   if (! pdi->has_children)
@@ -8795,19 +8525,20 @@ peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
    an empty DIE).  In either case *BYTES_READ will be set to the length of
    the initial number.  */
 
-static struct abbrev_info *
+static const struct abbrev_info *
 peek_die_abbrev (const die_reader_specs &reader,
                 const gdb_byte *info_ptr, unsigned int *bytes_read)
 {
   dwarf2_cu *cu = reader.cu;
-  bfd *abfd = cu->per_objfile->objfile->obfd;
+  bfd *abfd = reader.abfd;
   unsigned int abbrev_number
     = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
 
   if (abbrev_number == 0)
     return NULL;
 
-  abbrev_info *abbrev = reader.abbrev_table->lookup_abbrev (abbrev_number);
+  const abbrev_info *abbrev
+    = reader.abbrev_table->lookup_abbrev (abbrev_number);
   if (!abbrev)
     {
       error (_("Dwarf Error: Could not find abbrev number %d in %s"
@@ -8829,7 +8560,8 @@ skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
   while (1)
     {
       unsigned int bytes_read;
-      abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
+      const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+                                                  &bytes_read);
 
       if (abbrev == NULL)
        return info_ptr + bytes_read;
@@ -8846,7 +8578,7 @@ skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
 
 static const gdb_byte *
 skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
-             struct abbrev_info *abbrev)
+             const struct abbrev_info *abbrev)
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -9043,17 +8775,35 @@ queue_comp_unit (dwarf2_per_cu_data *per_cu,
                 enum language pretend_language)
 {
   per_cu->queued = 1;
-  per_cu->per_bfd->queue.emplace (per_cu, per_objfile, pretend_language);
+
+  gdb_assert (per_objfile->per_bfd->queue.has_value ());
+  per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language);
 }
 
-/* If PER_CU is not yet queued, add it to the queue.
+/* If PER_CU is not yet expanded of queued for expansion, add it to the queue.
+
    If DEPENDENT_CU is non-NULL, it has a reference to PER_CU so add a
    dependency.
-   The result is non-zero if PER_CU was queued, otherwise the result is zero
-   meaning either PER_CU is already queued or it is already loaded.
 
-   N.B. There is an invariant here that if a CU is queued then it is loaded.
-   The caller is required to load PER_CU if we return non-zero.  */
+   Return true if maybe_queue_comp_unit requires the caller to load the CU's
+   DIEs, false otherwise.
+
+   Explanation: there is an invariant that if a CU is queued for expansion
+   (present in `dwarf2_per_bfd::queue`), then its DIEs are loaded
+   (a dwarf2_cu object exists for this CU, and `dwarf2_per_objfile::get_cu`
+   returns non-nullptr).  If the CU gets enqueued by this function but its DIEs
+   are not yet loaded, the the caller must load the CU's DIEs to ensure the
+   invariant is respected.
+
+   The caller is therefore not required to load the CU's DIEs (we return false)
+   if:
+
+     - the CU is already expanded, and therefore does not get enqueued
+     - the CU gets enqueued for expansion, but its DIEs are already loaded
+
+   Note that the caller should not use this function's return value as an
+   indicator of whether the CU's DIEs are loaded right now, it should check
+   that by calling `dwarf2_per_objfile::get_cu` instead.  */
 
 static int
 maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
@@ -9078,23 +8828,38 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
   if (dependent_cu != NULL)
     dwarf2_add_dependence (dependent_cu, per_cu);
 
-  /* If it's already on the queue, we have nothing to do.  */
-  if (per_cu->queued)
-    return 0;
+  /* If it's already on the queue, we have nothing to do.  */
+  if (per_cu->queued)
+    {
+      /* Verify the invariant that if a CU is queued for expansion, its DIEs are
+        loaded.  */
+      gdb_assert (per_objfile->get_cu (per_cu) != nullptr);
+
+      /* If the CU is queued for expansion, it should not already be
+        expanded.  */
+      gdb_assert (!per_objfile->symtab_set_p (per_cu));
+
+      /* The DIEs are already loaded, the caller doesn't need to do it.  */
+      return 0;
+    }
+
+  bool queued = false;
+  if (!per_objfile->symtab_set_p (per_cu))
+    {
+      /* Add it to the queue.  */
+      queue_comp_unit (per_cu, per_objfile,  pretend_language);
+      queued = true;
+    }
 
   /* If the compilation unit is already loaded, just mark it as
      used.  */
   dwarf2_cu *cu = per_objfile->get_cu (per_cu);
   if (cu != nullptr)
-    {
-      cu->last_used = 0;
-      return 0;
-    }
+    cu->last_used = 0;
 
-  /* Add it to the queue.  */
-  queue_comp_unit (per_cu, per_objfile,  pretend_language);
-
-  return 1;
+  /* Ask the caller to load the CU's DIEs if the CU got enqueued for expansion
+     and the DIEs are not already loaded.  */
+  return queued && cu == nullptr;
 }
 
 /* Process the queue.  */
@@ -9102,18 +8867,14 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
 static void
 process_queue (dwarf2_per_objfile *per_objfile)
 {
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Expanding one or more symtabs of objfile %s ...\n",
-                         objfile_name (per_objfile->objfile));
-    }
+  dwarf_read_debug_printf ("Expanding one or more symtabs of objfile %s ...",
+                          objfile_name (per_objfile->objfile));
 
   /* The queue starts out with one item, but following a DIE reference
      may load a new CU, adding it to the end of the queue.  */
-  while (!per_objfile->per_bfd->queue.empty ())
+  while (!per_objfile->per_bfd->queue->empty ())
     {
-      dwarf2_queue_item &item = per_objfile->per_bfd->queue.front ();
+      dwarf2_queue_item &item = per_objfile->per_bfd->queue->front ();
       dwarf2_per_cu_data *per_cu = item.per_cu;
 
       if (!per_objfile->symtab_set_p (per_cu))
@@ -9146,7 +8907,7 @@ process_queue (dwarf2_per_objfile *per_objfile)
                }
 
              if (dwarf_read_debug >= debug_print_threshold)
-               fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
+               dwarf_read_debug_printf ("Expanding symtab of %s", buf);
 
              if (per_cu->is_debug_types)
                process_full_type_unit (cu, item.pretend_language);
@@ -9154,19 +8915,16 @@ process_queue (dwarf2_per_objfile *per_objfile)
                process_full_comp_unit (cu, item.pretend_language);
 
              if (dwarf_read_debug >= debug_print_threshold)
-               fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
+               dwarf_read_debug_printf ("Done expanding %s", buf);
            }
        }
 
       per_cu->queued = 0;
-      per_objfile->per_bfd->queue.pop ();
+      per_objfile->per_bfd->queue->pop ();
     }
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Done expanding symtabs of %s.\n",
-                         objfile_name (per_objfile->objfile));
-    }
+  dwarf_read_debug_printf ("Done expanding symtabs of %s.",
+                          objfile_name (per_objfile->objfile));
 }
 
 /* Read in full symbols for PST, and anything it depends on.  */
@@ -9928,6 +9686,21 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
 
   dwarf2_find_base_address (cu->dies, cu);
 
+  /* Before we start reading the top-level DIE, ensure it has a valid tag
+     type.  */
+  switch (cu->dies->tag)
+    {
+    case DW_TAG_compile_unit:
+    case DW_TAG_partial_unit:
+    case DW_TAG_type_unit:
+      break;
+    default:
+      error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"),
+            dwarf_tag_name (cu->dies->tag),
+            sect_offset_str (cu->per_cu->sect_off),
+            objfile_name (per_objfile->objfile));
+    }
+
   /* Do line number decoding in read_file_scope () */
   process_die (cu->dies, cu);
 
@@ -10199,7 +9972,6 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
        read them on-demand through read_type_die.  */
     case DW_TAG_subroutine_type:
     case DW_TAG_set_type:
-    case DW_TAG_array_type:
     case DW_TAG_pointer_type:
     case DW_TAG_ptr_to_member_type:
     case DW_TAG_reference_type:
@@ -10207,11 +9979,18 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_string_type:
       break;
 
+    case DW_TAG_array_type:
+      /* We only need to handle this case for Ada -- in other
+        languages, it's normal for the compiler to emit a typedef
+        instead.  */
+      if (cu->language != language_ada)
+       break;
+      /* FALLTHROUGH */
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
     case DW_TAG_typedef:
       /* Add a typedef symbol for the type definition, if it has a
-         DW_AT_name.  */
+        DW_AT_name.  */
       new_symbol (die, read_type_die (die, cu), cu);
       break;
     case DW_TAG_common_block:
@@ -10451,6 +10230,7 @@ dwarf2_compute_name (const char *name,
              struct attribute *attr;
              struct die_info *child;
              int first = 1;
+             const language_defn *cplus_lang = language_def (cu->language);
 
              die->building_fullname = 1;
 
@@ -10485,8 +10265,8 @@ dwarf2_compute_name (const char *name,
 
                  if (child->tag == DW_TAG_template_type_param)
                    {
-                     c_print_type (type, "", &buf, -1, 0, cu->language,
-                                   &type_print_raw_options);
+                     cplus_lang->print_type (type, "", &buf, -1, 0,
+                                             &type_print_raw_options);
                      continue;
                    }
 
@@ -10506,7 +10286,7 @@ dwarf2_compute_name (const char *name,
                  if (type->has_no_signedness ())
                    /* GDB prints characters as NUMBER 'CHAR'.  If that's
                       changed, this can use value_print instead.  */
-                   c_printchar (value, type, &buf);
+                   cplus_lang->printchar (value, type, &buf);
                  else
                    {
                      struct value_print_options opts;
@@ -10809,36 +10589,36 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
     {
       /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524
 
-        The import in the following code:
-        namespace A
-          {
-            typedef int B;
-          }
-
-        int main ()
-          {
-            using A::B;
-            B b;
-            return b;
-          }
-
-        ...
-         <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
-            <52>   DW_AT_decl_file   : 1
-            <53>   DW_AT_decl_line   : 6
-            <54>   DW_AT_import      : <0x75>
-         <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
-            <59>   DW_AT_name        : B
-            <5b>   DW_AT_decl_file   : 1
-            <5c>   DW_AT_decl_line   : 2
-            <5d>   DW_AT_type        : <0x6e>
-        ...
-         <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
-            <76>   DW_AT_byte_size   : 4
-            <77>   DW_AT_encoding    : 5        (signed)
-
-        imports the wrong die ( 0x75 instead of 0x58 ).
-        This case will be ignored until the gcc bug is fixed.  */
+       The import in the following code:
+       namespace A
+         {
+           typedef int B;
+         }
+
+       int main ()
+         {
+           using A::B;
+           B b;
+           return b;
+         }
+
+       ...
+        <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
+           <52>   DW_AT_decl_file   : 1
+           <53>   DW_AT_decl_line   : 6
+           <54>   DW_AT_import      : <0x75>
+        <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
+           <59>   DW_AT_name        : B
+           <5b>   DW_AT_decl_file   : 1
+           <5c>   DW_AT_decl_line   : 2
+           <5d>   DW_AT_type        : <0x6e>
+       ...
+        <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
+           <76>   DW_AT_byte_size   : 4
+           <77>   DW_AT_encoding    : 5        (signed)
+
+       imports the wrong die ( 0x75 instead of 0x58 ).
+       This case will be ignored until the gcc bug is fixed.  */
       return;
     }
 
@@ -11081,7 +10861,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   else
     {
       /* We cannot free any current entry in (*slot) as that struct line_header
-         may be already used by multiple CUs.  Create only temporary decoded
+        may be already used by multiple CUs.  Create only temporary decoded
         line_header for this CU - it may happen at most once for each line
         number information unit.  And if we're not using line_header_hash
         then this is what we want as well.  */
@@ -11459,10 +11239,9 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
   dwo_unit->sect_off = sect_off;
   dwo_unit->length = cu->per_cu->length;
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "  offset %s, dwo_id %s\n",
-                       sect_offset_str (sect_off),
-                       hex_string (dwo_unit->signature));
+  dwarf_read_debug_printf ("  offset %s, dwo_id %s",
+                          sect_offset_str (sect_off),
+                          hex_string (dwo_unit->signature));
 }
 
 /* Create the dwo_units for the CUs in a DWO_FILE.
@@ -11483,12 +11262,9 @@ create_cus_hash_table (dwarf2_per_objfile *per_objfile,
   if (info_ptr == NULL)
     return;
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
-                         section.get_name (),
-                         section.get_file_name ());
-    }
+  dwarf_read_debug_printf ("Reading %s for %s:",
+                          section.get_name (),
+                          section.get_file_name ());
 
   end_ptr = info_ptr + section.size;
   while (info_ptr < end_ptr)
@@ -11930,7 +11706,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
 {
   const struct dwop_section_names *names = &dwop_section_names;
 
-  if (section_is_p (sectp->name, &names->abbrev_dwo))
+  if (names->abbrev_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->abbrev.s.section != NULL)
@@ -11938,8 +11714,8 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->abbrev.s.section = sectp;
       sections->abbrev.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->info_dwo)
-          || section_is_p (sectp->name, &names->types_dwo))
+  else if (names->info_dwo.matches (sectp->name)
+          || names->types_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->info_or_types.s.section != NULL)
@@ -11947,7 +11723,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->info_or_types.s.section = sectp;
       sections->info_or_types.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_dwo))
+  else if (names->line_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->line.s.section != NULL)
@@ -11955,7 +11731,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->line.s.section = sectp;
       sections->line.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loc_dwo))
+  else if (names->loc_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->loc.s.section != NULL)
@@ -11963,7 +11739,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->loc.s.section = sectp;
       sections->loc.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macinfo_dwo))
+  else if (names->macinfo_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->macinfo.s.section != NULL)
@@ -11971,7 +11747,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->macinfo.s.section = sectp;
       sections->macinfo.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro_dwo))
+  else if (names->macro_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->macro.s.section != NULL)
@@ -11979,7 +11755,7 @@ locate_v1_virtual_dwo_sections (asection *sectp,
       sections->macro.s.section = sectp;
       sections->macro.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+  else if (names->str_offsets_dwo.matches (sectp->name))
     {
       /* There can be only one.  */
       if (sections->str_offsets.s.section != NULL)
@@ -12020,13 +11796,9 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
 
   gdb_assert (dwp_file->version == 1);
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V1 file: %s\n",
-                         kind,
-                         pulongest (unit_index), hex_string (signature),
-                         dwp_file->name);
-    }
+  dwarf_read_debug_printf ("Reading %s %s/%s in DWP V1 file: %s",
+                          kind, pulongest (unit_index), hex_string (signature),
+                          dwp_file->name);
 
   /* Fetch the sections of this DWO unit.
      Put a limit on the number of sections we look for so that bad data
@@ -12105,11 +11877,9 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
   /* Create one if necessary.  */
   if (*dwo_file_slot == NULL)
     {
-      if (dwarf_read_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
-                             virtual_dwo_name.c_str ());
-       }
+      dwarf_read_debug_printf ("Creating virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = new struct dwo_file;
       dwo_file->dwo_name = per_objfile->objfile->intern (virtual_dwo_name);
       dwo_file->comp_dir = comp_dir;
@@ -12132,11 +11902,9 @@ create_dwo_unit_in_dwp_v1 (dwarf2_per_objfile *per_objfile,
     }
   else
     {
-      if (dwarf_read_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
-                             virtual_dwo_name.c_str ());
-       }
+      dwarf_read_debug_printf ("Using existing virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = (struct dwo_file *) *dwo_file_slot;
     }
 
@@ -12217,13 +11985,9 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_objfile *per_objfile,
 
   gdb_assert (dwp_file->version == 2);
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
-                         kind,
-                         pulongest (unit_index), hex_string (signature),
-                         dwp_file->name);
-    }
+  dwarf_read_debug_printf ("Reading %s %s/%s in DWP V2 file: %s",
+                          kind, pulongest (unit_index), hex_string (signature),
+                          dwp_file->name);
 
   /* Fetch the section offsets of this DWO unit.  */
 
@@ -12298,11 +12062,9 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_objfile *per_objfile,
   /* Create one if necessary.  */
   if (*dwo_file_slot == NULL)
     {
-      if (dwarf_read_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
-                             virtual_dwo_name.c_str ());
-       }
+      dwarf_read_debug_printf ("Creating virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = new struct dwo_file;
       dwo_file->dwo_name = per_objfile->objfile->intern (virtual_dwo_name);
       dwo_file->comp_dir = comp_dir;
@@ -12343,11 +12105,9 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_objfile *per_objfile,
     }
   else
     {
-      if (dwarf_read_debug)
-       {
-         fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
-                             virtual_dwo_name.c_str ());
-       }
+      dwarf_read_debug_printf ("Using existing virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = (struct dwo_file *) *dwo_file_slot;
     }
 
@@ -12357,7 +12117,7 @@ create_dwo_unit_in_dwp_v2 (dwarf2_per_objfile *per_objfile,
   dwo_unit->section =
     XOBNEW (&per_objfile->per_bfd->obstack, struct dwarf2_section_info);
   *dwo_unit->section = create_dwp_v2_or_v5_section
-                         (per_objfile,
+                        (per_objfile,
                          is_debug_types
                          ? &dwp_file->sections.types
                          : &dwp_file->sections.info,
@@ -12391,13 +12151,9 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_objfile *per_objfile,
 
   gdb_assert (dwp_file->version == 5);
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V5 file: %s\n",
-                          kind,
-                          pulongest (unit_index), hex_string (signature),
-                          dwp_file->name);
-    }
+  dwarf_read_debug_printf ("Reading %s %s/%s in DWP V5 file: %s",
+                          kind, pulongest (unit_index), hex_string (signature),
+                          dwp_file->name);
 
   /* Fetch the section offsets of this DWO unit.  */
 
@@ -12406,51 +12162,51 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_objfile *per_objfile,
   for (int i = 0; i < dwp_htab->nr_columns; ++i)
     {
       uint32_t offset = read_4_bytes (dbfd,
-                                      dwp_htab->section_pool.v5.offsets
-                                      + (((unit_index - 1)
-                                          * dwp_htab->nr_columns
-                                          + i)
-                                         * sizeof (uint32_t)));
+                                     dwp_htab->section_pool.v5.offsets
+                                     + (((unit_index - 1)
+                                         * dwp_htab->nr_columns
+                                         + i)
+                                        * sizeof (uint32_t)));
       uint32_t size = read_4_bytes (dbfd,
-                                    dwp_htab->section_pool.v5.sizes
-                                    + (((unit_index - 1) * dwp_htab->nr_columns
-                                        + i)
-                                       * sizeof (uint32_t)));
+                                   dwp_htab->section_pool.v5.sizes
+                                   + (((unit_index - 1) * dwp_htab->nr_columns
+                                       + i)
+                                      * sizeof (uint32_t)));
 
       switch (dwp_htab->section_pool.v5.section_ids[i])
-        {
-          case DW_SECT_ABBREV_V5:
-            sections.abbrev_offset = offset;
-            sections.abbrev_size = size;
-            break;
-          case DW_SECT_INFO_V5:
-            sections.info_or_types_offset = offset;
-            sections.info_or_types_size = size;
-            break;
-          case DW_SECT_LINE_V5:
-            sections.line_offset = offset;
-            sections.line_size = size;
-            break;
-          case DW_SECT_LOCLISTS_V5:
-            sections.loclists_offset = offset;
-            sections.loclists_size = size;
-            break;
-          case DW_SECT_MACRO_V5:
-            sections.macro_offset = offset;
-            sections.macro_size = size;
-            break;
-          case DW_SECT_RNGLISTS_V5:
-            sections.rnglists_offset = offset;
-            sections.rnglists_size = size;
-            break;
-          case DW_SECT_STR_OFFSETS_V5:
-            sections.str_offsets_offset = offset;
-            sections.str_offsets_size = size;
-            break;
-          case DW_SECT_RESERVED_V5:
-          default:
-            break;
-        }
+       {
+         case DW_SECT_ABBREV_V5:
+           sections.abbrev_offset = offset;
+           sections.abbrev_size = size;
+           break;
+         case DW_SECT_INFO_V5:
+           sections.info_or_types_offset = offset;
+           sections.info_or_types_size = size;
+           break;
+         case DW_SECT_LINE_V5:
+           sections.line_offset = offset;
+           sections.line_size = size;
+           break;
+         case DW_SECT_LOCLISTS_V5:
+           sections.loclists_offset = offset;
+           sections.loclists_size = size;
+           break;
+         case DW_SECT_MACRO_V5:
+           sections.macro_offset = offset;
+           sections.macro_size = size;
+           break;
+         case DW_SECT_RNGLISTS_V5:
+           sections.rnglists_offset = offset;
+           sections.rnglists_size = size;
+           break;
+         case DW_SECT_STR_OFFSETS_V5:
+           sections.str_offsets_offset = offset;
+           sections.str_offsets_size = size;
+           break;
+         case DW_SECT_RESERVED_V5:
+         default:
+           break;
+       }
     }
 
   /* It's easier for the rest of the code if we fake a struct dwo_file and
@@ -12464,75 +12220,71 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_objfile *per_objfile,
 
   std::string virtual_dwo_name =
     string_printf ("virtual-dwo/%ld-%ld-%ld-%ld-%ld-%ld",
-                 (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
-                 (long) (sections.line_size ? sections.line_offset : 0),
-                 (long) (sections.loclists_size ? sections.loclists_offset : 0),
-                 (long) (sections.str_offsets_size
-                            ? sections.str_offsets_offset : 0),
-                 (long) (sections.macro_size ? sections.macro_offset : 0),
-                 (long) (sections.rnglists_size ? sections.rnglists_offset: 0));
+                (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+                (long) (sections.line_size ? sections.line_offset : 0),
+                (long) (sections.loclists_size ? sections.loclists_offset : 0),
+                (long) (sections.str_offsets_size
+                           ? sections.str_offsets_offset : 0),
+                (long) (sections.macro_size ? sections.macro_offset : 0),
+                (long) (sections.rnglists_size ? sections.rnglists_offset: 0));
   /* Can we use an existing virtual DWO file?  */
   dwo_file_slot = lookup_dwo_file_slot (per_objfile,
-                                        virtual_dwo_name.c_str (),
-                                        comp_dir);
+                                       virtual_dwo_name.c_str (),
+                                       comp_dir);
   /* Create one if necessary.  */
   if (*dwo_file_slot == NULL)
     {
-      if (dwarf_read_debug)
-        {
-          fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
-                              virtual_dwo_name.c_str ());
-        }
+      dwarf_read_debug_printf ("Creating virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = new struct dwo_file;
       dwo_file->dwo_name = per_objfile->objfile->intern (virtual_dwo_name);
       dwo_file->comp_dir = comp_dir;
       dwo_file->sections.abbrev =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.abbrev,
-                                     sections.abbrev_offset,
-                                     sections.abbrev_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.abbrev,
+                                    sections.abbrev_offset,
+                                    sections.abbrev_size);
       dwo_file->sections.line =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.line,
-                                     sections.line_offset, sections.line_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.line,
+                                    sections.line_offset, sections.line_size);
       dwo_file->sections.macro =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.macro,
-                                     sections.macro_offset,
-                                     sections.macro_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.macro,
+                                    sections.macro_offset,
+                                    sections.macro_size);
       dwo_file->sections.loclists =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.loclists,
-                                     sections.loclists_offset,
-                                     sections.loclists_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.loclists,
+                                    sections.loclists_offset,
+                                    sections.loclists_size);
       dwo_file->sections.rnglists =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.rnglists,
-                                     sections.rnglists_offset,
-                                     sections.rnglists_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.rnglists,
+                                    sections.rnglists_offset,
+                                    sections.rnglists_size);
       dwo_file->sections.str_offsets =
-        create_dwp_v2_or_v5_section (per_objfile,
-                                     &dwp_file->sections.str_offsets,
-                                     sections.str_offsets_offset,
-                                     sections.str_offsets_size);
+       create_dwp_v2_or_v5_section (per_objfile,
+                                    &dwp_file->sections.str_offsets,
+                                    sections.str_offsets_offset,
+                                    sections.str_offsets_size);
       /* The "str" section is global to the entire DWP file.  */
       dwo_file->sections.str = dwp_file->sections.str;
       /* The info or types section is assigned below to dwo_unit,
-         there's no need to record it in dwo_file.
-         Also, we can't simply record type sections in dwo_file because
-         we record a pointer into the vector in dwo_unit.  As we collect more
-         types we'll grow the vector and eventually have to reallocate space
-         for it, invalidating all copies of pointers into the previous
-         contents.  */
+        there's no need to record it in dwo_file.
+        Also, we can't simply record type sections in dwo_file because
+        we record a pointer into the vector in dwo_unit.  As we collect more
+        types we'll grow the vector and eventually have to reallocate space
+        for it, invalidating all copies of pointers into the previous
+        contents.  */
       *dwo_file_slot = dwo_file;
     }
   else
     {
-      if (dwarf_read_debug)
-        {
-          fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
-                              virtual_dwo_name.c_str ());
-        }
+      dwarf_read_debug_printf ("Using existing virtual DWO: %s",
+                              virtual_dwo_name.c_str ());
+
       dwo_file = (struct dwo_file *) *dwo_file_slot;
     }
 
@@ -12542,9 +12294,9 @@ create_dwo_unit_in_dwp_v5 (dwarf2_per_objfile *per_objfile,
   dwo_unit->section
     = XOBNEW (&per_objfile->per_bfd->obstack, struct dwarf2_section_info);
   *dwo_unit->section = create_dwp_v2_or_v5_section (per_objfile,
-                                              &dwp_file->sections.info,
-                                              sections.info_or_types_offset,
-                                              sections.info_or_types_size);
+                                             &dwp_file->sections.info,
+                                             sections.info_or_types_offset,
+                                             sections.info_or_types_size);
   /* dwo_unit->{offset,length,type_offset_in_tu} are set later.  */
 
   return dwo_unit;
@@ -12660,6 +12412,13 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile,
   else
     search_path = debug_file_directory;
 
+  /* Add the path for the executable binary to the list of search paths.  */
+  std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile));
+  search_path_holder.reset (concat (objfile_dir.c_str (),
+                                   dirname_separator_string,
+                                   search_path, nullptr));
+  search_path = search_path_holder.get ();
+
   openp_flags flags = OPF_RETURN_REALPATH;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
@@ -12738,57 +12497,57 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp,
 {
   const struct dwop_section_names *names = &dwop_section_names;
 
-  if (section_is_p (sectp->name, &names->abbrev_dwo))
+  if (names->abbrev_dwo.matches (sectp->name))
     {
       dwo_sections->abbrev.s.section = sectp;
       dwo_sections->abbrev.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->info_dwo))
+  else if (names->info_dwo.matches (sectp->name))
     {
       dwo_sections->info.s.section = sectp;
       dwo_sections->info.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_dwo))
+  else if (names->line_dwo.matches (sectp->name))
     {
       dwo_sections->line.s.section = sectp;
       dwo_sections->line.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loc_dwo))
+  else if (names->loc_dwo.matches (sectp->name))
     {
       dwo_sections->loc.s.section = sectp;
       dwo_sections->loc.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loclists_dwo))
+  else if (names->loclists_dwo.matches (sectp->name))
     {
       dwo_sections->loclists.s.section = sectp;
       dwo_sections->loclists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macinfo_dwo))
+  else if (names->macinfo_dwo.matches (sectp->name))
     {
       dwo_sections->macinfo.s.section = sectp;
       dwo_sections->macinfo.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro_dwo))
+  else if (names->macro_dwo.matches (sectp->name))
     {
       dwo_sections->macro.s.section = sectp;
       dwo_sections->macro.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->rnglists_dwo))
+  else if (names->rnglists_dwo.matches (sectp->name))
     {
       dwo_sections->rnglists.s.section = sectp;
       dwo_sections->rnglists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str_dwo))
+  else if (names->str_dwo.matches (sectp->name))
     {
       dwo_sections->str.s.section = sectp;
       dwo_sections->str.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+  else if (names->str_offsets_dwo.matches (sectp->name))
     {
       dwo_sections->str_offsets.s.section = sectp;
       dwo_sections->str_offsets.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->types_dwo))
+  else if (names->types_dwo.matches (sectp->name))
     {
       struct dwarf2_section_info type_section;
 
@@ -12812,8 +12571,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
   gdb_bfd_ref_ptr dbfd = open_dwo_file (per_objfile, dwo_name, comp_dir);
   if (dbfd == NULL)
     {
-      if (dwarf_read_debug)
-       fprintf_unfiltered (gdb_stdlog, "DWO file not found: %s\n", dwo_name);
+      dwarf_read_debug_printf ("DWO file not found: %s", dwo_name);
+
       return NULL;
     }
 
@@ -12838,11 +12597,10 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
     {
       create_debug_type_hash_table (per_objfile, dwo_file.get (),
                                    &dwo_file->sections.info, dwo_file->tus,
-                                   rcuh_kind::TYPE);
+                                   rcuh_kind::COMPILE);
     }
 
-  if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
+  dwarf_read_debug_printf ("DWO file found: %s", dwo_name);
 
   return dwo_file.release ();
 }
@@ -12864,17 +12622,17 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
-  if (section_is_p (sectp->name, &names->str_dwo))
+  if (names->str_dwo.matches (sectp->name))
     {
       dwp_file->sections.str.s.section = sectp;
       dwp_file->sections.str.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->cu_index))
+  else if (names->cu_index.matches (sectp->name))
     {
       dwp_file->sections.cu_index.s.section = sectp;
       dwp_file->sections.cu_index.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->tu_index))
+  else if (names->tu_index.matches (sectp->name))
     {
       dwp_file->sections.tu_index.s.section = sectp;
       dwp_file->sections.tu_index.size = bfd_section_size (sectp);
@@ -12899,42 +12657,42 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
-  if (section_is_p (sectp->name, &names->abbrev_dwo))
+  if (names->abbrev_dwo.matches (sectp->name))
     {
       dwp_file->sections.abbrev.s.section = sectp;
       dwp_file->sections.abbrev.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->info_dwo))
+  else if (names->info_dwo.matches (sectp->name))
     {
       dwp_file->sections.info.s.section = sectp;
       dwp_file->sections.info.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_dwo))
+  else if (names->line_dwo.matches (sectp->name))
     {
       dwp_file->sections.line.s.section = sectp;
       dwp_file->sections.line.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loc_dwo))
+  else if (names->loc_dwo.matches (sectp->name))
     {
       dwp_file->sections.loc.s.section = sectp;
       dwp_file->sections.loc.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macinfo_dwo))
+  else if (names->macinfo_dwo.matches (sectp->name))
     {
       dwp_file->sections.macinfo.s.section = sectp;
       dwp_file->sections.macinfo.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro_dwo))
+  else if (names->macro_dwo.matches (sectp->name))
     {
       dwp_file->sections.macro.s.section = sectp;
       dwp_file->sections.macro.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+  else if (names->str_offsets_dwo.matches (sectp->name))
     {
       dwp_file->sections.str_offsets.s.section = sectp;
       dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->types_dwo))
+  else if (names->types_dwo.matches (sectp->name))
     {
       dwp_file->sections.types.s.section = sectp;
       dwp_file->sections.types.size = bfd_section_size (sectp);
@@ -12959,37 +12717,37 @@ dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
-  if (section_is_p (sectp->name, &names->abbrev_dwo))
+  if (names->abbrev_dwo.matches (sectp->name))
     {
       dwp_file->sections.abbrev.s.section = sectp;
       dwp_file->sections.abbrev.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->info_dwo))
+  else if (names->info_dwo.matches (sectp->name))
     {
       dwp_file->sections.info.s.section = sectp;
       dwp_file->sections.info.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_dwo))
+  else if (names->line_dwo.matches (sectp->name))
    {
      dwp_file->sections.line.s.section = sectp;
      dwp_file->sections.line.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loclists_dwo))
+  else if (names->loclists_dwo.matches (sectp->name))
     {
       dwp_file->sections.loclists.s.section = sectp;
       dwp_file->sections.loclists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro_dwo))
+  else if (names->macro_dwo.matches (sectp->name))
     {
       dwp_file->sections.macro.s.section = sectp;
       dwp_file->sections.macro.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->rnglists_dwo))
+  else if (names->rnglists_dwo.matches (sectp->name))
     {
       dwp_file->sections.rnglists.s.section = sectp;
       dwp_file->sections.rnglists.size = bfd_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+  else if (names->str_offsets_dwo.matches (sectp->name))
     {
       dwp_file->sections.str_offsets.s.section = sectp;
       dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
@@ -13104,8 +12862,8 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
 
   if (dbfd == NULL)
     {
-      if (dwarf_read_debug)
-       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name.c_str ());
+      dwarf_read_debug_printf ("DWP file not found: %s", dwp_name.c_str ());
+
       return std::unique_ptr<dwp_file> ();
     }
 
@@ -13159,14 +12917,10 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
   dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table ();
   dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table ();
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "DWP file found: %s\n", dwp_file->name);
-      fprintf_unfiltered (gdb_stdlog,
-                         "    %s CUs, %s TUs\n",
-                         pulongest (dwp_file->cus ? dwp_file->cus->nr_units : 0),
-                         pulongest (dwp_file->tus ? dwp_file->tus->nr_units : 0));
-    }
+  dwarf_read_debug_printf ("DWP file found: %s", dwp_file->name);
+  dwarf_read_debug_printf ("    %s CUs, %s TUs",
+                          pulongest (dwp_file->cus ? dwp_file->cus->nr_units : 0),
+                          pulongest (dwp_file->tus ? dwp_file->tus->nr_units : 0));
 
   return dwp_file;
 }
@@ -13230,13 +12984,10 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir,
 
          if (dwo_cutu != NULL)
            {
-             if (dwarf_read_debug)
-               {
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "Virtual DWO %s %s found: @%s\n",
-                                     kind, hex_string (signature),
-                                     host_address_to_string (dwo_cutu));
-               }
+             dwarf_read_debug_printf ("Virtual DWO %s %s found: @%s",
+                                      kind, hex_string (signature),
+                                      host_address_to_string (dwo_cutu));
+
              return dwo_cutu;
            }
        }
@@ -13280,12 +13031,10 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir,
 
          if (dwo_cutu != NULL)
            {
-             if (dwarf_read_debug)
-               {
-                 fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
-                                     kind, dwo_name, hex_string (signature),
-                                     host_address_to_string (dwo_cutu));
-               }
+             dwarf_read_debug_printf ("DWO %s %s(%s) found: @%s",
+                                      kind, dwo_name, hex_string (signature),
+                                      host_address_to_string (dwo_cutu));
+
              return dwo_cutu;
            }
        }
@@ -13295,11 +13044,8 @@ lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir,
      someone deleted the DWO/DWP file, or the search path isn't set up
      correctly to find the file.  */
 
-  if (dwarf_read_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) not found\n",
-                         kind, dwo_name, hex_string (signature));
-    }
+  dwarf_read_debug_printf ("DWO %s %s(%s) not found",
+                          kind, dwo_name, hex_string (signature));
 
   /* This is a warning and not a complaint because it can be caused by
      pilot error (e.g., user accidentally deleting the DWO).  */
@@ -13435,6 +13181,37 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
               sect_offset_str (die->sect_off),
               sect_offset_str (origin_die->sect_off));
 
+  /* Find if the concrete and abstract trees are structurally the
+     same.  This is a shallow traversal and it is not bullet-proof;
+     the compiler can trick the debugger into believing that the trees
+     are isomorphic, whereas they actually are not.  However, the
+     likelyhood of this happening is pretty low, and a full-fledged
+     check would be an overkill.  */
+  bool are_isomorphic = true;
+  die_info *concrete_child = die->child;
+  die_info *abstract_child = origin_die->child;
+  while (concrete_child != nullptr || abstract_child != nullptr)
+    {
+      if (concrete_child == nullptr
+         || abstract_child == nullptr
+         || concrete_child->tag != abstract_child->tag)
+       {
+         are_isomorphic = false;
+         break;
+       }
+
+      concrete_child = concrete_child->sibling;
+      abstract_child = abstract_child->sibling;
+    }
+
+  /* Walk the origin's children in parallel to the concrete children.
+     This helps match an origin child in case the debug info misses
+     DW_AT_abstract_origin attributes.  Keep in mind that the abstract
+     origin tree may not have the same tree structure as the concrete
+     DIE, though.  */
+  die_info *corresponding_abstract_child
+    = are_isomorphic ? origin_die->child : nullptr;
+
   std::vector<sect_offset> offsets;
 
   for (child_die = die->child;
@@ -13450,8 +13227,13 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
         present in the abstract instance but not referenced in the concrete
         one.  */
       if (child_die->tag == DW_TAG_call_site
-          || child_die->tag == DW_TAG_GNU_call_site)
-       continue;
+         || child_die->tag == DW_TAG_GNU_call_site)
+       {
+         if (are_isomorphic)
+           corresponding_abstract_child
+             = corresponding_abstract_child->sibling;
+         continue;
+       }
 
       /* For each CHILD_DIE, find the corresponding child of
         ORIGIN_DIE.  If there is more than one layer of
@@ -13470,6 +13252,14 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
                                             &child_origin_cu);
        }
 
+      /* If missing DW_AT_abstract_origin, try the corresponding child
+        of the origin.  Clang emits such lexical scopes.  */
+      if (child_origin_die == child_die
+         && dwarf2_attr (child_die, DW_AT_abstract_origin, cu) == nullptr
+         && are_isomorphic
+         && child_die->tag == DW_TAG_lexical_block)
+       child_origin_die = corresponding_abstract_child;
+
       /* According to DWARF3 3.3.8.2 #3 new entries without their abstract
         counterpart may exist.  */
       if (child_origin_die != child_die)
@@ -13489,6 +13279,9 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
          else
            offsets.push_back (child_origin_die->sect_off);
        }
+
+      if (are_isomorphic)
+       corresponding_abstract_child = corresponding_abstract_child->sibling;
     }
   std::sort (offsets.begin (), offsets.end ());
   sect_offset *offsets_end = offsets.data () + offsets.size ();
@@ -13596,6 +13389,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
        }
     }
 
+  gdb_assert (cu->get_builder () != nullptr);
   newobj = cu->get_builder ()->push_context (0, lowpc);
   newobj->name = new_symbol (die, read_type_die (die, cu), cu,
                             (struct symbol *) templ_func);
@@ -13695,7 +13489,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       templ_func->n_template_arguments = template_args.size ();
       templ_func->template_arguments
-        = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
+       = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
                     templ_func->n_template_arguments);
       memcpy (templ_func->template_arguments,
              template_args.data (),
@@ -13784,19 +13578,19 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       || (*cu->get_builder ()->get_local_using_directives ()) != NULL)
     {
       struct block *block
-        = cu->get_builder ()->finish_block (0, cstk.old_blocks, NULL,
+       = cu->get_builder ()->finish_block (0, cstk.old_blocks, NULL,
                                     cstk.start_addr, highpc);
 
       /* Note that recording ranges after traversing children, as we
-         do here, means that recording a parent's ranges entails
-         walking across all its children's ranges as they appear in
-         the address map, which is quadratic behavior.
-
-         It would be nicer to record the parent's ranges before
-         traversing its children, simply overriding whatever you find
-         there.  But since we don't even decide whether to create a
-         block until after we've traversed its children, that's hard
-         to do.  */
+        do here, means that recording a parent's ranges entails
+        walking across all its children's ranges as they appear in
+        the address map, which is quadratic behavior.
+
+        It would be nicer to record the parent's ranges before
+        traversing its children, simply overriding whatever you find
+        there.  But since we don't even decide whether to create a
+        block until after we've traversed its children, that's hard
+        to do.  */
       dwarf2_record_block_ranges (die, block, baseaddr, cu);
     }
   *cu->get_builder ()->get_local_symbols () = cstk.locals;
@@ -13859,7 +13653,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        child_die = child_die->sibling)
     {
       if (child_die->tag != DW_TAG_call_site_parameter
-          && child_die->tag != DW_TAG_GNU_call_site_parameter)
+         && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          complaint (_("Tag %d is not DW_TAG_call_site_parameter in "
                       "DW_TAG_call_site child DIE %s [in module %s]"),
@@ -13894,8 +13688,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       /* DW_AT_call_all_calls is a superset
         of DW_AT_call_all_tail_calls.  */
       if (func_die
-          && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu)
-          && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
+         && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu)
+         && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
          && !dwarf2_flag_true_p (func_die, DW_AT_call_all_tail_calls, cu)
          && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu))
        {
@@ -13972,7 +13766,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            target_physname = dwarf2_physname (NULL, target_die, target_cu);
          if (target_physname == NULL)
            complaint (_("DW_AT_call_target target DIE has invalid "
-                        "physname, for referencing DIE %s [in module %s]"),
+                        "physname, for referencing DIE %s [in module %s]"),
                       sect_offset_str (die->sect_off), objfile_name (objfile));
          else
            SET_FIELD_PHYSNAME (call_site->target, target_physname);
@@ -13985,7 +13779,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
              <= PC_BOUNDS_INVALID)
            complaint (_("DW_AT_call_target target DIE has invalid "
-                        "low pc, for referencing DIE %s [in module %s]"),
+                        "low pc, for referencing DIE %s [in module %s]"),
                       sect_offset_str (die->sect_off), objfile_name (objfile));
          else
            {
@@ -14010,7 +13804,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       struct attribute *loc, *origin;
 
       if (child_die->tag != DW_TAG_call_site_parameter
-          && child_die->tag != DW_TAG_GNU_call_site_parameter)
+         && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          /* Already printed the complaint above.  */
          continue;
@@ -14251,11 +14045,11 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
          base = cu->header.read_address (obfd, buffer, &bytes_read);
          buffer += bytes_read;
          break;
-        case DW_RLE_base_addressx:
-          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
-          buffer += bytes_read;
-          base = read_addr_index (cu, addr_index);
-          break;
+       case DW_RLE_base_addressx:
+         addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         base = read_addr_index (cu, addr_index);
+         break;
        case DW_RLE_start_length:
          if (buffer + cu->header.addr_size > buf_end)
            {
@@ -14275,18 +14069,18 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
            }
          break;
        case DW_RLE_startx_length:
-          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
-          buffer += bytes_read;
-          range_beginning = read_addr_index (cu, addr_index);
-          if (buffer > buf_end)
-            {
-              overflow = true;
-              break;
-            }
-          range_end = (range_beginning
-                       + read_unsigned_leb128 (obfd, buffer, &bytes_read));
-          buffer += bytes_read;
-          break;
+         addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         range_beginning = read_addr_index (cu, addr_index);
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_end = (range_beginning
+                      + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+         buffer += bytes_read;
+         break;
        case DW_RLE_offset_pair:
          range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
          buffer += bytes_read;
@@ -14316,18 +14110,18 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
          buffer += bytes_read;
          break;
        case DW_RLE_startx_endx:
-          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
-          buffer += bytes_read;
-          range_beginning = read_addr_index (cu, addr_index);
-          if (buffer > buf_end)
-            {
-              overflow = true;
-              break;
-            }
-          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
-          buffer += bytes_read;
-          range_end = read_addr_index (cu, addr_index);
-          break;
+         addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         range_beginning = read_addr_index (cu, addr_index);
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         range_end = read_addr_index (cu, addr_index);
+         break;
        default:
          complaint (_("Invalid .debug_rnglists data (no base address)"));
          return false;
@@ -14491,7 +14285,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
 
 /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
    Return 1 if the attributes are present and valid, otherwise, return 0.
-   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+   If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'.  */
 
 static int
 dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
@@ -14499,6 +14293,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
                    dwarf2_psymtab *ranges_pst, dwarf_tag tag)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   int low_set = 0;
@@ -14520,7 +14315,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                                range_end + baseaddr)
                    - baseaddr);
-         addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+         addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                             lowpc, highpc - 1, ranges_pst);
        }
 
@@ -14578,7 +14373,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
     {
       attr = dwarf2_attr (die, DW_AT_low_pc, cu);
       if (attr != nullptr)
-        {
+       {
          low = attr->as_address ();
          high = attr_high->as_address ();
          if (cu->header.version >= 4 && attr_high->form_is_constant ())
@@ -14596,20 +14391,14 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
       attr = dwarf2_attr (die, DW_AT_ranges, cu);
       if (attr != nullptr && attr->form_is_unsigned ())
        {
-         /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
-            We take advantage of the fact that DW_AT_ranges does not appear
-            in DW_TAG_compile_unit of DWO files.
-
-            Attributes of the form DW_FORM_rnglistx have already had their
-            value changed by read_rnglist_index and already include
-            DW_AT_rnglists_base, so don't need to add the ranges base,
-            either.  */
-         int need_ranges_base = (die->tag != DW_TAG_compile_unit
-                                 && attr->form != DW_FORM_rnglistx);
-         unsigned int ranges_offset = (attr->as_unsigned ()
-                                       + (need_ranges_base
-                                          ? cu->ranges_base
-                                          : 0));
+         /* Offset in the .debug_ranges or .debug_rnglist section (depending
+            on DWARF version).  */
+         ULONGEST ranges_offset = attr->as_unsigned ();
+
+         /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
+            this value.  */
+         if (die->tag != DW_TAG_compile_unit)
+           ranges_offset += cu->gnu_ranges_base;
 
          /* Value of the DW_AT_ranges attribute is the offset in the
             .debug_ranges section.  */
@@ -14651,8 +14440,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 
 static void
 dwarf2_get_subprogram_pc_bounds (struct die_info *die,
-                                 CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                                 struct dwarf2_cu *cu)
+                                CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                                struct dwarf2_cu *cu)
 {
   CORE_ADDR low, high;
   struct die_info *child = die->child;
@@ -14675,8 +14464,8 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die,
   while (child && child->tag)
     {
       if (child->tag == DW_TAG_subprogram
-          || child->tag == DW_TAG_lexical_block)
-        dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu);
+         || child->tag == DW_TAG_lexical_block)
+       dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu);
       child = child->sibling;
     }
 }
@@ -14708,7 +14497,7 @@ get_scope_pc_bounds (struct die_info *die,
        {
          switch (child->tag) {
          case DW_TAG_subprogram:
-            dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu);
+           dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu);
            break;
          case DW_TAG_namespace:
          case DW_TAG_module:
@@ -14746,7 +14535,7 @@ get_scope_pc_bounds (struct die_info *die,
 
 static void
 dwarf2_record_block_ranges (struct die_info *die, struct block *block,
-                            CORE_ADDR baseaddr, struct dwarf2_cu *cu)
+                           CORE_ADDR baseaddr, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
   struct gdbarch *gdbarch = objfile->arch ();
@@ -14758,7 +14547,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
     {
       attr = dwarf2_attr (die, DW_AT_low_pc, cu);
       if (attr != nullptr)
-        {
+       {
          CORE_ADDR low = attr->as_address ();
          CORE_ADDR high = attr_high->as_address ();
 
@@ -14768,30 +14557,23 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
          low = gdbarch_adjust_dwarf2_addr (gdbarch, low + baseaddr);
          high = gdbarch_adjust_dwarf2_addr (gdbarch, high + baseaddr);
          cu->get_builder ()->record_block_range (block, low, high - 1);
-        }
+       }
     }
 
   attr = dwarf2_attr (die, DW_AT_ranges, cu);
   if (attr != nullptr && attr->form_is_unsigned ())
     {
-      /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
-        We take advantage of the fact that DW_AT_ranges does not appear
-        in DW_TAG_compile_unit of DWO files.
+      /* Offset in the .debug_ranges or .debug_rnglist section (depending
+        on DWARF version).  */
+      ULONGEST ranges_offset = attr->as_unsigned ();
 
-        Attributes of the form DW_FORM_rnglistx have already had their
-        value changed by read_rnglist_index and already include
-        DW_AT_rnglists_base, so don't need to add the ranges base,
-        either.  */
-      int need_ranges_base = (die->tag != DW_TAG_compile_unit
-                             && attr->form != DW_FORM_rnglistx);
-
-      /* The value of the DW_AT_ranges attribute is the offset of the
-         address range list in the .debug_ranges section.  */
-      unsigned long offset = (attr->as_unsigned ()
-                             + (need_ranges_base ? cu->ranges_base : 0));
+      /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
+        this value.  */
+      if (die->tag != DW_TAG_compile_unit)
+       ranges_offset += cu->gnu_ranges_base;
 
       std::vector<blockrange> blockvec;
-      dwarf2_ranges_process (offset, cu, die->tag,
+      dwarf2_ranges_process (ranges_offset, cu, die->tag,
        [&] (CORE_ADDR start, CORE_ADDR end)
        {
          start += baseaddr;
@@ -15063,21 +14845,21 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
          if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
            {
              /* For big endian bits, the DW_AT_bit_offset gives the
-                additional bit offset from the MSB of the containing
-                anonymous object to the MSB of the field.  We don't
-                have to do anything special since we don't need to
-                know the size of the anonymous object.  */
+                additional bit offset from the MSB of the containing
+                anonymous object to the MSB of the field.  We don't
+                have to do anything special since we don't need to
+                know the size of the anonymous object.  */
              SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
                                      + attr->constant_value (0)));
            }
          else
            {
              /* For little endian bits, compute the bit offset to the
-                MSB of the anonymous object, subtract off the number of
-                bits from the MSB of the field to the MSB of the
-                object, and then subtract off the number of bits of
-                the field itself.  The result is the bit offset of
-                the LSB of the field.  */
+                MSB of the anonymous object, subtract off the number of
+                bits from the MSB of the field to the MSB of the
+                object, and then subtract off the number of bits of
+                the field itself.  The result is the bit offset of
+                the LSB of the field.  */
              int anonymous_size;
              int bit_offset = attr->constant_value (0);
 
@@ -15118,7 +14900,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       fp->name = fieldname;
 
       /* Change accessibility for artificial fields (e.g. virtual table
-         pointer or virtual base class pointer) to private.  */
+        pointer or virtual base class pointer) to private.  */
       if (dwarf2_attr (die, DW_AT_artificial, cu))
        {
          FIELD_ARTIFICIAL (*fp) = 1;
@@ -15618,11 +15400,11 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
                            this_type->has_varargs ());
 
       /* Handle static member functions.
-         Dwarf2 has no clean way to discern C++ static and non-static
-         member functions.  G++ helps GDB by marking the first
-         parameter for non-static member functions (which is the this
-         pointer) as artificial.  We obtain this information from
-         read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
+        Dwarf2 has no clean way to discern C++ static and non-static
+        member functions.  G++ helps GDB by marking the first
+        parameter for non-static member functions (which is the this
+        pointer) as artificial.  We obtain this information from
+        read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
       if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0)
        fnp->voffset = VOFFSET_STATIC;
     }
@@ -15676,7 +15458,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   if (attr != nullptr)
     {
       if (attr->form_is_block () && attr->as_block ()->size > 0)
-        {
+       {
          struct dwarf_block *block = attr->as_block ();
 
          if (block->data[0] == DW_OP_constu)
@@ -15719,14 +15501,14 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
            }
        }
       else if (attr->form_is_section_offset ())
-        {
+       {
          dwarf2_complex_location_expr_complaint ();
-        }
+       }
       else
-        {
+       {
          dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
                                                 fieldname);
-        }
+       }
     }
   else
     {
@@ -15833,6 +15615,93 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
+/* Helper for quirk_ada_thick_pointer.  If TYPE is an array type that
+   requires rewriting, then copy it and return the updated copy.
+   Otherwise return nullptr.  */
+
+static struct type *
+rewrite_array_type (struct type *type)
+{
+  if (type->code () != TYPE_CODE_ARRAY)
+    return nullptr;
+
+  struct type *index_type = type->index_type ();
+  range_bounds *current_bounds = index_type->bounds ();
+
+  /* Handle multi-dimensional arrays.  */
+  struct type *new_target = rewrite_array_type (TYPE_TARGET_TYPE (type));
+  if (new_target == nullptr)
+    {
+      /* Maybe we don't need to rewrite this array.  */
+      if (current_bounds->low.kind () == PROP_CONST
+         && current_bounds->high.kind () == PROP_CONST)
+       return nullptr;
+    }
+
+  /* Either the target type was rewritten, or the bounds have to be
+     updated.  Either way we want to copy the type and update
+     everything.  */
+  struct type *copy = copy_type (type);
+  int nfields = copy->num_fields ();
+  field *new_fields
+    = ((struct field *) TYPE_ZALLOC (copy,
+                                    nfields * sizeof (struct field)));
+  memcpy (new_fields, copy->fields (), nfields * sizeof (struct field));
+  copy->set_fields (new_fields);
+  if (new_target != nullptr)
+    TYPE_TARGET_TYPE (copy) = new_target;
+
+  struct type *index_copy = copy_type (index_type);
+  range_bounds *bounds
+    = (struct range_bounds *) TYPE_ZALLOC (index_copy,
+                                          sizeof (range_bounds));
+  *bounds = *current_bounds;
+  bounds->low.set_const_val (1);
+  bounds->high.set_const_val (0);
+  index_copy->set_bounds (bounds);
+  copy->set_index_type (index_copy);
+
+  return copy;
+}
+
+/* While some versions of GCC will generate complicated DWARF for an
+   array (see quirk_ada_thick_pointer), more recent versions were
+   modified to emit an explicit thick pointer structure.  However, in
+   this case, the array still has DWARF expressions for its ranges,
+   and these must be ignored.  */
+
+static void
+quirk_ada_thick_pointer_struct (struct die_info *die, struct dwarf2_cu *cu,
+                               struct type *type)
+{
+  gdb_assert (cu->language == language_ada);
+
+  /* Check for a structure with two children.  */
+  if (type->code () != TYPE_CODE_STRUCT || type->num_fields () != 2)
+    return;
+
+  /* Check for P_ARRAY and P_BOUNDS members.  */
+  if (TYPE_FIELD_NAME (type, 0) == NULL
+      || strcmp (TYPE_FIELD_NAME (type, 0), "P_ARRAY") != 0
+      || TYPE_FIELD_NAME (type, 1) == NULL
+      || strcmp (TYPE_FIELD_NAME (type, 1), "P_BOUNDS") != 0)
+    return;
+
+  /* Make sure we're looking at a pointer to an array.  */
+  if (type->field (0).type ()->code () != TYPE_CODE_PTR)
+    return;
+
+  /* The Ada code already knows how to handle these types, so all that
+     we need to do is turn the bounds into static bounds.  However, we
+     don't want to rewrite existing array or index types in-place,
+     because those may be referenced in other contexts where this
+     rewriting is undesirable.  */
+  struct type *new_ary_type
+    = rewrite_array_type (TYPE_TARGET_TYPE (type->field (0).type ()));
+  if (new_ary_type != nullptr)
+    type->field (0).set_type (lookup_pointer_type (new_ary_type));
+}
+
 /* If the DIE has a DW_AT_alignment attribute, return its value, doing
    appropriate error checking and issuing complaints if there is a
    problem.  */
@@ -16019,7 +15888,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   if (cu->language == language_cplus && die->tag == DW_TAG_class_type)
-    TYPE_DECLARED_CLASS (type) = 1;
+    type->set_is_declared_class (true);
 
   /* Store the calling convention in the type if it's available in
      the die.  Otherwise the calling convention remains set to
@@ -16037,13 +15906,13 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr != nullptr)
     {
       if (attr->form_is_constant ())
-        TYPE_LENGTH (type) = attr->constant_value (0);
+       TYPE_LENGTH (type) = attr->constant_value (0);
       else
        {
          struct dynamic_prop prop;
          if (attr_to_dynamic_prop (attr, die, cu, &prop, cu->addr_type ()))
            type->add_dyn_prop (DYN_PROP_BYTE_SIZE, prop);
-          TYPE_LENGTH (type) = 0;
+         TYPE_LENGTH (type) = 0;
        }
     }
   else
@@ -16330,7 +16199,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
                    {
                      const char *fieldname = TYPE_FIELD_NAME (t, i);
 
-                      if (is_vtable_name (fieldname, cu))
+                     if (is_vtable_name (fieldname, cu))
                        {
                          set_type_vptr_fieldno (type, i);
                          break;
@@ -16352,8 +16221,8 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
                   && startswith (cu->producer, "IBM(R) XL C/C++ Advanced Edition"))
            {
              /* The IBM XLC compiler does not provide direct indication
-                of the containing type, but the vtable pointer is
-                always named __vfp.  */
+                of the containing type, but the vtable pointer is
+                always named __vfp.  */
 
              int i;
 
@@ -16408,6 +16277,8 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
   quirk_gcc_member_function_pointer (type, objfile);
   if (cu->language == language_rust && die->tag == DW_TAG_union_type)
     cu->rust_unions.push_back (type);
+  else if (cu->language == language_ada)
+    quirk_ada_thick_pointer_struct (die, cu, type);
 
   /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
      snapshots) has been known to create a die giving a declaration
@@ -16547,7 +16418,7 @@ update_enumeration_type_from_children (struct die_info *die,
     type->set_is_unsigned (true);
 
   if (flag_enum)
-    TYPE_FLAG_ENUM (type) = 1;
+    type->set_is_flag_enum (true);
 }
 
 /* Given a DW_AT_enumeration_type die, set its type.  We do not
@@ -16631,7 +16502,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
        set_type_align (type, TYPE_RAW_ALIGN (underlying_type));
     }
 
-  TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
+  type->set_is_declared_class (dwarf2_flag_true_p (die, DW_AT_enum_class, cu));
 
   set_die_type (die, type, cu);
 
@@ -16693,15 +16564,272 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (cu->per_cu->is_debug_types
       && die_is_declaration (die, cu))
     {
-      struct signatured_type *sig_type;
+      struct signatured_type *sig_type;
+
+      sig_type = (struct signatured_type *) cu->per_cu;
+      gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
+      if (sig_type->type_offset_in_section != die->sect_off)
+       return;
+    }
+
+  new_symbol (die, this_type, cu);
+}
+
+/* Helper function for quirk_ada_thick_pointer that examines a bounds
+   expression for an index type and finds the corresponding field
+   offset in the hidden "P_BOUNDS" structure.  Returns true on success
+   and updates *FIELD, false if it fails to recognize an
+   expression.  */
+
+static bool
+recognize_bound_expression (struct die_info *die, enum dwarf_attribute name,
+                           int *bounds_offset, struct field *field,
+                           struct dwarf2_cu *cu)
+{
+  struct attribute *attr = dwarf2_attr (die, name, cu);
+  if (attr == nullptr || !attr->form_is_block ())
+    return false;
+
+  const struct dwarf_block *block = attr->as_block ();
+  const gdb_byte *start = block->data;
+  const gdb_byte *end = block->data + block->size;
+
+  /* The expression to recognize generally looks like:
+
+     (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref;
+     DW_OP_plus_uconst: 4; DW_OP_deref_size: 4)
+
+     However, the second "plus_uconst" may be missing:
+
+     (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref;
+     DW_OP_deref_size: 4)
+
+     This happens when the field is at the start of the structure.
+
+     Also, the final deref may not be sized:
+
+     (DW_OP_push_object_address; DW_OP_plus_uconst: 4; DW_OP_deref;
+     DW_OP_deref)
+
+     This happens when the size of the index type happens to be the
+     same as the architecture's word size.  This can occur with or
+     without the second plus_uconst.  */
+
+  if (end - start < 2)
+    return false;
+  if (*start++ != DW_OP_push_object_address)
+    return false;
+  if (*start++ != DW_OP_plus_uconst)
+    return false;
+
+  uint64_t this_bound_off;
+  start = gdb_read_uleb128 (start, end, &this_bound_off);
+  if (start == nullptr || (int) this_bound_off != this_bound_off)
+    return false;
+  /* Update *BOUNDS_OFFSET if needed, or alternatively verify that it
+     is consistent among all bounds.  */
+  if (*bounds_offset == -1)
+    *bounds_offset = this_bound_off;
+  else if (*bounds_offset != this_bound_off)
+    return false;
+
+  if (start == end || *start++ != DW_OP_deref)
+    return false;
+
+  int offset = 0;
+  if (start ==end)
+    return false;
+  else if (*start == DW_OP_deref_size || *start == DW_OP_deref)
+    {
+      /* This means an offset of 0.  */
+    }
+  else if (*start++ != DW_OP_plus_uconst)
+    return false;
+  else
+    {
+      /* The size is the parameter to DW_OP_plus_uconst.  */
+      uint64_t val;
+      start = gdb_read_uleb128 (start, end, &val);
+      if (start == nullptr)
+       return false;
+      if ((int) val != val)
+       return false;
+      offset = val;
+    }
+
+  if (start == end)
+    return false;
+
+  uint64_t size;
+  if (*start == DW_OP_deref_size)
+    {
+      start = gdb_read_uleb128 (start + 1, end, &size);
+      if (start == nullptr)
+       return false;
+    }
+  else if (*start == DW_OP_deref)
+    {
+      size = cu->header.addr_size;
+      ++start;
+    }
+  else
+    return false;
+
+  SET_FIELD_BITPOS (*field, 8 * offset);
+  if (size != TYPE_LENGTH (field->type ()))
+    FIELD_BITSIZE (*field) = 8 * size;
+
+  return true;
+}
+
+/* With -fgnat-encodings=minimal, gcc will emit some unusual DWARF for
+   some kinds of Ada arrays:
+
+   <1><11db>: Abbrev Number: 7 (DW_TAG_array_type)
+      <11dc>   DW_AT_name        : (indirect string, offset: 0x1bb8): string
+      <11e0>   DW_AT_data_location: 2 byte block: 97 6
+         (DW_OP_push_object_address; DW_OP_deref)
+      <11e3>   DW_AT_type        : <0x1173>
+      <11e7>   DW_AT_sibling     : <0x1201>
+   <2><11eb>: Abbrev Number: 8 (DW_TAG_subrange_type)
+      <11ec>   DW_AT_type        : <0x1206>
+      <11f0>   DW_AT_lower_bound : 6 byte block: 97 23 8 6 94 4
+         (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref;
+          DW_OP_deref_size: 4)
+      <11f7>   DW_AT_upper_bound : 8 byte block: 97 23 8 6 23 4 94 4
+         (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref;
+          DW_OP_plus_uconst: 4; DW_OP_deref_size: 4)
+
+   This actually represents a "thick pointer", which is a structure
+   with two elements: one that is a pointer to the array data, and one
+   that is a pointer to another structure; this second structure holds
+   the array bounds.
+
+   This returns a new type on success, or nullptr if this didn't
+   recognize the type.  */
+
+static struct type *
+quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
+                        struct type *type)
+{
+  struct attribute *attr = dwarf2_attr (die, DW_AT_data_location, cu);
+  /* So far we've only seen this with block form.  */
+  if (attr == nullptr || !attr->form_is_block ())
+    return nullptr;
+
+  /* Note that this will fail if the structure layout is changed by
+     the compiler.  However, we have no good way to recognize some
+     other layout, because we don't know what expression the compiler
+     might choose to emit should this happen.  */
+  struct dwarf_block *blk = attr->as_block ();
+  if (blk->size != 2
+      || blk->data[0] != DW_OP_push_object_address
+      || blk->data[1] != DW_OP_deref)
+    return nullptr;
+
+  int bounds_offset = -1;
+  int max_align = -1;
+  std::vector<struct field> range_fields;
+  for (struct die_info *child_die = die->child;
+       child_die;
+       child_die = child_die->sibling)
+    {
+      if (child_die->tag == DW_TAG_subrange_type)
+       {
+         struct type *underlying = read_subrange_index_type (child_die, cu);
+
+         int this_align = type_align (underlying);
+         if (this_align > max_align)
+           max_align = this_align;
+
+         range_fields.emplace_back ();
+         range_fields.emplace_back ();
+
+         struct field &lower = range_fields[range_fields.size () - 2];
+         struct field &upper = range_fields[range_fields.size () - 1];
+
+         lower.set_type (underlying);
+         FIELD_ARTIFICIAL (lower) = 1;
+
+         upper.set_type (underlying);
+         FIELD_ARTIFICIAL (upper) = 1;
+
+         if (!recognize_bound_expression (child_die, DW_AT_lower_bound,
+                                          &bounds_offset, &lower, cu)
+             || !recognize_bound_expression (child_die, DW_AT_upper_bound,
+                                             &bounds_offset, &upper, cu))
+           return nullptr;
+       }
+    }
+
+  /* This shouldn't really happen, but double-check that we found
+     where the bounds are stored.  */
+  if (bounds_offset == -1)
+    return nullptr;
+
+  struct objfile *objfile = cu->per_objfile->objfile;
+  for (int i = 0; i < range_fields.size (); i += 2)
+    {
+      char name[20];
 
-      sig_type = (struct signatured_type *) cu->per_cu;
-      gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
-      if (sig_type->type_offset_in_section != die->sect_off)
-       return;
+      /* Set the name of each field in the bounds.  */
+      xsnprintf (name, sizeof (name), "LB%d", i / 2);
+      FIELD_NAME (range_fields[i]) = objfile->intern (name);
+      xsnprintf (name, sizeof (name), "UB%d", i / 2);
+      FIELD_NAME (range_fields[i + 1]) = objfile->intern (name);
     }
 
-  new_symbol (die, this_type, cu);
+  struct type *bounds = alloc_type (objfile);
+  bounds->set_code (TYPE_CODE_STRUCT);
+
+  bounds->set_num_fields (range_fields.size ());
+  bounds->set_fields
+    ((struct field *) TYPE_ALLOC (bounds, (bounds->num_fields ()
+                                          * sizeof (struct field))));
+  memcpy (bounds->fields (), range_fields.data (),
+         bounds->num_fields () * sizeof (struct field));
+
+  int last_fieldno = range_fields.size () - 1;
+  int bounds_size = (TYPE_FIELD_BITPOS (bounds, last_fieldno) / 8
+                    + TYPE_LENGTH (bounds->field (last_fieldno).type ()));
+  TYPE_LENGTH (bounds) = align_up (bounds_size, max_align);
+
+  /* Rewrite the existing array type in place.  Specifically, we
+     remove any dynamic properties we might have read, and we replace
+     the index types.  */
+  struct type *iter = type;
+  for (int i = 0; i < range_fields.size (); i += 2)
+    {
+      gdb_assert (iter->code () == TYPE_CODE_ARRAY);
+      iter->main_type->dyn_prop_list = nullptr;
+      iter->set_index_type
+       (create_static_range_type (NULL, bounds->field (i).type (), 1, 0));
+      iter = TYPE_TARGET_TYPE (iter);
+    }
+
+  struct type *result = alloc_type (objfile);
+  result->set_code (TYPE_CODE_STRUCT);
+
+  result->set_num_fields (2);
+  result->set_fields
+    ((struct field *) TYPE_ZALLOC (result, (result->num_fields ()
+                                           * sizeof (struct field))));
+
+  /* The names are chosen to coincide with what the compiler does with
+     -fgnat-encodings=all, which the Ada code in gdb already
+     understands.  */
+  TYPE_FIELD_NAME (result, 0) = "P_ARRAY";
+  result->field (0).set_type (lookup_pointer_type (type));
+
+  TYPE_FIELD_NAME (result, 1) = "P_BOUNDS";
+  result->field (1).set_type (lookup_pointer_type (bounds));
+  SET_FIELD_BITPOS (result->field (1), 8 * bounds_offset);
+
+  result->set_name (type->name ());
+  TYPE_LENGTH (result) = (TYPE_LENGTH (result->field (0).type ())
+                         + TYPE_LENGTH (result->field (1).type ()));
+
+  return result;
 }
 
 /* Extract all information from a DW_TAG_array_type DIE and put it in
@@ -16773,16 +16901,24 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
        {
          struct type *child_type = read_type_die (child_die, cu);
 
-          if (child_type != NULL)
-            {
+         if (child_type != NULL)
+           {
              /* The range type was succesfully read.  Save it for the
-                 array type creation.  */
+                array type creation.  */
              range_types.push_back (child_type);
-            }
+           }
        }
       child_die = child_die->sibling;
     }
 
+  if (range_types.empty ())
+    {
+      complaint (_("unable to find array range - DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_objfile->objfile));
+      return NULL;
+    }
+
   /* Dwarf2 dimensions are output from left to right, create the
      necessary array types in backwards order.  */
 
@@ -16793,17 +16929,27 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
       int i = 0;
 
       while (i < range_types.size ())
-       type = create_array_type_with_stride (NULL, type, range_types[i++],
-                                             byte_stride_prop, bit_stride);
+       {
+         type = create_array_type_with_stride (NULL, type, range_types[i++],
+                                               byte_stride_prop, bit_stride);
+         bit_stride = 0;
+         byte_stride_prop = nullptr;
+       }
     }
   else
     {
       size_t ndim = range_types.size ();
       while (ndim-- > 0)
-       type = create_array_type_with_stride (NULL, type, range_types[ndim],
-                                             byte_stride_prop, bit_stride);
+       {
+         type = create_array_type_with_stride (NULL, type, range_types[ndim],
+                                               byte_stride_prop, bit_stride);
+         bit_stride = 0;
+         byte_stride_prop = nullptr;
+       }
     }
 
+  gdb_assert (type != element_type);
+
   /* Understand Dwarf2 support for vector types (like they occur on
      the PowerPC w/ AltiVec).  Gcc just adds another attribute to the
      array type.  This is not part of the Dwarf2/3 standard yet, but a
@@ -16833,8 +16979,16 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
 
   maybe_set_alignment (cu, die, type);
 
+  struct type *replacement_type = nullptr;
+  if (cu->language == language_ada)
+    {
+      replacement_type = quirk_ada_thick_pointer (die, cu, type);
+      if (replacement_type != nullptr)
+       type = replacement_type;
+    }
+
   /* Install the type in the die.  */
-  set_die_type (die, type, cu);
+  set_die_type (die, type, cu, replacement_type != nullptr);
 
   /* set_die_type should be already done.  */
   set_descriptive_type (type, die, cu);
@@ -16996,20 +17150,20 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
     {
       /* Support the .debug_loc offsets.  */
       if (attr->form_is_block ())
-        {
+       {
          /* Ok.  */
-        }
+       }
       else if (attr->form_is_section_offset ())
-        {
+       {
          dwarf2_complex_location_expr_complaint ();
          attr = NULL;
-        }
+       }
       else
-        {
+       {
          dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
                                                 "common block member");
          attr = NULL;
-        }
+       }
     }
 
   if (die->child != NULL)
@@ -17346,7 +17500,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
 
 static struct type *
 read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
-                          enum type_code refcode)
+                         enum type_code refcode)
 {
   struct comp_unit_head *cu_header = &cu->header;
   struct type *type, *target_type;
@@ -17678,8 +17832,8 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
       int nparams, iparams;
 
       /* Count the number of parameters.
-         FIXME: GDB currently ignores vararg functions, but knows about
-         vararg member functions.  */
+        FIXME: GDB currently ignores vararg functions, but knows about
+        vararg member functions.  */
       nparams = 0;
       child_die = die->child;
       while (child_die && child_die->tag)
@@ -17803,6 +17957,279 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
   return this_type;
 }
 
+/* Helper for get_dwarf2_rational_constant that computes the value of
+   a given gmp_mpz given an attribute.  */
+
+static void
+get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+{
+  /* GCC will sometimes emit a 16-byte constant value as a DWARF
+     location expression that pushes an implicit value.  */
+  if (attr->form == DW_FORM_exprloc)
+    {
+      dwarf_block *blk = attr->as_block ();
+      if (blk->size > 0 && blk->data[0] == DW_OP_implicit_value)
+       {
+         uint64_t len;
+         const gdb_byte *ptr = safe_read_uleb128 (blk->data + 1,
+                                                  blk->data + blk->size,
+                                                  &len);
+         if (ptr - blk->data + len <= blk->size)
+           {
+             mpz_import (value->val, len,
+                         bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                         1, 0, 0, ptr);
+             return;
+           }
+       }
+
+      /* On failure set it to 1.  */
+      *value = gdb_mpz (1);
+    }
+  else if (attr->form_is_block ())
+    {
+      dwarf_block *blk = attr->as_block ();
+      mpz_import (value->val, blk->size,
+                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                 1, 0, 0, blk->data);
+    }
+  else
+    *value = gdb_mpz (attr->constant_value (1));
+}
+
+/* Assuming DIE is a rational DW_TAG_constant, read the DIE's
+   numerator and denominator into NUMERATOR and DENOMINATOR (resp).
+
+   If the numerator and/or numerator attribute is missing,
+   a complaint is filed, and NUMERATOR and DENOMINATOR are left
+   untouched.  */
+
+static void
+get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
+                             gdb_mpz *numerator, gdb_mpz *denominator)
+{
+  struct attribute *num_attr, *denom_attr;
+
+  num_attr = dwarf2_attr (die, DW_AT_GNU_numerator, cu);
+  if (num_attr == nullptr)
+    complaint (_("DW_AT_GNU_numerator missing in %s DIE at %s"),
+              dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+
+  denom_attr = dwarf2_attr (die, DW_AT_GNU_denominator, cu);
+  if (denom_attr == nullptr)
+    complaint (_("DW_AT_GNU_denominator missing in %s DIE at %s"),
+              dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+
+  if (num_attr == nullptr || denom_attr == nullptr)
+    return;
+
+  get_mpz (cu, numerator, num_attr);
+  get_mpz (cu, denominator, denom_attr);
+}
+
+/* Same as get_dwarf2_rational_constant, but extracting an unsigned
+   rational constant, rather than a signed one.
+
+   If the rational constant has a negative value, a complaint
+   is filed, and NUMERATOR and DENOMINATOR are left untouched.  */
+
+static void
+get_dwarf2_unsigned_rational_constant (struct die_info *die,
+                                      struct dwarf2_cu *cu,
+                                      gdb_mpz *numerator,
+                                      gdb_mpz *denominator)
+{
+  gdb_mpz num (1);
+  gdb_mpz denom (1);
+
+  get_dwarf2_rational_constant (die, cu, &num, &denom);
+  if (mpz_sgn (num.val) == -1 && mpz_sgn (denom.val) == -1)
+    {
+      mpz_neg (num.val, num.val);
+      mpz_neg (denom.val, denom.val);
+    }
+  else if (mpz_sgn (num.val) == -1)
+    {
+      complaint (_("unexpected negative value for DW_AT_GNU_numerator"
+                  " in DIE at %s"),
+                sect_offset_str (die->sect_off));
+      return;
+    }
+  else if (mpz_sgn (denom.val) == -1)
+    {
+      complaint (_("unexpected negative value for DW_AT_GNU_denominator"
+                  " in DIE at %s"),
+                sect_offset_str (die->sect_off));
+      return;
+    }
+
+  *numerator = std::move (num);
+  *denominator = std::move (denom);
+}
+
+/* Assuming that ENCODING is a string whose contents starting at the
+   K'th character is "_nn" where "nn" is a decimal number, scan that
+   number and set RESULT to the value. K is updated to point to the
+   character immediately following the number.
+
+   If the string does not conform to the format described above, false
+   is returned, and K may or may not be changed.  */
+
+static bool
+ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
+{
+  /* The next character should be an underscore ('_') followed
+     by a digit.  */
+  if (encoding[k] != '_' || !isdigit (encoding[k + 1]))
+    return false;
+
+  /* Skip the underscore.  */
+  k++;
+  int start = k;
+
+  /* Determine the number of digits for our number.  */
+  while (isdigit (encoding[k]))
+    k++;
+  if (k == start)
+    return false;
+
+  std::string copy (&encoding[start], k - start);
+  if (mpz_set_str (result->val, copy.c_str (), 10) == -1)
+    return false;
+
+  return true;
+}
+
+/* Scan two numbers from ENCODING at OFFSET, assuming the string is of
+   the form _NN_DD, where NN and DD are decimal numbers.  Set NUM and
+   DENOM, update OFFSET, and return true on success.  Return false on
+   failure.  */
+
+static bool
+ada_get_gnat_encoded_ratio (const char *encoding, int &offset,
+                           gdb_mpz *num, gdb_mpz *denom)
+{
+  if (!ada_get_gnat_encoded_number (encoding, offset, num))
+    return false;
+  return ada_get_gnat_encoded_number (encoding, offset, denom);
+}
+
+/* Assuming DIE corresponds to a fixed point type, finish the creation
+   of the corresponding TYPE by setting its type-specific data.  CU is
+   the DIE's CU.  SUFFIX is the "XF" type name suffix coming from GNAT
+   encodings.  It is nullptr if the GNAT encoding should be
+   ignored.  */
+
+static void
+finish_fixed_point_type (struct type *type, const char *suffix,
+                        struct die_info *die, struct dwarf2_cu *cu)
+{
+  gdb_assert (type->code () == TYPE_CODE_FIXED_POINT
+             && TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FIXED_POINT);
+
+  /* If GNAT encodings are preferred, don't examine the
+     attributes.  */
+  struct attribute *attr = nullptr;
+  if (suffix == nullptr)
+    {
+      attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
+      if (attr == nullptr)
+       attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
+      if (attr == nullptr)
+       attr = dwarf2_attr (die, DW_AT_small, cu);
+    }
+
+  /* Numerator and denominator of our fixed-point type's scaling factor.
+     The default is a scaling factor of 1, which we use as a fallback
+     when we are not able to decode it (problem with the debugging info,
+     unsupported forms, bug in GDB, etc...).  Using that as the default
+     allows us to at least print the unscaled value, which might still
+     be useful to a user.  */
+  gdb_mpz scale_num (1);
+  gdb_mpz scale_denom (1);
+
+  if (attr == nullptr)
+    {
+      int offset = 0;
+      if (suffix != nullptr
+         && ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+                                        &scale_denom)
+         /* The number might be encoded as _nn_dd_nn_dd, where the
+            second ratio is the 'small value.  In this situation, we
+            want the second value.  */
+         && (suffix[offset] != '_'
+             || ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+                                            &scale_denom)))
+       {
+         /* Found it.  */
+       }
+      else
+       {
+         /* Scaling factor not found.  Assume a scaling factor of 1,
+            and hope for the best.  At least the user will be able to
+            see the encoded value.  */
+         scale_num = 1;
+         scale_denom = 1;
+         complaint (_("no scale found for fixed-point type (DIE at %s)"),
+                    sect_offset_str (die->sect_off));
+       }
+    }
+  else if (attr->name == DW_AT_binary_scale)
+    {
+      LONGEST scale_exp = attr->constant_value (0);
+      gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+
+      mpz_mul_2exp (num_or_denom->val, num_or_denom->val, std::abs (scale_exp));
+    }
+  else if (attr->name == DW_AT_decimal_scale)
+    {
+      LONGEST scale_exp = attr->constant_value (0);
+      gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+
+      mpz_ui_pow_ui (num_or_denom->val, 10, std::abs (scale_exp));
+    }
+  else if (attr->name == DW_AT_small)
+    {
+      struct die_info *scale_die;
+      struct dwarf2_cu *scale_cu = cu;
+
+      scale_die = follow_die_ref (die, attr, &scale_cu);
+      if (scale_die->tag == DW_TAG_constant)
+       get_dwarf2_unsigned_rational_constant (scale_die, scale_cu,
+                                              &scale_num, &scale_denom);
+      else
+       complaint (_("%s DIE not supported as target of DW_AT_small attribute"
+                    " (DIE at %s)"),
+                  dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+    }
+  else
+    {
+      complaint (_("unsupported scale attribute %s for fixed-point type"
+                  " (DIE at %s)"),
+                dwarf_attr_name (attr->name),
+                sect_offset_str (die->sect_off));
+    }
+
+  gdb_mpq &scaling_factor = type->fixed_point_info ().scaling_factor;
+  mpz_set (mpq_numref (scaling_factor.val), scale_num.val);
+  mpz_set (mpq_denref (scaling_factor.val), scale_denom.val);
+  mpq_canonicalize (scaling_factor.val);
+}
+
+/* The gnat-encoding suffix for fixed point.  */
+
+#define GNAT_FIXED_POINT_SUFFIX "___XF_"
+
+/* If NAME encodes an Ada fixed-point type, return a pointer to the
+   "XF" suffix of the name.  The text after this is what encodes the
+   'small and 'delta information.  Otherwise, return nullptr.  */
+
+static const char *
+gnat_encoded_fixed_point_type_info (const char *name)
+{
+  return strstr (name, GNAT_FIXED_POINT_SUFFIX);
+}
+
 /* Allocate a floating-point type of size BITS and name NAME.  Pass NAME_HINT
    (which may be different from NAME) to the architecture back-end to allow
    it to guess the correct format if necessary.  */
@@ -17844,6 +18271,32 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
   return type;
 }
 
+/* Return true if DIE has a DW_AT_small attribute whose value is
+   a constant rational, where both the numerator and denominator
+   are equal to zero.
+
+   CU is the DIE's Compilation Unit.  */
+
+static bool
+has_zero_over_zero_small_attribute (struct die_info *die,
+                                   struct dwarf2_cu *cu)
+{
+  struct attribute *attr = dwarf2_attr (die, DW_AT_small, cu);
+  if (attr == nullptr)
+    return false;
+
+  struct dwarf2_cu *scale_cu = cu;
+  struct die_info *scale_die
+    = follow_die_ref (die, attr, &scale_cu);
+
+  if (scale_die->tag != DW_TAG_constant)
+    return false;
+
+  gdb_mpz num (1), denom (1);
+  get_dwarf2_rational_constant (scale_die, cu, &num, &denom);
+  return mpz_sgn (num.val) == 0 && mpz_sgn (denom.val) == 0;
+}
+
 /* Initialise and return a floating point type of size BITS suitable for
    use as a component of a complex number.  The NAME_HINT is passed through
    when initialising the floating point type and is the name of the complex
@@ -17954,6 +18407,49 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
        }
     }
 
+  if ((encoding == DW_ATE_signed_fixed || encoding == DW_ATE_unsigned_fixed)
+      && cu->language == language_ada
+      && has_zero_over_zero_small_attribute (die, cu))
+    {
+      /* brobecker/2018-02-24: This is a fixed point type for which
+        the scaling factor is represented as fraction whose value
+        does not make sense (zero divided by zero), so we should
+        normally never see these.  However, there is a small category
+        of fixed point types for which GNAT is unable to provide
+        the scaling factor via the standard DWARF mechanisms, and
+        for which the info is provided via the GNAT encodings instead.
+        This is likely what this DIE is about.  */
+      encoding = (encoding == DW_ATE_signed_fixed
+                 ? DW_ATE_signed
+                 : DW_ATE_unsigned);
+    }
+
+  /* With GNAT encodings, fixed-point information will be encoded in
+     the type name.  Note that this can also occur with the above
+     zero-over-zero case, which is why this is a separate "if" rather
+     than an "else if".  */
+  const char *gnat_encoding_suffix = nullptr;
+  if ((encoding == DW_ATE_signed || encoding == DW_ATE_unsigned)
+      && cu->language == language_ada
+      && name != nullptr)
+    {
+      gnat_encoding_suffix = gnat_encoded_fixed_point_type_info (name);
+      if (gnat_encoding_suffix != nullptr)
+       {
+         gdb_assert (startswith (gnat_encoding_suffix,
+                                 GNAT_FIXED_POINT_SUFFIX));
+         name = obstack_strndup (&cu->per_objfile->objfile->objfile_obstack,
+                                 name, gnat_encoding_suffix - name);
+         /* Use -1 here so that SUFFIX points at the "_" after the
+            "XF".  */
+         gnat_encoding_suffix += strlen (GNAT_FIXED_POINT_SUFFIX) - 1;
+
+         encoding = (encoding == DW_ATE_signed
+                     ? DW_ATE_signed_fixed
+                     : DW_ATE_unsigned_fixed);
+       }
+    }
+
   switch (encoding)
     {
       case DW_ATE_address:
@@ -18030,6 +18526,14 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
          return set_die_type (die, type, cu);
        }
        break;
+      case DW_ATE_signed_fixed:
+       type = init_fixed_point_type (objfile, bits, 0, name);
+       finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
+       break;
+      case DW_ATE_unsigned_fixed:
+       type = init_fixed_point_type (objfile, bits, 1, name);
+       finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
+       break;
 
       default:
        complaint (_("unsupported DW_AT_encoding: '%s'"),
@@ -18566,7 +19070,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
                 int num_extra_attrs)
 {
   unsigned int abbrev_number, bytes_read, i;
-  struct abbrev_info *abbrev;
+  const struct abbrev_info *abbrev;
   struct die_info *die;
   struct dwarf2_cu *cu = reader->cu;
   bfd *abfd = reader->abfd;
@@ -18620,7 +19124,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
 
   attr = die->attr (DW_AT_rnglists_base);
   if (attr != nullptr)
-    cu->ranges_base = attr->as_unsigned ();
+    cu->rnglists_base = attr->as_unsigned ();
 
   if (any_need_reprocess)
     {
@@ -18664,20 +19168,27 @@ read_full_die (const struct die_reader_specs *reader,
    symbol for.  */
 
 static int
-is_type_tag_for_partial (int tag)
+is_type_tag_for_partial (int tag, enum language lang)
 {
   switch (tag)
     {
 #if 0
     /* Some types that would be reasonable to generate partial symbols for,
-       that we don't at present.  */
-    case DW_TAG_array_type:
+       that we don't at present.  Note that normally this does not
+       matter, mainly because C compilers don't give names to these
+       types, but instead emit DW_TAG_typedef.  */
     case DW_TAG_file_type:
     case DW_TAG_ptr_to_member_type:
     case DW_TAG_set_type:
     case DW_TAG_string_type:
     case DW_TAG_subroutine_type:
 #endif
+
+      /* GNAT may emit an array with a name, but no typedef, so we
+        need to make a symbol in this case.  */
+    case DW_TAG_array_type:
+      return lang == language_ada;
+
     case DW_TAG_base_type:
     case DW_TAG_class_type:
     case DW_TAG_interface_type:
@@ -18723,7 +19234,8 @@ load_partial_dies (const struct die_reader_specs *reader,
 
   while (1)
     {
-      abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
+      const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+                                                  &bytes_read);
 
       /* A NULL abbrev means the end of a series of children.  */
       if (abbrev == NULL)
@@ -18771,7 +19283,7 @@ load_partial_dies (const struct die_reader_specs *reader,
         later variables referencing them via DW_AT_specification (for
         static members).  */
       if (!load_all
-         && !is_type_tag_for_partial (abbrev->tag)
+         && !is_type_tag_for_partial (abbrev->tag, cu->language)
          && abbrev->tag != DW_TAG_constant
          && abbrev->tag != DW_TAG_enumerator
          && abbrev->tag != DW_TAG_subprogram
@@ -18815,6 +19327,7 @@ load_partial_dies (const struct die_reader_specs *reader,
          && pdi.is_declaration == 0
          && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
              || pdi.tag == DW_TAG_base_type
+             || pdi.tag == DW_TAG_array_type
              || pdi.tag == DW_TAG_subrange_type))
        {
          if (building_psymtab && pdi.raw_name != NULL)
@@ -18954,7 +19467,7 @@ load_partial_dies (const struct die_reader_specs *reader,
 }
 
 partial_die_info::partial_die_info (sect_offset sect_off_,
-                                   struct abbrev_info *abbrev)
+                                   const struct abbrev_info *abbrev)
   : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
 {
 }
@@ -18993,12 +19506,12 @@ partial_die_info::read (const struct die_reader_specs *reader,
       attribute attr;
       info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
       /* String and address offsets that need to do the reprocessing have
-         already been read at this point, so there is no need to wait until
+        already been read at this point, so there is no need to wait until
         the loop terminates to do the reprocessing.  */
       if (attr.requires_reprocessing_p ())
        read_attribute_reprocess (reader, &attr, tag);
       /* Store the data if it is of an attribute we want to keep in a
-         partial symbol table.  */
+        partial symbol table.  */
       switch (attr.name)
        {
        case DW_AT_name:
@@ -19040,20 +19553,20 @@ partial_die_info::read (const struct die_reader_specs *reader,
                high_pc_relative = 1;
          break;
        case DW_AT_location:
-          /* Support the .debug_loc offsets.  */
-          if (attr.form_is_block ())
-            {
+         /* Support the .debug_loc offsets.  */
+         if (attr.form_is_block ())
+           {
              d.locdesc = attr.as_block ();
-            }
-          else if (attr.form_is_section_offset ())
-            {
+           }
+         else if (attr.form_is_section_offset ())
+           {
              dwarf2_complex_location_expr_complaint ();
-            }
-          else
-            {
+           }
+         else
+           {
              dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
                                                     "partial symbol information");
-            }
+           }
          break;
        case DW_AT_external:
          is_external = attr.as_boolean ();
@@ -19091,12 +19604,12 @@ partial_die_info::read (const struct die_reader_specs *reader,
                sibling = sibling_ptr;
            }
          break;
-        case DW_AT_byte_size:
-          has_byte_size = 1;
-          break;
-        case DW_AT_const_value:
-          has_const_value = 1;
-          break;
+       case DW_AT_byte_size:
+         has_byte_size = 1;
+         break;
+       case DW_AT_const_value:
+         has_const_value = 1;
+         break;
        case DW_AT_calling_convention:
          /* DWARF doesn't provide a way to identify a program's source-level
             entry point.  DW_AT_calling_convention attributes are only meant
@@ -19140,26 +19653,15 @@ partial_die_info::read (const struct die_reader_specs *reader,
 
        case DW_AT_ranges:
          {
-           /* DW_AT_rnglists_base does not apply to DIEs from the DWO
-              skeleton.  We take advantage of the fact the DW_AT_ranges
-              does not appear in DW_TAG_compile_unit of DWO files.
-
-              Attributes of the form DW_FORM_rnglistx have already had
-               their value changed by read_rnglist_index and already
-              include DW_AT_rnglists_base, so don't need to add the ranges
-              base, either.  */
-           int need_ranges_base = (tag != DW_TAG_compile_unit
-                                   && attr.form != DW_FORM_rnglistx);
-           /* It would be nice to reuse dwarf2_get_pc_bounds here,
-              but that requires a full DIE, so instead we just
-              reimplement it.  */
-           unsigned int ranges_offset = (attr.constant_value (0)
-                                         + (need_ranges_base
-                                            ? cu->ranges_base
-                                            : 0));
-
-           /* Value of the DW_AT_ranges attribute is the offset in the
-              .debug_ranges section.  */
+           /* Offset in the .debug_ranges or .debug_rnglist section (depending
+              on DWARF version).  */
+           ULONGEST ranges_offset = attr.as_unsigned ();
+
+           /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
+              this value.  */
+           if (tag != DW_TAG_compile_unit)
+             ranges_offset += cu->gnu_ranges_base;
+
            if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
                                    nullptr, tag))
              has_pc_info = 1;
@@ -19484,22 +19986,30 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
 }
 
 /* Read the .debug_loclists or .debug_rnglists header (they are the same format)
-   contents from the given SECTION in the HEADER.  */
+   contents from the given SECTION in the HEADER.
+
+   HEADER_OFFSET is the offset of the header in the section.  */
 static void
 read_loclists_rnglists_header (struct loclists_rnglists_header *header,
-                              struct dwarf2_section_info *section)
+                              struct dwarf2_section_info *section,
+                              sect_offset header_offset)
 {
   unsigned int bytes_read;
   bfd *abfd = section->get_bfd_owner ();
-  const gdb_byte *info_ptr = section->buffer;
+  const gdb_byte *info_ptr = section->buffer + to_underlying (header_offset);
+
   header->length = read_initial_length (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
+
   header->version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
+
   header->addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
+
   header->segment_collector_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
+
   header->offset_entry_count = read_4_bytes (abfd, info_ptr);
 }
 
@@ -19527,42 +20037,66 @@ lookup_loclist_base (struct dwarf2_cu *cu)
 
 /* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset from the
    array of offsets in the .debug_loclists section.  */
-static CORE_ADDR
+
+static sect_offset
 read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct objfile *objfile = per_objfile->objfile;
   bfd *abfd = objfile->obfd;
+  ULONGEST loclist_header_size =
+    (cu->header.initial_length_size == 4 ? LOCLIST_HEADER_SIZE32
+     : LOCLIST_HEADER_SIZE64);
   ULONGEST loclist_base = lookup_loclist_base (cu);
+
+  /* Offset in .debug_loclists of the offset for LOCLIST_INDEX.  */
+  ULONGEST start_offset =
+    loclist_base + loclist_index * cu->header.offset_size;
+
+  /* Get loclists section.  */
   struct dwarf2_section_info *section = cu_debug_loc_section (cu);
 
+  /* Read the loclists section content.  */
   section->read (objfile);
   if (section->buffer == NULL)
-    complaint (_("DW_FORM_loclistx used without .debug_loclists "
-               "section [in module %s]"), objfile_name (objfile));
+    error (_("DW_FORM_loclistx used without .debug_loclists "
+            "section [in module %s]"), objfile_name (objfile));
+
+  /* DW_AT_loclists_base points after the .debug_loclists contribution header,
+     so if loclist_base is smaller than the header size, we have a problem.  */
+  if (loclist_base < loclist_header_size)
+    error (_("DW_AT_loclists_base is smaller than header size [in module %s]"),
+          objfile_name (objfile));
+
+  /* Read the header of the loclists contribution.  */
   struct loclists_rnglists_header header;
-  read_loclists_rnglists_header (&header, section);
+  read_loclists_rnglists_header (&header, section,
+                                (sect_offset) (loclist_base - loclist_header_size));
+
+  /* Verify the loclist index is valid.  */
   if (loclist_index >= header.offset_entry_count)
-    complaint (_("DW_FORM_loclistx pointing outside of "
-               ".debug_loclists offset array [in module %s]"),
-               objfile_name (objfile));
-  if (loclist_base + loclist_index * cu->header.offset_size
-       >= section->size)
-    complaint (_("DW_FORM_loclistx pointing outside of "
-               ".debug_loclists section [in module %s]"),
-               objfile_name (objfile));
-  const gdb_byte *info_ptr
-    = section->buffer + loclist_base + loclist_index * cu->header.offset_size;
+    error (_("DW_FORM_loclistx pointing outside of "
+            ".debug_loclists offset array [in module %s]"),
+          objfile_name (objfile));
+
+  /* Validate that reading won't go beyond the end of the section.  */
+  if (start_offset + cu->header.offset_size > section->size)
+    error (_("Reading DW_FORM_loclistx index beyond end of"
+            ".debug_loclists section [in module %s]"),
+          objfile_name (objfile));
+
+  const gdb_byte *info_ptr = section->buffer + start_offset;
 
   if (cu->header.offset_size == 4)
-    return bfd_get_32 (abfd, info_ptr) + loclist_base;
+    return (sect_offset) (bfd_get_32 (abfd, info_ptr) + loclist_base);
   else
-    return bfd_get_64 (abfd, info_ptr) + loclist_base;
+    return (sect_offset) (bfd_get_64 (abfd, info_ptr) + loclist_base);
 }
 
 /* Given a DW_FORM_rnglistx value RNGLIST_INDEX, fetch the offset from the
    array of offsets in the .debug_rnglists section.  */
-static CORE_ADDR
+
+static sect_offset
 read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
                    dwarf_tag tag)
 {
@@ -19572,8 +20106,14 @@ read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
   ULONGEST rnglist_header_size =
     (cu->header.initial_length_size == 4 ? RNGLIST_HEADER_SIZE32
      : RNGLIST_HEADER_SIZE64);
+
+  /* When reading a DW_FORM_rnglistx from a DWO, we read from the DWO's
+     .debug_rnglists.dwo section.  The rnglists base given in the skeleton
+     doesn't apply.  */
   ULONGEST rnglist_base =
-      (cu->dwo_unit != nullptr) ? rnglist_header_size : cu->ranges_base;
+      (cu->dwo_unit != nullptr) ? rnglist_header_size : cu->rnglists_base;
+
+  /* Offset in .debug_rnglists of the offset for RNGLIST_INDEX.  */
   ULONGEST start_offset =
     rnglist_base + rnglist_index * cu->header.offset_size;
 
@@ -19587,22 +20127,25 @@ read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
             "[in module %s]"),
           objfile_name (objfile));
 
-  /* Verify the rnglist index is valid.  */
+  /* DW_AT_rnglists_base points after the .debug_rnglists contribution header,
+     so if rnglist_base is smaller than the header size, we have a problem.  */
+  if (rnglist_base < rnglist_header_size)
+    error (_("DW_AT_rnglists_base is smaller than header size [in module %s]"),
+          objfile_name (objfile));
+
+  /* Read the header of the rnglists contribution.  */
   struct loclists_rnglists_header header;
-  read_loclists_rnglists_header (&header, section);
+  read_loclists_rnglists_header (&header, section,
+                                (sect_offset) (rnglist_base - rnglist_header_size));
+
+  /* Verify the rnglist index is valid.  */
   if (rnglist_index >= header.offset_entry_count)
     error (_("DW_FORM_rnglistx index pointing outside of "
             ".debug_rnglists offset array [in module %s]"),
           objfile_name (objfile));
 
-  /* Validate that the offset is within the section's range.  */
-  if (start_offset >= section->size)
-    error (_("DW_FORM_rnglistx pointing outside of "
-             ".debug_rnglists section [in module %s]"),
-          objfile_name (objfile));
-
   /* Validate that reading won't go beyond the end of the section.  */
-  if (start_offset + cu->header.offset_size > rnglist_base + section->size)
+  if (start_offset + cu->header.offset_size > section->size)
     error (_("Reading DW_FORM_rnglistx index beyond end of"
             ".debug_rnglists section [in module %s]"),
           objfile_name (objfile));
@@ -19610,9 +20153,9 @@ read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
   const gdb_byte *info_ptr = section->buffer + start_offset;
 
   if (cu->header.offset_size == 4)
-    return read_4_bytes (abfd, info_ptr) + rnglist_base;
+    return (sect_offset) (read_4_bytes (abfd, info_ptr) + rnglist_base);
   else
-    return read_8_bytes (abfd, info_ptr) + rnglist_base;
+    return (sect_offset) (read_8_bytes (abfd, info_ptr) + rnglist_base);
 }
 
 /* Process the attributes that had to be skipped in the first round. These
@@ -19630,13 +20173,23 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
       case DW_FORM_GNU_addr_index:
        attr->set_address (read_addr_index (cu,
                                            attr->as_unsigned_reprocess ()));
-        break;
+       break;
       case DW_FORM_loclistx:
-       attr->set_address (read_loclist_index (cu, attr->as_unsigned ()));
-        break;
+       {
+         sect_offset loclists_sect_off
+           = read_loclist_index (cu, attr->as_unsigned_reprocess ());
+
+         attr->set_unsigned (to_underlying (loclists_sect_off));
+       }
+       break;
       case DW_FORM_rnglistx:
-       attr->set_address (read_rnglist_index (cu, attr->as_unsigned (), tag));
-        break;
+       {
+         sect_offset rnglists_sect_off
+           = read_rnglist_index (cu, attr->as_unsigned_reprocess (), tag);
+
+         attr->set_unsigned (to_underlying (rnglists_sect_off));
+       }
+       break;
       case DW_FORM_strx:
       case DW_FORM_strx1:
       case DW_FORM_strx2:
@@ -19678,23 +20231,23 @@ read_attribute_value (const struct die_reader_specs *reader,
   switch (form)
     {
     case DW_FORM_ref_addr:
-      if (cu->header.version == 2)
-       attr->set_unsigned (cu->header.read_address (abfd, info_ptr,
+      if (cu_header->version == 2)
+       attr->set_unsigned (cu_header->read_address (abfd, info_ptr,
                                                     &bytes_read));
       else
-       attr->set_unsigned (cu->header.read_offset (abfd, info_ptr,
+       attr->set_unsigned (cu_header->read_offset (abfd, info_ptr,
                                                    &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_GNU_ref_alt:
-      attr->set_unsigned (cu->header.read_offset (abfd, info_ptr,
+      attr->set_unsigned (cu_header->read_offset (abfd, info_ptr,
                                                  &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_addr:
       {
        struct gdbarch *gdbarch = objfile->arch ();
-       CORE_ADDR addr = cu->header.read_address (abfd, info_ptr, &bytes_read);
+       CORE_ADDR addr = cu_header->read_address (abfd, info_ptr, &bytes_read);
        addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr);
        attr->set_address (addr);
        info_ptr += bytes_read;
@@ -19736,7 +20289,7 @@ read_attribute_value (const struct die_reader_specs *reader,
       attr->set_block (blk);
       break;
     case DW_FORM_sec_offset:
-      attr->set_unsigned (cu->header.read_offset (abfd, info_ptr,
+      attr->set_unsigned (cu_header->read_offset (abfd, info_ptr,
                                                  &bytes_read));
       info_ptr += bytes_read;
       break;
@@ -19775,7 +20328,7 @@ read_attribute_value (const struct die_reader_specs *reader,
       /* FALLTHROUGH */
     case DW_FORM_GNU_strp_alt:
       {
-       dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
+       dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd, true);
        LONGEST str_offset = cu_header->read_offset (abfd, info_ptr,
                                                     &bytes_read);
 
@@ -19825,22 +20378,22 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     case DW_FORM_ref1:
-      attr->set_unsigned ((to_underlying (cu->header.sect_off)
+      attr->set_unsigned ((to_underlying (cu_header->sect_off)
                           + read_1_byte (abfd, info_ptr)));
       info_ptr += 1;
       break;
     case DW_FORM_ref2:
-      attr->set_unsigned ((to_underlying (cu->header.sect_off)
+      attr->set_unsigned ((to_underlying (cu_header->sect_off)
                           + read_2_bytes (abfd, info_ptr)));
       info_ptr += 2;
       break;
     case DW_FORM_ref4:
-      attr->set_unsigned ((to_underlying (cu->header.sect_off)
+      attr->set_unsigned ((to_underlying (cu_header->sect_off)
                           + read_4_bytes (abfd, info_ptr)));
       info_ptr += 4;
       break;
     case DW_FORM_ref8:
-      attr->set_unsigned ((to_underlying (cu->header.sect_off)
+      attr->set_unsigned ((to_underlying (cu_header->sect_off)
                           + read_8_bytes (abfd, info_ptr)));
       info_ptr += 8;
       break;
@@ -19849,7 +20402,7 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      attr->set_unsigned ((to_underlying (cu->header.sect_off)
+      attr->set_unsigned ((to_underlying (cu_header->sect_off)
                           + read_unsigned_leb128 (abfd, info_ptr,
                                                   &bytes_read)));
       info_ptr += bytes_read;
@@ -19931,8 +20484,8 @@ read_attribute_value (const struct die_reader_specs *reader,
       && attr->as_unsigned () >= 0xffffffff)
     {
       complaint
-        (_("Suspicious DW_AT_byte_size value treated as zero instead of %s"),
-         hex_string (attr->as_unsigned ()));
+       (_("Suspicious DW_AT_byte_size value treated as zero instead of %s"),
+        hex_string (attr->as_unsigned ()));
       attr->set_unsigned (0);
     }
 
@@ -19943,7 +20496,7 @@ read_attribute_value (const struct die_reader_specs *reader,
 
 static const gdb_byte *
 read_attribute (const struct die_reader_specs *reader,
-               struct attribute *attr, struct attr_abbrev *abbrev,
+               struct attribute *attr, const struct attr_abbrev *abbrev,
                const gdb_byte *info_ptr)
 {
   attr->name = abbrev->name;
@@ -20108,12 +20661,12 @@ read_str_index (struct dwarf2_cu *cu,
     error (_("%s used without %s section"
             " in CU at offset %s [in module %s]"),
           form_name, str_section->get_name (),
-           sect_offset_str (cu->header.sect_off), objf_name);
+          sect_offset_str (cu->header.sect_off), objf_name);
   if (str_offsets_section->buffer == NULL)
     error (_("%s used without %s section"
             " in CU at offset %s [in module %s]"),
           form_name, str_section->get_name (),
-           sect_offset_str (cu->header.sect_off), objf_name);
+          sect_offset_str (cu->header.sect_off), objf_name);
   info_ptr = (str_offsets_section->buffer
              + str_offsets_base
              + str_index * cu->header.offset_size);
@@ -20282,7 +20835,7 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
     {
       str = attr->as_string ();
       if (str == nullptr)
-        complaint (_("string type expected for attribute %s for "
+       complaint (_("string type expected for attribute %s for "
                     "DIE at %s in module %s"),
                   dwarf_attr_name (name), sect_offset_str (die->sect_off),
                   objfile_name (cu->per_objfile->objfile));
@@ -20373,7 +20926,7 @@ get_debug_line_section (struct dwarf2_cu *cu)
     section = &cu->dwo_unit->dwo_file->sections.line;
   else if (cu->per_cu->is_dwz)
     {
-      dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
+      dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd, true);
 
       section = &dwz->line;
     }
@@ -20838,9 +21391,9 @@ lnp_state_machine::record_line (bool end_sequence)
          bool file_changed
            = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
          bool ignore_this_line
-           = ((file_changed && !end_sequence && m_last_address == m_address
-               && !m_is_stmt && m_stmt_at_address)
-              || (!end_sequence && m_line == 0));
+          = ((file_changed && !end_sequence && m_last_address == m_address
+              && !m_is_stmt && m_stmt_at_address)
+             || (!end_sequence && m_line == 0));
 
          if ((file_changed && !ignore_this_line) || end_sequence)
            {
@@ -21017,25 +21570,25 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                  }
                  break;
                case DW_LNE_define_file:
-                  {
-                    const char *cur_file;
+                 {
+                   const char *cur_file;
                    unsigned int mod_time, length;
                    dir_index dindex;
 
-                    cur_file = read_direct_string (abfd, line_ptr,
+                   cur_file = read_direct_string (abfd, line_ptr,
                                                   &bytes_read);
-                    line_ptr += bytes_read;
-                    dindex = (dir_index)
-                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                    line_ptr += bytes_read;
-                    mod_time =
-                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                    line_ptr += bytes_read;
-                    length =
-                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                    line_ptr += bytes_read;
-                    lh->add_file_name (cur_file, dindex, mod_time, length);
-                  }
+                   line_ptr += bytes_read;
+                   dindex = (dir_index)
+                     read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+                   mod_time =
+                     read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+                   length =
+                     read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+                   lh->add_file_name (cur_file, dindex, mod_time, length);
+                 }
                  break;
                case DW_LNE_set_discriminator:
                  {
@@ -21186,17 +21739,20 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
   if (decode_for_pst_p)
     {
       /* Now that we're done scanning the Line Header Program, we can
-         create the psymtab of each included file.  */
+        create the psymtab of each included file.  */
       for (auto &file_entry : lh->file_names ())
-        if (file_entry.included_p == 1)
-          {
+       if (file_entry.included_p == 1)
+         {
            gdb::unique_xmalloc_ptr<char> name_holder;
            const char *include_name =
              psymtab_include_file_name (lh, file_entry, pst,
                                         comp_dir, &name_holder);
            if (include_name != NULL)
-              dwarf2_create_include_psymtab (include_name, pst, objfile);
-          }
+             dwarf2_create_include_psymtab
+               (cu->per_objfile->per_bfd, include_name, pst,
+                cu->per_objfile->per_bfd->partial_symtabs.get (),
+                objfile->per_bfd);
+         }
     }
   else
     {
@@ -21325,7 +21881,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
       if ((block->data[0] == DW_OP_addr
           && block->size == 1 + cu_header->addr_size)
          || ((block->data[0] == DW_OP_GNU_addr_index
-               || block->data[0] == DW_OP_addrx)
+              || block->data[0] == DW_OP_addrx)
              && (block->size
                  == 1 + leb128_size (&block->data[1]))))
        {
@@ -21345,7 +21901,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
          SET_SYMBOL_VALUE_ADDRESS
            (sym,
             SYMBOL_VALUE_ADDRESS (sym)
-            + objfile->section_offsets[SYMBOL_SECTION (sym)]);
+            + objfile->section_offsets[sym->section_index ()]);
          return;
        }
     }
@@ -21419,7 +21975,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        }
 
       /* Default assumptions.
-         Use the passed type or decode it from the die.  */
+        Use the passed type or decode it from the die.  */
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
       SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
       if (type != NULL)
@@ -21435,10 +21991,10 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_file : DW_AT_decl_file,
                          cu);
-      if (attr != nullptr && attr->form_is_unsigned ())
+      if (attr != nullptr && attr->is_nonnegative ())
        {
          file_name_index file_index
-           = (file_name_index) attr->as_unsigned ();
+           = (file_name_index) attr->as_nonnegative ();
          struct file_entry *fe;
 
          if (cu->line_header != NULL)
@@ -21480,12 +22036,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
              || cu->language == language_ada
              || cu->language == language_fortran)
            {
-              /* Subprograms marked external are stored as a global symbol.
-                 Ada and Fortran subprograms, whether marked external or
-                 not, are always stored as a global symbol, because we want
-                 to be able to access them globally.  For instance, we want
-                 to be able to break on a nested subprogram without having
-                 to specify the context.  */
+             /* Subprograms marked external are stored as a global symbol.
+                Ada and Fortran subprograms, whether marked external or
+                not, are always stored as a global symbol, because we want
+                to be able to access them globally.  For instance, we want
+                to be able to break on a nested subprogram without having
+                to specify the context.  */
              list_to_add = cu->get_builder ()->get_global_symbols ();
            }
          else
@@ -21588,11 +22144,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          else
            {
              /* We do not know the address of this symbol.
-                If it is an external symbol and we have type information
-                for it, enter the symbol as a LOC_UNRESOLVED symbol.
-                The address of the variable will then be determined from
-                the minimal symbol table whenever the variable is
-                referenced.  */
+                If it is an external symbol and we have type information
+                for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                The address of the variable will then be determined from
+                the minimal symbol table whenever the variable is
+                referenced.  */
              attr2 = dwarf2_attr (die, DW_AT_external, cu);
 
              /* Fortran explicitly imports any global symbols to the local
@@ -21708,8 +22264,9 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
          list_to_add = cu->list_in_scope;
          break;
+       case DW_TAG_array_type:
        case DW_TAG_base_type:
-        case DW_TAG_subrange_type:
+       case DW_TAG_subrange_type:
          SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
          SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
          list_to_add = cu->list_in_scope;
@@ -22410,13 +22967,13 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
         template class <class Enum> Class{};
         Class<enum E> class_e;
 
-         1: DW_TAG_class_type (Class)
-           2: DW_TAG_enumeration_type (E)
-             3: DW_TAG_enumerator (enum1:0)
-             3: DW_TAG_enumerator (enum2:1)
-             ...
-           2: DW_TAG_template_type_param
-              DW_AT_type  DW_FORM_ref_udata (E)
+        1: DW_TAG_class_type (Class)
+          2: DW_TAG_enumeration_type (E)
+            3: DW_TAG_enumerator (enum1:0)
+            3: DW_TAG_enumerator (enum2:1)
+            ...
+          2: DW_TAG_template_type_param
+             DW_AT_type  DW_FORM_ref_udata (E)
 
         Besides being broken debug info, it can put GDB into an
         infinite loop.  Consider:
@@ -22491,7 +23048,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
        return determine_prefix (parent, cu);
       case DW_TAG_enumeration_type:
        parent_type = read_type_die (parent, cu);
-       if (TYPE_DECLARED_CLASS (parent_type))
+       if (parent_type->is_declared_class ())
          {
            if (parent_type->name () != NULL)
              return parent_type->name ();
@@ -22513,7 +23070,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
 
 static char *
 typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
-                 int physname, struct dwarf2_cu *cu)
+                int physname, struct dwarf2_cu *cu)
 {
   const char *lead = "";
   const char *sep;
@@ -22921,6 +23478,12 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
 
   target_cu = cu;
 
+  dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
+                            "source CU contains target offset: %d",
+                            sect_offset_str (cu->per_cu->sect_off),
+                            sect_offset_str (sect_off),
+                            cu->header.offset_in_cu_p (sect_off));
+
   if (cu->per_cu->is_debug_types)
     {
       /* .debug_types CUs cannot reference anything outside their CU.
@@ -22937,12 +23500,23 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
       per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 per_objfile);
 
-      /* If necessary, add it to the queue and load its DIEs.  */
-      if (maybe_queue_comp_unit (cu, per_cu, per_objfile, cu->language))
+      dwarf_read_debug_printf_v ("target CU offset: %s, "
+                                "target CU DIEs loaded: %d",
+                                sect_offset_str (per_cu->sect_off),
+                                per_objfile->get_cu (per_cu) != nullptr);
+
+      /* If necessary, add it to the queue and load its DIEs.
+
+        Even if maybe_queue_comp_unit doesn't require us to load the CU's DIEs,
+        it doesn't mean they are currently loaded.  Since we require them
+        to be loaded, we must check for ourselves.  */
+      if (maybe_queue_comp_unit (cu, per_cu, per_objfile, cu->language)
+         || per_objfile->get_cu (per_cu) == nullptr)
        load_full_comp_unit (per_cu, per_objfile, per_objfile->get_cu (per_cu),
                             false, cu->language);
 
       target_cu = per_objfile->get_cu (per_cu);
+      gdb_assert (target_cu != nullptr);
     }
   else if (cu->dies == NULL)
     {
@@ -23316,10 +23890,14 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
      we can get here for DW_AT_imported_declaration where we need
      the DIE not the type.  */
 
-  /* If necessary, add it to the queue and load its DIEs.  */
+  /* If necessary, add it to the queue and load its DIEs.
 
+     Even if maybe_queue_comp_unit doesn't require us to load the CU's DIEs,
+     it doesn't mean they are currently loaded.  Since we require them
+     to be loaded, we must check for ourselves.  */
   if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu, per_objfile,
-                            language_minimal))
+                            language_minimal)
+      || per_objfile->get_cu (&sig_type->per_cu) == nullptr)
     read_signatured_type (sig_type, per_objfile);
 
   sig_cu = per_objfile->get_cu (&sig_type->per_cu);
@@ -23370,8 +23948,8 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
   if (sig_type == NULL)
     {
       error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
-               " from DIE at %s [in module %s]"),
-             hex_string (signature), sect_offset_str (src_die->sect_off),
+              " from DIE at %s [in module %s]"),
+            hex_string (signature), sect_offset_str (src_die->sect_off),
             objfile_name ((*ref_cu)->per_objfile->objfile));
     }
 
@@ -23763,7 +24341,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu, bool *computed)
            }
          break;
 
-        case DW_OP_GNU_push_tls_address:
+       case DW_OP_GNU_push_tls_address:
        case DW_OP_form_tls_address:
          /* The top of the stack has the offset from the beginning
             of the thread control block at which the variable is located.  */
@@ -23781,7 +24359,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu, bool *computed)
                return 0;
            }
          stack[stacki]++;
-          break;
+         break;
 
        case DW_OP_GNU_uninit:
          if (computed != nullptr)
@@ -23813,7 +24391,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu, bool *computed)
        }
 
       /* Enforce maximum stack depth of SIZE-1 to avoid writing
-         outside of the allocated space.  Also enforce minimum>0.  */
+        outside of the allocated space.  Also enforce minimum>0.  */
       if (stacki >= ARRAY_SIZE (stack) - 1)
        {
          if (computed == nullptr)
@@ -24082,6 +24660,8 @@ dwarf2_per_cu_data::get_header () const
 
       read_comp_unit_head (&m_header, info_ptr, this->section,
                           rcuh_kind::COMPILE);
+
+      m_header_read_in = true;
     }
 
   return &m_header;
@@ -24317,6 +24897,15 @@ dwarf2_per_objfile::set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu)
 void
 dwarf2_per_objfile::age_comp_units ()
 {
+  dwarf_read_debug_printf_v ("running");
+
+  /* This is not expected to be called in the middle of CU expansion.  There is
+     an invariant that if a CU is in the CUs-to-expand queue, its DIEs are
+     loaded in memory.  Calling age_comp_units while the queue is in use could
+     make us free the DIEs for a CU that is in the queue and therefore break
+     that invariant.  */
+  gdb_assert (!this->per_bfd->queue.has_value ());
+
   /* Start by clearing all marks.  */
   for (auto pair : m_dwarf2_cus)
     pair.second->mark = false;
@@ -24339,6 +24928,8 @@ dwarf2_per_objfile::age_comp_units ()
 
       if (!cu->mark)
        {
+         dwarf_read_debug_printf_v ("deleting old CU %s",
+                                    sect_offset_str (cu->per_cu->sect_off));
          delete cu;
          it = m_dwarf2_cus.erase (it);
        }
@@ -24431,7 +25022,8 @@ per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
      * Make the type as complete as possible before fetching more types.  */
 
 static struct type *
-set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
+             bool skip_data_location)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct dwarf2_per_cu_offset_and_type **slot, ofs;
@@ -24452,6 +25044,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
       && type->code () != TYPE_CODE_METHODPTR
       && type->code () != TYPE_CODE_MEMBERPTR
       && type->code () != TYPE_CODE_METHOD
+      && type->code () != TYPE_CODE_FIXED_POINT
       && !HAVE_GNAT_AUX_INFO (type))
     INIT_GNAT_SPECIFIC (type);
 
@@ -24461,7 +25054,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct type *prop_type = cu->addr_sized_int_type (false);
       if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
-        type->add_dyn_prop (DYN_PROP_ALLOCATED, prop);
+       type->add_dyn_prop (DYN_PROP_ALLOCATED, prop);
     }
 
   /* Read DW_AT_associated and set in type.  */
@@ -24470,13 +25063,16 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct type *prop_type = cu->addr_sized_int_type (false);
       if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
-        type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
+       type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
     }
 
   /* Read DW_AT_data_location and set in type.  */
-  attr = dwarf2_attr (die, DW_AT_data_location, cu);
-  if (attr_to_dynamic_prop (attr, die, cu, &prop, cu->addr_type ()))
-    type->add_dyn_prop (DYN_PROP_DATA_LOCATION, prop);
+  if (!skip_data_location)
+    {
+      attr = dwarf2_attr (die, DW_AT_data_location, cu);
+      if (attr_to_dynamic_prop (attr, die, cu, &prop, cu->addr_type ()))
+       type->add_dyn_prop (DYN_PROP_DATA_LOCATION, prop);
+    }
 
   if (per_objfile->die_type_hash == NULL)
     per_objfile->die_type_hash
This page took 0.124267 seconds and 4 git commands to generate.