+/* 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>;
+