diff options
Diffstat (limited to 'gdb/dwarf2/read.h')
-rw-r--r-- | gdb/dwarf2/read.h | 694 |
1 files changed, 527 insertions, 167 deletions
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 12d5f06..a5cfb31 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -1,6 +1,6 @@ /* DWARF 2 debugging format support for GDB. - Copyright (C) 1994-2024 Free Software Foundation, Inc. + Copyright (C) 1994-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -20,14 +20,18 @@ #ifndef GDB_DWARF2_READ_H #define GDB_DWARF2_READ_H +#if CXX_STD_THREAD +#include <mutex> +#endif #include <queue> -#include <unordered_map> -#include "dwarf2/comp-unit-head.h" +#include "dwarf2/abbrev.h" +#include "dwarf2/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 "dwarf2/dwz.h" #include "gdbsupport/gdb_obstack.h" #include "gdbsupport/function-view.h" #include "gdbsupport/packed.h" @@ -38,67 +42,87 @@ extern struct cmd_list_element *show_dwarf_cmdlist; struct tu_stats { - int nr_uniq_abbrev_tables; - int nr_symtabs; - int nr_symtab_sharers; - int nr_stmt_less_type_units; - int nr_all_type_units_reallocs; - int nr_tus; + int nr_uniq_abbrev_tables = 0; + int nr_symtabs = 0; + int nr_symtab_sharers = 0; + int nr_stmt_less_type_units = 0; + int nr_all_type_units_reallocs = 0; + int nr_tus = 0; }; +struct abbrev_table_cache; struct dwarf2_cu; struct dwarf2_debug_sections; struct dwarf2_per_bfd; -struct dwarf2_per_cu_data; +struct dwarf2_per_cu; struct mapped_index; struct mapped_debug_names; struct signatured_type; -struct type_unit_group; /* One item on the queue of compilation units to read in full symbols for. */ struct dwarf2_queue_item { - dwarf2_queue_item (dwarf2_per_cu_data *cu, dwarf2_per_objfile *per_objfile, - enum language lang) + dwarf2_queue_item (dwarf2_per_cu *cu, dwarf2_per_objfile *per_objfile) : per_cu (cu), - per_objfile (per_objfile), - pretend_language (lang) - { + per_objfile (per_objfile) { } ~dwarf2_queue_item (); DISABLE_COPY_AND_ASSIGN (dwarf2_queue_item); - dwarf2_per_cu_data *per_cu; + dwarf2_per_cu *per_cu; dwarf2_per_objfile *per_objfile; - 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. */ +/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list. + This includes type_unit_group and quick_file_names. */ + +struct stmt_list_hash +{ + bool operator== (const stmt_list_hash &other) const noexcept; + + /* The DWO unit this table is from or NULL if there is none. */ + struct dwo_unit *dwo_unit; + + /* Offset in .debug_line or .debug_line.dwo. */ + sect_offset line_sect_off; +}; + +struct stmt_list_hash_hash +{ + using is_avalanching = void; + + std::uint64_t operator() (const stmt_list_hash &key) const noexcept; +}; + +/* A deleter for dwarf2_per_cu 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 +struct dwarf2_per_cu_deleter { - void operator() (dwarf2_per_cu_data *data); + void operator() (dwarf2_per_cu *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; +/* A specialization of unique_ptr for dwarf2_per_cu and subclasses. */ +using dwarf2_per_cu_up = std::unique_ptr<dwarf2_per_cu, dwarf2_per_cu_deleter>; /* 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 +struct dwarf2_per_cu { - dwarf2_per_cu_data () - : is_debug_types (false), - is_dwz (false), + /* LENGTH is the length of the unit. If the value is 0, it means it is not + known, and may be set later using the set_length method. */ + dwarf2_per_cu (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section, + sect_offset sect_off, unsigned int length, bool is_dwz) + : sect_off (sect_off), + m_length (length), + is_debug_types (false), + is_dwz (is_dwz), reading_dwo_directly (false), tu_read (false), lto_artificial (false), @@ -106,8 +130,12 @@ struct dwarf2_per_cu_data m_header_read_in (false), mark (false), files_read (false), - scanned (false) + scanned (false), + section (section), + per_bfd (per_bfd) { + gdb_assert (per_bfd != nullptr); + gdb_assert (section != nullptr); } /* The start offset and length of this compilation unit. @@ -115,17 +143,14 @@ struct dwarf2_per_cu_data 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 {}; + 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 + Struct dwarf2_per_cu is contained in struct signatured_type iff this is non-zero. */ unsigned int is_debug_types : 1; @@ -209,22 +234,22 @@ public: struct dwarf2_section_info *section = nullptr; /* Backlink to the owner of this. */ - dwarf2_per_bfd *per_bfd = nullptr; + dwarf2_per_bfd *per_bfd; - /* 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. + /* DWARF header of this unit. Note that dwarf2_cu reads its own version of + the header, which may differ from this one, since it may pass + rch_kind::TYPE to read_unit_head, whereas for dwarf2_per_cu we always pass + ruh_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; + mutable 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; + file_and_directory_up fnd; /* The file table. This can be NULL if there was no file table or it's currently not read in. @@ -246,10 +271,10 @@ public: 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. */ - std::vector<dwarf2_per_cu_data *> imported_symtabs; + std::vector<dwarf2_per_cu *> imported_symtabs; /* Get the header of this per_cu, reading it if necessary. */ - const comp_unit_head *get_header () const; + const unit_head *get_header () const; /* Return the address size given in the compilation unit header for this CU. */ @@ -281,24 +306,6 @@ public: 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 (); @@ -365,11 +372,16 @@ public: /* Entry in the signatured_types hash table. */ -struct signatured_type : public dwarf2_per_cu_data +struct signatured_type : public dwarf2_per_cu { - signatured_type (ULONGEST signature) - : signature (signature) - {} + signatured_type (dwarf2_per_bfd *per_bfd, dwarf2_section_info *section, + sect_offset sect_off, unsigned int length, bool is_dwz, + ULONGEST signature) + : dwarf2_per_cu (per_bfd, section, sect_off, length, is_dwz), + signature (signature) + { + this->is_debug_types = true; + } /* The type's signature. */ ULONGEST signature; @@ -387,8 +399,9 @@ struct signatured_type : public dwarf2_per_cu_data 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; + can share them. This is the key of the group this type unit is part + of. */ + std::optional<stmt_list_hash> type_unit_group_key; /* Containing DWO unit. This field is valid iff per_cu.reading_dwo_directly. */ @@ -397,6 +410,87 @@ struct signatured_type : public dwarf2_per_cu_data using signatured_type_up = std::unique_ptr<signatured_type>; +/* Hash a signatured_type object based on its signature. */ + +struct signatured_type_hash +{ + using is_transparent = void; + + std::size_t operator() (ULONGEST signature) const noexcept + { return signature; } + + std::size_t operator() (const signatured_type *sig_type) const noexcept + { return (*this) (sig_type->signature); } +}; + +/* Compare signatured_type objects based on their signatures. */ + +struct signatured_type_eq +{ + using is_transparent = void; + + bool operator() (ULONGEST sig, const signatured_type *sig_type) const noexcept + { return sig == sig_type->signature; } + + bool operator() (const signatured_type *sig_type_a, + const signatured_type *sig_type_b) const noexcept + { return (*this) (sig_type_a->signature, sig_type_b); } +}; + +/* Unordered set of signatured_type objects using their signature as the + key. */ + +using signatured_type_set + = gdb::unordered_set<signatured_type *, signatured_type_hash, + signatured_type_eq>; + +struct dwo_file; + +using dwo_file_up = std::unique_ptr<dwo_file>; + +/* This is used when looking up entries in a dwo_file_set. */ + +struct dwo_file_search +{ + /* Name of the DWO to look for. */ + const char *dwo_name; + + /* Compilation directory to look for. */ + const char *comp_dir; +}; + +/* Hash function for dwo_file objects, using their dwo_name and comp_dir as + identity. */ + +struct dwo_file_hash +{ + using is_transparent = void; + + std::size_t operator() (const dwo_file_search &search) const noexcept; + std::size_t operator() (const dwo_file_up &file) const noexcept; +}; + +/* Equal function for dwo_file objects, using their dwo_name and comp_dir as + identity. */ + +struct dwo_file_eq +{ + using is_transparent = void; + + bool operator() (const dwo_file_search &search, + const dwo_file_up &dwo_file) const noexcept; + bool operator() (const dwo_file_up &a, const dwo_file_up &b) const noexcept; +}; + +/* Set of dwo_file objects, using their dwo_name and comp_dir as identity. */ + +using dwo_file_up_set + = gdb::unordered_set<dwo_file_up, dwo_file_hash, dwo_file_eq>; + +struct dwp_file; + +using dwp_file_up = std::unique_ptr<dwp_file>; + /* Some DWARF data can be shared across objfiles who share the same BFD, this data is stored in this object. @@ -417,46 +511,79 @@ struct dwarf2_per_bfd DISABLE_COPY_AND_ASSIGN (dwarf2_per_bfd); - /* Return the CU given its index. */ - dwarf2_per_cu_data *get_cu (int index) const + /* Return the filename of the BFD. */ + const char *filename () const + { return bfd_get_filename (this->obfd); } + + /* Return the unit given its index. */ + dwarf2_per_cu *get_unit (int index) const { return this->all_units[index].get (); } /* Return the CU given its index in the CU table in the index. */ - dwarf2_per_cu_data *get_index_cu (int index) const + dwarf2_per_cu *get_index_cu (int index) const { if (this->all_comp_units_index_cus.empty ()) - return get_cu (index); + return get_unit (index); return this->all_comp_units_index_cus[index]; } - dwarf2_per_cu_data *get_index_tu (int index) const + dwarf2_per_cu *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_up allocate_per_cu (); + /* Return the separate '.dwz' debug file. If there is no + .gnu_debugaltlink or .debug_sup section in the file, then the + result depends on REQUIRE: if REQUIRE is true, error out; if + REQUIRE is false, return nullptr. */ + struct dwz_file *get_dwz_file (bool require = false) + { + gdb_assert (!require || this->dwz_file.has_value ()); + + struct dwz_file *result = nullptr; + + if (this->dwz_file.has_value ()) + { + result = this->dwz_file->get (); + if (require && result == nullptr) + error (_("could not find supplementary DWARF file")); + } + + return result; + } + + /* A convenience function to allocate a dwarf2_per_cu. The returned object + has its "index" field set properly. The object is allocated on the + dwarf2_per_bfd obstack. */ + dwarf2_per_cu_up allocate_per_cu (dwarf2_section_info *section, + sect_offset sect_off, unsigned int length, + bool is_dwz); /* 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_up allocate_signatured_type (ULONGEST signature); + signatured_type_up allocate_signatured_type (dwarf2_section_info *section, + sect_offset sect_off, + unsigned int length, + bool is_dwz, + ULONGEST signature); /* Map all the DWARF section data needed when scanning .debug_info. */ void map_info_sections (struct objfile *objfile); + /* Set the 'index_table' member and then call start_reading on + it. */ + void start_reading (dwarf_scanner_base_up new_table); + private: /* This function is mapped across the sections and remembers the offset and size of each of the debugging sections we are interested in. */ - void locate_sections (bfd *abfd, asection *sectp, - const dwarf2_debug_sections &names); + void locate_sections (asection *sectp, const dwarf2_debug_sections &names); public: /* The corresponding BFD. */ @@ -490,41 +617,37 @@ 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_up> all_units; + std::vector<dwarf2_per_cu_up> all_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; + gdb::array_view<dwarf2_per_cu_up> all_comp_units; + gdb::array_view<dwarf2_per_cu_up> all_type_units; - /* Table of struct type_unit_group objects. - The hash key is the DW_AT_stmt_list value. */ - htab_up type_unit_groups; + std::vector<dwarf2_per_cu *> all_comp_units_index_cus; + std::vector<dwarf2_per_cu *> all_comp_units_index_tus; - /* A table mapping .debug_types signatures to its signatured_type entry. - This is NULL if the .debug_types section hasn't been read in yet. */ - htab_up signatured_types; + /* Set of signatured_types, used to look up by signature. */ + signatured_type_set signatured_types; /* Type unit statistics, to see how well the scaling improvements are doing. */ - struct tu_stats tu_stats {}; + struct tu_stats tu_stats; - /* A table mapping DW_AT_dwo_name values to struct dwo_file objects. - This is NULL if the table hasn't been allocated yet. */ - htab_up dwo_files; + /* Set of dwo_file objects. */ + dwo_file_up_set dwo_files; - /* True if we've checked for whether there is a DWP file. */ - bool dwp_checked = false; +#if CXX_STD_THREAD + /* Mutex to synchronize access to DWO_FILES. */ + std::mutex dwo_files_lock; +#endif /* The DWP file if there is one, or NULL. */ - std::unique_ptr<struct dwp_file> dwp_file; + dwp_file_up dwp_file; /* The shared '.dwz' file, if one exists. This is used when the original data was compressed using 'dwz -m'. */ - std::optional<std::unique_ptr<struct dwz_file>> dwz_file; + std::optional<dwz_file_up> dwz_file; /* Whether copy relocations are supported by this object format. */ bool can_copy; @@ -534,7 +657,7 @@ public: bool has_section_at_zero = false; /* The mapped index, or NULL in the readnow case. */ - std::unique_ptr<dwarf_scanner_base> index_table; + dwarf_scanner_base_up 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 @@ -543,18 +666,19 @@ public: sorted all the TUs into "type unit groups", grouped by their DW_AT_stmt_list value. Therefore the only sharing done here is with a CU and its associated TU group if there is one. */ - htab_up quick_file_names_table; + gdb::unordered_map<stmt_list_hash, quick_file_names *, stmt_list_hash_hash> + quick_file_names_table; /* The CUs we recently read. */ - std::vector<dwarf2_per_cu_data *> just_read_cus; + std::vector<dwarf2_per_cu *> just_read_cus; /* 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; + index_cache_resource_up index_cache_res; /* Mapping from abstract origin DIE to concrete DIEs that reference it as DW_AT_abstract_origin. */ - std::unordered_map<sect_offset, std::vector<sect_offset>> + gdb::unordered_map<sect_offset, std::vector<sect_offset>> abstract_to_concrete; /* Current directory, captured at the moment that object this was @@ -584,9 +708,9 @@ public: return *this; } - dwarf2_per_cu_data *operator* () const + dwarf2_per_cu *operator* () const { - return m_per_bfd->get_cu (m_index); + return m_per_bfd->get_unit (m_index); } bool operator== (const all_units_iterator &other) const @@ -655,9 +779,12 @@ struct type_unit_group_unshareable struct symtab **symtabs = nullptr; }; +using type_unit_group_unshareable_up + = std::unique_ptr<type_unit_group_unshareable>; + struct per_cu_and_offset { - dwarf2_per_cu_data *per_cu; + dwarf2_per_cu *per_cu; sect_offset offset; bool operator== (const per_cu_and_offset &other) const noexcept @@ -670,7 +797,7 @@ struct per_cu_and_offset_hash { std::uint64_t operator() (const per_cu_and_offset &key) const noexcept { - return (std::hash<dwarf2_per_cu_data *> () (key.per_cu) + return (std::hash<dwarf2_per_cu *> () (key.per_cu) + std::hash<sect_offset> () (key.offset)); } }; @@ -693,7 +820,7 @@ struct dwarf2_per_objfile BUF is assumed to be in a compilation unit described by CU_HEADER. Return *BYTES_READ_PTR count of bytes read from BUF. */ const char *read_line_string (const gdb_byte *buf, - const struct comp_unit_head *cu_header, + const struct unit_head *unit_header, unsigned int *bytes_read_ptr); /* Return pointer to string at .debug_line_str offset as read from BUF. @@ -703,18 +830,18 @@ struct dwarf2_per_objfile /* Return true if the symtab corresponding to PER_CU has been set, false otherwise. */ - bool symtab_set_p (const dwarf2_per_cu_data *per_cu) const; + bool symtab_set_p (const dwarf2_per_cu *per_cu) const; /* Return the compunit_symtab associated to PER_CU, if it has been created. */ - compunit_symtab *get_symtab (const dwarf2_per_cu_data *per_cu) const; + compunit_symtab *get_symtab (const dwarf2_per_cu *per_cu) const; /* Set the compunit_symtab associated to PER_CU. */ - void set_symtab (const dwarf2_per_cu_data *per_cu, compunit_symtab *symtab); + void set_symtab (const dwarf2_per_cu *per_cu, compunit_symtab *symtab); - /* Get the type_unit_group_unshareable corresponding to TU_GROUP. If one + /* Get the type_unit_group_unshareable corresponding to TU_GROUP_KEY. If one does not exist, create it. */ type_unit_group_unshareable *get_type_unit_group_unshareable - (type_unit_group *tu_group); + (stmt_list_hash tu_group_key); struct type *get_type_for_signatured_type (signatured_type *sig_type) const; @@ -722,13 +849,13 @@ struct dwarf2_per_objfile struct type *type); /* Get the dwarf2_cu matching PER_CU for this objfile. */ - dwarf2_cu *get_cu (dwarf2_per_cu_data *per_cu); + dwarf2_cu *get_cu (dwarf2_per_cu *per_cu); /* Set the dwarf2_cu matching PER_CU for this objfile. */ - void set_cu (dwarf2_per_cu_data *per_cu, std::unique_ptr<dwarf2_cu> cu); + void set_cu (dwarf2_per_cu *per_cu, dwarf2_cu_up cu); /* Remove/free the dwarf2_cu matching PER_CU for this objfile. */ - void remove_cu (dwarf2_per_cu_data *per_cu); + void remove_cu (dwarf2_per_cu *per_cu); /* Free all cached compilation units. */ void remove_all_cus (); @@ -759,7 +886,7 @@ struct dwarf2_per_objfile or the type may come from a DWO file. Furthermore, while it's more logical to use per_cu->section+offset, with Fission the section with the data is in the DWO file but we don't know that section at the point we need it. - We have to use something in dwarf2_per_cu_data (or the pointer to it) + We have to use something in dwarf2_per_cu (or the pointer to it) because we can enter the lookup routine, get_die_type_at_offset, from outside this file, and thus won't necessarily have PER_CU->cu. Fortunately, PER_CU is stable for the life of the objfile. */ @@ -776,31 +903,197 @@ struct dwarf2_per_objfile 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 - that the CU/TU has not been expanded yet. */ + /* Hold the corresponding compunit_symtab for each CU or TU. This is indexed + by dwarf2_per_cu::index. A NULL value means that the CU/TU has not been + expanded yet. */ std::vector<compunit_symtab *> m_symtabs; - /* Map from a type unit group to the corresponding unshared + /* Map from a type unit group key to the corresponding unshared structure. */ - typedef std::unique_ptr<type_unit_group_unshareable> - type_unit_group_unshareable_up; - - std::unordered_map<type_unit_group *, type_unit_group_unshareable_up> + gdb::unordered_map<stmt_list_hash, type_unit_group_unshareable_up, + stmt_list_hash_hash> m_type_units; /* Map from signatured types to the corresponding struct type. */ - std::unordered_map<signatured_type *, struct type *> m_type_map; + gdb::unordered_map<signatured_type *, struct type *> m_type_map; - /* Map from the objfile-independent dwarf2_per_cu_data instances to the + /* Map from the objfile-independent dwarf2_per_cu instances to the corresponding objfile-dependent dwarf2_cu instances. */ - std::unordered_map<dwarf2_per_cu_data *, - std::unique_ptr<dwarf2_cu>> m_dwarf2_cus; + gdb::unordered_map<dwarf2_per_cu *, dwarf2_cu_up> m_dwarf2_cus; +}; + +class cutu_reader +{ +public: + + cutu_reader (dwarf2_per_cu &this_cu, + dwarf2_per_objfile &per_objfile, + const struct abbrev_table *abbrev_table, + dwarf2_cu *existing_cu, + bool skip_partial, + enum language pretend_language, + const abbrev_table_cache *abbrev_cache = nullptr); + + cutu_reader (dwarf2_per_cu &this_cu, + dwarf2_per_objfile &per_objfile, + enum language pretend_language, + struct dwarf2_cu &parent_cu, + struct dwo_file &dwo_file); + + DISABLE_COPY_AND_ASSIGN (cutu_reader); + + /* Return true if either: + + - the unit is empty (just a header without any DIE) + - the unit is a partial unit and this cutu_reader was built with SKIP + PARTIAL true. */ + bool is_dummy () const { return m_dummy_p; } + + dwarf2_cu *cu () const { return m_cu; } + + die_info *top_level_die () const { return m_top_level_die; } + + const gdb_byte *info_ptr () const { return m_info_ptr; } + + bfd *abfd () const { return m_abfd; } + + const gdb_byte *buffer () const { return m_buffer; } + + const gdb_byte *buffer_end () const { return m_buffer_end; } + + const dwarf2_section_info *section () const { return m_die_section; } + + /* Release the CU created by this cutu_reader. */ + dwarf2_cu_up release_cu (); + + /* Release the abbrev table, transferring ownership to the + caller. */ + abbrev_table_up release_abbrev_table () + { + return std::move (m_abbrev_table_holder); + } + + /* Read all DIES of the debug info section in memory. */ + void read_all_dies (); + + const gdb_byte *read_attribute (attribute *attr, const attr_abbrev *abbrev, + const gdb_byte *info_ptr, + bool allow_reprocess = true); + + const abbrev_info *peek_die_abbrev (const gdb_byte *info_ptr, + unsigned int *bytes_read); + + const gdb_byte *skip_one_die (const gdb_byte *info_ptr, + const abbrev_info *abbrev, + bool do_skip_children = true); + + const gdb_byte *skip_children (const gdb_byte *info_ptr); + +private: + /* Skip the attribute at INFO_PTR, knowing it has form FORM. Return a pointer + just past the attribute. */ + const gdb_byte *skip_one_attribute (dwarf_form form, + const gdb_byte *info_ptr); + + void init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section, + struct dwo_file *dwo_file, + const struct abbrev_table *abbrev_table); + + void init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu, + dwarf2_per_objfile *per_objfile, + dwarf2_cu *existing_cu, + enum language pretend_language); + + void read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit, + die_info *stub_comp_unit_die, + const char *stub_comp_dir); + + void prepare_one_comp_unit (struct dwarf2_cu *cu, + enum language pretend_language); + + /* Helpers to build the in-memory DIE tree. */ + + die_info *read_toplevel_die (gdb::array_view<attribute *> extra_attrs = {}); + + die_info *read_die_and_siblings (die_info *parent); + + die_info *read_die_and_children (die_info *parent); + + die_info *read_full_die (int num_extra_attrs, bool allow_reprocess); + + const gdb_byte *read_attribute_value (attribute *attr, unsigned form, + LONGEST implicit_const, + const gdb_byte *info_ptr, + bool allow_reprocess); + + void read_attribute_reprocess (attribute *attr, + dwarf_tag tag = DW_TAG_padding); + + const char *read_dwo_str_index (ULONGEST str_index); + + gdb_bfd_ref_ptr open_dwo_file (dwarf2_per_bfd *per_bfd, const char *file_name, + const char *comp_dir); + + dwo_file_up open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, + const char *comp_dir); + + void locate_dwo_sections (objfile *objfile, dwo_file &dwo_file); + + void create_dwo_unit_hash_tables (dwo_file &dwo_file, dwarf2_cu &skeleton_cu, + dwarf2_section_info §ion, + ruh_kind section_kind); + + dwo_unit *lookup_dwo_cutu (dwarf2_cu *cu, const char *dwo_name, + const char *comp_dir, ULONGEST signature, + int is_debug_types); + + dwo_unit *lookup_dwo_comp_unit (dwarf2_cu *cu, const char *dwo_name, + const char *comp_dir, ULONGEST signature); + + dwo_unit *lookup_dwo_type_unit (dwarf2_cu *cu, const char *dwo_name, + const char *comp_dir); + + dwo_unit *lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, + const char *dwo_name); + + /* The bfd of die_section. */ + bfd *m_abfd; + + /* The CU of the DIE we are parsing. */ + struct dwarf2_cu *m_cu; + + /* Non-NULL if reading a DWO file (including one packaged into a DWP). */ + struct dwo_file *m_dwo_file; + + /* The section the die comes from. + This is either .debug_info or .debug_types, or the .dwo variants. */ + struct dwarf2_section_info *m_die_section; + + /* die_section->buffer. */ + const gdb_byte *m_buffer; + + /* The end of the buffer. */ + const gdb_byte *m_buffer_end; + + /* The abbreviation table to use when reading the DIEs. */ + const struct abbrev_table *m_abbrev_table; + + const gdb_byte *m_info_ptr = nullptr; + struct die_info *m_top_level_die = nullptr; + bool m_dummy_p = false; + + dwarf2_cu_up m_new_cu; + + /* The ordinary abbreviation table. */ + abbrev_table_up m_abbrev_table_holder; + + /* The DWO abbreviation table. */ + abbrev_table_up m_dwo_abbrev_table; }; /* Converts DWARF language names to GDB language names. */ -enum language dwarf_lang_to_enum_language (unsigned int lang); +enum language dwarf_lang_to_enum_language (ULONGEST lang); /* Get the dwarf2_per_objfile associated to OBJFILE. */ @@ -809,8 +1102,7 @@ dwarf2_per_objfile *get_dwarf2_per_objfile (struct objfile *objfile); /* 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, +struct type *dwarf2_get_die_type (cu_offset die_offset, dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile); /* Given an index in .debug_addr, fetch the value. @@ -818,7 +1110,7 @@ struct type *dwarf2_get_die_type (cu_offset die_offset, long after the debug information has been read, and thus per_cu->cu may no longer exist. */ -unrelocated_addr dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu, +unrelocated_addr dwarf2_read_addr_index (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile, unsigned int addr_index); @@ -828,7 +1120,7 @@ unrelocated_addr dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu, PER_CU->DWARF2_PER_OBJFILE->OBJFILE. */ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off - (sect_offset sect_off, dwarf2_per_cu_data *per_cu, + (sect_offset sect_off, dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile, gdb::function_view<CORE_ADDR ()> get_frame_pc, bool resolve_abstract_p = false); @@ -837,7 +1129,7 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_sect_off offset. */ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off - (cu_offset offset_in_cu, dwarf2_per_cu_data *per_cu, + (cu_offset offset_in_cu, dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile, gdb::function_view<CORE_ADDR ()> get_frame_pc); @@ -847,7 +1139,7 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_loc_cu_off does not have a DW_AT_const_value, return NULL. */ extern const gdb_byte *dwarf2_fetch_constant_bytes - (sect_offset sect_off, dwarf2_per_cu_data *per_cu, + (sect_offset sect_off, dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile, obstack *obstack, LONGEST *len); @@ -856,10 +1148,10 @@ extern const gdb_byte *dwarf2_fetch_constant_bytes the DIE in question is a variable declaration (definitions are excluded), then *VAR_NAME is set to the variable's name. */ -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); +type *dwarf2_fetch_die_type_sect_off (sect_offset sect_off, + dwarf2_per_cu *per_cu, + dwarf2_per_objfile *per_objfile, + const char **var_name = nullptr); /* When non-zero, dump line number entries as they are read in. */ extern unsigned int dwarf_line_debug; @@ -875,9 +1167,6 @@ extern void dwarf2_get_section_info (struct objfile *, asection **, const gdb_byte **, bfd_size_type *); -/* Return true if the producer of the inferior is clang. */ -extern bool producer_is_clang (struct dwarf2_cu *cu); - /* Interface for DWARF indexing methods. */ struct dwarf2_base_index_functions : public quick_symbol_functions @@ -914,8 +1203,7 @@ struct dwarf2_base_index_functions : public quick_symbol_functions return nullptr; } - void map_symbol_filenames (struct objfile *objfile, - gdb::function_view<symbol_filename_ftype> fun, + void map_symbol_filenames (objfile *objfile, symbol_filename_listener fun, bool need_fullname) override; }; @@ -925,11 +1213,11 @@ struct dwarf2_base_index_functions : public quick_symbol_functions EXPANSION_NOTIFY on it. */ extern bool dw2_expand_symtabs_matching_one - (dwarf2_per_cu_data *per_cu, + (dwarf2_per_cu *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, - gdb::function_view<expand_symtabs_lang_matcher_ftype> lang_matcher); + expand_symtabs_file_matcher file_matcher, + expand_symtabs_expansion_listener expansion_notify, + expand_symtabs_lang_matcher lang_matcher); /* If FILE_MATCHER is non-NULL, set all the dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE @@ -937,24 +1225,13 @@ extern bool dw2_expand_symtabs_matching_one extern void dw_expand_symtabs_matching_file_matcher (dwarf2_per_objfile *per_objfile, - gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher); + expand_symtabs_file_matcher file_matcher); /* Return pointer to string at .debug_str offset STR_OFFSET. */ extern const char *read_indirect_string_at_offset (dwarf2_per_objfile *per_objfile, LONGEST str_offset); -/* Allocate a hash table for signatured types. */ - -extern htab_up allocate_signatured_type_table (); - -/* Return a new dwarf2_per_cu_data allocated on the per-bfd - obstack, and constructed with the specified field values. */ - -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); - /* Initialize the views on all_units. */ extern void finalize_all_units (dwarf2_per_bfd *per_bfd); @@ -963,8 +1240,91 @@ extern void finalize_all_units (dwarf2_per_bfd *per_bfd); extern void create_all_units (dwarf2_per_objfile *per_objfile); -/* Create a quick_file_names hash table. */ +/* Find the base address of the compilation unit for range lists and + location lists. It will normally be specified by DW_AT_low_pc. + In DWARF-3 draft 4, the base address could be overridden by + DW_AT_entry_pc. It's been removed, but GCC still uses this for + compilation units with discontinuous ranges. */ + +extern void dwarf2_find_base_address (die_info *die, dwarf2_cu *cu); + +/* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return + values. Keep the items ordered with increasing constraints compliance. */ + +enum pc_bounds_kind +{ + /* No attribute DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges was found. */ + PC_BOUNDS_NOT_PRESENT, + + /* Some of the attributes DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges + were present but they do not form a valid range of PC addresses. */ + PC_BOUNDS_INVALID, + + /* Discontiguous range was found - that is DW_AT_ranges was found. */ + PC_BOUNDS_RANGES, + + /* Contiguous range was found - DW_AT_low_pc and DW_AT_high_pc were found. */ + PC_BOUNDS_HIGH_LOW, +}; + +/* Get low and high pc attributes from a die. See enum pc_bounds_kind + definition for the return value. *LOWPC and *HIGHPC are set iff + neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */ + +extern pc_bounds_kind dwarf2_get_pc_bounds (die_info *die, + unrelocated_addr *lowpc, + unrelocated_addr *highpc, + dwarf2_cu *cu, addrmap_mutable *map, + void *datum); + +/* Locate the .debug_info compilation unit from CU's objfile which contains + the DIE at OFFSET. Raises an error on failure. */ + +extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off, + unsigned int + offset_in_dwz, + dwarf2_per_bfd + *per_bfd); + +/* Decode simple location descriptions. + + Given a pointer to a DWARF block that defines a location, compute + the location. Returns true if the expression was computable by + this function, false otherwise. On a true return, *RESULT is set. + + Note that this function does not implement a full DWARF expression + evaluator. Instead, it is used for a few limited purposes: + + - Getting the address of a symbol that has a constant address. For + example, if a symbol has a location like "DW_OP_addr", the address + can be extracted. + + - Getting the offset of a virtual function in its vtable. There + are two forms of this, one of which involves DW_OP_deref -- so this + function handles derefs in a peculiar way to make this 'work'. + (Probably this area should be rewritten.) + + - Getting the offset of a field, when it is constant. + + Opcodes that cannot be part of a constant expression, for example + those involving registers, simply result in a return of + 'false'. + + This function may emit a complaint. */ + +extern bool decode_locdesc (dwarf_block *blk, dwarf2_cu *cu, CORE_ADDR *result); + +/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. + Return 1 if the attributes are present and valid, otherwise, return 0. + TAG is passed to dwarf2_ranges_process. If MAP is not NULL, then + ranges in MAP are set, using DATUM as the value. */ + +extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return, + unrelocated_addr *high_return, dwarf2_cu *cu, + addrmap_mutable *map, void *datum, + dwarf_tag tag); -extern htab_up create_quick_file_names_table (unsigned int nr_initial_entries); +extern file_and_directory &find_file_and_directory (die_info *die, + dwarf2_cu *cu); #endif /* GDB_DWARF2_READ_H */ |