/* 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;
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;
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.
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
/* 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 {};
/* 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. */
/* 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;
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
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;
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. */
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. */
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);
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;
/* 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
/* 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 */