]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/dwarf2/read.h
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / dwarf2 / read.h
index cd57d9026ae63cf63c6437e65daf7705084189e4..66c6fe3fe8732210e074eedc9c03fe6167b735fc 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2020 Free Software Foundation, Inc.
+   Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include <queue>
 #include <unordered_map>
-#include "dwarf2/comp-unit.h"
+#include "dwarf2/comp-unit-head.h"
+#include "dwarf2/file-and-dir.h"
 #include "dwarf2/index-cache.h"
+#include "dwarf2/mapped-index.h"
 #include "dwarf2/section.h"
+#include "dwarf2/cu.h"
 #include "filename-seen-cache.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include "gdbsupport/hash_enum.h"
-#include "psympriv.h"
+#include "gdbsupport/function-view.h"
+#include "gdbsupport/packed.h"
 
 /* Hold 'maintenance (set|show) dwarf' commands.  */
 extern struct cmd_list_element *set_dwarf_cmdlist;
@@ -41,10 +45,12 @@ struct tu_stats
   int nr_symtab_sharers;
   int nr_stmt_less_type_units;
   int nr_all_type_units_reallocs;
+  int nr_tus;
 };
 
 struct dwarf2_cu;
 struct dwarf2_debug_sections;
+struct dwarf2_per_bfd;
 struct dwarf2_per_cu_data;
 struct mapped_index;
 struct mapped_debug_names;
@@ -72,6 +78,342 @@ struct dwarf2_queue_item
   enum language pretend_language;
 };
 
+/* A deleter for dwarf2_per_cu_data that knows to downcast to
+   signatured_type as appropriate.  This approach lets us avoid a
+   virtual destructor, which saves a bit of space.  */
+
+struct dwarf2_per_cu_data_deleter
+{
+  void operator() (dwarf2_per_cu_data *data);
+};
+
+/* A specialization of unique_ptr for dwarf2_per_cu_data and
+   subclasses.  */
+typedef std::unique_ptr<dwarf2_per_cu_data, dwarf2_per_cu_data_deleter>
+    dwarf2_per_cu_data_up;
+
+/* Persistent data held for a compilation unit, even when not
+   processing it.  We put a pointer to this structure in the
+   psymtab.  */
+
+struct dwarf2_per_cu_data
+{
+  dwarf2_per_cu_data ()
+    : is_debug_types (false),
+      is_dwz (false),
+      reading_dwo_directly (false),
+      tu_read (false),
+      queued (false),
+      m_header_read_in (false),
+      mark (false),
+      files_read (false),
+      scanned (false)
+  {
+  }
+
+  /* The start offset and length of this compilation unit.
+     NOTE: Unlike comp_unit_head.length, this length includes
+     initial_length_size.
+     If the DIE refers to a DWO file, this is always of the original die,
+     not the DWO file.  */
+  sect_offset sect_off {};
+
+private:
+  unsigned int m_length = 0;
+
+  /* DWARF standard version this data has been read from (such as 4 or 5).  */
+  unsigned char m_dwarf_version = 0;
+
+public:
+  /* Non-zero if this CU is from .debug_types.
+     Struct dwarf2_per_cu_data is contained in struct signatured_type iff
+     this is non-zero.  */
+  unsigned int is_debug_types : 1;
+
+  /* Non-zero if this CU is from the .dwz file.  */
+  unsigned int is_dwz : 1;
+
+  /* Non-zero if reading a TU directly from a DWO file, bypassing the stub.
+     This flag is only valid if is_debug_types is true.
+     We can't read a CU directly from a DWO file: There are required
+     attributes in the stub.  */
+  unsigned int reading_dwo_directly : 1;
+
+  /* Non-zero if the TU has been read.
+     This is used to assist the "Stay in DWO Optimization" for Fission:
+     When reading a DWO, it's faster to read TUs from the DWO instead of
+     fetching them from random other DWOs (due to comdat folding).
+     If the TU has already been read, the optimization is unnecessary
+     (and unwise - we don't want to change where gdb thinks the TU lives
+     "midflight").
+     This flag is only valid if is_debug_types is true.  */
+  unsigned int tu_read : 1;
+
+  /* Wrap the following in struct packed instead of bitfields to avoid
+     data races when the bitfields end up on the same memory location
+     (per C++ memory model).  */
+
+  /* If addresses have been read for this CU (usually from
+     .debug_aranges), then this flag is set.  */
+  packed<bool, 1> addresses_seen = false;
+
+  /* Flag indicating this compilation unit will be read in before
+     any of the current compilation units are processed.  */
+  packed<bool, 1> queued;
+
+  /* True if HEADER has been read in.
+
+     Don't access this field directly.  It should be private, but we can't make
+     it private at the moment.  */
+  mutable packed<bool, 1> m_header_read_in;
+
+  /* A temporary mark bit used when iterating over all CUs in
+     expand_symtabs_matching.  */
+  packed<unsigned int, 1> mark;
+
+  /* True if we've tried to read the file table.  There will be no
+     point in trying to read it again next time.  */
+  packed<bool, 1> files_read;
+
+private:
+  /* The unit type of this CU.  */
+  std::atomic<packed<dwarf_unit_type, 1>> m_unit_type {(dwarf_unit_type)0};
+
+  /* The language of this CU.  */
+  std::atomic<packed<language, LANGUAGE_BYTES>> m_lang {language_unknown};
+
+  /* The original DW_LANG_* value of the CU, as provided to us by
+     DW_AT_language.  It is interesting to keep this value around in cases where
+     we can't use the values from the language enum, as the mapping to them is
+     lossy, and, while that is usually fine, things like the index have an
+     understandable bias towards not exposing internal GDB structures to the
+     outside world, and so prefer to use DWARF constants in their stead. */
+  std::atomic<packed<dwarf_source_language, 2>> m_dw_lang
+       { (dwarf_source_language) 0 };
+
+public:
+  /* True if this CU has been scanned by the indexer; false if
+     not.  */
+  std::atomic<bool> scanned;
+
+  /* Our index in the unshared "symtabs" vector.  */
+  unsigned index = 0;
+
+  /* The section this CU/TU lives in.
+     If the DIE refers to a DWO file, this is always the original die,
+     not the DWO file.  */
+  struct dwarf2_section_info *section = nullptr;
+
+  /* Backlink to the owner of this.  */
+  dwarf2_per_bfd *per_bfd = nullptr;
+
+  /* DWARF header of this CU.  Note that dwarf2_cu reads its own version of the
+     header, which may differ from this one, since it may pass rcuh_kind::TYPE
+     to read_comp_unit_head, whereas for dwarf2_per_cu_data we always pass
+     rcuh_kind::COMPILE.
+
+     Don't access this field directly, use the get_header method instead.  It
+     should be private, but we can't make it private at the moment.  */
+  mutable comp_unit_head m_header;
+
+  /* The file and directory for this CU.  This is cached so that we
+     don't need to re-examine the DWO in some situations.  This may be
+     nullptr, depending on the CU; for example a partial unit won't
+     have one.  */
+  std::unique_ptr<file_and_directory> fnd;
+
+  /* The file table.  This can be NULL if there was no file table
+     or it's currently not read in.
+     NOTE: This points into dwarf2_per_objfile->per_bfd->quick_file_names_table.  */
+  struct quick_file_names *file_names = nullptr;
+
+  /* The CUs we import using DW_TAG_imported_unit.  This is filled in
+     while reading psymtabs, used to compute the psymtab dependencies,
+     and then cleared.  Then it is filled in again while reading full
+     symbols, and only deleted when the objfile is destroyed.
+
+     This is also used to work around a difference between the way gold
+     generates .gdb_index version <=7 and the way gdb does.  Arguably this
+     is a gold bug.  For symbols coming from TUs, gold records in the index
+     the CU that includes the TU instead of the TU itself.  This breaks
+     dw2_lookup_symbol: It assumes that if the index says symbol X lives
+     in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
+     will find X.  Alas TUs live in their own symtab, so after expanding CU Y
+     we need to look in TU Z to find X.  Fortunately, this is akin to
+     DW_TAG_imported_unit, so we just use the same mechanism: For
+     .gdb_index version <=7 this also records the TUs that the CU referred
+     to.  Concurrently with this change gdb was modified to emit version 8
+     indices so we only pay a price for gold generated indices.
+     http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
+
+     This currently needs to be a public member due to how
+     dwarf2_per_cu_data is allocated and used.  Ideally in future things
+     could be refactored to make this private.  Until then please try to
+     avoid direct access to this member, and instead use the helper
+     functions above.  */
+  std::vector <dwarf2_per_cu_data *> *imported_symtabs = nullptr;
+
+  /* Return true of IMPORTED_SYMTABS is empty or not yet allocated.  */
+  bool imported_symtabs_empty () const
+  {
+    return (imported_symtabs == nullptr || imported_symtabs->empty ());
+  }
+
+  /* Push P to the back of IMPORTED_SYMTABS, allocated IMPORTED_SYMTABS
+     first if required.  */
+  void imported_symtabs_push (dwarf2_per_cu_data *p)
+  {
+    if (imported_symtabs == nullptr)
+      imported_symtabs = new std::vector <dwarf2_per_cu_data *>;
+    imported_symtabs->push_back (p);
+  }
+
+  /* Return the size of IMPORTED_SYMTABS if it is allocated, otherwise
+     return 0.  */
+  size_t imported_symtabs_size () const
+  {
+    if (imported_symtabs == nullptr)
+      return 0;
+    return imported_symtabs->size ();
+  }
+
+  /* Delete IMPORTED_SYMTABS and set the pointer back to nullptr.  */
+  void imported_symtabs_free ()
+  {
+    delete imported_symtabs;
+    imported_symtabs = nullptr;
+  }
+
+  /* Get the header of this per_cu, reading it if necessary.  */
+  const comp_unit_head *get_header () const;
+
+  /* Return the address size given in the compilation unit header for
+     this CU.  */
+  int addr_size () const;
+
+  /* Return the offset size given in the compilation unit header for
+     this CU.  */
+  int offset_size () const;
+
+  /* Return the DW_FORM_ref_addr size given in the compilation unit
+     header for this CU.  */
+  int ref_addr_size () const;
+
+  /* Return length of this CU.  */
+  unsigned int length () const
+  {
+    /* Make sure it's set already.  */
+    gdb_assert (m_length != 0);
+    return m_length;
+  }
+
+  void set_length (unsigned int length, bool strict_p = true)
+  {
+    if (m_length == 0)
+      /* Set if not set already.  */
+      m_length = length;
+    else if (strict_p)
+      /* If already set, verify that it's the same value.  */
+      gdb_assert (m_length == length);
+  }
+
+  /* Return DWARF version number of this CU.  */
+  short version () const
+  {
+    /* Make sure it's set already.  */
+    gdb_assert (m_dwarf_version != 0);
+    return m_dwarf_version;
+  }
+
+  void set_version (short version)
+  {
+    if (m_dwarf_version == 0)
+      /* Set if not set already.  */
+      m_dwarf_version = version;
+    else
+      /* If already set, verify that it's the same value.  */
+      gdb_assert (m_dwarf_version == version);
+  }
+
+  dwarf_unit_type unit_type (bool strict_p = true) const
+  {
+    dwarf_unit_type ut = m_unit_type.load ();
+    if (strict_p)
+      gdb_assert (ut != 0);
+    return ut;
+  }
+
+  void set_unit_type (dwarf_unit_type unit_type)
+  {
+    /* Set if not set already.  */
+    packed<dwarf_unit_type, 1> nope = (dwarf_unit_type)0;
+    if (m_unit_type.compare_exchange_strong (nope, unit_type))
+      return;
+
+    /* If already set, verify that it's the same value.  */
+    nope = unit_type;
+    if (m_unit_type.compare_exchange_strong (nope, unit_type))
+      return;
+    gdb_assert_not_reached ();
+  }
+
+  enum language lang (bool strict_p = true) const
+  {
+    enum language l = m_lang.load ();
+    if (strict_p)
+      gdb_assert (l != language_unknown);
+    return l;
+  }
+
+  /* Return the language of this CU, as a DWARF DW_LANG_* value.  This
+     may be 0 in some situations.  */
+  dwarf_source_language dw_lang () const
+  { return m_dw_lang.load (); }
+
+  /* Set the language of this CU.  LANG is the language in gdb terms,
+     and DW_LANG is the language as a DW_LANG_* value.  These may
+     differ, as DW_LANG can be 0 for included units, whereas in this
+     situation LANG would be set by the importing CU.  */
+  void set_lang (enum language lang, dwarf_source_language dw_lang);
+
+  /* Free any cached file names.  */
+  void free_cached_file_names ();
+};
+
+/* Entry in the signatured_types hash table.  */
+
+struct signatured_type : public dwarf2_per_cu_data
+{
+  signatured_type (ULONGEST signature)
+    : signature (signature)
+  {}
+
+  /* The type's signature.  */
+  ULONGEST signature;
+
+  /* Offset in the TU of the type's DIE, as read from the TU header.
+     If this TU is a DWO stub and the definition lives in a DWO file
+     (specified by DW_AT_GNU_dwo_name), this value is unusable.  */
+  cu_offset type_offset_in_tu {};
+
+  /* Offset in the section of the type's DIE.
+     If the definition lives in a DWO file, this is the offset in the
+     .debug_types.dwo section.
+     The value is zero until the actual value is known.
+     Zero is otherwise not a valid section offset.  */
+  sect_offset type_offset_in_section {};
+
+  /* Type units are grouped by their DW_AT_stmt_list entry so that they
+     can share them.  This points to the containing symtab.  */
+  struct type_unit_group *type_unit_group = nullptr;
+
+  /* Containing DWO unit.
+     This field is valid iff per_cu.reading_dwo_directly.  */
+  struct dwo_unit *dwo_unit = nullptr;
+};
+
+using signatured_type_up = std::unique_ptr<signatured_type>;
+
 /* Some DWARF data can be shared across objfiles who share the same BFD,
    this data is stored in this object.
 
@@ -92,44 +434,39 @@ struct dwarf2_per_bfd
 
   DISABLE_COPY_AND_ASSIGN (dwarf2_per_bfd);
 
-  /* Return the CU/TU given its index.
-
-     This is intended for loops like:
-
-     for (i = 0; i < (dwarf2_per_bfd->n_comp_units
-                     + dwarf2_per_bfd->n_type_units); ++i)
-       {
-         dwarf2_per_cu_data *per_cu = dwarf2_per_bfd->get_cutu (i);
+  /* Return the CU given its index.  */
+  dwarf2_per_cu_data *get_cu (int index) const
+  {
+    return this->all_units[index].get ();
+  }
 
-         ...;
-       }
-  */
-  dwarf2_per_cu_data *get_cutu (int index);
+  /* Return the CU given its index in the CU table in the index.  */
+  dwarf2_per_cu_data *get_index_cu (int index) const
+  {
+    if (this->all_comp_units_index_cus.empty ())
+      return get_cu (index);
 
-  /* Return the CU given its index.
-     This differs from get_cutu in that it's for when you know INDEX refers to a
-     CU.  */
-  dwarf2_per_cu_data *get_cu (int index);
+    return this->all_comp_units_index_cus[index];
+  }
 
-  /* Return the TU given its index.
-     This differs from get_cutu in that it's for when you know INDEX refers to a
-     TU.  */
-  signatured_type *get_tu (int index);
+  dwarf2_per_cu_data *get_index_tu (int index) const
+  {
+    return this->all_comp_units_index_tus[index];
+  }
 
   /* A convenience function to allocate a dwarf2_per_cu_data.  The
      returned object has its "index" field set properly.  The object
      is allocated on the dwarf2_per_bfd obstack.  */
-  dwarf2_per_cu_data *allocate_per_cu ();
+  dwarf2_per_cu_data_up allocate_per_cu ();
 
   /* A convenience function to allocate a signatured_type.  The
      returned object has its "index" field set properly.  The object
      is allocated on the dwarf2_per_bfd obstack.  */
-  signatured_type *allocate_signatured_type ();
+  signatured_type_up allocate_signatured_type (ULONGEST signature);
 
-  /* Return the number of partial symtabs allocated with allocate_per_cu
-     and allocate_signatured_type so far.  */
-  int num_psymtabs () const
-  { return m_num_psymtabs; }
+  /* Map all the DWARF section data needed when scanning
+     .debug_info.  */
+  void map_info_sections (struct objfile *objfile);
 
 private:
   /* This function is mapped across the sections and remembers the
@@ -142,9 +479,9 @@ public:
   /* The corresponding BFD.  */
   bfd *obfd;
 
-  /* Objects that can be shared across objfiles are stored in this
-     obstack or on the psymtab obstack, while objects that are
-     objfile-specific are stored on the objfile obstack.  */
+  /* Objects that can be shared across objfiles may be stored in this
+     obstack, while objects that are objfile-specific are stored on
+     the objfile obstack.  */
   auto_obstack obstack;
 
   dwarf2_section_info info {};
@@ -170,10 +507,15 @@ public:
 
   /* Table of all the compilation units.  This is used to locate
      the target compilation unit of a particular reference.  */
-  std::vector<dwarf2_per_cu_data *> all_comp_units;
+  std::vector<dwarf2_per_cu_data_up> all_units;
 
-  /* The .debug_types-related CUs (TUs).  */
-  std::vector<signatured_type *> all_type_units;
+  /* The all_units vector contains both CUs and TUs.  Provide views on the
+     vector that are limited to either the CU part or the TU part.  */
+  gdb::array_view<dwarf2_per_cu_data_up> all_comp_units;
+  gdb::array_view<dwarf2_per_cu_data_up> all_type_units;
+
+  std::vector<dwarf2_per_cu_data*> all_comp_units_index_cus;
+  std::vector<dwarf2_per_cu_data*> all_comp_units_index_tus;
 
   /* Table of struct type_unit_group objects.
      The hash key is the DW_AT_stmt_list value.  */
@@ -199,7 +541,7 @@ public:
 
   /* The shared '.dwz' file, if one exists.  This is used when the
      original data was compressed using 'dwz -m'.  */
-  std::unique_ptr<struct dwz_file> dwz_file;
+  std::optional<std::unique_ptr<struct dwz_file>> dwz_file;
 
   /* Whether copy relocations are supported by this object format.  */
   bool can_copy;
@@ -208,15 +550,8 @@ public:
      VMA of 0.  */
   bool has_section_at_zero = false;
 
-  /* True if we are using the mapped index,
-     or we are faking it for OBJF_READNOW's sake.  */
-  bool using_index = false;
-
-  /* The mapped index, or NULL if .gdb_index is missing or not being used.  */
-  std::unique_ptr<mapped_index> index_table;
-
-  /* The mapped index, or NULL if .debug_names is missing or not being used.  */
-  std::unique_ptr<mapped_debug_names> debug_names_table;
+  /* The mapped index, or NULL in the readnow case.  */
+  std::unique_ptr<dwarf_scanner_base> index_table;
 
   /* When using index_table, this keeps track of all quick_file_names entries.
      TUs typically share line table entries with a CU, so we maintain a
@@ -227,17 +562,9 @@ public:
      CU and its associated TU group if there is one.  */
   htab_up quick_file_names_table;
 
-  /* Set during partial symbol reading, to prevent queueing of full
-     symbols.  */
-  bool reading_partial_symbols = false;
-
   /* The CUs we recently read.  */
   std::vector<dwarf2_per_cu_data *> just_read_cus;
 
-  /* Table containing all filenames.  This is an optional because the
-     table is lazily constructed on first access.  */
-  gdb::optional<filename_seen_cache> filenames_cache;
-
   /* If we loaded the index from an external file, this contains the
      resources associated to the open file, memory mapping, etc.  */
   std::unique_ptr<index_cache_resource> index_cache_res;
@@ -248,19 +575,75 @@ public:
                     gdb::hash_enum<sect_offset>>
     abstract_to_concrete;
 
-  /* CUs that are queued to be read.  */
-  std::queue<dwarf2_queue_item> queue;
+  /* The address map that is used by the DWARF index code.  */
+  struct addrmap *index_addrmap = nullptr;
+};
+
+/* An iterator for all_units that is based on index.  This
+   approach makes it possible to iterate over all_units safely,
+   when some caller in the loop may add new units.  */
+
+class all_units_iterator
+{
+public:
 
-  /* We keep a separate reference to the partial symtabs, in case we
-     are sharing them between objfiles.  This is only set after
-     partial symbols have been read the first time.  */
-  std::shared_ptr<psymtab_storage> partial_symtabs;
+  all_units_iterator (dwarf2_per_bfd *per_bfd, bool start)
+    : m_per_bfd (per_bfd),
+      m_index (start ? 0 : per_bfd->all_units.size ())
+  {
+  }
+
+  all_units_iterator &operator++ ()
+  {
+    ++m_index;
+    return *this;
+  }
+
+  dwarf2_per_cu_data *operator* () const
+  {
+    return m_per_bfd->get_cu (m_index);
+  }
+
+  bool operator== (const all_units_iterator &other) const
+  {
+    return m_index == other.m_index;
+  }
+
+
+  bool operator!= (const all_units_iterator &other) const
+  {
+    return m_index != other.m_index;
+  }
 
 private:
 
-  /* The total number of per_cu and signatured_type objects that have
-     been created so far for this reader.  */
-  size_t m_num_psymtabs = 0;
+  dwarf2_per_bfd *m_per_bfd;
+  size_t m_index;
+};
+
+/* A range adapter for the all_units_iterator.  */
+class all_units_range
+{
+public:
+
+  all_units_range (dwarf2_per_bfd *per_bfd)
+    : m_per_bfd (per_bfd)
+  {
+  }
+
+  all_units_iterator begin ()
+  {
+    return all_units_iterator (m_per_bfd, true);
+  }
+
+  all_units_iterator end ()
+  {
+    return all_units_iterator (m_per_bfd, false);
+  }
+
+private:
+
+  dwarf2_per_bfd *m_per_bfd;
 };
 
 /* This is the per-objfile data associated with a type_unit_group.  */
@@ -308,15 +691,10 @@ struct dwarf2_per_objfile
                                const struct comp_unit_head *cu_header,
                                unsigned int *bytes_read_ptr);
 
-  /* Resize the M_SYMTABS vector to the needed size (the number of partial
-     symtabs allocated by the per-bfd).  */
-  void resize_symtabs ()
-  {
-    /* The symtabs vector should only grow, not shrink.  */
-    gdb_assert (per_bfd->num_psymtabs () >= m_symtabs.size ());
-
-    m_symtabs.resize (per_bfd->num_psymtabs ());
-  }
+  /* Return pointer to string at .debug_line_str offset as read from BUF.
+     The offset_size is OFFSET_SIZE.  */
+  const char *read_line_string (const gdb_byte *buf,
+                               unsigned int offset_size);
 
   /* Return true if the symtab corresponding to PER_CU has been set,
      false otherwise.  */
@@ -338,15 +716,11 @@ struct dwarf2_per_objfile
   void set_type_for_signatured_type (signatured_type *sig_type,
                                     struct type *type);
 
-  /* Find an integer type SIZE_IN_BYTES bytes in size and return it.
-     UNSIGNED_P controls if the integer is unsigned or not.  */
-  struct type *int_type (int size_in_bytes, bool unsigned_p) const;
-
   /* Get the dwarf2_cu matching PER_CU for this objfile.  */
   dwarf2_cu *get_cu (dwarf2_per_cu_data *per_cu);
 
   /* Set the dwarf2_cu matching PER_CU for this objfile.  */
-  void set_cu (dwarf2_per_cu_data *per_cu, dwarf2_cu *cu);
+  void set_cu (dwarf2_per_cu_data *per_cu, std::unique_ptr<dwarf2_cu> cu);
 
   /* Remove/free the dwarf2_cu matching PER_CU for this objfile.  */
   void remove_cu (dwarf2_per_cu_data *per_cu);
@@ -358,6 +732,15 @@ struct dwarf2_per_objfile
      any that are too old.  */
   void age_comp_units ();
 
+  /* Apply any needed adjustments to ADDR, returning an adjusted but
+     still unrelocated address.  */
+  unrelocated_addr adjust (unrelocated_addr addr);
+
+  /* Apply any needed adjustments to ADDR and then relocate the
+     address according to the objfile's section offsets, returning a
+     relocated address.  */
+  CORE_ADDR relocate (unrelocated_addr addr);
+
   /* Back link.  */
   struct objfile *objfile;
 
@@ -373,6 +756,12 @@ struct dwarf2_per_objfile
   /* Table containing line_header indexed by offset and offset_in_dwz.  */
   htab_up line_header_hash;
 
+  /* The CU containing the m_builder in scope.  */
+  dwarf2_cu *sym_cu = nullptr;
+
+  /* CUs that are queued to be read.  */
+  std::optional<std::queue<dwarf2_queue_item>> queue;
+
 private:
   /* Hold the corresponding compunit_symtab for each CU or TU.  This
      is indexed by dwarf2_per_cu_data::index.  A NULL value means
@@ -392,306 +781,195 @@ private:
 
   /* Map from the objfile-independent dwarf2_per_cu_data instances to the
      corresponding objfile-dependent dwarf2_cu instances.  */
-  std::unordered_map<dwarf2_per_cu_data *, dwarf2_cu *> m_dwarf2_cus;
-};
-
-/* Get the dwarf2_per_objfile associated to OBJFILE.  */
-
-dwarf2_per_objfile *get_dwarf2_per_objfile (struct objfile *objfile);
-
-/* A partial symtab specialized for DWARF.  */
-struct dwarf2_psymtab : public partial_symtab
-{
-  dwarf2_psymtab (const char *filename, struct objfile *objfile,
-                 dwarf2_per_cu_data *per_cu)
-    : partial_symtab (filename, objfile, 0),
-      per_cu_data (per_cu)
-  {
-  }
-
-  void read_symtab (struct objfile *) override;
-  void expand_psymtab (struct objfile *) override;
-  bool readin_p (struct objfile *) const override;
-  compunit_symtab *get_compunit_symtab (struct objfile *) const override;
-
-  struct dwarf2_per_cu_data *per_cu_data;
+  std::unordered_map<dwarf2_per_cu_data *,
+                    std::unique_ptr<dwarf2_cu>> m_dwarf2_cus;
 };
 
-/* Persistent data held for a compilation unit, even when not
-   processing it.  We put a pointer to this structure in the
-   psymtab.  */
-
-struct dwarf2_per_cu_data
-{
-  /* The start offset and length of this compilation unit.
-     NOTE: Unlike comp_unit_head.length, this length includes
-     initial_length_size.
-     If the DIE refers to a DWO file, this is always of the original die,
-     not the DWO file.  */
-  sect_offset sect_off;
-  unsigned int length;
+/* Converts DWARF language names to GDB language names.  */
 
-  /* DWARF standard version this data has been read from (such as 4 or 5).  */
-  short dwarf_version;
+enum language dwarf_lang_to_enum_language (unsigned int lang);
 
-  /* Flag indicating this compilation unit will be read in before
-     any of the current compilation units are processed.  */
-  unsigned int queued : 1;
+/* Get the dwarf2_per_objfile associated to OBJFILE.  */
 
-  /* This flag will be set when reading partial DIEs if we need to load
-     absolutely all DIEs for this compilation unit, instead of just the ones
-     we think are interesting.  It gets set if we look for a DIE in the
-     hash table and don't find it.  */
-  unsigned int load_all_dies : 1;
+dwarf2_per_objfile *get_dwarf2_per_objfile (struct objfile *objfile);
 
-  /* Non-zero if this CU is from .debug_types.
-     Struct dwarf2_per_cu_data is contained in struct signatured_type iff
-     this is non-zero.  */
-  unsigned int is_debug_types : 1;
+/* Return the type of the DIE at DIE_OFFSET in the CU named by
+   PER_CU.  */
 
-  /* Non-zero if this CU is from the .dwz file.  */
-  unsigned int is_dwz : 1;
+struct type *dwarf2_get_die_type (cu_offset die_offset,
+                                 dwarf2_per_cu_data *per_cu,
+                                 dwarf2_per_objfile *per_objfile);
 
-  /* Non-zero if reading a TU directly from a DWO file, bypassing the stub.
-     This flag is only valid if is_debug_types is true.
-     We can't read a CU directly from a DWO file: There are required
-     attributes in the stub.  */
-  unsigned int reading_dwo_directly : 1;
+/* Given an index in .debug_addr, fetch the value.
+   NOTE: This can be called during dwarf expression evaluation,
+   long after the debug information has been read, and thus per_cu->cu
+   may no longer exist.  */
 
-  /* Non-zero if the TU has been read.
-     This is used to assist the "Stay in DWO Optimization" for Fission:
-     When reading a DWO, it's faster to read TUs from the DWO instead of
-     fetching them from random other DWOs (due to comdat folding).
-     If the TU has already been read, the optimization is unnecessary
-     (and unwise - we don't want to change where gdb thinks the TU lives
-     "midflight").
-     This flag is only valid if is_debug_types is true.  */
-  unsigned int tu_read : 1;
+unrelocated_addr dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu,
+                                        dwarf2_per_objfile *per_objfile,
+                                        unsigned int addr_index);
 
-  /* Our index in the unshared "symtabs" vector.  */
-  unsigned index;
+/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
+   Returned value is intended for DW_OP_call*.  Returned
+   dwarf2_locexpr_baton->data has lifetime of
+   PER_CU->DWARF2_PER_OBJFILE->OBJFILE.  */
 
-  /* The section this CU/TU lives in.
-     If the DIE refers to a DWO file, this is always the original die,
-     not the DWO file.  */
-  struct dwarf2_section_info *section;
+struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off
+  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
+   dwarf2_per_objfile *per_objfile,
+   gdb::function_view<CORE_ADDR ()> get_frame_pc,
+   bool resolve_abstract_p = false);
 
-  /* The unit type of this CU.  */
-  enum dwarf_unit_type unit_type;
+/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
+   offset.  */
 
-  /* The language of this CU.  */
-  enum language lang;
+struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off
+  (cu_offset offset_in_cu, dwarf2_per_cu_data *per_cu,
+   dwarf2_per_objfile *per_objfile,
+   gdb::function_view<CORE_ADDR ()> get_frame_pc);
 
-  /* Backlink to the owner of this.  */
-  dwarf2_per_bfd *per_bfd;
+/* If the DIE at SECT_OFF in PER_CU has a DW_AT_const_value, return a
+   pointer to the constant bytes and set LEN to the length of the
+   data.  If memory is needed, allocate it on OBSTACK.  If the DIE
+   does not have a DW_AT_const_value, return NULL.  */
 
-  /* DWARF header of this CU.  Note that dwarf2_cu reads its own version of the
-     header, which may differ from this one, since it may pass rcuh_kind::TYPE
-     to read_comp_unit_head, whereas for dwarf2_per_cu_data we always pass
-     rcuh_kind::COMPILE.
+extern const gdb_byte *dwarf2_fetch_constant_bytes
+  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
+   dwarf2_per_objfile *per_objfile, obstack *obstack,
+   LONGEST *len);
 
-     Don't access this field directly, use the get_header method instead.  It
-     should be private, but we can't make it private at the moment.  */
-  mutable comp_unit_head m_header;
+/* Return the type of the die at SECT_OFF in PER_CU.  Return NULL if no
+   valid type for this die is found.  If VAR_NAME is non-null, and if
+   the DIE in question is a variable declaration (definitions are
+   excluded), then *VAR_NAME is set to the variable's name.  */
 
-  /* True if HEADER has been read in.
+struct type *dwarf2_fetch_die_type_sect_off
+  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
+   dwarf2_per_objfile *per_objfile,
+   const char **var_name = nullptr);
 
-     Don't access this field directly.  It should be private, but we can't make
-     it private at the moment.  */
-  mutable bool m_header_read_in;
+/* When non-zero, dump line number entries as they are read in.  */
+extern unsigned int dwarf_line_debug;
 
-  /* When dwarf2_per_bfd::using_index is true, the 'quick' field
-     is active.  Otherwise, the 'psymtab' field is active.  */
-  union
-  {
-    /* The partial symbol table associated with this compilation unit,
-       or NULL for unread partial units.  */
-    dwarf2_psymtab *psymtab;
+/* Dwarf2 sections that can be accessed by dwarf2_get_section_info.  */
+enum dwarf2_section_enum {
+  DWARF2_DEBUG_FRAME,
+  DWARF2_EH_FRAME
+};
 
-    /* Data needed by the "quick" functions.  */
-    struct dwarf2_per_cu_quick_data *quick;
-  } v;
+extern void dwarf2_get_section_info (struct objfile *,
+                                    enum dwarf2_section_enum,
+                                    asection **, const gdb_byte **,
+                                    bfd_size_type *);
 
-  /* The CUs we import using DW_TAG_imported_unit.  This is filled in
-     while reading psymtabs, used to compute the psymtab dependencies,
-     and then cleared.  Then it is filled in again while reading full
-     symbols, and only deleted when the objfile is destroyed.
+/* Return true if the producer of the inferior is clang.  */
+extern bool producer_is_clang (struct dwarf2_cu *cu);
 
-     This is also used to work around a difference between the way gold
-     generates .gdb_index version <=7 and the way gdb does.  Arguably this
-     is a gold bug.  For symbols coming from TUs, gold records in the index
-     the CU that includes the TU instead of the TU itself.  This breaks
-     dw2_lookup_symbol: It assumes that if the index says symbol X lives
-     in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
-     will find X.  Alas TUs live in their own symtab, so after expanding CU Y
-     we need to look in TU Z to find X.  Fortunately, this is akin to
-     DW_TAG_imported_unit, so we just use the same mechanism: For
-     .gdb_index version <=7 this also records the TUs that the CU referred
-     to.  Concurrently with this change gdb was modified to emit version 8
-     indices so we only pay a price for gold generated indices.
-     http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
+/* Interface for DWARF indexing methods.  */
 
-     This currently needs to be a public member due to how
-     dwarf2_per_cu_data is allocated and used.  Ideally in future things
-     could be refactored to make this private.  Until then please try to
-     avoid direct access to this member, and instead use the helper
-     functions above.  */
-  std::vector <dwarf2_per_cu_data *> *imported_symtabs;
+struct dwarf2_base_index_functions : public quick_symbol_functions
+{
+  bool has_symbols (struct objfile *objfile) override;
 
-  /* Return true of IMPORTED_SYMTABS is empty or not yet allocated.  */
-  bool imported_symtabs_empty () const
-  {
-    return (imported_symtabs == nullptr || imported_symtabs->empty ());
-  }
+  bool has_unexpanded_symtabs (struct objfile *objfile) override;
 
-  /* Push P to the back of IMPORTED_SYMTABS, allocated IMPORTED_SYMTABS
-     first if required.  */
-  void imported_symtabs_push (dwarf2_per_cu_data *p)
-  {
-    if (imported_symtabs == nullptr)
-      imported_symtabs = new std::vector <dwarf2_per_cu_data *>;
-    imported_symtabs->push_back (p);
-  }
+  struct symtab *find_last_source_symtab (struct objfile *objfile) override;
 
-  /* Return the size of IMPORTED_SYMTABS if it is allocated, otherwise
-     return 0.  */
-  size_t imported_symtabs_size () const
-  {
-    if (imported_symtabs == nullptr)
-      return 0;
-    return imported_symtabs->size ();
-  }
+  void forget_cached_source_info (struct objfile *objfile) override;
 
-  /* Delete IMPORTED_SYMTABS and set the pointer back to nullptr.  */
-  void imported_symtabs_free ()
+  enum language lookup_global_symbol_language (struct objfile *objfile,
+                                              const char *name,
+                                              domain_enum domain,
+                                              bool *symbol_found_p) override
   {
-    delete imported_symtabs;
-    imported_symtabs = nullptr;
+    *symbol_found_p = false;
+    return language_unknown;
   }
 
-  /* Get the header of this per_cu, reading it if necessary.  */
-  const comp_unit_head *get_header () const;
+  void print_stats (struct objfile *objfile, bool print_bcache) override;
 
-  /* Return the address size given in the compilation unit header for
-     this CU.  */
-  int addr_size () const;
+  void expand_all_symtabs (struct objfile *objfile) override;
 
-  /* Return the offset size given in the compilation unit header for
-     this CU.  */
-  int offset_size () const;
+  /* A helper function that finds the per-cu object from an "adjusted"
+     PC -- a PC with the base text offset removed.  */
+  virtual dwarf2_per_cu_data *find_per_cu (dwarf2_per_bfd *per_bfd,
+                                          unrelocated_addr adjusted_pc);
 
-  /* Return the DW_FORM_ref_addr size given in the compilation unit
-     header for this CU.  */
-  int ref_addr_size () const;
+  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;
 
-  /* Return DWARF version number of this CU.  */
-  short version () const
+  struct compunit_symtab *find_compunit_symtab_by_address
+    (struct objfile *objfile, CORE_ADDR address) override
   {
-    return dwarf_version;
+    return nullptr;
   }
 
-  /* A type unit group has a per_cu object that is recognized by
-     having no section.  */
-  bool type_unit_group_p () const
-  {
-    return section == nullptr;
-  }
+  void map_symbol_filenames (struct objfile *objfile,
+                            gdb::function_view<symbol_filename_ftype> fun,
+                            bool need_fullname) override;
 };
 
-/* Entry in the signatured_types hash table.  */
-
-struct signatured_type
-{
-  /* The "per_cu" object of this type.
-     This struct is used iff per_cu.is_debug_types.
-     N.B.: This is the first member so that it's easy to convert pointers
-     between them.  */
-  struct dwarf2_per_cu_data per_cu;
-
-  /* The type's signature.  */
-  ULONGEST signature;
-
-  /* Offset in the TU of the type's DIE, as read from the TU header.
-     If this TU is a DWO stub and the definition lives in a DWO file
-     (specified by DW_AT_GNU_dwo_name), this value is unusable.  */
-  cu_offset type_offset_in_tu;
+/* If FILE_MATCHER is NULL or if PER_CU has
+   dwarf2_per_cu_quick_data::MARK set (see
+   dw_expand_symtabs_matching_file_matcher), expand the CU and call
+   EXPANSION_NOTIFY on it.  */
 
-  /* Offset in the section of the type's DIE.
-     If the definition lives in a DWO file, this is the offset in the
-     .debug_types.dwo section.
-     The value is zero until the actual value is known.
-     Zero is otherwise not a valid section offset.  */
-  sect_offset type_offset_in_section;
-
-  /* Type units are grouped by their DW_AT_stmt_list entry so that they
-     can share them.  This points to the containing symtab.  */
-  struct type_unit_group *type_unit_group;
-
-  /* Containing DWO unit.
-     This field is valid iff per_cu.reading_dwo_directly.  */
-  struct dwo_unit *dwo_unit;
-};
+extern 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);
+
+/* Helper for dw2_expand_symtabs_matching that works with a
+   mapped_index_base instead of the containing objfile.  This is split
+   to a separate function in order to be able to unit test the
+   name_components matching using a mock mapped_index_base.  For each
+   symbol name that matches, calls MATCH_CALLBACK, passing it the
+   symbol's index in the mapped_index_base symbol table.  */
+
+extern 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,
+   gdb::function_view<bool (offset_type)> match_callback,
+   dwarf2_per_objfile *per_objfile);
 
-/* Open the separate '.dwz' debug file, if needed.  Return NULL if
-   there is no .gnu_debugaltlink section in the file.  Error if there
-   is such a section but the file cannot be found.  */
+/* If FILE_MATCHER is non-NULL, set all the
+   dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE
+   that match FILE_MATCHER.  */
 
-extern dwz_file *dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd);
+extern void dw_expand_symtabs_matching_file_matcher
+  (dwarf2_per_objfile *per_objfile,
+   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher);
 
-/* Return the type of the DIE at DIE_OFFSET in the CU named by
-   PER_CU.  */
-
-struct type *dwarf2_get_die_type (cu_offset die_offset,
-                                 dwarf2_per_cu_data *per_cu,
-                                 dwarf2_per_objfile *per_objfile);
+/* Return pointer to string at .debug_str offset STR_OFFSET.  */
 
-/* Given an index in .debug_addr, fetch the value.
-   NOTE: This can be called during dwarf expression evaluation,
-   long after the debug information has been read, and thus per_cu->cu
-   may no longer exist.  */
+extern const char *read_indirect_string_at_offset
+  (dwarf2_per_objfile *per_objfile, LONGEST str_offset);
 
-CORE_ADDR dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu,
-                                 dwarf2_per_objfile *per_objfile,
-                                 unsigned int addr_index);
+/* Allocate a hash table for signatured types.  */
 
-/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
-   Returned value is intended for DW_OP_call*.  Returned
-   dwarf2_locexpr_baton->data has lifetime of
-   PER_CU->DWARF2_PER_OBJFILE->OBJFILE.  */
+extern htab_up allocate_signatured_type_table ();
 
-struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off
-  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
-   dwarf2_per_objfile *per_objfile,
-   CORE_ADDR (*get_frame_pc) (void *baton),
-   void *baton, bool resolve_abstract_p = false);
+/* Return a new dwarf2_per_cu_data allocated on the per-bfd
+   obstack, and constructed with the specified field values.  */
 
-/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
-   offset.  */
+extern dwarf2_per_cu_data_up create_cu_from_index_list
+  (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
+   int is_dwz, sect_offset sect_off, ULONGEST length);
 
-struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off
-  (cu_offset offset_in_cu, dwarf2_per_cu_data *per_cu,
-   dwarf2_per_objfile *per_objfile,
-   CORE_ADDR (*get_frame_pc) (void *baton),
-   void *baton);
+/* Initialize the views on all_units.  */
 
-/* If the DIE at SECT_OFF in PER_CU has a DW_AT_const_value, return a
-   pointer to the constant bytes and set LEN to the length of the
-   data.  If memory is needed, allocate it on OBSTACK.  If the DIE
-   does not have a DW_AT_const_value, return NULL.  */
+extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
 
-extern const gdb_byte *dwarf2_fetch_constant_bytes
-  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
-   dwarf2_per_objfile *per_objfile, obstack *obstack,
-   LONGEST *len);
+/* Create a list of all compilation units in OBJFILE.  */
 
-/* Return the type of the die at SECT_OFF in PER_CU.  Return NULL if no
-   valid type for this die is found.  */
+extern void create_all_units (dwarf2_per_objfile *per_objfile);
 
-struct type *dwarf2_fetch_die_type_sect_off
-  (sect_offset sect_off, dwarf2_per_cu_data *per_cu,
-   dwarf2_per_objfile *per_objfile);
+/* Create a quick_file_names hash table.  */
 
-/* When non-zero, dump line number entries as they are read in.  */
-extern unsigned int dwarf_line_debug;
+extern htab_up create_quick_file_names_table (unsigned int nr_initial_entries);
 
 #endif /* DWARF2READ_H */