X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fdwarf2%2Fread.c;h=7c148aecdf5aec45b02374b90a0d4f92c14cd909;hb=30bf8e1ce4498467d62387b0d8a7009e3fbe2ab1;hp=9292e52c0001c1779e1bc22cf65136ee3160e8dc;hpb=81e33ce2894678a60ed4d5e4471cd6eb968056c2;p=binutils-gdb.git diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 9292e52c000..7c148aecdf5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -1,6 +1,6 @@ /* DWARF 2 debugging format support for GDB. - Copyright (C) 1994-2021 Free Software Foundation, Inc. + Copyright (C) 1994-2022 Free Software Foundation, Inc. Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, Inc. with support from Florida State University (under contract @@ -64,7 +64,6 @@ #include "block.h" #include "addrmap.h" #include "typeprint.h" -#include "psympriv.h" #include "c-lang.h" #include "go-lang.h" #include "valprint.h" @@ -89,6 +88,11 @@ #include "gdbsupport/pathstuff.h" #include "count-one-bits.h" #include +#include "dwarf2/abbrev-cache.h" +#include "cooked-index.h" +#include "split-name.h" +#include "gdbsupport/parallel-for.h" +#include "gdbsupport/thread-pool.h" /* When == 1, print basic high level tracing messages. When > 1, be more verbose. @@ -362,7 +366,7 @@ struct mapped_debug_names final : public mapped_index_base { return this->name_count; } }; -/* See dwarf2read.h. */ +/* See dwarf2/read.h. */ dwarf2_per_objfile * get_dwarf2_per_objfile (struct objfile *objfile) @@ -477,13 +481,8 @@ struct stmt_list_hash that can be shared across objfiles. The non-shareable parts are in type_unit_group_unshareable. */ -struct type_unit_group : public dwarf2_per_cu_data +struct type_unit_group { - /* The TUs that share this DW_AT_stmt_list entry. - This is added to while parsing type units to build partial symtabs, - and is deleted afterwards and not used again. */ - std::vector *tus = nullptr; - /* The data used to construct the hash key. */ struct stmt_list_hash hash {}; }; @@ -791,7 +790,8 @@ public: dwarf2_per_objfile *per_objfile, struct abbrev_table *abbrev_table, dwarf2_cu *existing_cu, - bool skip_partial); + bool skip_partial, + abbrev_cache *cache = nullptr); explicit cutu_reader (struct dwarf2_per_cu_data *this_cu, dwarf2_per_objfile *per_objfile, @@ -800,6 +800,8 @@ public: DISABLE_COPY_AND_ASSIGN (cutu_reader); + cutu_reader (cutu_reader &&) = default; + const gdb_byte *info_ptr = nullptr; struct die_info *comp_unit_die = nullptr; bool dummy_p = false; @@ -808,6 +810,13 @@ public: for dummy CUs. */ void keep (); + /* Release the abbrev table, transferring ownership to the + caller. */ + abbrev_table_up release_abbrev_table () + { + return std::move (m_abbrev_table_holder); + } + private: void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu, dwarf2_per_objfile *per_objfile, @@ -823,150 +832,6 @@ private: abbrev_table_up m_dwo_abbrev_table; }; -/* When we construct a partial symbol table entry we only - need this much information. */ -struct partial_die_info : public allocate_on_obstack - { - partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev); - - /* Disable assign but still keep copy ctor, which is needed - load_partial_dies. */ - partial_die_info& operator=(const partial_die_info& rhs) = delete; - partial_die_info (const partial_die_info &) = default; - - /* Adjust the partial die before generating a symbol for it. This - function may set the is_external flag or change the DIE's - name. */ - void fixup (struct dwarf2_cu *cu); - - /* Read a minimal amount of information into the minimal die - structure. */ - const gdb_byte *read (const struct die_reader_specs *reader, - const struct abbrev_info &abbrev, - const gdb_byte *info_ptr); - - /* Compute the name of this partial DIE. This memoizes the - result, so it is safe to call multiple times. */ - const char *name (dwarf2_cu *cu); - - /* Offset of this DIE. */ - const sect_offset sect_off; - - /* DWARF-2 tag for this DIE. */ - const ENUM_BITFIELD(dwarf_tag) tag : 16; - - /* Assorted flags describing the data found in this DIE. */ - const unsigned int has_children : 1; - - unsigned int is_external : 1; - unsigned int is_declaration : 1; - unsigned int has_type : 1; - unsigned int has_specification : 1; - unsigned int has_pc_info : 1; - unsigned int may_be_inlined : 1; - - /* This DIE has been marked DW_AT_main_subprogram. */ - unsigned int main_subprogram : 1; - - /* Flag set if the SCOPE field of this structure has been - computed. */ - unsigned int scope_set : 1; - - /* Flag set if the DIE has a byte_size attribute. */ - unsigned int has_byte_size : 1; - - /* Flag set if the DIE has a DW_AT_const_value attribute. */ - unsigned int has_const_value : 1; - - /* Flag set if any of the DIE's children are template arguments. */ - unsigned int has_template_arguments : 1; - - /* Flag set if fixup has been called on this die. */ - unsigned int fixup_called : 1; - - /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */ - unsigned int is_dwz : 1; - - /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt. */ - unsigned int spec_is_dwz : 1; - - unsigned int canonical_name : 1; - - /* The name of this DIE. Normally the value of DW_AT_name, but - sometimes a default name for unnamed DIEs. */ - const char *raw_name = nullptr; - - /* The linkage name, if present. */ - const char *linkage_name = nullptr; - - /* The scope to prepend to our children. This is generally - allocated on the comp_unit_obstack, so will disappear - when this compilation unit leaves the cache. */ - const char *scope = nullptr; - - /* Some data associated with the partial DIE. The tag determines - which field is live. */ - union - { - /* The location description associated with this DIE, if any. */ - struct dwarf_block *locdesc; - /* The offset of an import, for DW_TAG_imported_unit. */ - sect_offset sect_off; - } d {}; - - /* If HAS_PC_INFO, the PC range associated with this DIE. */ - CORE_ADDR lowpc = 0; - CORE_ADDR highpc = 0; - - /* Pointer into the info_buffer (or types_buffer) pointing at the target of - DW_AT_sibling, if any. */ - /* NOTE: This member isn't strictly necessary, partial_die_info::read - could return DW_AT_sibling values to its caller load_partial_dies. */ - const gdb_byte *sibling = nullptr; - - /* If HAS_SPECIFICATION, the offset of the DIE referred to by - DW_AT_specification (or DW_AT_abstract_origin or - DW_AT_extension). */ - sect_offset spec_offset {}; - - /* Pointers to this DIE's parent, first child, and next sibling, - if any. */ - struct partial_die_info *die_parent = nullptr; - struct partial_die_info *die_child = nullptr; - struct partial_die_info *die_sibling = nullptr; - - friend struct partial_die_info * - dwarf2_cu::find_partial_die (sect_offset sect_off); - - private: - /* Only need to do look up in dwarf2_cu::find_partial_die. */ - partial_die_info (sect_offset sect_off) - : partial_die_info (sect_off, DW_TAG_padding, 0) - { - } - - partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_, - int has_children_) - : sect_off (sect_off_), tag (tag_), has_children (has_children_) - { - is_external = 0; - is_declaration = 0; - has_type = 0; - has_specification = 0; - has_pc_info = 0; - may_be_inlined = 0; - main_subprogram = 0; - scope_set = 0; - has_byte_size = 0; - has_const_value = 0; - has_template_arguments = 0; - fixup_called = 0; - is_dwz = 0; - spec_is_dwz = 0; - canonical_name = 0; - } - }; - /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte, but this would require a corresponding change in unpack_field_as_long and friends. */ @@ -1076,9 +941,9 @@ static void show_dwarf_max_cache_age (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("The upper bound on the age of cached " - "DWARF compilation units is %s.\n"), - value); + gdb_printf (file, _("The upper bound on the age of cached " + "DWARF compilation units is %s.\n"), + value); } /* local function prototypes */ @@ -1086,63 +951,14 @@ show_dwarf_max_cache_age (struct ui_file *file, int from_tty, static void dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu); -static dwarf2_psymtab *create_partial_symtab - (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, - const char *name); - -static void build_type_psymtabs_reader (const struct die_reader_specs *reader, - const gdb_byte *info_ptr, - struct die_info *type_unit_die); +class cooked_index_storage; +static void build_type_psymtabs_reader (cutu_reader *reader, + cooked_index_storage *storage); static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile); -static void scan_partial_symbols (struct partial_die_info *, - CORE_ADDR *, CORE_ADDR *, - int, struct dwarf2_cu *); - -static void add_partial_symbol (struct partial_die_info *, - struct dwarf2_cu *); - -static void add_partial_namespace (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int set_addrmap, struct dwarf2_cu *cu); - -static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, - CORE_ADDR *highpc, int set_addrmap, - struct dwarf2_cu *cu); - -static void add_partial_enumeration (struct partial_die_info *enum_pdi, - struct dwarf2_cu *cu); - -static void add_partial_subprogram (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int need_pc, struct dwarf2_cu *cu); - static unsigned int peek_abbrev_code (bfd *, const gdb_byte *); -static struct partial_die_info *load_partial_dies - (const struct die_reader_specs *, const gdb_byte *, int); - -/* A pair of partial_die_info and compilation unit. */ -struct cu_partial_die_info -{ - /* The compilation unit of the partial_die_info. */ - struct dwarf2_cu *cu; - /* A partial_die_info. */ - struct partial_die_info *pdi; - - cu_partial_die_info (struct dwarf2_cu *cu, struct partial_die_info *pdi) - : cu (cu), - pdi (pdi) - { /* Nothing. */ } - -private: - cu_partial_die_info () = delete; -}; - -static const struct cu_partial_die_info find_partial_die (sect_offset, int, - struct dwarf2_cu *); - static const gdb_byte *read_attribute (const struct die_reader_specs *, struct attribute *, const struct attr_abbrev *, @@ -1192,8 +1008,8 @@ static struct die_info *die_specification (struct die_info *die, static line_header_up dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu); -static void dwarf_decode_lines (struct line_header *, const char *, - struct dwarf2_cu *, dwarf2_psymtab *, +static void dwarf_decode_lines (struct line_header *, + struct dwarf2_cu *, CORE_ADDR, int decode_mapping); static void dwarf2_start_subfile (struct dwarf2_cu *, const char *, @@ -1282,7 +1098,8 @@ enum pc_bounds_kind static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, - dwarf2_psymtab *); + addrmap *, + void *); static void get_scope_pc_bounds (struct die_info *, CORE_ADDR *, CORE_ADDR *, @@ -1426,15 +1243,12 @@ static void dwarf2_symbol_mark_computed (const struct attribute *attr, static const gdb_byte *skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, - const struct abbrev_info *abbrev); - -static hashval_t partial_die_hash (const void *item); - -static int partial_die_eq (const void *item_lhs, const void *item_rhs); + const struct abbrev_info *abbrev, + bool do_skip_children = true); static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit (sect_offset sect_off, unsigned int offset_in_dwz, - dwarf2_per_objfile *per_objfile); + dwarf2_per_bfd *per_bfd); static void prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, @@ -1522,27 +1336,14 @@ dwarf2_per_cu_data_deleter::operator() (dwarf2_per_cu_data *data) delete data; } -/* The return type of find_file_and_directory. Note, the enclosed - string pointers are only valid while this object is valid. */ - -struct file_and_directory -{ - /* The filename. This is never NULL. */ - const char *name; - - /* The compilation directory. NULL if not known. If we needed to - compute a new string, this points to COMP_DIR_STORAGE, otherwise, - points directly to the DW_AT_comp_dir string attribute owned by - the obstack that owns the DIE. */ - const char *comp_dir; - - /* If we needed to build a new string for comp_dir, this is what - owns the storage. */ - std::string comp_dir_storage; -}; +static file_and_directory &find_file_and_directory + (struct die_info *die, struct dwarf2_cu *cu); -static file_and_directory find_file_and_directory (struct die_info *die, - struct dwarf2_cu *cu); +static const char *compute_include_file_name + (const struct line_header *lh, + const file_entry &fe, + const file_and_directory &cu_info, + gdb::unique_xmalloc_ptr *name_holder); static htab_up allocate_signatured_type_table (); @@ -1639,6 +1440,73 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs) +/* An iterator for all_comp_units that is based on index. This + approach makes it possible to iterate over all_comp_units safely, + when some caller in the loop may add new units. */ + +class all_comp_units_iterator +{ +public: + + all_comp_units_iterator (dwarf2_per_bfd *per_bfd, bool start) + : m_per_bfd (per_bfd), + m_index (start ? 0 : per_bfd->all_comp_units.size ()) + { + } + + all_comp_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_comp_units_iterator &other) const + { + return m_index == other.m_index; + } + + + bool operator!= (const all_comp_units_iterator &other) const + { + return m_index != other.m_index; + } + +private: + + dwarf2_per_bfd *m_per_bfd; + size_t m_index; +}; + +/* A range adapter for the all_comp_units_iterator. */ +class all_comp_units_range +{ +public: + + all_comp_units_range (dwarf2_per_bfd *per_bfd) + : m_per_bfd (per_bfd) + { + } + + all_comp_units_iterator begin () + { + return all_comp_units_iterator (m_per_bfd, true); + } + + all_comp_units_iterator end () + { + return all_comp_units_iterator (m_per_bfd, false); + } + +private: + + dwarf2_per_bfd *m_per_bfd; +}; + /* See declaration. */ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names, @@ -1656,7 +1524,10 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names, dwarf2_per_bfd::~dwarf2_per_bfd () { for (auto &per_cu : all_comp_units) - per_cu->imported_symtabs_free (); + { + per_cu->imported_symtabs_free (); + per_cu->free_cached_file_names (); + } /* Everything else should be on this->obstack. */ } @@ -1703,9 +1574,9 @@ private: bool dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const { - gdb_assert (per_cu->index < this->m_symtabs.size ()); - - return this->m_symtabs[per_cu->index] != nullptr; + if (per_cu->index < this->m_symtabs.size ()) + return this->m_symtabs[per_cu->index] != nullptr; + return false; } /* See read.h. */ @@ -1713,9 +1584,9 @@ dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const compunit_symtab * dwarf2_per_objfile::get_symtab (const dwarf2_per_cu_data *per_cu) const { - gdb_assert (per_cu->index < this->m_symtabs.size ()); - - return this->m_symtabs[per_cu->index]; + if (per_cu->index < this->m_symtabs.size ()) + return this->m_symtabs[per_cu->index]; + return nullptr; } /* See read.h. */ @@ -1724,9 +1595,9 @@ void dwarf2_per_objfile::set_symtab (const dwarf2_per_cu_data *per_cu, compunit_symtab *symtab) { - gdb_assert (per_cu->index < this->m_symtabs.size ()); + if (per_cu->index >= this->m_symtabs.size ()) + this->m_symtabs.resize (per_cu->index + 1); gdb_assert (this->m_symtabs[per_cu->index] == nullptr); - this->m_symtabs[per_cu->index] = symtab; } @@ -1952,6 +1823,25 @@ dwarf2_get_section_info (struct objfile *objfile, *sizep = info->size; } +/* See dwarf2/read.h. */ + +void +dwarf2_per_bfd::map_info_sections (struct objfile *objfile) +{ + info.read (objfile); + abbrev.read (objfile); + line.read (objfile); + str.read (objfile); + str_offsets.read (objfile); + line_str.read (objfile); + ranges.read (objfile); + rnglists.read (objfile); + addr.read (objfile); + + for (auto §ion : types) + section.read (objfile); +} + /* DWARF quick_symbol_functions support. */ @@ -1968,6 +1858,10 @@ struct quick_file_names /* The number of entries in file_names, real_names. */ unsigned int num_file_names; + /* The CU directory, as given by DW_AT_comp_dir. May be + nullptr. */ + const char *comp_dir; + /* The file names from the line table, after being run through file_full_name. */ const char **file_names; @@ -1977,49 +1871,6 @@ struct quick_file_names const char **real_names; }; -/* When using the index (and thus not using psymtabs), each CU has an - object of this type. This is used to hold information needed by - the various "quick" methods. */ -struct dwarf2_per_cu_quick_data -{ - /* 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; - - /* A temporary mark bit used when iterating over all CUs in - expand_symtabs_matching. */ - unsigned int mark : 1; - - /* True if we've tried to read the file table and found there isn't one. - There will be no point in trying to read it again next time. */ - unsigned int no_file_data : 1; -}; - -/* A subclass of psymbol_functions that arranges to read the DWARF - partial symbols when needed. */ -struct lazy_dwarf_reader : public psymbol_functions -{ - using psymbol_functions::psymbol_functions; - - bool can_lazily_read_symbols () override - { - return true; - } - - void read_partial_symbols (struct objfile *objfile) override - { - if (dwarf2_has_info (objfile, nullptr)) - dwarf2_build_psymtabs (objfile, this); - } -}; - -static quick_symbol_functions_up -make_lazy_dwarf_reader () -{ - return quick_symbol_functions_up (new lazy_dwarf_reader); -} - struct dwarf2_base_index_functions : public quick_symbol_functions { bool has_symbols (struct objfile *objfile) override; @@ -2164,25 +2015,6 @@ eq_file_name_entry (const void *a, const void *b) return eq_stmt_list_entry (&ea->hash, &eb->hash); } -/* Delete function for a quick_file_names. */ - -static void -delete_file_name_entry (void *e) -{ - struct quick_file_names *file_data = (struct quick_file_names *) e; - int i; - - for (i = 0; i < file_data->num_file_names; ++i) - { - xfree ((void*) file_data->file_names[i]); - if (file_data->real_names) - xfree ((void*) file_data->real_names[i]); - } - - /* The space for the struct itself lives on the obstack, so we don't - free it here. */ -} - /* Create a quick_file_names hash table. */ static htab_up @@ -2190,7 +2022,7 @@ create_quick_file_names_table (unsigned int nr_initial_entries) { return htab_up (htab_create_alloc (nr_initial_entries, hash_file_name_entry, eq_file_name_entry, - delete_file_name_entry, xcalloc, xfree)); + nullptr, xcalloc, xfree)); } /* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This @@ -2222,11 +2054,6 @@ static void dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, bool skip_partial) { - /* Skip type_unit_groups, reading the type units they contain - is handled elsewhere. */ - if (per_cu->type_unit_group_p ()) - return; - { /* The destructor of dwarf2_queue_guard frees any entries left on the queue. After this point we're guaranteed to leave this function @@ -2269,8 +2096,6 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, bool skip_partial) { - gdb_assert (per_objfile->per_bfd->using_index); - if (!per_objfile->symtab_set_p (per_cu)) { free_cached_comp_units freer (per_objfile); @@ -2319,8 +2144,6 @@ create_cu_from_index_list (dwarf2_per_bfd *per_bfd, the_cu->sect_off = sect_off; the_cu->length = length; the_cu->section = section; - the_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack, - struct dwarf2_per_cu_quick_data); the_cu->is_dwz = is_dwz; return the_cu; } @@ -2401,9 +2224,6 @@ create_signatured_type_table_from_index sig_type->type_offset_in_tu = type_offset_in_tu; sig_type->section = section; sig_type->sect_off = sect_off; - sig_type->v.quick - = OBSTACK_ZALLOC (&per_bfd->obstack, - struct dwarf2_per_cu_quick_data); slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); *slot = sig_type.get (); @@ -2452,9 +2272,6 @@ create_signatured_type_table_from_debug_names sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu; sig_type->section = section; sig_type->sect_off = sect_off; - sig_type->v.quick - = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, - struct dwarf2_per_cu_quick_data); slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); *slot = sig_type.get (); @@ -2522,12 +2339,14 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile, &per_bfd->obstack); } -/* Read the address map data from DWARF-5 .debug_aranges, and use it to - populate the psymtabs_addrmap. */ +/* Read the address map data from DWARF-5 .debug_aranges, and use it + to populate given addrmap. Returns true on success, false on + failure. */ -static void -create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, - struct dwarf2_section_info *section) +static bool +read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, + struct dwarf2_section_info *section, + addrmap *mutable_map) { struct objfile *objfile = per_objfile->objfile; bfd *abfd = objfile->obfd; @@ -2535,15 +2354,19 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, const CORE_ADDR baseaddr = objfile->text_section_offset (); dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - auto_obstack temp_obstack; - addrmap *mutable_map = addrmap_create_mutable (&temp_obstack); - std::unordered_map> debug_info_offset_to_per_cu; for (const auto &per_cu : per_bfd->all_comp_units) { + /* A TU will not need aranges, and skipping them here is an easy + way of ignoring .debug_types -- and possibly seeing a + duplicate section offset -- entirely. The same applies to + units coming from a dwz file. */ + if (per_cu->is_debug_types || per_cu->is_dwz) + continue; + const auto insertpair = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu.get ()); @@ -2552,7 +2375,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, warning (_("Section .debug_aranges in %s has duplicate " "debug_info_offset %s, ignoring .debug_aranges."), objfile_name (objfile), sect_offset_str (per_cu->sect_off)); - return; + return false; } } @@ -2583,7 +2406,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, plongest (entry_addr - section->buffer), plongest (bytes_read + entry_length), pulongest (section->size)); - return; + return false; } /* The version number. */ @@ -2595,7 +2418,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, "has unsupported version %d, ignoring .debug_aranges."), objfile_name (objfile), plongest (entry_addr - section->buffer), version); - return; + return false; } const uint64_t debug_info_offset @@ -2611,7 +2434,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, objfile_name (objfile), plongest (entry_addr - section->buffer), pulongest (debug_info_offset)); - return; + return false; } dwarf2_per_cu_data *const per_cu = per_cu_it->second; @@ -2622,7 +2445,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, "address_size %u is invalid, ignoring .debug_aranges."), objfile_name (objfile), plongest (entry_addr - section->buffer), address_size); - return; + return false; } const uint8_t segment_selector_size = *addr++; @@ -2634,7 +2457,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, objfile_name (objfile), plongest (entry_addr - section->buffer), segment_selector_size); - return; + return false; } /* Must pad to an alignment boundary that is twice the address @@ -2655,7 +2478,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, "ignoring .debug_aranges."), objfile_name (objfile), plongest (entry_addr - section->buffer)); - return; + return false; } ULONGEST start = extract_unsigned_integer (addr, address_size, dwarf5_byte_order); @@ -2677,10 +2500,28 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, - baseaddr); addrmap_set_empty (mutable_map, start, end - 1, per_cu); } + + per_cu->addresses_seen = true; } - per_bfd->index_addrmap = addrmap_create_fixed (mutable_map, - &per_bfd->obstack); + return true; +} + +/* Read the address map data from DWARF-5 .debug_aranges, and use it to + populate the psymtabs_addrmap. */ + +static void +create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, + struct dwarf2_section_info *section) +{ + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + + auto_obstack temp_obstack; + addrmap *mutable_map = addrmap_create_mutable (&temp_obstack); + + if (read_addrmap_from_aranges (per_objfile, section, mutable_map)) + per_bfd->index_addrmap = addrmap_create_fixed (mutable_map, + &per_bfd->obstack); } /* A helper function that reads the .gdb_index from BUFFER and fills @@ -2785,6 +2626,15 @@ to use the section anyway."), ++i; map->constant_pool = buffer.slice (metadata[i]); + if (map->constant_pool.empty () && !map->symbol_table.empty ()) + { + /* An empty constant pool implies that all symbol table entries are + empty. Make map->symbol_table.empty () == true. */ + map->symbol_table + = offset_view (gdb::array_view (symbol_table, + symbol_table)); + } + return 1; } @@ -2876,7 +2726,6 @@ dwarf2_read_gdb_index create_addrmap_from_index (per_objfile, map.get ()); per_bfd->index_table = std::move (map); - per_bfd->using_index = 1; per_bfd->quick_file_names_table = create_quick_file_names_table (per_bfd->all_comp_units.size ()); @@ -2899,13 +2748,11 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, gdb_assert (! this_cu->is_debug_types); + this_cu->files_read = true; /* Our callers never want to match partial units -- instead they will match the enclosing full CU. */ if (comp_unit_die->tag == DW_TAG_partial_unit) - { - this_cu->v.quick->no_file_data = 1; - return; - } + return; lh_cu = this_cu; slot = NULL; @@ -2928,42 +2775,59 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, &find_entry, INSERT); if (*slot != NULL) { - lh_cu->v.quick->file_names = (struct quick_file_names *) *slot; + lh_cu->file_names = (struct quick_file_names *) *slot; return; } lh = dwarf_decode_line_header (line_offset, cu); } - if (lh == NULL) - { - lh_cu->v.quick->no_file_data = 1; - return; - } + + file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu); + + int offset = 0; + if (!fnd.is_unknown ()) + ++offset; + else if (lh == nullptr) + return; qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names); qfn->hash.dwo_unit = cu->dwo_unit; qfn->hash.line_sect_off = line_offset; - gdb_assert (slot != NULL); - *slot = qfn; - - file_and_directory fnd = find_file_and_directory (comp_unit_die, cu); + /* There may not be a DW_AT_stmt_list. */ + if (slot != nullptr) + *slot = qfn; - int offset = 0; - if (strcmp (fnd.name, "") != 0) - ++offset; + std::vector include_names; + if (lh != nullptr) + { + for (const auto &entry : lh->file_names ()) + { + gdb::unique_xmalloc_ptr name_holder; + const char *include_name = + compute_include_file_name (lh.get (), entry, fnd, &name_holder); + if (include_name != nullptr) + { + include_name = per_objfile->objfile->intern (include_name); + include_names.push_back (include_name); + } + } + } - qfn->num_file_names = offset + lh->file_names_size (); + qfn->num_file_names = offset + include_names.size (); + qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile); qfn->file_names = XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *, qfn->num_file_names); if (offset != 0) - qfn->file_names[0] = xstrdup (fnd.name); - for (int i = 0; i < lh->file_names_size (); ++i) - qfn->file_names[i + offset] = lh->file_full_name (i + 1, - fnd.comp_dir).release (); + qfn->file_names[0] = xstrdup (fnd.get_name ()); + + if (!include_names.empty ()) + memcpy (&qfn->file_names[offset], include_names.data (), + include_names.size () * sizeof (const char *)); + qfn->real_names = NULL; - lh_cu->v.quick->file_names = qfn; + lh_cu->file_names = qfn; } /* A helper for the "quick" functions which attempts to read the line @@ -2975,22 +2839,15 @@ dw2_get_file_names (dwarf2_per_cu_data *this_cu, { /* This should never be called for TUs. */ gdb_assert (! this_cu->is_debug_types); - /* Nor type unit groups. */ - gdb_assert (! this_cu->type_unit_group_p ()); - if (this_cu->v.quick->file_names != NULL) - return this_cu->v.quick->file_names; - /* If we know there is no line data, no point in looking again. */ - if (this_cu->v.quick->no_file_data) - return NULL; + if (this_cu->files_read) + return this_cu->file_names; cutu_reader reader (this_cu, per_objfile); if (!reader.dummy_p) dw2_get_file_names_reader (&reader, reader.comp_unit_die); - if (this_cu->v.quick->no_file_data) - return NULL; - return this_cu->v.quick->file_names; + return this_cu->file_names; } /* A helper for the "quick" functions which computes and caches the @@ -3005,7 +2862,17 @@ dw2_get_real_path (dwarf2_per_objfile *per_objfile, qfn->num_file_names, const char *); if (qfn->real_names[index] == NULL) - qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release (); + { + const char *dirname = nullptr; + + if (!IS_ABSOLUTE_PATH (qfn->file_names[index])) + dirname = qfn->comp_dir; + + gdb::unique_xmalloc_ptr fullname; + fullname = find_source_or_rewrite (qfn->file_names[index], dirname); + + qfn->real_names[index] = fullname.release (); + } return qfn->real_names[index]; } @@ -3021,28 +2888,29 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile) if (cust == NULL) return NULL; - return compunit_primary_filetab (cust); + return cust->primary_filetab (); } -/* Traversal function for dw2_forget_cached_source_info. */ +/* See read.h. */ -static int -dw2_free_cached_file_names (void **slot, void *info) +void +dwarf2_per_cu_data::free_cached_file_names () { - struct quick_file_names *file_data = (struct quick_file_names *) *slot; + if (fnd != nullptr) + fnd->forget_fullname (); - if (file_data->real_names) - { - int i; + if (per_bfd == nullptr) + return; - for (i = 0; i < file_data->num_file_names; ++i) + struct quick_file_names *file_data = file_names; + if (file_data != nullptr && file_data->real_names != nullptr) + { + for (int i = 0; i < file_data->num_file_names; ++i) { - xfree ((void*) file_data->real_names[i]); - file_data->real_names[i] = NULL; + xfree ((void *) file_data->real_names[i]); + file_data->real_names[i] = nullptr; } } - - return 1; } void @@ -3051,8 +2919,8 @@ dwarf2_base_index_functions::forget_cached_source_info { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - htab_traverse_noresize (per_objfile->per_bfd->quick_file_names_table.get (), - dw2_free_cached_file_names, NULL); + for (auto &per_cu : per_objfile->per_bfd->all_comp_units) + per_cu->free_cached_file_names (); } /* Struct used to manage iterating over all CUs looking for a symbol. */ @@ -3221,8 +3089,8 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile, if (!per_objfile->symtab_set_p (per_cu)) ++count; } - printf_filtered (_(" Number of read CUs: %d\n"), total - count); - printf_filtered (_(" Number of unread CUs: %d\n"), count); + gdb_printf (_(" Number of read CUs: %d\n"), total - count); + gdb_printf (_(" Number of unread CUs: %d\n"), count); } /* This dumps minimal information about the index. @@ -3235,16 +3103,15 @@ dwarf2_gdb_index::dump (struct objfile *objfile) { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - gdb_assert (per_objfile->per_bfd->using_index); - printf_filtered (".gdb_index:"); + gdb_printf (".gdb_index:"); if (per_objfile->per_bfd->index_table != NULL) { - printf_filtered (" version %d\n", - per_objfile->per_bfd->index_table->version); + gdb_printf (" version %d\n", + per_objfile->per_bfd->index_table->version); } else - printf_filtered (" faked for \"readnow\"\n"); - printf_filtered ("\n"); + gdb_printf (" faked for \"readnow\"\n"); + gdb_printf ("\n"); } void @@ -4107,7 +3974,7 @@ dw2_expand_symtabs_matching_one gdb::function_view file_matcher, gdb::function_view expansion_notify) { - if (file_matcher == NULL || per_cu->v.quick->mark) + if (file_matcher == NULL || per_cu->mark) { bool symtab_was_null = !per_objfile->symtab_set_p (per_cu); @@ -4248,12 +4115,33 @@ dw_expand_symtabs_matching_file_matcher if (per_cu->is_debug_types) continue; - per_cu->v.quick->mark = 0; + per_cu->mark = 0; /* We only need to look at symtabs not already expanded. */ if (per_objfile->symtab_set_p (per_cu.get ())) continue; + if (per_cu->fnd != nullptr) + { + file_and_directory *fnd = per_cu->fnd.get (); + + if (file_matcher (fnd->get_name (), false)) + { + per_cu->mark = 1; + continue; + } + + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if ((basenames_may_differ + || file_matcher (lbasename (fnd->get_name ()), true)) + && file_matcher (fnd->get_fullname (), false)) + { + per_cu->mark = 1; + continue; + } + } + quick_file_names *file_data = dw2_get_file_names (per_cu.get (), per_objfile); if (file_data == NULL) @@ -4263,7 +4151,7 @@ dw_expand_symtabs_matching_file_matcher continue; else if (htab_find (visited_found.get (), file_data) != NULL) { - per_cu->v.quick->mark = 1; + per_cu->mark = 1; continue; } @@ -4273,7 +4161,7 @@ dw_expand_symtabs_matching_file_matcher if (file_matcher (file_data->file_names[j], false)) { - per_cu->v.quick->mark = 1; + per_cu->mark = 1; break; } @@ -4287,12 +4175,12 @@ dw_expand_symtabs_matching_file_matcher this_real_name = dw2_get_real_path (per_objfile, file_data, j); if (file_matcher (this_real_name, false)) { - per_cu->v.quick->mark = 1; + per_cu->mark = 1; break; } } - void **slot = htab_find_slot (per_cu->v.quick->mark + void **slot = htab_find_slot (per_cu->mark ? visited_found.get () : visited_not_found.get (), file_data, INSERT); @@ -4319,13 +4207,16 @@ dwarf2_gdb_index::expand_symtabs_matching dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher); - if (symbol_matcher == NULL && lookup_name == NULL) + /* This invariant is documented in quick-functions.h. */ + gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); + if (lookup_name == nullptr) { - for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) + for (dwarf2_per_cu_data *per_cu + : all_comp_units_range (per_objfile->per_bfd)) { QUIT; - if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile, + if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, expansion_notify)) return false; @@ -4358,8 +4249,8 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust, { int i; - if (COMPUNIT_BLOCKVECTOR (cust) != NULL - && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc)) + if (cust->blockvector () != nullptr + && blockvector_contains_pc (cust->blockvector (), pc)) return cust; if (cust->includes == NULL) @@ -4430,21 +4321,40 @@ dwarf2_base_index_functions::map_symbol_filenames for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) { - if (per_objfile->symtab_set_p (per_cu.get ())) + if (!per_cu->is_debug_types + && per_objfile->symtab_set_p (per_cu.get ())) { - if (per_cu->v.quick->file_names != nullptr) - qfn_cache.insert (per_cu->v.quick->file_names); + if (per_cu->file_names != nullptr) + qfn_cache.insert (per_cu->file_names); } } - for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) + for (dwarf2_per_cu_data *per_cu + : all_comp_units_range (per_objfile->per_bfd)) { /* We only need to look at symtabs not already expanded. */ - if (per_objfile->symtab_set_p (per_cu.get ())) + if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu)) continue; - quick_file_names *file_data = dw2_get_file_names (per_cu.get (), - per_objfile); + if (per_cu->fnd != nullptr) + { + file_and_directory *fnd = per_cu->fnd.get (); + + const char *filename = fnd->get_name (); + const char *key = filename; + const char *fullname = nullptr; + + if (need_fullname) + { + fullname = fnd->get_fullname (); + key = fullname; + } + + if (!filenames_cache.seen (key)) + fun (filename, fullname); + } + + quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile); if (file_data == nullptr || qfn_cache.find (file_data) != qfn_cache.end ()) continue; @@ -4452,18 +4362,19 @@ dwarf2_base_index_functions::map_symbol_filenames for (int j = 0; j < file_data->num_file_names; ++j) { const char *filename = file_data->file_names[j]; - filenames_cache.seen (filename); - } - } + const char *key = filename; + const char *fullname = nullptr; - filenames_cache.traverse ([&] (const char *filename) - { - gdb::unique_xmalloc_ptr this_real_name; + if (need_fullname) + { + fullname = dw2_get_real_path (per_objfile, file_data, j); + key = fullname; + } - if (need_fullname) - this_real_name = gdb_realpath (filename); - fun (filename, this_real_name.get ()); - }); + if (!filenames_cache.seen (key)) + fun (filename, fullname); + } + } } bool @@ -4812,7 +4723,6 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges); per_bfd->debug_names_table = std::move (map); - per_bfd->using_index = 1; per_bfd->quick_file_names_table = create_quick_file_names_table (per_bfd->all_comp_units.size ()); @@ -5238,13 +5148,12 @@ dwarf2_debug_names_index::dump (struct objfile *objfile) { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - gdb_assert (per_objfile->per_bfd->using_index); - printf_filtered (".debug_names:"); + gdb_printf (".debug_names:"); if (per_objfile->per_bfd->debug_names_table) - printf_filtered (" exists\n"); + gdb_printf (" exists\n"); else - printf_filtered (" faked for \"readnow\"\n"); - printf_filtered ("\n"); + gdb_printf (" faked for \"readnow\"\n"); + gdb_printf ("\n"); } void @@ -5307,13 +5216,16 @@ dwarf2_debug_names_index::expand_symtabs_matching dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher); - if (symbol_matcher == NULL && lookup_name == NULL) + /* This invariant is documented in quick-functions.h. */ + gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); + if (lookup_name == nullptr) { - for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) + for (dwarf2_per_cu_data *per_cu + : all_comp_units_range (per_objfile->per_bfd)) { QUIT; - if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile, + if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, expansion_notify)) return false; @@ -5398,6 +5310,8 @@ get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz) return global_index_cache.lookup_gdb_index (build_id, &dwz->index_cache_res); } +static quick_symbol_functions_up make_cooked_index_funcs (); + /* See dwarf2/public.h. */ void @@ -5416,29 +5330,9 @@ dwarf2_initialize_objfile (struct objfile *objfile) { dwarf_read_debug_printf ("readnow requested"); - /* When using READNOW, the using_index flag (set below) indicates that - PER_BFD was already initialized, when we loaded some other objfile. */ - if (per_bfd->using_index) - { - dwarf_read_debug_printf ("using_index already set"); - per_objfile->resize_symtabs (); - objfile->qf.push_front (make_dwarf_gdb_index ()); - return; - } - - per_bfd->using_index = 1; create_all_comp_units (per_objfile); per_bfd->quick_file_names_table = create_quick_file_names_table (per_bfd->all_comp_units.size ()); - per_objfile->resize_symtabs (); - - for (int i = 0; i < per_bfd->all_comp_units.size (); ++i) - { - dwarf2_per_cu_data *per_cu = per_bfd->get_cu (i); - - per_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack, - struct dwarf2_per_cu_quick_data); - } /* Arrange for gdb to see the "quick" functions. However, these functions will be no-ops because we will have expanded all @@ -5452,7 +5346,6 @@ dwarf2_initialize_objfile (struct objfile *objfile) if (per_bfd->debug_names_table != nullptr) { dwarf_read_debug_printf ("re-using shared debug names table"); - per_objfile->resize_symtabs (); objfile->qf.push_front (make_dwarf_debug_names ()); return; } @@ -5462,27 +5355,20 @@ dwarf2_initialize_objfile (struct objfile *objfile) if (per_bfd->index_table != nullptr) { dwarf_read_debug_printf ("re-using shared index table"); - per_objfile->resize_symtabs (); objfile->qf.push_front (make_dwarf_gdb_index ()); return; } - /* There might already be partial symtabs built for this BFD. This happens - when loading the same binary twice with the index-cache enabled. If so, - don't try to read an index. The objfile / per_objfile initialization will - be completed in dwarf2_build_psymtabs, in the standard partial symtabs - code path. */ - if (per_bfd->partial_symtabs != nullptr) + if (per_bfd->cooked_index_table != nullptr) { - dwarf_read_debug_printf ("re-using shared partial symtabs"); - objfile->qf.push_front (make_lazy_dwarf_reader ()); + dwarf_read_debug_printf ("re-using cooked index table"); + objfile->qf.push_front (make_cooked_index_funcs ()); return; } if (dwarf2_read_debug_names (per_objfile)) { dwarf_read_debug_printf ("found debug names"); - per_objfile->resize_symtabs (); objfile->qf.push_front (make_dwarf_debug_names ()); return; } @@ -5492,7 +5378,6 @@ dwarf2_initialize_objfile (struct objfile *objfile) get_gdb_index_contents_from_section)) { dwarf_read_debug_printf ("found gdb index from file"); - per_objfile->resize_symtabs (); objfile->qf.push_front (make_dwarf_gdb_index ()); return; } @@ -5504,13 +5389,12 @@ dwarf2_initialize_objfile (struct objfile *objfile) { dwarf_read_debug_printf ("found gdb index from cache"); global_index_cache.hit (); - per_objfile->resize_symtabs (); objfile->qf.push_front (make_dwarf_gdb_index ()); return; } global_index_cache.miss (); - objfile->qf.push_front (make_lazy_dwarf_reader ()); + objfile->qf.push_front (make_cooked_index_funcs ()); } @@ -5518,50 +5402,21 @@ dwarf2_initialize_objfile (struct objfile *objfile) /* Build a partial symbol table. */ void -dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf) +dwarf2_build_psymtabs (struct objfile *objfile, bool already_attached) { dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - if (per_bfd->partial_symtabs != nullptr) + if (already_attached) { - /* Partial symbols were already read, so now we can simply - attach them. */ - if (psf == nullptr) - { - psf = new psymbol_functions (per_bfd->partial_symtabs); - objfile->qf.emplace_front (psf); - } - else - psf->set_partial_symtabs (per_bfd->partial_symtabs); - per_objfile->resize_symtabs (); - return; - } - - if (psf == nullptr) - { - psf = new psymbol_functions; - objfile->qf.emplace_front (psf); + if (per_objfile->per_bfd->cooked_index_table != nullptr) + return; } - const std::shared_ptr &partial_symtabs - = psf->get_partial_symtabs (); - - /* Set the local reference to partial symtabs, so that we don't try - to read them again if reading another objfile with the same BFD. - If we can't in fact share, this won't make a difference anyway as - the dwarf2_per_bfd object won't be shared. */ - per_bfd->partial_symtabs = partial_symtabs; + else + objfile->qf.push_front (make_cooked_index_funcs ()); try { - /* This isn't really ideal: all the data we allocate on the - objfile's obstack is still uselessly kept around. However, - freeing it seems unsafe. */ - psymtab_discarder psymtabs (partial_symtabs.get ()); dwarf2_build_psymtabs_hard (per_objfile); - psymtabs.keep (); - - per_objfile->resize_symtabs (); /* (maybe) store an index in the cache. */ global_index_cache.store (per_objfile); @@ -5642,107 +5497,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile, return (sect_offset) read_offset (abfd, info_ptr, offset_size); } -/* A partial symtab that is used only for include files. */ -struct dwarf2_include_psymtab : public partial_symtab -{ - dwarf2_include_psymtab (const char *filename, - psymtab_storage *partial_symtabs, - objfile_per_bfd_storage *objfile_per_bfd) - : partial_symtab (filename, partial_symtabs, objfile_per_bfd) - { - } - - void read_symtab (struct objfile *objfile) override - { - /* It's an include file, no symbols to read for it. - Everything is in the includer symtab. */ - - /* The expansion of a dwarf2_include_psymtab is just a trigger for - expansion of the includer psymtab. We use the dependencies[0] field to - model the includer. But if we go the regular route of calling - expand_psymtab here, and having expand_psymtab call expand_dependencies - to expand the includer, we'll only use expand_psymtab on the includer - (making it a non-toplevel psymtab), while if we expand the includer via - another path, we'll use read_symtab (making it a toplevel psymtab). - So, don't pretend a dwarf2_include_psymtab is an actual toplevel - psymtab, and trigger read_symtab on the includer here directly. */ - includer ()->read_symtab (objfile); - } - - void expand_psymtab (struct objfile *objfile) override - { - /* This is not called by read_symtab, and should not be called by any - expand_dependencies. */ - gdb_assert (false); - } - - bool readin_p (struct objfile *objfile) const override - { - return includer ()->readin_p (objfile); - } - - compunit_symtab *get_compunit_symtab (struct objfile *objfile) const override - { - return nullptr; - } - -private: - partial_symtab *includer () const - { - /* An include psymtab has exactly one dependency: the psymtab that - includes it. */ - gdb_assert (this->number_of_dependencies == 1); - return this->dependencies[0]; - } -}; - -/* Allocate a new partial symtab for file named NAME and mark this new - partial symtab as being an include of PST. */ - -static void -dwarf2_create_include_psymtab (dwarf2_per_bfd *per_bfd, - const char *name, - dwarf2_psymtab *pst, - psymtab_storage *partial_symtabs, - objfile_per_bfd_storage *objfile_per_bfd) -{ - dwarf2_include_psymtab *subpst - = new dwarf2_include_psymtab (name, partial_symtabs, objfile_per_bfd); - - if (!IS_ABSOLUTE_PATH (subpst->filename)) - subpst->dirname = pst->dirname; - - subpst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (1); - subpst->dependencies[0] = pst; - subpst->number_of_dependencies = 1; -} - -/* Read the Line Number Program data and extract the list of files - included by the source file represented by PST. Build an include - partial symtab for each of these included files. */ - -static void -dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, - struct die_info *die, - dwarf2_psymtab *pst) -{ - line_header_up lh; - struct attribute *attr; - - attr = dwarf2_attr (die, DW_AT_stmt_list, cu); - if (attr != nullptr && attr->form_is_unsigned ()) - lh = dwarf_decode_line_header ((sect_offset) attr->as_unsigned (), cu); - if (lh == NULL) - return; /* No linetable, so no includes. */ - - /* NOTE: pst->dirname is DW_AT_comp_dir (if present). Also note - that we pass in the raw text_low here; that is ok because we're - only decoding the line table to make include partial symtabs, and - so the addresses aren't really used. */ - dwarf_decode_lines (lh.get (), pst->dirname, cu, pst, - pst->raw_text_low (), 1); -} - static hashval_t hash_signatured_type (const void *item) { @@ -5904,16 +5658,8 @@ add_type_unit (dwarf2_per_objfile *per_objfile, ULONGEST sig, void **slot) = per_objfile->per_bfd->allocate_signatured_type (sig); signatured_type *sig_type = sig_type_holder.get (); - per_objfile->resize_symtabs (); - per_objfile->per_bfd->all_comp_units.emplace_back (sig_type_holder.release ()); - if (per_objfile->per_bfd->using_index) - { - sig_type->v.quick = - OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, - struct dwarf2_per_cu_quick_data); - } if (slot == NULL) { @@ -5939,17 +5685,14 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile, /* Make sure we're not clobbering something we don't expect to. */ gdb_assert (! sig_entry->queued); gdb_assert (per_objfile->get_cu (sig_entry) == NULL); - if (per_bfd->using_index) - { - gdb_assert (sig_entry->v.quick != NULL); - gdb_assert (!per_objfile->symtab_set_p (sig_entry)); - } - else - gdb_assert (sig_entry->v.psymtab == NULL); + gdb_assert (!per_objfile->symtab_set_p (sig_entry)); gdb_assert (sig_entry->signature == dwo_entry->signature); - gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0); + gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0 + || (to_underlying (sig_entry->type_offset_in_section) + == to_underlying (dwo_entry->type_offset_in_tu))); gdb_assert (sig_entry->type_unit_group == NULL); - gdb_assert (sig_entry->dwo_unit == NULL); + gdb_assert (sig_entry->dwo_unit == NULL + || sig_entry->dwo_unit == dwo_entry); sig_entry->section = dwo_entry->section; sig_entry->sect_off = dwo_entry->sect_off; @@ -5980,7 +5723,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) struct dwo_unit find_dwo_entry, *dwo_entry; void **slot; - gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index); + gdb_assert (cu->dwo_unit); /* If TU skeletons have been removed then we may not have read in any TUs yet. */ @@ -6027,7 +5770,8 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) if (sig_entry == NULL) sig_entry = add_type_unit (per_objfile, sig, slot); - fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry); + if (sig_entry->dwo_unit == nullptr) + fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry); sig_entry->tu_read = 1; return sig_entry; } @@ -6045,7 +5789,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) struct dwo_unit *dwo_entry; void **slot; - gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index); + gdb_assert (cu->dwo_unit); gdb_assert (dwp_file != NULL); /* If TU skeletons have been removed then we may not have read in any @@ -6086,7 +5830,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) { dwarf2_per_objfile *per_objfile = cu->per_objfile; - if (cu->dwo_unit && per_objfile->per_bfd->using_index) + if (cu->dwo_unit) { /* We're in a DWO/DWP file, and we're using .gdb_index. These cases require special processing. */ @@ -6300,11 +6044,11 @@ read_cutu_die_from_dwo (dwarf2_cu *cu, if (dwarf_die_debug) { - fprintf_unfiltered (gdb_stdlog, - "Read die from %s@0x%x of %s:\n", - section->get_name (), - (unsigned) (begin_info_ptr - section->buffer), - bfd_get_filename (abfd)); + gdb_printf (gdb_stdlog, + "Read die from %s@0x%x of %s:\n", + section->get_name (), + (unsigned) (begin_info_ptr - section->buffer), + bfd_get_filename (abfd)); dump_die (comp_unit_die, dwarf_die_debug); } @@ -6339,6 +6083,14 @@ lookup_dwo_id (struct dwarf2_cu *cu, struct die_info* comp_unit_die) static struct dwo_unit * lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name) { +#if CXX_STD_THREAD + /* We need a lock here both to handle the DWO hash table, and BFD, + which is not thread-safe. */ + static std::mutex dwo_lock; + + std::lock_guard guard (dwo_lock); +#endif + dwarf2_per_cu_data *per_cu = cu->per_cu; struct dwo_unit *dwo_unit; const char *comp_dir; @@ -6431,7 +6183,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, dwarf2_per_objfile *per_objfile, struct abbrev_table *abbrev_table, dwarf2_cu *existing_cu, - bool skip_partial) + bool skip_partial, + abbrev_cache *cache) : die_reader_specs {}, m_this_cu (this_cu) { @@ -6447,9 +6200,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, int rereading_dwo_cu = 0; if (dwarf_die_debug) - fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n", - this_cu->is_debug_types ? "type" : "comp", - sect_offset_str (this_cu->sect_off)); + gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n", + this_cu->is_debug_types ? "type" : "comp", + sect_offset_str (this_cu->sect_off)); /* If we're reading a TU directly from a DWO file, including a virtual DWO file (instead of going through the stub), short-circuit all of this. */ @@ -6485,9 +6238,14 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, } else { - /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu - in per_objfile yet. */ - gdb_assert (per_objfile->get_cu (this_cu) == nullptr); + /* If an existing_cu is provided, a dwarf2_cu must not exist for + this_cu in per_objfile yet. Here, CACHE doubles as a flag to + let us know that the CU is being scanned using the parallel + indexer. This assert is avoided in this case because (1) it + is irrelevant, and (2) the get_cu method is not + thread-safe. */ + gdb_assert (cache != nullptr + || per_objfile->get_cu (this_cu) == nullptr); m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile)); cu = m_new_cu.get (); } @@ -6555,10 +6313,16 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off); else { - abbrev_section->read (objfile); - m_abbrev_table_holder - = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off); - abbrev_table = m_abbrev_table_holder.get (); + if (cache != nullptr) + abbrev_table = cache->find (abbrev_section, + cu->header.abbrev_sect_off); + if (abbrev_table == nullptr) + { + abbrev_section->read (objfile); + m_abbrev_table_holder + = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off); + abbrev_table = m_abbrev_table_holder.get (); + } } /* Read the top level CU/TU die. */ @@ -6662,9 +6426,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, const gdb_byte *begin_info_ptr, *info_ptr; if (dwarf_die_debug) - fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n", - this_cu->is_debug_types ? "type" : "comp", - sect_offset_str (this_cu->sect_off)); + gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n", + this_cu->is_debug_types ? "type" : "comp", + sect_offset_str (this_cu->sect_off)); gdb_assert (per_objfile->get_cu (this_cu) == nullptr); @@ -6759,34 +6523,7 @@ allocate_type_unit_groups_table () static std::unique_ptr create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct) { - dwarf2_per_objfile *per_objfile = cu->per_objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - std::unique_ptr tu_group (new type_unit_group); - tu_group->per_bfd = per_bfd; - - if (per_bfd->using_index) - { - tu_group->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack, - struct dwarf2_per_cu_quick_data); - } - else - { - unsigned int line_offset = to_underlying (line_offset_struct); - dwarf2_psymtab *pst; - std::string name; - - /* Give the symtab a useful name for debug purposes. */ - if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0) - name = string_printf ("", - (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB)); - else - name = string_printf ("", line_offset); - - pst = create_partial_symtab (tu_group.get (), per_objfile, - name.c_str ()); - pst->anonymous = true; - } tu_group->hash.dwo_unit = cu->dwo_unit; tu_group->hash.line_sect_off = line_offset_struct; @@ -6848,165 +6585,235 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list) return tu_group; } -/* Partial symbol tables. */ -/* Create a psymtab named NAME and assign it to PER_CU. +/* An instance of this is created when scanning DWARF to create a + cooked index. */ - The caller must fill in the following details: - dirname, textlow, texthigh. */ - -static dwarf2_psymtab * -create_partial_symtab (dwarf2_per_cu_data *per_cu, - dwarf2_per_objfile *per_objfile, - const char *name) +class cooked_index_storage { - dwarf2_psymtab *pst - = new dwarf2_psymtab (name, per_objfile->per_bfd->partial_symtabs.get (), - per_objfile->objfile->per_bfd, per_cu); - - pst->psymtabs_addrmap_supported = true; - - /* This is the glue that links PST into GDB's symbol API. */ - per_cu->v.psymtab = pst; - - return pst; -} +public: -/* DIE reader function for process_psymtab_comp_unit. */ + cooked_index_storage () + : m_reader_hash (htab_create_alloc (10, hash_cutu_reader, + eq_cutu_reader, + htab_delete_entry, + xcalloc, xfree)), + m_index (new cooked_index), + m_addrmap_storage (), + m_addrmap (addrmap_create_mutable (&m_addrmap_storage)) + { + } -static void -process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, - const gdb_byte *info_ptr, - struct die_info *comp_unit_die, - enum language pretend_language) -{ - struct dwarf2_cu *cu = reader->cu; - dwarf2_per_objfile *per_objfile = cu->per_objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - struct objfile *objfile = per_objfile->objfile; - struct gdbarch *gdbarch = objfile->arch (); - struct dwarf2_per_cu_data *per_cu = cu->per_cu; - CORE_ADDR baseaddr; - CORE_ADDR best_lowpc = 0, best_highpc = 0; - dwarf2_psymtab *pst; - enum pc_bounds_kind cu_bounds_kind; - const char *filename; + DISABLE_COPY_AND_ASSIGN (cooked_index_storage); - gdb_assert (! per_cu->is_debug_types); + /* Return the current abbrev cache. */ + abbrev_cache *get_abbrev_cache () + { + return &m_abbrev_cache; + } - prepare_one_comp_unit (cu, comp_unit_die, pretend_language); + /* Return the DIE reader corresponding to PER_CU. If no such reader + has been registered, return NULL. */ + cutu_reader *get_reader (dwarf2_per_cu_data *per_cu) + { + int index = per_cu->index; + return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (), + &index, index); + } - /* Allocate a new partial symbol table structure. */ - gdb::unique_xmalloc_ptr debug_filename; - static const char artificial[] = ""; - filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu); - if (filename == NULL) - filename = ""; - else if (strcmp (filename, artificial) == 0) - { - debug_filename.reset (concat (artificial, "@", - sect_offset_str (per_cu->sect_off), - (char *) NULL)); - filename = debug_filename.get (); - } + /* Preserve READER by storing it in the local hash table. */ + cutu_reader *preserve (std::unique_ptr reader) + { + m_abbrev_cache.add (reader->release_abbrev_table ()); + + int index = reader->cu->per_cu->index; + void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index, + index, INSERT); + gdb_assert (*slot == nullptr); + cutu_reader *result = reader.get (); + *slot = reader.release (); + return result; + } - pst = create_partial_symtab (per_cu, per_objfile, filename); + /* Add an entry to the index. The arguments describe the entry; see + cooked-index.h. The new entry is returned. */ + const cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag, + cooked_index_flag flags, + const char *name, + const cooked_index_entry *parent_entry, + dwarf2_per_cu_data *per_cu) + { + return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu); + } - /* This must be done before calling dwarf2_build_include_psymtabs. */ - pst->dirname = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu); + /* Install the current addrmap into the index being constructed, + then transfer ownership of the index to the caller. */ + std::unique_ptr release () + { + m_index->install_addrmap (m_addrmap); + return std::move (m_index); + } - baseaddr = objfile->text_section_offset (); + /* Return the mutable addrmap that is currently being created. */ + addrmap *get_addrmap () + { + return m_addrmap; + } - dwarf2_find_base_address (comp_unit_die, cu); +private: - /* Possibly set the default values of LOWPC and HIGHPC from - `DW_AT_ranges'. */ - cu_bounds_kind = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, - &best_highpc, cu, pst); - if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc) - { - CORE_ADDR low - = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr) - - baseaddr); - CORE_ADDR high - = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr) - - baseaddr - 1); - /* Store the contiguous range if it is not empty; it can be - empty for CUs with no code. */ - addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap, - low, high, pst); - } + /* Hash function for a cutu_reader. */ + static hashval_t hash_cutu_reader (const void *a) + { + const cutu_reader *reader = (const cutu_reader *) a; + return reader->cu->per_cu->index; + } - /* Check if comp unit has_children. - If so, read the rest of the partial symbols from this comp unit. - If not, there's no more debug_info for this comp unit. */ - if (comp_unit_die->has_children) - { - struct partial_die_info *first_die; - CORE_ADDR lowpc, highpc; + /* Equality function for cutu_reader. */ + static int eq_cutu_reader (const void *a, const void *b) + { + const cutu_reader *ra = (const cutu_reader *) a; + const int *rb = (const int *) b; + return ra->cu->per_cu->index == *rb; + } - lowpc = ((CORE_ADDR) -1); - highpc = ((CORE_ADDR) 0); + /* The abbrev cache used by this indexer. */ + abbrev_cache m_abbrev_cache; + /* A hash table of cutu_reader objects. */ + htab_up m_reader_hash; + /* The index that is being constructed. */ + std::unique_ptr m_index; + + /* Storage for the writeable addrmap. */ + auto_obstack m_addrmap_storage; + /* A writeable addrmap being constructed by this scanner. */ + addrmap *m_addrmap; +}; - first_die = load_partial_dies (reader, info_ptr, 1); +/* An instance of this is created to index a CU. */ - scan_partial_symbols (first_die, &lowpc, &highpc, - cu_bounds_kind <= PC_BOUNDS_INVALID, cu); +class cooked_indexer +{ +public: - /* If we didn't find a lowpc, set it to highpc to avoid - complaints from `maint check'. */ - if (lowpc == ((CORE_ADDR) -1)) - lowpc = highpc; + cooked_indexer (cooked_index_storage *storage, + dwarf2_per_cu_data *per_cu, + enum language language) + : m_index_storage (storage), + m_per_cu (per_cu), + m_language (language), + m_obstack (), + m_die_range_map (addrmap_create_mutable (&m_obstack)) + { + } - /* If the compilation unit didn't have an explicit address range, - then use the information extracted from its child dies. */ - if (cu_bounds_kind <= PC_BOUNDS_INVALID) - { - best_lowpc = lowpc; - best_highpc = highpc; - } - } - pst->set_text_low (gdbarch_adjust_dwarf2_addr (gdbarch, - best_lowpc + baseaddr) - - baseaddr); - pst->set_text_high (gdbarch_adjust_dwarf2_addr (gdbarch, - best_highpc + baseaddr) - - baseaddr); + DISABLE_COPY_AND_ASSIGN (cooked_indexer); - pst->end (); + /* Index the given CU. */ + void make_index (cutu_reader *reader); - if (!cu->per_cu->imported_symtabs_empty ()) - { - int i; - int len = cu->per_cu->imported_symtabs_size (); +private: - /* Fill in 'dependencies' here; we fill in 'users' in a - post-pass. */ - pst->number_of_dependencies = len; - pst->dependencies - = per_bfd->partial_symtabs->allocate_dependencies (len); - for (i = 0; i < len; ++i) - { - pst->dependencies[i] - = cu->per_cu->imported_symtabs->at (i)->v.psymtab; - } + /* A helper function to turn a section offset into an address that + can be used in an addrmap. */ + CORE_ADDR form_addr (sect_offset offset, bool is_dwz) + { + CORE_ADDR value = to_underlying (offset); + if (is_dwz) + value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1); + return value; + } - cu->per_cu->imported_symtabs_free (); - } + /* A helper function to scan the PC bounds of READER and record them + in the storage's addrmap. */ + void check_bounds (cutu_reader *reader); - /* Get the list of files included in the current compilation unit, - and build a psymtab for each of them. */ - dwarf2_build_include_psymtabs (cu, comp_unit_die, pst); + /* Ensure that the indicated CU exists. The cutu_reader for it is + returned. FOR_SCANNING is true if the caller intends to scan all + the DIEs in the CU; when false, this use is assumed to be to look + up just a single DIE. */ + cutu_reader *ensure_cu_exists (cutu_reader *reader, + dwarf2_per_objfile *per_objfile, + sect_offset sect_off, + bool is_dwz, + bool for_scanning); + + /* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is + the entry for the enclosing scope (nullptr at top level). FULLY + is true when a full scan must be done -- in some languages, + function scopes must be fully explored in order to find nested + functions. This returns a pointer to just after the spot where + reading stopped. */ + const gdb_byte *index_dies (cutu_reader *reader, + const gdb_byte *info_ptr, + const cooked_index_entry *parent_entry, + bool fully); + + /* Scan the attributes for a given DIE and update the out + parameters. Returns a pointer to the byte after the DIE. */ + const gdb_byte *scan_attributes (dwarf2_per_cu_data *scanning_per_cu, + cutu_reader *reader, + const gdb_byte *watermark_ptr, + const gdb_byte *info_ptr, + const abbrev_info *abbrev, + const char **name, + const char **linkage_name, + cooked_index_flag *flags, + sect_offset *sibling_offset, + const cooked_index_entry **parent_entry, + CORE_ADDR *maybe_defer, + bool for_specification); + + /* Handle DW_TAG_imported_unit, by scanning the DIE to find + DW_AT_import, and then scanning the referenced CU. Returns a + pointer to the byte after the DIE. */ + const gdb_byte *index_imported_unit (cutu_reader *reader, + const gdb_byte *info_ptr, + const abbrev_info *abbrev); + + /* Recursively read DIEs, recording the section offsets in + m_die_range_map and then calling index_dies. */ + const gdb_byte *recurse (cutu_reader *reader, + const gdb_byte *info_ptr, + const cooked_index_entry *parent_entry, + bool fully); + + /* The storage object, where the results are kept. */ + cooked_index_storage *m_index_storage; + /* The CU that we are reading on behalf of. This object might be + asked to index one CU but to treat the results as if they come + from some including CU; in this case the including CU would be + recorded here. */ + dwarf2_per_cu_data *m_per_cu; + /* The language that we're assuming when reading. */ + enum language m_language; + + /* Temporary storage. */ + auto_obstack m_obstack; + /* An addrmap that maps from section offsets (see the form_addr + method) to newly-created entries. See m_deferred_entries to + understand this. */ + addrmap *m_die_range_map; + + /* A single deferred entry. */ + struct deferred_entry + { + sect_offset die_offset; + const char *name; + CORE_ADDR spec_offset; + dwarf_tag tag; + cooked_index_flag flags; + }; - dwarf_read_debug_printf ("Psymtab for %s unit @%s: %s - %s" - ", %d global, %d static syms", - per_cu->is_debug_types ? "type" : "comp", - sect_offset_str (per_cu->sect_off), - paddress (gdbarch, pst->text_low (objfile)), - paddress (gdbarch, pst->text_high (objfile)), - (int) pst->global_psymbols.size (), - (int) pst->static_psymbols.size ()); -} + /* The generated DWARF can sometimes have the declaration for a + method in a class (or perhaps namespace) scope, with the + definition appearing outside this scope... just one of the many + bad things about DWARF. In order to handle this situation, we + defer certain entries until the end of scanning, at which point + we'll know the containing context of all the DIEs that we might + have scanned. This vector stores these deferred entries. */ + std::vector m_deferred_entries; +}; /* Subroutine of dwarf2_build_psymtabs_hard to simplify it. Process compilation unit THIS_CU for a psymtab. */ @@ -7014,17 +6821,10 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, static void process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, dwarf2_per_objfile *per_objfile, - bool want_partial_unit, - enum language pretend_language) + cooked_index_storage *storage) { - /* If this compilation unit was already read in, free the - cached copy in order to read it in again. This is - necessary because we skipped some symbols when we first - read in the compilation unit (see load_partial_dies). - This problem could be avoided, but the benefit is unclear. */ - per_objfile->remove_cu (this_cu); - - cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false); + cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false, + storage->get_abbrev_cache ()); if (reader.comp_unit_die == nullptr) return; @@ -7052,59 +6852,41 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, /* Nothing. */ } else if (this_cu->is_debug_types) - build_type_psymtabs_reader (&reader, reader.info_ptr, - reader.comp_unit_die); - else if (want_partial_unit - || reader.comp_unit_die->tag != DW_TAG_partial_unit) - process_psymtab_comp_unit_reader (&reader, reader.info_ptr, - reader.comp_unit_die, - pretend_language); - - /* Age out any secondary CUs. */ - per_objfile->age_comp_units (); + build_type_psymtabs_reader (&reader, storage); + else if (reader.comp_unit_die->tag != DW_TAG_partial_unit) + { + bool nope = false; + if (this_cu->scanned.compare_exchange_strong (nope, true)) + { + prepare_one_comp_unit (reader.cu, reader.comp_unit_die, + language_minimal); + gdb_assert (storage != nullptr); + cooked_indexer indexer (storage, this_cu, reader.cu->per_cu->lang); + indexer.make_index (&reader); + } + } } /* Reader function for build_type_psymtabs. */ static void -build_type_psymtabs_reader (const struct die_reader_specs *reader, - const gdb_byte *info_ptr, - struct die_info *type_unit_die) +build_type_psymtabs_reader (cutu_reader *reader, + cooked_index_storage *storage) { - dwarf2_per_objfile *per_objfile = reader->cu->per_objfile; struct dwarf2_cu *cu = reader->cu; struct dwarf2_per_cu_data *per_cu = cu->per_cu; - struct signatured_type *sig_type; - struct type_unit_group *tu_group; - struct attribute *attr; - struct partial_die_info *first_die; - CORE_ADDR lowpc, highpc; - dwarf2_psymtab *pst; + struct die_info *type_unit_die = reader->comp_unit_die; gdb_assert (per_cu->is_debug_types); - sig_type = (struct signatured_type *) per_cu; if (! type_unit_die->has_children) return; - attr = type_unit_die->attr (DW_AT_stmt_list); - tu_group = get_type_unit_group (cu, attr); - - if (tu_group->tus == nullptr) - tu_group->tus = new std::vector; - tu_group->tus->push_back (sig_type); - prepare_one_comp_unit (cu, type_unit_die, language_minimal); - pst = create_partial_symtab (per_cu, per_objfile, ""); - pst->anonymous = true; - - first_die = load_partial_dies (reader, info_ptr, 1); - lowpc = (CORE_ADDR) -1; - highpc = (CORE_ADDR) 0; - scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu); - - pst->end (); + gdb_assert (storage != nullptr); + cooked_indexer indexer (storage, per_cu, cu->per_cu->lang); + indexer.make_index (reader); } /* Struct used to sort TUs by their abbreviation table offset. */ @@ -7143,7 +6925,8 @@ struct tu_abbrev_offset dwarf2_per_objfile->per_bfd->type_unit_groups. */ static void -build_type_psymtabs (dwarf2_per_objfile *per_objfile) +build_type_psymtabs (dwarf2_per_objfile *per_objfile, + cooked_index_storage *storage) { struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats; abbrev_table_up abbrev_table; @@ -7212,8 +6995,7 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile) cutu_reader reader (tu.sig_type, per_objfile, abbrev_table.get (), nullptr, false); if (!reader.dummy_p) - build_type_psymtabs_reader (&reader, reader.info_ptr, - reader.comp_unit_die); + build_type_psymtabs_reader (&reader, storage); } } @@ -7238,36 +7020,11 @@ print_tu_stats (dwarf2_per_objfile *per_objfile) tu_stats->nr_all_type_units_reallocs); } -/* Traversal function for build_type_psymtabs. */ - -static int -build_type_psymtab_dependencies (void **slot, void *info) +struct skeleton_data { - dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - struct type_unit_group *tu_group = (struct type_unit_group *) *slot; - dwarf2_psymtab *pst = tu_group->v.psymtab; - int len = (tu_group->tus == nullptr) ? 0 : tu_group->tus->size (); - int i; - - gdb_assert (len > 0); - gdb_assert (tu_group->type_unit_group_p ()); - - pst->number_of_dependencies = len; - pst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (len); - for (i = 0; i < len; ++i) - { - struct signatured_type *iter = tu_group->tus->at (i); - gdb_assert (iter->is_debug_types); - pst->dependencies[i] = iter->v.psymtab; - iter->type_unit_group = tu_group; - } - - delete tu_group->tus; - tu_group->tus = nullptr; - - return 1; -} + dwarf2_per_objfile *per_objfile; + cooked_index_storage *storage; +}; /* Traversal function for process_skeletonless_type_unit. Read a TU in a DWO file and build partial symbols for it. */ @@ -7276,15 +7033,16 @@ static int process_skeletonless_type_unit (void **slot, void *info) { struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot; - dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info; + skeleton_data *data = (skeleton_data *) info; /* If this TU doesn't exist in the global table, add it and read it in. */ - if (per_objfile->per_bfd->signatured_types == NULL) - per_objfile->per_bfd->signatured_types = allocate_signatured_type_table (); + if (data->per_objfile->per_bfd->signatured_types == NULL) + data->per_objfile->per_bfd->signatured_types + = allocate_signatured_type_table (); signatured_type find_entry (dwo_unit->signature); - slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (), + slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (), &find_entry, INSERT); /* If we've already seen this type there's nothing to do. What's happening is we're doing our own version of comdat-folding here. */ @@ -7294,15 +7052,14 @@ process_skeletonless_type_unit (void **slot, void *info) /* This does the job that create_all_comp_units would have done for this TU. */ signatured_type *entry - = add_type_unit (per_objfile, dwo_unit->signature, slot); - fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit); + = add_type_unit (data->per_objfile, dwo_unit->signature, slot); + fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit); *slot = entry; /* This does the job that build_type_psymtabs would have done. */ - cutu_reader reader (entry, per_objfile, nullptr, nullptr, false); + cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false); if (!reader.dummy_p) - build_type_psymtabs_reader (&reader, reader.info_ptr, - reader.comp_unit_die); + build_type_psymtabs_reader (&reader, data->storage); return 1; } @@ -7326,36 +7083,18 @@ process_dwo_file_for_skeletonless_type_units (void **slot, void *info) Note: This can't be done until we know what all the DWO files are. */ static void -process_skeletonless_type_units (dwarf2_per_objfile *per_objfile) +process_skeletonless_type_units (dwarf2_per_objfile *per_objfile, + cooked_index_storage *storage) { + skeleton_data data { per_objfile, storage }; + /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */ if (get_dwp_file (per_objfile) == NULL && per_objfile->per_bfd->dwo_files != NULL) { htab_traverse_noresize (per_objfile->per_bfd->dwo_files.get (), process_dwo_file_for_skeletonless_type_units, - per_objfile); - } -} - -/* Compute the 'user' field for each psymtab in DWARF2_PER_OBJFILE. */ - -static void -set_partial_user (dwarf2_per_objfile *per_objfile) -{ - for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) - { - dwarf2_psymtab *pst = per_cu->v.psymtab; - - if (pst == NULL) - continue; - - for (int j = 0; j < pst->number_of_dependencies; ++j) - { - /* Set the 'user' field only if it is not already set. */ - if (pst->dependencies[j]->user == NULL) - pst->dependencies[j]->user = pst; - } + &data); } } @@ -7371,95 +7110,107 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile) dwarf_read_debug_printf ("Building psymtabs of objfile %s ...", objfile_name (objfile)); - scoped_restore restore_reading_psyms - = make_scoped_restore (&per_bfd->reading_partial_symbols, true); - - per_bfd->info.read (objfile); - - /* Any cached compilation units will be linked by the per-objfile - read_in_chain. Make sure to free them when we're done. */ - free_cached_comp_units freer (per_objfile); + per_bfd->map_info_sections (objfile); + cooked_index_storage index_storage; create_all_comp_units (per_objfile); - build_type_psymtabs (per_objfile); + build_type_psymtabs (per_objfile, &index_storage); + std::vector> indexes; - /* Create a temporary address map on a temporary obstack. We later - copy this to the final obstack. */ - auto_obstack temp_obstack; + per_bfd->quick_file_names_table + = create_quick_file_names_table (per_bfd->all_comp_units.size ()); + if (!per_bfd->debug_aranges.empty ()) + read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges, + index_storage.get_addrmap ()); - scoped_restore save_psymtabs_addrmap - = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap, - addrmap_create_mutable (&temp_obstack)); + { + /* Ensure that complaints are handled correctly. */ + complaint_interceptor complaint_handler; + + using iter_type = decltype (per_bfd->all_comp_units.begin ()); + + /* Each thread returns a pair holding a cooked index, and a vector + of errors that should be printed. The latter is done because + GDB's I/O system is not thread-safe. run_on_main_thread could be + used, but that would mean the messages are printed after the + prompt, which looks weird. */ + using result_type = std::pair, + std::vector>; + std::vector results + = gdb::parallel_for_each (1, per_bfd->all_comp_units.begin (), + per_bfd->all_comp_units.end (), + [=] (iter_type iter, iter_type end) + { + std::vector errors; + cooked_index_storage thread_storage; + for (; iter != end; ++iter) + { + dwarf2_per_cu_data *per_cu = iter->get (); + try + { + process_psymtab_comp_unit (per_cu, per_objfile, + &thread_storage); + } + catch (gdb_exception &except) + { + errors.push_back (std::move (except)); + } + } + return result_type (thread_storage.release (), std::move (errors)); + }); - for (const auto &per_cu : per_bfd->all_comp_units) - { - if (per_cu->v.psymtab != NULL) - /* In case a forward DW_TAG_imported_unit has read the CU already. */ - continue; - process_psymtab_comp_unit (per_cu.get (), per_objfile, false, - language_minimal); - } + /* Only show a given exception a single time. */ + std::unordered_set seen_exceptions; + for (auto &one_result : results) + { + indexes.push_back (std::move (one_result.first)); + for (auto &one_exc : one_result.second) + if (seen_exceptions.insert (one_exc).second) + exception_print (gdb_stderr, one_exc); + } + } /* This has to wait until we read the CUs, we need the list of DWOs. */ - process_skeletonless_type_units (per_objfile); - - /* Now that all TUs have been processed we can fill in the dependencies. */ - if (per_bfd->type_unit_groups != NULL) - { - htab_traverse_noresize (per_bfd->type_unit_groups.get (), - build_type_psymtab_dependencies, per_objfile); - } + process_skeletonless_type_units (per_objfile, &index_storage); if (dwarf_read_debug > 0) print_tu_stats (per_objfile); - set_partial_user (per_objfile); - - per_bfd->partial_symtabs->psymtabs_addrmap - = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap, - per_bfd->partial_symtabs->obstack ()); - /* At this point we want to keep the address map. */ - save_psymtabs_addrmap.release (); + indexes.push_back (index_storage.release ()); + /* Remove any NULL entries. This might happen if parallel-for + decides to throttle the number of threads that were used. */ + indexes.erase + (std::remove_if (indexes.begin (), + indexes.end (), + [] (const std::unique_ptr &entry) + { + return entry == nullptr; + }), + indexes.end ()); + indexes.shrink_to_fit (); + per_bfd->cooked_index_table.reset + (new cooked_index_vector (std::move (indexes))); + + const cooked_index_entry *main_entry + = per_bfd->cooked_index_table->get_main (); + if (main_entry != nullptr) + set_objfile_main_name (objfile, main_entry->name, + main_entry->per_cu->lang); dwarf_read_debug_printf ("Done building psymtabs of %s", objfile_name (objfile)); } -/* Load the partial DIEs for a secondary CU into memory. - This is also used when rereading a primary CU with load_all_dies. */ - static void -load_partial_comp_unit (dwarf2_per_cu_data *this_cu, - dwarf2_per_objfile *per_objfile, - dwarf2_cu *existing_cu) +read_comp_units_from_section (dwarf2_per_objfile *per_objfile, + struct dwarf2_section_info *section, + struct dwarf2_section_info *abbrev_section, + unsigned int is_dwz, + htab_up &types_htab, + rcuh_kind section_kind) { - cutu_reader reader (this_cu, per_objfile, nullptr, existing_cu, false); - - if (!reader.dummy_p) - { - prepare_one_comp_unit (reader.cu, reader.comp_unit_die, - language_minimal); - - /* Check if comp unit has_children. - If so, read the rest of the partial symbols from this comp unit. - If not, there's no more debug_info for this comp unit. */ - if (reader.comp_unit_die->has_children) - load_partial_dies (&reader, reader.info_ptr, 0); - - reader.keep (); - } -} - -static void -read_comp_units_from_section (dwarf2_per_objfile *per_objfile, - struct dwarf2_section_info *section, - struct dwarf2_section_info *abbrev_section, - unsigned int is_dwz, - htab_up &types_htab, - rcuh_kind section_kind) -{ - const gdb_byte *info_ptr; - struct objfile *objfile = per_objfile->objfile; + const gdb_byte *info_ptr; + struct objfile *objfile = per_objfile->objfile; dwarf_read_debug_printf ("Reading %s for %s", section->get_name (), @@ -7532,612 +7283,18 @@ create_all_comp_units (dwarf2_per_objfile *per_objfile) dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd); if (dwz != NULL) - read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1, - types_htab, rcuh_kind::COMPILE); - - per_objfile->per_bfd->signatured_types = std::move (types_htab); -} - -/* Process all loaded DIEs for compilation unit CU, starting at - FIRST_DIE. The caller should pass SET_ADDRMAP == 1 if the compilation - unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or - DW_AT_ranges). See the comments of add_partial_subprogram on how - SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated. */ - -static void -scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, - CORE_ADDR *highpc, int set_addrmap, - struct dwarf2_cu *cu) -{ - struct partial_die_info *pdi; - - /* Now, march along the PDI's, descending into ones which have - interesting children but skipping the children of the other ones, - until we reach the end of the compilation unit. */ - - pdi = first_die; - - while (pdi != NULL) - { - pdi->fixup (cu); - - /* Anonymous namespaces or modules have no name but have interesting - children, so we need to look at them. Ditto for anonymous - enums. */ - - if (pdi->raw_name != NULL || pdi->tag == DW_TAG_namespace - || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type - || pdi->tag == DW_TAG_imported_unit - || pdi->tag == DW_TAG_inlined_subroutine) - { - switch (pdi->tag) - { - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: - add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu); - if (cu->per_cu->lang == language_cplus) - scan_partial_symbols (pdi->die_child, lowpc, highpc, - set_addrmap, cu); - break; - case DW_TAG_constant: - case DW_TAG_variable: - case DW_TAG_typedef: - case DW_TAG_union_type: - if (!pdi->is_declaration - || (pdi->tag == DW_TAG_variable && pdi->is_external)) - { - add_partial_symbol (pdi, cu); - } - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - if (!pdi->is_declaration) - { - add_partial_symbol (pdi, cu); - } - if ((cu->per_cu->lang == language_rust - || cu->per_cu->lang == language_cplus) - && pdi->has_children) - scan_partial_symbols (pdi->die_child, lowpc, highpc, - set_addrmap, cu); - break; - case DW_TAG_enumeration_type: - if (!pdi->is_declaration) - add_partial_enumeration (pdi, cu); - break; - case DW_TAG_base_type: - case DW_TAG_subrange_type: - /* File scope base type definitions are added to the partial - symbol table. */ - add_partial_symbol (pdi, cu); - break; - case DW_TAG_namespace: - add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu); - break; - case DW_TAG_module: - if (!pdi->is_declaration) - add_partial_module (pdi, lowpc, highpc, set_addrmap, cu); - break; - case DW_TAG_imported_unit: - { - struct dwarf2_per_cu_data *per_cu; - - /* For now we don't handle imported units in type units. */ - if (cu->per_cu->is_debug_types) - { - error (_("Dwarf Error: DW_TAG_imported_unit is not" - " supported in type units [in module %s]"), - objfile_name (cu->per_objfile->objfile)); - } - - per_cu = dwarf2_find_containing_comp_unit - (pdi->d.sect_off, pdi->is_dwz, cu->per_objfile); - - /* Go read the partial unit, if needed. */ - if (per_cu->v.psymtab == NULL) - process_psymtab_comp_unit (per_cu, cu->per_objfile, true, - cu->per_cu->lang); - - if (pdi->die_parent == nullptr - && per_cu->unit_type == DW_UT_compile - && per_cu->lang == language_cplus) - /* Regard import as hint. See corresponding code in - process_imported_unit_die. */ - break; - - cu->per_cu->imported_symtabs_push (per_cu); - } - break; - case DW_TAG_imported_declaration: - add_partial_symbol (pdi, cu); - break; - default: - break; - } - } - - /* If the die has a sibling, skip to the sibling. */ - - pdi = pdi->die_sibling; - } -} - -/* Functions used to compute the fully scoped name of a partial DIE. - - Normally, this is simple. For C++, the parent DIE's fully scoped - name is concatenated with "::" and the partial DIE's name. - Enumerators are an exception; they use the scope of their parent - enumeration type, i.e. the name of the enumeration type is not - prepended to the enumerator. - - There are two complexities. One is DW_AT_specification; in this - case "parent" means the parent of the target of the specification, - instead of the direct parent of the DIE. The other is compilers - which do not emit DW_TAG_namespace; in this case we try to guess - the fully qualified name of structure types from their members' - linkage names. This must be done using the DIE's children rather - than the children of any DW_AT_specification target. We only need - to do this for structures at the top level, i.e. if the target of - any DW_AT_specification (if any; otherwise the DIE itself) does not - have a parent. */ - -/* Compute the scope prefix associated with PDI's parent, in - compilation unit CU. The result will be allocated on CU's - comp_unit_obstack, or a copy of the already allocated PDI->NAME - field. NULL is returned if no prefix is necessary. */ -static const char * -partial_die_parent_scope (struct partial_die_info *pdi, - struct dwarf2_cu *cu) -{ - const char *grandparent_scope; - struct partial_die_info *parent, *real_pdi; - - /* We need to look at our parent DIE; if we have a DW_AT_specification, - then this means the parent of the specification DIE. */ - - real_pdi = pdi; - while (real_pdi->has_specification) - { - auto res = find_partial_die (real_pdi->spec_offset, - real_pdi->spec_is_dwz, cu); - real_pdi = res.pdi; - cu = res.cu; - } - - parent = real_pdi->die_parent; - if (parent == NULL) - return NULL; - - if (parent->scope_set) - return parent->scope; - - parent->fixup (cu); - - grandparent_scope = partial_die_parent_scope (parent, cu); - - /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus - DW_TAG_namespace DIEs with a name of "::" for the global namespace. - Work around this problem here. */ - if (cu->per_cu->lang == language_cplus - && parent->tag == DW_TAG_namespace - && strcmp (parent->name (cu), "::") == 0 - && grandparent_scope == NULL) - { - parent->scope = NULL; - parent->scope_set = 1; - return NULL; - } - - /* Nested subroutines in Fortran get a prefix. */ - if (pdi->tag == DW_TAG_enumerator) - /* Enumerators should not get the name of the enumeration as a prefix. */ - parent->scope = grandparent_scope; - else if (parent->tag == DW_TAG_namespace - || parent->tag == DW_TAG_module - || parent->tag == DW_TAG_structure_type - || parent->tag == DW_TAG_class_type - || parent->tag == DW_TAG_interface_type - || parent->tag == DW_TAG_union_type - || parent->tag == DW_TAG_enumeration_type - || (cu->per_cu->lang == language_fortran - && parent->tag == DW_TAG_subprogram - && pdi->tag == DW_TAG_subprogram)) - { - if (grandparent_scope == NULL) - parent->scope = parent->name (cu); - else - parent->scope = typename_concat (&cu->comp_unit_obstack, - grandparent_scope, - parent->name (cu), 0, cu); - } - else - { - /* FIXME drow/2004-04-01: What should we be doing with - function-local names? For partial symbols, we should probably be - ignoring them. */ - complaint (_("unhandled containing DIE tag %s for DIE at %s"), - dwarf_tag_name (parent->tag), - sect_offset_str (pdi->sect_off)); - parent->scope = grandparent_scope; - } - - parent->scope_set = 1; - return parent->scope; -} - -/* Return the fully scoped name associated with PDI, from compilation unit - CU. The result will be allocated with malloc. */ - -static gdb::unique_xmalloc_ptr -partial_die_full_name (struct partial_die_info *pdi, - struct dwarf2_cu *cu) -{ - const char *parent_scope; - - /* If this is a template instantiation, we can not work out the - template arguments from partial DIEs. So, unfortunately, we have - to go through the full DIEs. At least any work we do building - types here will be reused if full symbols are loaded later. */ - if (pdi->has_template_arguments) - { - pdi->fixup (cu); - - if (pdi->name (cu) != NULL && strchr (pdi->name (cu), '<') == NULL) - { - struct die_info *die; - struct attribute attr; - struct dwarf2_cu *ref_cu = cu; - - /* DW_FORM_ref_addr is using section offset. */ - attr.name = (enum dwarf_attribute) 0; - attr.form = DW_FORM_ref_addr; - attr.u.unsnd = to_underlying (pdi->sect_off); - die = follow_die_ref (NULL, &attr, &ref_cu); - - return make_unique_xstrdup (dwarf2_full_name (NULL, die, ref_cu)); - } - } - - parent_scope = partial_die_parent_scope (pdi, cu); - if (parent_scope == NULL) - return NULL; - else - return gdb::unique_xmalloc_ptr (typename_concat (NULL, parent_scope, - pdi->name (cu), - 0, cu)); -} - -static void -add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) -{ - dwarf2_per_objfile *per_objfile = cu->per_objfile; - struct objfile *objfile = per_objfile->objfile; - struct gdbarch *gdbarch = objfile->arch (); - CORE_ADDR addr = 0; - const char *actual_name = NULL; - CORE_ADDR baseaddr; - - baseaddr = objfile->text_section_offset (); - - gdb::unique_xmalloc_ptr built_actual_name - = partial_die_full_name (pdi, cu); - if (built_actual_name != NULL) - actual_name = built_actual_name.get (); - - if (actual_name == NULL) - actual_name = pdi->name (cu); - - partial_symbol psymbol; - memset (&psymbol, 0, sizeof (psymbol)); - psymbol.ginfo.set_language (cu->per_cu->lang, - &objfile->objfile_obstack); - psymbol.ginfo.set_section_index (-1); - - /* The code below indicates that the psymbol should be installed by - setting this. */ - gdb::optional where; - - switch (pdi->tag) - { - case DW_TAG_inlined_subroutine: - case DW_TAG_subprogram: - addr = (gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr) - - baseaddr); - if (pdi->is_external - || cu->per_cu->lang == language_ada - || (cu->per_cu->lang == language_fortran - && pdi->die_parent != NULL - && pdi->die_parent->tag == DW_TAG_subprogram)) - { - /* Normally, only "external" DIEs are part of the global scope. - But in Ada and Fortran, we want to be able to access nested - procedures globally. So all Ada and Fortran subprograms are - stored in the global scope. */ - where = psymbol_placement::GLOBAL; - } - else - where = psymbol_placement::STATIC; - - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_BLOCK; - psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile)); - psymbol.ginfo.value.address = addr; - - if (pdi->main_subprogram && actual_name != NULL) - set_objfile_main_name (objfile, actual_name, cu->per_cu->lang); - break; - case DW_TAG_constant: - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_STATIC; - where = (pdi->is_external - ? psymbol_placement::GLOBAL - : psymbol_placement::STATIC); - break; - case DW_TAG_variable: - if (pdi->d.locdesc) - addr = decode_locdesc (pdi->d.locdesc, cu); - - if (pdi->d.locdesc - && addr == 0 - && !per_objfile->per_bfd->has_section_at_zero) - { - /* A global or static variable may also have been stripped - out by the linker if unused, in which case its address - will be nullified; do not add such variables into partial - symbol table then. */ - } - else if (pdi->is_external) - { - /* Global Variable. - Don't enter into the minimal symbol tables as there is - a minimal symbol table entry from the ELF symbols already. - Enter into partial symbol table if it has a location - descriptor or a type. - If the location descriptor is missing, new_symbol will create - a LOC_UNRESOLVED symbol, the address of the variable will then - be determined from the minimal symbol table whenever the variable - is referenced. - The address for the partial symbol table entry is not - used by GDB, but it comes in handy for debugging partial symbol - table building. */ - - if (pdi->d.locdesc || pdi->has_type) - { - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_STATIC; - psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile)); - psymbol.ginfo.value.address = addr; - where = psymbol_placement::GLOBAL; - } - } - else - { - int has_loc = pdi->d.locdesc != NULL; - - /* Static Variable. Skip symbols whose value we cannot know (those - without location descriptors or constant values). */ - if (!has_loc && !pdi->has_const_value) - return; - - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_STATIC; - psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile)); - if (has_loc) - psymbol.ginfo.value.address = addr; - where = psymbol_placement::STATIC; - } - break; - case DW_TAG_array_type: - case DW_TAG_typedef: - case DW_TAG_base_type: - case DW_TAG_subrange_type: - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_TYPEDEF; - where = psymbol_placement::STATIC; - break; - case DW_TAG_imported_declaration: - case DW_TAG_namespace: - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_TYPEDEF; - where = psymbol_placement::GLOBAL; - break; - case DW_TAG_module: - /* With Fortran 77 there might be a "BLOCK DATA" module - available without any name. If so, we skip the module as it - doesn't bring any value. */ - if (actual_name != nullptr) - { - psymbol.domain = MODULE_DOMAIN; - psymbol.aclass = LOC_TYPEDEF; - where = psymbol_placement::GLOBAL; - } - break; - case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - /* Skip external references. The DWARF standard says in the section - about "Structure, Union, and Class Type Entries": "An incomplete - structure, union or class type is represented by a structure, - union or class entry that does not have a byte size attribute - and that has a DW_AT_declaration attribute." */ - if (!pdi->has_byte_size && pdi->is_declaration) - return; - - /* NOTE: carlton/2003-10-07: See comment in new_symbol about - static vs. global. */ - psymbol.domain = STRUCT_DOMAIN; - psymbol.aclass = LOC_TYPEDEF; - where = (cu->per_cu->lang == language_cplus - ? psymbol_placement::GLOBAL - : psymbol_placement::STATIC); - break; - case DW_TAG_enumerator: - psymbol.domain = VAR_DOMAIN; - psymbol.aclass = LOC_CONST; - where = (cu->per_cu->lang == language_cplus - ? psymbol_placement::GLOBAL - : psymbol_placement::STATIC); - break; - default: - break; - } - - if (where.has_value ()) - { - if (built_actual_name != nullptr) - actual_name = objfile->intern (actual_name); - if (pdi->linkage_name == nullptr - || cu->per_cu->lang == language_ada) - psymbol.ginfo.set_linkage_name (actual_name); - else - { - psymbol.ginfo.set_demangled_name (actual_name, - &objfile->objfile_obstack); - psymbol.ginfo.set_linkage_name (pdi->linkage_name); - } - cu->per_cu->v.psymtab->add_psymbol - (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (), - objfile); - } -} - -/* Read a partial die corresponding to a namespace; also, add a symbol - corresponding to that namespace to the symbol table. NAMESPACE is - the name of the enclosing namespace. */ - -static void -add_partial_namespace (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int set_addrmap, struct dwarf2_cu *cu) -{ - /* Add a symbol for the namespace. */ - - add_partial_symbol (pdi, cu); - - /* Now scan partial symbols in that namespace. */ - - if (pdi->has_children) - scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu); -} - -/* Read a partial die corresponding to a Fortran module. */ - -static void -add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, - CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu) -{ - /* Add a symbol for the namespace. */ - - add_partial_symbol (pdi, cu); - - /* Now scan partial symbols in that module. */ - - if (pdi->has_children) - scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu); -} - -/* Read a partial die corresponding to a subprogram or an inlined - subprogram and create a partial symbol for that subprogram. - When the CU language allows it, this routine also defines a partial - symbol for each nested subprogram that this subprogram contains. - If SET_ADDRMAP is true, record the covered ranges in the addrmap. - Set *LOWPC and *HIGHPC to the lowest and highest PC values found in PDI. - - PDI may also be a lexical block, in which case we simply search - recursively for subprograms defined inside that lexical block. - Again, this is only performed when the CU language allows this - type of definitions. */ - -static void -add_partial_subprogram (struct partial_die_info *pdi, - CORE_ADDR *lowpc, CORE_ADDR *highpc, - int set_addrmap, struct dwarf2_cu *cu) -{ - if (pdi->tag == DW_TAG_subprogram || pdi->tag == DW_TAG_inlined_subroutine) - { - if (pdi->has_pc_info) - { - if (pdi->lowpc < *lowpc) - *lowpc = pdi->lowpc; - if (pdi->highpc > *highpc) - *highpc = pdi->highpc; - if (set_addrmap) - { - struct objfile *objfile = cu->per_objfile->objfile; - dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd; - struct gdbarch *gdbarch = objfile->arch (); - CORE_ADDR baseaddr; - CORE_ADDR this_highpc; - CORE_ADDR this_lowpc; - - baseaddr = objfile->text_section_offset (); - this_lowpc - = (gdbarch_adjust_dwarf2_addr (gdbarch, - pdi->lowpc + baseaddr) - - baseaddr); - this_highpc - = (gdbarch_adjust_dwarf2_addr (gdbarch, - pdi->highpc + baseaddr) - - baseaddr); - addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap, - this_lowpc, this_highpc - 1, - cu->per_cu->v.psymtab); - } - } - - if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined)) - { - if (!pdi->is_declaration) - /* Ignore subprogram DIEs that do not have a name, they are - illegal. Do not emit a complaint at this point, we will - do so when we convert this psymtab into a symtab. */ - if (pdi->name (cu)) - add_partial_symbol (pdi, cu); - } - } - - if (! pdi->has_children) - return; - - if (cu->per_cu->lang == language_ada - || cu->per_cu->lang == language_fortran) { - pdi = pdi->die_child; - while (pdi != NULL) - { - pdi->fixup (cu); - if (pdi->tag == DW_TAG_subprogram - || pdi->tag == DW_TAG_inlined_subroutine - || pdi->tag == DW_TAG_lexical_block) - add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu); - pdi = pdi->die_sibling; - } + /* Pre-read the sections we'll need to construct an index. */ + struct objfile *objfile = per_objfile->objfile; + dwz->abbrev.read (objfile); + dwz->info.read (objfile); + dwz->str.read (objfile); + dwz->line.read (objfile); + read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1, + types_htab, rcuh_kind::COMPILE); } -} - -/* Read a partial die corresponding to an enumeration type. */ - -static void -add_partial_enumeration (struct partial_die_info *enum_pdi, - struct dwarf2_cu *cu) -{ - struct partial_die_info *pdi; - - if (enum_pdi->name (cu) != NULL) - add_partial_symbol (enum_pdi, cu); - pdi = enum_pdi->die_child; - while (pdi) - { - if (pdi->tag != DW_TAG_enumerator || pdi->raw_name == NULL) - complaint (_("malformed enumerator DIE ignored")); - else - add_partial_symbol (pdi, cu); - pdi = pdi->die_sibling; - } + per_objfile->per_bfd->signatured_types = std::move (types_htab); } /* Return the initial uleb128 in the die at INFO_PTR. */ @@ -8205,12 +7362,15 @@ skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr) /* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. INFO_PTR should point just after the initial uleb128 of a DIE, and the abbrev corresponding to that skipped uleb128 should be passed in - ABBREV. Returns a pointer to this DIE's sibling, skipping any - children. */ + ABBREV. + + If DO_SKIP_CHILDREN is true, or if the DIE has no children, this + returns a pointer to this DIE's sibling, skipping any children. + Otherwise, returns a pointer to the DIE's first child. */ static const gdb_byte * skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, - const struct abbrev_info *abbrev) + const struct abbrev_info *abbrev, bool do_skip_children) { unsigned int bytes_read; struct attribute attr; @@ -8220,10 +7380,29 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, const gdb_byte *buffer_end = reader->buffer_end; unsigned int form, i; + if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1) + { + /* We only handle DW_FORM_ref4 here. */ + const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset; + unsigned int offset = read_4_bytes (abfd, sibling_data); + const gdb_byte *sibling_ptr + = buffer + to_underlying (cu->header.sect_off) + offset; + if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end) + return sibling_ptr; + /* Fall through to the slow way. */ + } + else if (abbrev->size_if_constant != 0) + { + info_ptr += abbrev->size_if_constant; + if (do_skip_children && abbrev->has_children) + return skip_children (reader, info_ptr); + return info_ptr; + } + for (i = 0; i < abbrev->num_attrs; i++) { /* The only abbrev we care about is DW_AT_sibling. */ - if (abbrev->attrs[i].name == DW_AT_sibling) + if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling) { read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr); if (attr.form == DW_FORM_ref_addr) @@ -8340,77 +7519,26 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, } } - if (abbrev->has_children) + if (do_skip_children && abbrev->has_children) return skip_children (reader, info_ptr); else return info_ptr; } + +/* Reading in full CUs. */ -/* Locate ORIG_PDI's sibling. - INFO_PTR should point to the start of the next DIE after ORIG_PDI. */ +/* Add PER_CU to the queue. */ -static const gdb_byte * -locate_pdi_sibling (const struct die_reader_specs *reader, - struct partial_die_info *orig_pdi, - const gdb_byte *info_ptr) +static void +queue_comp_unit (dwarf2_per_cu_data *per_cu, + dwarf2_per_objfile *per_objfile, + enum language pretend_language) { - /* Do we know the sibling already? */ + per_cu->queued = 1; - if (orig_pdi->sibling) - return orig_pdi->sibling; - - /* Are there any children to deal with? */ - - if (!orig_pdi->has_children) - return info_ptr; - - /* Skip the children the long way. */ - - return skip_children (reader, info_ptr); -} - -/* Expand this partial symbol table into a full symbol table. SELF is - not NULL. */ - -void -dwarf2_psymtab::read_symtab (struct objfile *objfile) -{ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - - gdb_assert (!per_objfile->symtab_set_p (per_cu_data)); - - /* If this psymtab is constructed from a debug-only objfile, the - has_section_at_zero flag will not necessarily be correct. We - can get the correct value for this flag by looking at the data - associated with the (presumably stripped) associated objfile. */ - if (objfile->separate_debug_objfile_backlink) - { - dwarf2_per_objfile *per_objfile_backlink - = get_dwarf2_per_objfile (objfile->separate_debug_objfile_backlink); - - per_objfile->per_bfd->has_section_at_zero - = per_objfile_backlink->per_bfd->has_section_at_zero; - } - - expand_psymtab (objfile); - - process_cu_includes (per_objfile); -} - -/* Reading in full CUs. */ - -/* Add PER_CU to the queue. */ - -static void -queue_comp_unit (dwarf2_per_cu_data *per_cu, - dwarf2_per_objfile *per_objfile, - enum language pretend_language) -{ - per_cu->queued = 1; - - gdb_assert (per_objfile->per_bfd->queue.has_value ()); - per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language); -} + gdb_assert (per_objfile->per_bfd->queue.has_value ()); + per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language); +} /* If PER_CU is not yet expanded of queued for expansion, add it to the queue. @@ -8443,18 +7571,6 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu, dwarf2_per_objfile *per_objfile, enum language pretend_language) { - /* We may arrive here during partial symbol reading, if we need full - DIEs to process an unusual case (e.g. template arguments). Do - not queue PER_CU, just tell our caller to load its DIEs. */ - if (per_cu->per_bfd->reading_partial_symbols) - { - dwarf2_cu *cu = per_objfile->get_cu (per_cu); - - if (cu == NULL || cu->dies == NULL) - return 1; - return 0; - } - /* Mark the dependence relation so that we don't flush PER_CU too early. */ if (dependent_cu != NULL) @@ -8559,39 +7675,6 @@ process_queue (dwarf2_per_objfile *per_objfile) objfile_name (per_objfile->objfile)); } -/* Read in full symbols for PST, and anything it depends on. */ - -void -dwarf2_psymtab::expand_psymtab (struct objfile *objfile) -{ - gdb_assert (!readin_p (objfile)); - - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - free_cached_comp_units freer (per_objfile); - expand_dependencies (objfile); - - dw2_do_instantiate_symtab (per_cu_data, per_objfile, false); - gdb_assert (get_compunit_symtab (objfile) != nullptr); -} - -/* See psympriv.h. */ - -bool -dwarf2_psymtab::readin_p (struct objfile *objfile) const -{ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - return per_objfile->symtab_set_p (per_cu_data); -} - -/* See psympriv.h. */ - -compunit_symtab * -dwarf2_psymtab::get_compunit_symtab (struct objfile *objfile) const -{ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - return per_objfile->get_symtab (per_cu_data); -} - /* Trivial hash function for die_info: the hash value of a DIE is its offset in .debug_info for this objfile. */ @@ -8774,7 +7857,7 @@ fixup_go_packaging (struct dwarf2_cu *cu) struct symbol *sym = list->symbol[i]; if (sym->language () == language_go - && SYMBOL_CLASS (sym) == LOC_BLOCK) + && sym->aclass () == LOC_BLOCK) { gdb::unique_xmalloc_ptr this_package_name (go_symbol_package_name (sym)); @@ -8811,9 +7894,9 @@ fixup_go_packaging (struct dwarf2_cu *cu) sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd); /* This is not VAR_DOMAIN because we want a way to ensure a lookup of, e.g., "main" finds the "main" module and not C's main(). */ - SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; - SYMBOL_TYPE (sym) = type; + sym->set_domain (STRUCT_DOMAIN); + sym->set_aclass_index (LOC_TYPEDEF); + sym->set_type (type); add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ()); } @@ -8933,9 +8016,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) #define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$" if (type->num_fields () == 1 - && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX)) + && startswith (type->field (0).name (), RUST_ENUM_PREFIX)) { - const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX); + const char *name = type->field (0).name () + strlen (RUST_ENUM_PREFIX); /* Decode the field name to find the offset of the discriminant. */ @@ -8948,18 +8031,18 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) name = tail; if (*name != '$' || index >= field_type->num_fields () - || (TYPE_FIELD_LOC_KIND (field_type, index) + || (field_type->field (index).loc_kind () != FIELD_LOC_KIND_BITPOS)) { complaint (_("Could not parse Rust enum encoding string \"%s\"" "[in module %s]"), - TYPE_FIELD_NAME (type, 0), + type->field (0).name (), objfile_name (objfile)); return; } ++name; - bit_offset += TYPE_FIELD_BITPOS (field_type, index); + bit_offset += field_type->field (index).loc_bitpos (); field_type = field_type->field (index).type (); } @@ -8975,17 +8058,17 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) /* Put the discriminant at index 0. */ type->field (0).set_type (field_type); TYPE_FIELD_ARTIFICIAL (type, 0) = 1; - TYPE_FIELD_NAME (type, 0) = "<>"; - SET_FIELD_BITPOS (type->field (0), bit_offset); + type->field (0).set_name ("<>"); + type->field (0).set_loc_bitpos (bit_offset); /* The order of fields doesn't really matter, so put the real field at index 1 and the data-less field at index 2. */ type->field (1) = saved_field; - TYPE_FIELD_NAME (type, 1) - = rust_last_path_segment (type->field (1).type ()->name ()); + type->field (1).set_name + (rust_last_path_segment (type->field (1).type ()->name ())); type->field (1).type ()->set_name (rust_fully_qualify (&objfile->objfile_obstack, type->name (), - TYPE_FIELD_NAME (type, 1))); + type->field (1).name ())); const char *dataless_name = rust_fully_qualify (&objfile->objfile_obstack, type->name (), @@ -8995,8 +8078,8 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) type->field (2).set_type (dataless_type); /* NAME points into the original discriminant name, which already has the correct lifetime. */ - TYPE_FIELD_NAME (type, 2) = name; - SET_FIELD_BITPOS (type->field (2), 0); + type->field (2).set_name (name); + type->field (2).set_loc_bitpos (0); /* Indicate that this is a variant type. */ static discriminant_range ranges[1] = { { 0, 0 } }; @@ -9004,7 +8087,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) } /* A union with a single anonymous field is probably an old-style univariant enum. */ - else if (type->num_fields () == 1 && streq (TYPE_FIELD_NAME (type, 0), "")) + else if (type->num_fields () == 1 && streq (type->field (0).name (), "")) { /* Smash this type to be a structure type. We have to do this because the type has already been recorded. */ @@ -9013,7 +8096,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) struct type *field_type = type->field (0).type (); const char *variant_name = rust_last_path_segment (field_type->name ()); - TYPE_FIELD_NAME (type, 0) = variant_name; + type->field (0).set_name (variant_name); field_type->set_name (rust_fully_qualify (&objfile->objfile_obstack, type->name (), variant_name)); @@ -9037,7 +8120,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) /* Could be data-less variant, so keep going. */ disr_type = nullptr; } - else if (strcmp (TYPE_FIELD_NAME (disr_type, 0), + else if (strcmp (disr_type->field (0).name (), "RUST$ENUM$DISR") != 0) { /* Not a Rust enum. */ @@ -9072,7 +8155,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) /* Install the discriminant at index 0 in the union. */ type->field (0) = *disr_field; TYPE_FIELD_ARTIFICIAL (type, 0) = 1; - TYPE_FIELD_NAME (type, 0) = "<>"; + type->field (0).set_name ("<>"); /* We need a way to find the correct discriminant given a variant name. For convenience we build a map here. */ @@ -9080,11 +8163,11 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) std::unordered_map discriminant_map; for (int i = 0; i < enum_type->num_fields (); ++i) { - if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL) + if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL) { const char *name - = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i)); - discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i); + = rust_last_path_segment (enum_type->field (i).name ()); + discriminant_map[name] = enum_type->field (i).loc_enumval (); } } @@ -9122,7 +8205,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) sub_type->set_num_fields (sub_type->num_fields () - 1); sub_type->set_fields (sub_type->fields () + 1); } - TYPE_FIELD_NAME (type, i) = variant_name; + type->field (i).set_name (variant_name); sub_type->set_name (rust_fully_qualify (&objfile->objfile_obstack, type->name (), variant_name)); @@ -9351,7 +8434,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language) get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu); addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr); - static_block = cu->get_builder ()->end_symtab_get_static_block (addr, 0, 1); + static_block + = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1); /* If the comp unit has DW_AT_ranges, it may have discontiguous ranges. Also, DW_AT_ranges may record ranges not belonging to any child DIEs @@ -9360,9 +8444,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language) this comp unit. */ dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu); - cust = cu->get_builder ()->end_symtab_from_static_block (static_block, - SECT_OFF_TEXT (objfile), - 0); + cust = cu->get_builder ()->end_compunit_symtab_from_static_block + (static_block, SECT_OFF_TEXT (objfile), 0); if (cust != NULL) { @@ -9372,8 +8455,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language) compilation is from a C file generated by language preprocessors, do not set the language if it was already deduced by start_subfile. */ if (!(cu->per_cu->lang == language_c - && COMPUNIT_FILETABS (cust)->language != language_unknown)) - COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang; + && cust->primary_filetab ()->language () != language_unknown)) + cust->primary_filetab ()->set_language (cu->per_cu->lang); /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can produce DW_AT_location with location lists but it can be possibly @@ -9388,12 +8471,12 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language) options - this waits on GCC PR other/32998 (-frecord-gcc-switches). */ if (cu->has_loclist && gcc_4_minor >= 5) - cust->locations_valid = 1; + cust->set_locations_valid (true); if (gcc_4_minor >= 5) - cust->epilogue_unwind_valid = 1; + cust->set_epilogue_unwind_valid (true); - cust->call_site_htab = cu->call_site_htab; + cust->set_call_site_htab (cu->call_site_htab); } per_objfile->set_symtab (cu->per_cu, cust); @@ -9457,8 +8540,8 @@ process_full_type_unit (dwarf2_cu *cu, do not set the language if it was already deduced by start_subfile. */ if (!(cu->per_cu->lang == language_c - && COMPUNIT_FILETABS (cust)->language != language_c)) - COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang; + && cust->primary_filetab ()->language () != language_c)) + cust->primary_filetab ()->set_language (cu->per_cu->lang); } } else @@ -9495,7 +8578,8 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz); dwarf2_per_objfile *per_objfile = cu->per_objfile; dwarf2_per_cu_data *per_cu - = dwarf2_find_containing_comp_unit (sect_off, is_dwz, per_objfile); + = dwarf2_find_containing_comp_unit (sect_off, is_dwz, + per_objfile->per_bfd); /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit into another compilation unit, at root level. Regard this as a hint, @@ -9588,6 +8672,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_interface_type: case DW_TAG_structure_type: case DW_TAG_union_type: + case DW_TAG_namelist: process_structure_scope (die, cu); break; case DW_TAG_enumeration_type: @@ -9615,6 +8700,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) /* FALLTHROUGH */ case DW_TAG_base_type: case DW_TAG_subrange_type: + case DW_TAG_generic_subrange: case DW_TAG_typedef: /* Add a typedef symbol for the type definition, if it has a DW_AT_name. */ @@ -9928,7 +9014,7 @@ dwarf2_compute_name (const char *name, else if (bytes != NULL) { v = allocate_value (type); - memcpy (value_contents_writeable (v), bytes, + memcpy (value_contents_writeable (v).data (), bytes, TYPE_LENGTH (type)); } else @@ -10057,9 +9143,8 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu) to look up their definition from their declaration so the only disadvantage remains the minimal symbol variant `long name(params)' does not have the proper inferior type. */ - demangled.reset (gdb_demangle (mangled, - (DMGL_PARAMS | DMGL_ANSI - | DMGL_RET_DROP))); + demangled = gdb_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI + | DMGL_RET_DROP)); } if (demangled) canon = demangled.get (); @@ -10369,38 +9454,25 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu) return cu->producer_is_gcc_lt_4_3; } -static file_and_directory +static file_and_directory & find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu) { - file_and_directory res; + if (cu->per_cu->fnd != nullptr) + return *cu->per_cu->fnd; /* Find the filename. Do not use dwarf2_name here, since the filename is not a source language identifier. */ - res.name = dwarf2_string_attr (die, DW_AT_name, cu); - res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu); + file_and_directory res (dwarf2_string_attr (die, DW_AT_name, cu), + dwarf2_string_attr (die, DW_AT_comp_dir, cu)); - if (res.comp_dir == NULL - && producer_is_gcc_lt_4_3 (cu) && res.name != NULL - && IS_ABSOLUTE_PATH (res.name)) - { - res.comp_dir_storage = ldirname (res.name); - if (!res.comp_dir_storage.empty ()) - res.comp_dir = res.comp_dir_storage.c_str (); - } - if (res.comp_dir != NULL) - { - /* Irix 6.2 native cc prepends .: to the compilation - directory, get rid of it. */ - const char *cp = strchr (res.comp_dir, ':'); - - if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/') - res.comp_dir = cp + 1; - } - - if (res.name == NULL) - res.name = ""; + if (res.get_comp_dir () == nullptr + && producer_is_gcc_lt_4_3 (cu) + && res.get_name () != nullptr + && IS_ABSOLUTE_PATH (res.get_name ())) + res.set_comp_dir (ldirname (res.get_name ())); - return res; + cu->per_cu->fnd.reset (new file_and_directory (std::move (res))); + return *cu->per_cu->fnd; } /* Handle DW_AT_stmt_list for a compilation unit. @@ -10410,7 +9482,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu) static void handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, - const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */ + CORE_ADDR lowpc) /* ARI: editCase function */ { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct attribute *attr; @@ -10498,9 +9570,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, gdb_assert (die->tag != DW_TAG_partial_unit); } decode_mapping = (die->tag != DW_TAG_partial_unit); - dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc, - decode_mapping); - + dwarf_decode_lines (cu->line_header, cu, lowpc, decode_mapping); } /* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */ @@ -10528,9 +9598,10 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) lowpc = highpc; lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); - file_and_directory fnd = find_file_and_directory (die, cu); + file_and_directory &fnd = find_file_and_directory (die, cu); - cu->start_symtab (fnd.name, fnd.comp_dir, lowpc); + cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile), + lowpc); gdb_assert (per_objfile->sym_cu == nullptr); scoped_restore restore_sym_cu @@ -10538,8 +9609,13 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) /* Decode line number information if present. We do this before processing child DIEs, so that the line header table is available - for DW_AT_decl_file. */ - handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, lowpc); + for DW_AT_decl_file. The PC check is here because, if LOWPC and + HIGHPC are both 0x0, then there won't be any interesting code in + the CU, but a check later on (in + lnp_state_machine::check_line_address) will fail to properly + exclude an entry that was removed via --gc-sections. */ + if (lowpc != highpc) + handle_DW_AT_stmt_list (die, cu, lowpc); /* Process all dies in compilation unit. */ if (die->child != NULL) @@ -10618,15 +9694,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die) if (lh == NULL) { if (first_time) - start_symtab ("", NULL, 0); + start_compunit_symtab ("", NULL, 0); else { gdb_assert (tug_unshare->symtabs == NULL); gdb_assert (m_builder == nullptr); struct compunit_symtab *cust = tug_unshare->compunit_symtab; m_builder.reset (new struct buildsym_compunit - (COMPUNIT_OBJFILE (cust), "", - COMPUNIT_DIRNAME (cust), + (cust->objfile (), "", + cust->dirname (), compunit_language (cust), 0, cust)); list_in_scope = get_builder ()->get_file_symbols (); @@ -10639,7 +9715,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die) if (first_time) { - struct compunit_symtab *cust = start_symtab ("", NULL, 0); + struct compunit_symtab *cust = start_compunit_symtab ("", NULL, 0); /* Note: We don't assign tu_group->compunit_symtab yet because we're still initializing it, and our caller (a few levels up) @@ -10647,7 +9723,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die) time. */ tug_unshare->symtabs - = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack, + = XOBNEWVEC (&cust->objfile ()->objfile_obstack, struct symtab *, line_header->file_names_size ()); auto &file_names = line_header->file_names (); @@ -10677,8 +9753,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die) gdb_assert (m_builder == nullptr); struct compunit_symtab *cust = tug_unshare->compunit_symtab; m_builder.reset (new struct buildsym_compunit - (COMPUNIT_OBJFILE (cust), "", - COMPUNIT_DIRNAME (cust), + (cust->objfile (), "", + cust->dirname (), compunit_language (cust), 0, cust)); list_in_scope = get_builder ()->get_file_symbols (); @@ -12016,10 +11092,10 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile, gdb::unique_xmalloc_ptr search_path_holder; if (search_cwd) { - if (*debug_file_directory != '\0') + if (!debug_file_directory.empty ()) { search_path_holder.reset (concat (".", dirname_separator_string, - debug_file_directory, + debug_file_directory.c_str (), (char *) NULL)); search_path = search_path_holder.get (); } @@ -12027,7 +11103,7 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile, search_path = "."; } else - search_path = debug_file_directory; + search_path = debug_file_directory.c_str (); /* Add the path for the executable binary to the list of search paths. */ std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile)); @@ -12098,7 +11174,7 @@ open_dwo_file (dwarf2_per_objfile *per_objfile, /* That didn't work, try debug-file-directory, which, despite its name, is a list of paths. */ - if (*debug_file_directory == '\0') + if (debug_file_directory.empty ()) return NULL; return try_open_dwop_file (per_objfile, file_name, @@ -12109,69 +11185,47 @@ open_dwo_file (dwarf2_per_objfile *per_objfile, size of each of the DWO debugging sections we are interested in. */ static void -dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, - dwo_sections *dwo_sections) +dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd, + asection *sectp, dwo_sections *dwo_sections) { const struct dwop_section_names *names = &dwop_section_names; + struct dwarf2_section_info *dw_sect = nullptr; + if (names->abbrev_dwo.matches (sectp->name)) - { - dwo_sections->abbrev.s.section = sectp; - dwo_sections->abbrev.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->abbrev; else if (names->info_dwo.matches (sectp->name)) - { - dwo_sections->info.s.section = sectp; - dwo_sections->info.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->info; else if (names->line_dwo.matches (sectp->name)) - { - dwo_sections->line.s.section = sectp; - dwo_sections->line.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->line; else if (names->loc_dwo.matches (sectp->name)) - { - dwo_sections->loc.s.section = sectp; - dwo_sections->loc.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->loc; else if (names->loclists_dwo.matches (sectp->name)) - { - dwo_sections->loclists.s.section = sectp; - dwo_sections->loclists.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->loclists; else if (names->macinfo_dwo.matches (sectp->name)) - { - dwo_sections->macinfo.s.section = sectp; - dwo_sections->macinfo.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->macinfo; else if (names->macro_dwo.matches (sectp->name)) - { - dwo_sections->macro.s.section = sectp; - dwo_sections->macro.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->macro; else if (names->rnglists_dwo.matches (sectp->name)) - { - dwo_sections->rnglists.s.section = sectp; - dwo_sections->rnglists.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->rnglists; else if (names->str_dwo.matches (sectp->name)) - { - dwo_sections->str.s.section = sectp; - dwo_sections->str.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->str; else if (names->str_offsets_dwo.matches (sectp->name)) - { - dwo_sections->str_offsets.s.section = sectp; - dwo_sections->str_offsets.size = bfd_section_size (sectp); - } + dw_sect = &dwo_sections->str_offsets; else if (names->types_dwo.matches (sectp->name)) { struct dwarf2_section_info type_section; memset (&type_section, 0, sizeof (type_section)); - type_section.s.section = sectp; - type_section.size = bfd_section_size (sectp); dwo_sections->types.push_back (type_section); + dw_sect = &dwo_sections->types.back (); + } + + if (dw_sect != nullptr) + { + dw_sect->s.section = sectp; + dw_sect->size = bfd_section_size (sectp); + dw_sect->read (objfile); } } @@ -12199,8 +11253,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, dwo_file->dbfd = std::move (dbfd); for (asection *sec : gdb_bfd_sections (dwo_file->dbfd)) - dwarf2_locate_dwo_sections (dwo_file->dbfd.get (), sec, - &dwo_file->sections); + dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), + sec, &dwo_file->sections); create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info, dwo_file->cus); @@ -12227,8 +11281,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, we are interested in. */ static void -dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, - dwp_file *dwp_file) +dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd, + asection *sectp, dwp_file *dwp_file) { const struct dwop_section_names *names = &dwop_section_names; unsigned int elf_section_nr = elf_section_data (sectp)->this_idx; @@ -12239,20 +11293,19 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, dwp_file->elf_sections[elf_section_nr] = sectp; /* Look for specific sections that we need. */ + struct dwarf2_section_info *dw_sect = nullptr; if (names->str_dwo.matches (sectp->name)) - { - dwp_file->sections.str.s.section = sectp; - dwp_file->sections.str.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.str; else if (names->cu_index.matches (sectp->name)) - { - dwp_file->sections.cu_index.s.section = sectp; - dwp_file->sections.cu_index.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.cu_index; else if (names->tu_index.matches (sectp->name)) + dw_sect = &dwp_file->sections.tu_index; + + if (dw_sect != nullptr) { - dwp_file->sections.tu_index.s.section = sectp; - dwp_file->sections.tu_index.size = bfd_section_size (sectp); + dw_sect->s.section = sectp; + dw_sect->size = bfd_section_size (sectp); + dw_sect->read (objfile); } } @@ -12262,7 +11315,8 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */ static void -dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) +dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd, + asection *sectp, void *dwp_file_ptr) { struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr; const struct dwop_section_names *names = &dwop_section_names; @@ -12274,45 +11328,29 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) dwp_file->elf_sections[elf_section_nr] = sectp; /* Look for specific sections that we need. */ + struct dwarf2_section_info *dw_sect = nullptr; if (names->abbrev_dwo.matches (sectp->name)) - { - dwp_file->sections.abbrev.s.section = sectp; - dwp_file->sections.abbrev.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.abbrev; else if (names->info_dwo.matches (sectp->name)) - { - dwp_file->sections.info.s.section = sectp; - dwp_file->sections.info.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.info; else if (names->line_dwo.matches (sectp->name)) - { - dwp_file->sections.line.s.section = sectp; - dwp_file->sections.line.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.line; else if (names->loc_dwo.matches (sectp->name)) - { - dwp_file->sections.loc.s.section = sectp; - dwp_file->sections.loc.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.loc; else if (names->macinfo_dwo.matches (sectp->name)) - { - dwp_file->sections.macinfo.s.section = sectp; - dwp_file->sections.macinfo.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.macinfo; else if (names->macro_dwo.matches (sectp->name)) - { - dwp_file->sections.macro.s.section = sectp; - dwp_file->sections.macro.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.macro; else if (names->str_offsets_dwo.matches (sectp->name)) - { - dwp_file->sections.str_offsets.s.section = sectp; - dwp_file->sections.str_offsets.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.str_offsets; else if (names->types_dwo.matches (sectp->name)) + dw_sect = &dwp_file->sections.types; + + if (dw_sect != nullptr) { - dwp_file->sections.types.s.section = sectp; - dwp_file->sections.types.size = bfd_section_size (sectp); + dw_sect->s.section = sectp; + dw_sect->size = bfd_section_size (sectp); + dw_sect->read (objfile); } } @@ -12322,7 +11360,8 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */ static void -dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) +dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd, + asection *sectp, void *dwp_file_ptr) { struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr; const struct dwop_section_names *names = &dwop_section_names; @@ -12334,40 +11373,27 @@ dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) dwp_file->elf_sections[elf_section_nr] = sectp; /* Look for specific sections that we need. */ + struct dwarf2_section_info *dw_sect = nullptr; if (names->abbrev_dwo.matches (sectp->name)) - { - dwp_file->sections.abbrev.s.section = sectp; - dwp_file->sections.abbrev.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.abbrev; else if (names->info_dwo.matches (sectp->name)) - { - dwp_file->sections.info.s.section = sectp; - dwp_file->sections.info.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.info; else if (names->line_dwo.matches (sectp->name)) - { - dwp_file->sections.line.s.section = sectp; - dwp_file->sections.line.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.line; else if (names->loclists_dwo.matches (sectp->name)) - { - dwp_file->sections.loclists.s.section = sectp; - dwp_file->sections.loclists.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.loclists; else if (names->macro_dwo.matches (sectp->name)) - { - dwp_file->sections.macro.s.section = sectp; - dwp_file->sections.macro.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.macro; else if (names->rnglists_dwo.matches (sectp->name)) - { - dwp_file->sections.rnglists.s.section = sectp; - dwp_file->sections.rnglists.size = bfd_section_size (sectp); - } + dw_sect = &dwp_file->sections.rnglists; else if (names->str_offsets_dwo.matches (sectp->name)) + dw_sect = &dwp_file->sections.str_offsets; + + if (dw_sect != nullptr) { - dwp_file->sections.str_offsets.s.section = sectp; - dwp_file->sections.str_offsets.size = bfd_section_size (sectp); + dw_sect->s.section = sectp; + dw_sect->size = bfd_section_size (sectp); + dw_sect->read (objfile); } } @@ -12427,7 +11453,7 @@ open_dwp_file (dwarf2_per_objfile *per_objfile, const char *file_name) [IWBN if the dwp file name was recorded in the executable, akin to .gnu_debuglink, but that doesn't exist yet.] Strip the directory from FILE_NAME and search again. */ - if (*debug_file_directory != '\0') + if (!debug_file_directory.empty ()) { /* Don't implicitly search the current directory here. If the user wants to search "." to handle this case, @@ -12494,7 +11520,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) dwp_file->num_sections, asection *); for (asection *sec : gdb_bfd_sections (dwp_file->dbfd)) - dwarf2_locate_common_dwp_sections (dwp_file->dbfd.get (), sec, + dwarf2_locate_common_dwp_sections (objfile, dwp_file->dbfd.get (), sec, dwp_file.get ()); dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0); @@ -12524,10 +11550,10 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile) for (asection *sec : gdb_bfd_sections (dwp_file->dbfd)) { if (dwp_file->version == 2) - dwarf2_locate_v2_dwp_sections (dwp_file->dbfd.get (), sec, + dwarf2_locate_v2_dwp_sections (objfile, dwp_file->dbfd.get (), sec, dwp_file.get ()); else - dwarf2_locate_v5_dwp_sections (dwp_file->dbfd.get (), sec, + dwarf2_locate_v5_dwp_sections (objfile, dwp_file->dbfd.get (), sec, dwp_file.get ()); } @@ -12978,7 +12004,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) } /* Ignore functions with missing or invalid low and high pc attributes. */ - if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL) + if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr) <= PC_BOUNDS_INVALID) { attr = dwarf2_attr (die, DW_AT_external, cu); @@ -13151,7 +12177,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) as multiple lexical blocks? Handling children in a sane way would be nasty. Might be easier to properly extend generic blocks to describe ranges. */ - switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr)) { case PC_BOUNDS_NOT_PRESENT: /* DW_TAG_lexical_block has no attributes, process its children as if @@ -13213,6 +12239,11 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) cu->get_builder ()->set_local_using_directives (cstk.local_using_directives); } +static void dwarf2_ranges_read_low_addrs (unsigned offset, + struct dwarf2_cu *cu, + dwarf_tag tag, + std::vector &result); + /* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */ static void @@ -13223,7 +12254,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) struct gdbarch *gdbarch = objfile->arch (); CORE_ADDR pc, baseaddr; struct attribute *attr; - struct call_site *call_site, call_site_local; void **slot; int nparams; struct die_info *child_die; @@ -13246,12 +12276,14 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) } pc = attr->as_address () + baseaddr; pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc); + pc -= baseaddr; if (cu->call_site_htab == NULL) - cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq, - NULL, &objfile->objfile_obstack, + cu->call_site_htab = htab_create_alloc_ex (16, call_site::hash, + call_site::eq, NULL, + &objfile->objfile_obstack, hashtab_obstack_allocate, NULL); - call_site_local.pc = pc; + struct call_site call_site_local (pc, nullptr, nullptr); slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT); if (*slot != NULL) { @@ -13281,14 +12313,16 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) nparams++; } - call_site - = ((struct call_site *) - obstack_alloc (&objfile->objfile_obstack, - sizeof (*call_site) - + (sizeof (*call_site->parameter) * (nparams - 1)))); + struct call_site *call_site + = new (XOBNEWVAR (&objfile->objfile_obstack, + struct call_site, + sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams)) + struct call_site (pc, cu->per_cu, per_objfile); *slot = call_site; - memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter)); - call_site->pc = pc; + + /* We never call the destructor of call_site, so we must ensure it is + trivially destructible. */ + gdb_static_assert(std::is_trivially_destructible::value); if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu) || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu)) @@ -13349,7 +12383,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin. */ attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); } - SET_FIELD_DWARF_BLOCK (call_site->target, NULL); + + call_site->target.set_loc_dwarf_block (nullptr); if (!attr || (attr->form_is_block () && attr->as_block ()->size == 0)) /* Keep NULL DWARF_BLOCK. */; else if (attr->form_is_block ()) @@ -13363,7 +12398,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) dlbaton->per_objfile = per_objfile; dlbaton->per_cu = cu->per_cu; - SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton); + call_site->target.set_loc_dwarf_block (dlbaton); } else if (attr->form_is_ref ()) { @@ -13372,6 +12407,10 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) target_die = follow_die_ref (die, attr, &target_cu); gdb_assert (target_cu->per_objfile->objfile == objfile); + + struct attribute *ranges_attr + = dwarf2_attr (target_die, DW_AT_ranges, target_cu); + if (die_is_declaration (target_die, target_cu)) { const char *target_physname; @@ -13385,22 +12424,36 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) "physname, for referencing DIE %s [in module %s]"), sect_offset_str (die->sect_off), objfile_name (objfile)); else - SET_FIELD_PHYSNAME (call_site->target, target_physname); + call_site->target.set_loc_physname (target_physname); + } + else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ()) + { + ULONGEST ranges_offset = (ranges_attr->as_unsigned () + + target_cu->gnu_ranges_base); + std::vector addresses; + dwarf2_ranges_read_low_addrs (ranges_offset, target_cu, + target_die->tag, addresses); + CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR, + addresses.size ()); + std::copy (addresses.begin (), addresses.end (), saved); + call_site->target.set_loc_array (addresses.size (), saved); } else { CORE_ADDR lowpc; /* DW_AT_entry_pc should be preferred. */ - if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL) + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, + nullptr, nullptr) <= PC_BOUNDS_INVALID) complaint (_("DW_AT_call_target target DIE has invalid " "low pc, for referencing DIE %s [in module %s]"), sect_offset_str (die->sect_off), objfile_name (objfile)); else { - lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); - SET_FIELD_PHYSADDR (call_site->target, lowpc); + lowpc = (gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr) + - baseaddr); + call_site->target.set_loc_physaddr (lowpc); } } } @@ -13409,9 +12462,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) "block nor reference, for DIE %s [in module %s]"), sect_offset_str (die->sect_off), objfile_name (objfile)); - call_site->per_cu = cu->per_cu; - call_site->per_objfile = per_objfile; - for (child_die = die->child; child_die && child_die->tag; child_die = child_die->sibling) @@ -13615,7 +12665,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu, /* Base address selection entry. */ gdb::optional base; const gdb_byte *buffer; - CORE_ADDR baseaddr; bool overflow = false; ULONGEST addr_index; struct dwarf2_section_info *rnglists_section; @@ -13632,8 +12681,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu, } buffer = rnglists_section->buffer + offset; - baseaddr = objfile->text_section_offset (); - while (1) { /* Initialize it due to a false compiler warning. */ @@ -13775,7 +12822,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu, /* A not-uncommon case of bad debug info. Don't pollute the addrmap with bad data. */ - if (range_beginning + baseaddr == 0 + if (range_beginning == 0 && !per_objfile->per_bfd->has_section_at_zero) { complaint (_(".debug_rnglists entry has start address of zero" @@ -13817,7 +12864,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag, gdb::optional base; unsigned int dummy; const gdb_byte *buffer; - CORE_ADDR baseaddr; if (cu_header->version >= 5) return dwarf2_rnglists_process (offset, cu, tag, callback); @@ -13833,8 +12879,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag, } buffer = per_objfile->per_bfd->ranges.buffer + offset; - baseaddr = objfile->text_section_offset (); - while (1) { CORE_ADDR range_beginning, range_end; @@ -13885,7 +12929,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag, /* A not-uncommon case of bad debug info. Don't pollute the addrmap with bad data. */ - if (range_beginning + baseaddr == 0 + if (range_beginning == 0 && !per_objfile->per_bfd->has_section_at_zero) { complaint (_(".debug_ranges entry has start address of zero" @@ -13901,15 +12945,15 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag, /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. Return 1 if the attributes are present and valid, otherwise, return 0. - If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'. */ + TAG is passed to dwarf2_ranges_process. If MAP is not NULL, then + ranges in MAP are set, using DATUM as the value. */ static int dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, CORE_ADDR *high_return, struct dwarf2_cu *cu, - dwarf2_psymtab *ranges_pst, dwarf_tag tag) + addrmap *map, void *datum, dwarf_tag tag) { struct objfile *objfile = cu->per_objfile->objfile; - dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd; struct gdbarch *gdbarch = objfile->arch (); const CORE_ADDR baseaddr = objfile->text_section_offset (); int low_set = 0; @@ -13920,7 +12964,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, retval = dwarf2_ranges_process (offset, cu, tag, [&] (CORE_ADDR range_beginning, CORE_ADDR range_end) { - if (ranges_pst != NULL) + if (map != nullptr) { CORE_ADDR lowpc; CORE_ADDR highpc; @@ -13931,8 +12975,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, highpc = (gdbarch_adjust_dwarf2_addr (gdbarch, range_end + baseaddr) - baseaddr); - addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap, - lowpc, highpc - 1, ranges_pst); + addrmap_set_empty (map, lowpc, highpc - 1, datum); } /* FIXME: This is recording everything as a low-high @@ -13968,6 +13011,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, return 1; } +/* Process ranges and fill in a vector of the low PC values only. */ + +static void +dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu, + dwarf_tag tag, + std::vector &result) +{ + dwarf2_ranges_process (offset, cu, tag, + [&] (CORE_ADDR start, CORE_ADDR end) + { + result.push_back (start); + }); +} + /* 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. */ @@ -13975,7 +13032,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, struct dwarf2_cu *cu, - dwarf2_psymtab *pst) + addrmap *map, void *datum) { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct attribute *attr; @@ -14018,8 +13075,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, /* Value of the DW_AT_ranges attribute is the offset in the .debug_ranges section. */ - if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst, - die->tag)) + if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, + map, datum, die->tag)) return PC_BOUNDS_INVALID; /* Found discontinuous range of addresses. */ ret = PC_BOUNDS_RANGES; @@ -14062,7 +13119,8 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die, CORE_ADDR low, high; struct die_info *child = die->child; - if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES) + if (dwarf2_get_pc_bounds (die, &low, &high, cu, nullptr, nullptr) + >= PC_BOUNDS_RANGES) { *lowpc = std::min (*lowpc, low); *highpc = std::max (*highpc, high); @@ -14099,7 +13157,8 @@ get_scope_pc_bounds (struct die_info *die, CORE_ADDR best_high = (CORE_ADDR) 0; CORE_ADDR current_low, current_high; - if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL) + if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, + nullptr, nullptr) >= PC_BOUNDS_RANGES) { best_low = current_low; @@ -14227,6 +13286,7 @@ check_producer (struct dwarf2_cu *cu) { cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6); cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3); + cu->producer_is_gcc_11 = major == 11; } else if (producer_is_icc (cu->producer, &major, &minor)) { @@ -14312,14 +13372,14 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu) } } -/* Look for DW_AT_data_member_location. Set *OFFSET to the byte - offset. If the attribute was not found return 0, otherwise return - 1. If it was found but could not properly be handled, set *OFFSET - to 0. */ +/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset. Set + *OFFSET to the byte offset. If the attribute was not found return + 0, otherwise return 1. If it was found but could not properly be + handled, set *OFFSET to 0. */ static int -handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, - LONGEST *offset) +handle_member_location (struct die_info *die, struct dwarf2_cu *cu, + LONGEST *offset) { struct attribute *attr; @@ -14343,15 +13403,25 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, return 1; } + else + { + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + if (attr != nullptr) + { + *offset = attr->constant_value (0); + return 1; + } + } return 0; } -/* Look for DW_AT_data_member_location and store the results in FIELD. */ +/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and + store the results in FIELD. */ static void -handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, - struct field *field) +handle_member_location (struct die_info *die, struct dwarf2_cu *cu, + struct field *field) { struct attribute *attr; @@ -14361,7 +13431,20 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, if (attr->form_is_constant ()) { LONGEST offset = attr->constant_value (0); - SET_FIELD_BITPOS (*field, offset * bits_per_byte); + + /* Work around this GCC 11 bug, where it would erroneously use -1 + data member locations, instead of 0: + + Negative DW_AT_data_member_location + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378 + */ + if (offset == -1 && cu->producer_is_gcc_11) + { + complaint (_("DW_AT_data_member_location value of -1, assuming 0")); + offset = 0; + } + + field->set_loc_bitpos (offset * bits_per_byte); } else if (attr->form_is_section_offset ()) dwarf2_complex_location_expr_complaint (); @@ -14370,7 +13453,7 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, bool handled; CORE_ADDR offset = decode_locdesc (attr->as_block (), cu, &handled); if (handled) - SET_FIELD_BITPOS (*field, offset * bits_per_byte); + field->set_loc_bitpos (offset * bits_per_byte); else { dwarf2_per_objfile *per_objfile = cu->per_objfile; @@ -14387,12 +13470,18 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu, dlbaton->per_objfile = per_objfile; dlbaton->per_cu = cu->per_cu; - SET_FIELD_DWARF_BLOCK (*field, dlbaton); + field->set_loc_dwarf_block (dlbaton); } } else dwarf2_complex_location_expr_complaint (); } + else + { + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + if (attr != nullptr) + field->set_loc_bitpos (attr->constant_value (0)); + } } /* Add an aggregate field to the field list. */ @@ -14433,14 +13522,27 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, fp = &new_field->field; - if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu)) - { + if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item) + && !die_is_declaration (die, cu)) + { + if (die->tag == DW_TAG_namelist_item) + { + /* Typically, DW_TAG_namelist_item are references to namelist items. + If so, follow that reference. */ + struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu); + struct die_info *item_die = nullptr; + struct dwarf2_cu *item_cu = cu; + if (attr1->form_is_ref ()) + item_die = follow_die_ref (die, attr1, &item_cu); + if (item_die != nullptr) + die = item_die; + } /* Data member other than a C++ static data member. */ /* Get type of field. */ fp->set_type (die_type (die, cu)); - SET_FIELD_BITPOS (*fp, 0); + fp->set_loc_bitpos (0); /* Get bit size of field (zero if none). */ attr = dwarf2_attr (die, DW_AT_bit_size, cu); @@ -14454,7 +13556,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } /* Get bit offset of field. */ - handle_data_member_location (die, cu, fp); + handle_member_location (die, cu, fp); attr = dwarf2_attr (die, DW_AT_bit_offset, cu); if (attr != nullptr && attr->form_is_constant ()) { @@ -14465,8 +13567,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, anonymous object to the MSB of the field. We don't have to do anything special since we don't need to know the size of the anonymous object. */ - SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp) - + attr->constant_value (0))); + fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0)); } else { @@ -14495,16 +13596,11 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, bit field. */ anonymous_size = TYPE_LENGTH (fp->type ()); } - SET_FIELD_BITPOS (*fp, - (FIELD_BITPOS (*fp) - + anonymous_size * bits_per_byte - - bit_offset - FIELD_BITSIZE (*fp))); + fp->set_loc_bitpos (fp->loc_bitpos () + + anonymous_size * bits_per_byte + - bit_offset - FIELD_BITSIZE (*fp)); } } - attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); - if (attr != NULL) - SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp) - + attr->constant_value (0))); /* Get name of field. */ fieldname = dwarf2_name (die, cu); @@ -14513,7 +13609,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, /* The name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ - fp->name = fieldname; + fp->set_name (fieldname); /* Change accessibility for artificial fields (e.g. virtual table pointer or virtual base class pointer) to private. */ @@ -14558,17 +13654,17 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, /* The name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ - SET_FIELD_PHYSNAME (*fp, physname ? physname : ""); + fp->set_loc_physname (physname ? physname : ""); fp->set_type (die_type (die, cu)); - FIELD_NAME (*fp) = fieldname; + fp->set_name (fieldname); } else if (die->tag == DW_TAG_inheritance) { /* C++ base class field. */ - handle_data_member_location (die, cu, fp); + handle_member_location (die, cu, fp); FIELD_BITSIZE (*fp) = 0; fp->set_type (die_type (die, cu)); - FIELD_NAME (*fp) = fp->type ()->name (); + fp->set_name (fp->type ()->name ()); } else gdb_assert_not_reached ("missing case in dwarf2_add_field"); @@ -14811,7 +13907,7 @@ add_variant_property (struct field_info *fip, struct type *type, offset_map[fip->fields[i].offset] = i; struct objfile *objfile = cu->per_objfile->objfile; - gdb::array_view parts + gdb::array_view parts = create_variant_parts (&objfile->objfile_obstack, offset_map, fip, fip->variant_parts); @@ -15203,10 +14299,10 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile) return; /* Check for __pfn and __delta members. */ - if (TYPE_FIELD_NAME (type, 0) == NULL - || strcmp (TYPE_FIELD_NAME (type, 0), "__pfn") != 0 - || TYPE_FIELD_NAME (type, 1) == NULL - || strcmp (TYPE_FIELD_NAME (type, 1), "__delta") != 0) + if (type->field (0).name () == NULL + || strcmp (type->field (0).name (), "__pfn") != 0 + || type->field (1).name () == NULL + || strcmp (type->field (1).name (), "__delta") != 0) return; /* Find the type of the method. */ @@ -15297,10 +14393,10 @@ quirk_ada_thick_pointer_struct (struct die_info *die, struct dwarf2_cu *cu, return; /* Check for P_ARRAY and P_BOUNDS members. */ - if (TYPE_FIELD_NAME (type, 0) == NULL - || strcmp (TYPE_FIELD_NAME (type, 0), "P_ARRAY") != 0 - || TYPE_FIELD_NAME (type, 1) == NULL - || strcmp (TYPE_FIELD_NAME (type, 1), "P_BOUNDS") != 0) + if (type->field (0).name () == NULL + || strcmp (type->field (0).name (), "P_ARRAY") != 0 + || type->field (1).name () == NULL + || strcmp (type->field (1).name (), "P_BOUNDS") != 0) return; /* Make sure we're looking at a pointer to an array. */ @@ -15498,6 +14594,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) { type->set_code (TYPE_CODE_UNION); } + else if (die->tag == DW_TAG_namelist) + { + type->set_code (TYPE_CODE_NAMELIST); + } else { type->set_code (TYPE_CODE_STRUCT); @@ -15700,7 +14800,8 @@ handle_struct_member_die (struct die_info *child_die, struct type *type, struct dwarf2_cu *cu) { if (child_die->tag == DW_TAG_member - || child_die->tag == DW_TAG_variable) + || child_die->tag == DW_TAG_variable + || child_die->tag == DW_TAG_namelist_item) { /* NOTE: carlton/2002-11-05: A C++ static data member should be a DW_TAG_member that is a declaration, but @@ -15743,8 +14844,10 @@ handle_struct_member_die (struct die_info *child_die, struct type *type, handle_variant (child_die, type, fi, template_args, cu); } -/* Finish creating a structure or union type, including filling in - its members and creating a symbol for it. */ +/* Finish creating a structure or union type, including filling in its + members and creating a symbol for it. This function also handles Fortran + namelist variables, their items or members and creating a symbol for + them. */ static void process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) @@ -15813,7 +14916,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) i >= TYPE_N_BASECLASSES (t); --i) { - const char *fieldname = TYPE_FIELD_NAME (t, i); + const char *fieldname = t->field (i).name (); if (is_vtable_name (fieldname, cu)) { @@ -15846,7 +14949,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) i >= TYPE_N_BASECLASSES (type); --i) { - if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0) + if (strcmp (type->field (i).name (), "__vfp") == 0) { set_type_vptr_fieldno (type, i); set_type_vptr_basetype (type, type); @@ -16017,8 +15120,8 @@ update_enumeration_type_from_children (struct die_info *die, fields.emplace_back (); struct field &field = fields.back (); - FIELD_NAME (field) = dwarf2_physname (name, child_die, cu); - SET_FIELD_ENUMVAL (field, value); + field.set_name (dwarf2_physname (name, child_die, cu)); + field.set_loc_enumval (value); } if (!fields.empty ()) @@ -16292,7 +15395,7 @@ recognize_bound_expression (struct die_info *die, enum dwarf_attribute name, else return false; - SET_FIELD_BITPOS (*field, 8 * offset); + field->set_loc_bitpos (8 * offset); if (size != TYPE_LENGTH (field->type ())) FIELD_BITSIZE (*field) = 8 * size; @@ -16391,9 +15494,9 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu, /* Set the name of each field in the bounds. */ xsnprintf (name, sizeof (name), "LB%d", i / 2); - FIELD_NAME (range_fields[i]) = objfile->intern (name); + range_fields[i].set_name (objfile->intern (name)); xsnprintf (name, sizeof (name), "UB%d", i / 2); - FIELD_NAME (range_fields[i + 1]) = objfile->intern (name); + range_fields[i + 1].set_name (objfile->intern (name)); } struct type *bounds = alloc_type (objfile); @@ -16407,7 +15510,7 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu, bounds->num_fields () * sizeof (struct field)); int last_fieldno = range_fields.size () - 1; - int bounds_size = (TYPE_FIELD_BITPOS (bounds, last_fieldno) / 8 + int bounds_size = (bounds->field (last_fieldno).loc_bitpos () / 8 + TYPE_LENGTH (bounds->field (last_fieldno).type ())); TYPE_LENGTH (bounds) = align_up (bounds_size, max_align); @@ -16435,12 +15538,12 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu, /* The names are chosen to coincide with what the compiler does with -fgnat-encodings=all, which the Ada code in gdb already understands. */ - TYPE_FIELD_NAME (result, 0) = "P_ARRAY"; + result->field (0).set_name ("P_ARRAY"); result->field (0).set_type (lookup_pointer_type (type)); - TYPE_FIELD_NAME (result, 1) = "P_BOUNDS"; + result->field (1).set_name ("P_BOUNDS"); result->field (1).set_type (lookup_pointer_type (bounds)); - SET_FIELD_BITPOS (result->field (1), 8 * bounds_offset); + result->field (1).set_loc_bitpos (8 * bounds_offset); result->set_name (type->name ()); TYPE_LENGTH (result) = (TYPE_LENGTH (result->field (0).type ()) @@ -16514,7 +15617,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) child_die = die->child; while (child_die && child_die->tag) { - if (child_die->tag == DW_TAG_subrange_type) + if (child_die->tag == DW_TAG_subrange_type + || child_die->tag == DW_TAG_generic_subrange) { struct type *child_type = read_type_die (child_die, cu); @@ -16748,7 +15852,7 @@ mark_common_block_symbol_computed (struct symbol *sym, gdb_assert (ptr - baton->data == baton->size); SYMBOL_LOCATION_BATON (sym) = baton; - SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index; + sym->set_aclass_index (dwarf2_locexpr_index); } /* Create appropriate locally-scoped variables for all the @@ -16847,7 +15951,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu) } sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu); - SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block; + sym->set_value_common_block (common_block); } } @@ -17306,7 +16410,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) /* Pass 0 as the default as we know this attribute is constant and the default value will not be returned. */ LONGEST sz = len->constant_value (0); - prop_type = cu->per_objfile->int_type (sz, true); + prop_type = objfile_int_type (objfile, sz, true); } else { @@ -18133,16 +17237,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) break; case DW_ATE_UTF: { - if (bits == 16) - type = builtin_type (arch)->builtin_char16; - else if (bits == 32) - type = builtin_type (arch)->builtin_char32; - else - { - complaint (_("unsupported DW_ATE_UTF bit size: '%d'"), - bits); - type = dwarf2_init_integer_type (cu, objfile, bits, 1, name); - } + type = init_character_type (objfile, bits, 1, name); return set_die_type (die, type, cu); } break; @@ -18162,7 +17257,9 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) break; } - if (name && strcmp (name, "char") == 0) + if (type->code () == TYPE_CODE_INT + && name != nullptr + && strcmp (name, "char") == 0) type->set_has_no_signedness (true); maybe_set_alignment (cu, die, type); @@ -18238,7 +17335,22 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, baton->locexpr.per_cu = cu->per_cu; baton->locexpr.per_objfile = per_objfile; - struct dwarf_block *block = attr->as_block (); + struct dwarf_block *block; + if (attr->form == DW_FORM_data16) + { + size_t data_size = 16; + block = XOBNEW (obstack, struct dwarf_block); + block->size = (data_size + + 2 /* Extra bytes for DW_OP and arg. */); + gdb_byte *data = XOBNEWVEC (obstack, gdb_byte, block->size); + data[0] = DW_OP_implicit_value; + data[1] = data_size; + memcpy (&data[2], attr->as_block ()->data, data_size); + block->data = data; + } + else + block = attr->as_block (); + baton->locexpr.size = block->size; baton->locexpr.data = block->data; switch (attr->name) @@ -18265,6 +17377,9 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, if (target_attr == NULL) target_attr = dwarf2_attr (target_die, DW_AT_data_member_location, target_cu); + if (target_attr == nullptr) + target_attr = dwarf2_attr (target_die, DW_AT_data_bit_offset, + target_cu); if (target_attr == NULL) { const char *name = var_decl_name (target_die, target_cu); @@ -18308,11 +17423,11 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, } break; case DW_AT_data_member_location: + case DW_AT_data_bit_offset: { LONGEST offset; - if (!handle_data_member_location (target_die, target_cu, - &offset)) + if (!handle_member_location (target_die, target_cu, &offset)) return 0; baton = XOBNEW (obstack, struct dwarf2_property_baton); @@ -18327,42 +17442,34 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, } else if (attr->form_is_constant ()) prop->set_const_val (attr->constant_value (0)); - else + else if (attr->form_is_section_offset ()) { - dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form), - dwarf2_name (die, cu)); - return 0; + switch (attr->name) + { + case DW_AT_string_length: + baton = XOBNEW (obstack, struct dwarf2_property_baton); + baton->property_type = default_type; + fill_in_loclist_baton (cu, &baton->loclist, attr); + prop->set_loclist (baton); + gdb_assert (prop->baton () != NULL); + break; + default: + goto invalid; + } } + else + goto invalid; return 1; + + invalid: + dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form), + dwarf2_name (die, cu)); + return 0; } /* See read.h. */ -struct type * -dwarf2_per_objfile::int_type (int size_in_bytes, bool unsigned_p) const -{ - struct type *int_type; - - /* Helper macro to examine the various builtin types. */ -#define TRY_TYPE(F) \ - int_type = (unsigned_p \ - ? objfile_type (objfile)->builtin_unsigned_ ## F \ - : objfile_type (objfile)->builtin_ ## F); \ - if (int_type != NULL && TYPE_LENGTH (int_type) == size_in_bytes) \ - return int_type - - TRY_TYPE (char); - TRY_TYPE (short); - TRY_TYPE (int); - TRY_TYPE (long); - TRY_TYPE (long_long); - -#undef TRY_TYPE - - gdb_assert_not_reached ("unable to find suitable integer type"); -} - /* Read the DW_AT_type attribute for a sub-range. If this attribute is not present (which is valid) then compute the default type based on the compilation units address size. */ @@ -18684,11 +17791,11 @@ read_die_and_siblings (const struct die_reader_specs *reader, if (dwarf_die_debug) { - fprintf_unfiltered (gdb_stdlog, - "Read die from %s@0x%x of %s:\n", - reader->die_section->get_name (), - (unsigned) (info_ptr - reader->die_section->buffer), - bfd_get_filename (reader->abfd)); + gdb_printf (gdb_stdlog, + "Read die from %s@0x%x of %s:\n", + reader->die_section->get_name (), + (unsigned) (info_ptr - reader->die_section->buffer), + bfd_get_filename (reader->abfd)); dump_die (die, dwarf_die_debug); } @@ -18790,11 +17897,11 @@ read_full_die (const struct die_reader_specs *reader, if (dwarf_die_debug) { - fprintf_unfiltered (gdb_stdlog, - "Read die from %s@0x%x of %s:\n", - reader->die_section->get_name (), - (unsigned) (info_ptr - reader->die_section->buffer), - bfd_get_filename (reader->abfd)); + gdb_printf (gdb_stdlog, + "Read die from %s@0x%x of %s:\n", + reader->die_section->get_name (), + (unsigned) (info_ptr - reader->die_section->buffer), + bfd_get_filename (reader->abfd)); dump_die (*diep, dwarf_die_debug); } @@ -18802,827 +17909,841 @@ read_full_die (const struct die_reader_specs *reader, } -/* Returns nonzero if TAG represents a type that we might generate a partial - symbol for. */ - -static int -is_type_tag_for_partial (int tag, enum language lang) +void +cooked_indexer::check_bounds (cutu_reader *reader) { - switch (tag) + if (reader->cu->per_cu->addresses_seen) + return; + + dwarf2_cu *cu = reader->cu; + + CORE_ADDR best_lowpc = 0, best_highpc = 0; + /* Possibly set the default values of LOWPC and HIGHPC from + `DW_AT_ranges'. */ + dwarf2_find_base_address (reader->comp_unit_die, cu); + enum pc_bounds_kind cu_bounds_kind + = dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc, + cu, m_index_storage->get_addrmap (), cu->per_cu); + if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc) { -#if 0 - /* Some types that would be reasonable to generate partial symbols for, - that we don't at present. Note that normally this does not - matter, mainly because C compilers don't give names to these - types, but instead emit DW_TAG_typedef. */ - case DW_TAG_file_type: - case DW_TAG_ptr_to_member_type: - case DW_TAG_set_type: - case DW_TAG_string_type: - case DW_TAG_subroutine_type: -#endif + struct objfile *objfile = cu->per_objfile->objfile; + CORE_ADDR baseaddr = objfile->text_section_offset (); + struct gdbarch *gdbarch = objfile->arch (); + CORE_ADDR low + = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr) + - baseaddr); + CORE_ADDR high + = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr) + - baseaddr - 1); + /* Store the contiguous range if it is not empty; it can be + empty for CUs with no code. */ + addrmap_set_empty (m_index_storage->get_addrmap (), low, high, + cu->per_cu); - /* GNAT may emit an array with a name, but no typedef, so we - need to make a symbol in this case. */ - case DW_TAG_array_type: - return lang == language_ada; + cu->per_cu->addresses_seen = true; + } +} - case DW_TAG_base_type: +/* Helper function that returns true if TAG can have a linkage + name. */ + +static bool +tag_can_have_linkage_name (enum dwarf_tag tag) +{ + switch (tag) + { + /* We include types here because an anonymous C++ type might + have a name for linkage purposes. */ case DW_TAG_class_type: - case DW_TAG_interface_type: - case DW_TAG_enumeration_type: case DW_TAG_structure_type: - case DW_TAG_subrange_type: - case DW_TAG_typedef: case DW_TAG_union_type: - return 1; + case DW_TAG_variable: + case DW_TAG_subprogram: + return true; + default: - return 0; + return false; } } -/* Load all DIEs that are interesting for partial symbols into memory. */ - -static struct partial_die_info * -load_partial_dies (const struct die_reader_specs *reader, - const gdb_byte *info_ptr, int building_psymtab) +cutu_reader * +cooked_indexer::ensure_cu_exists (cutu_reader *reader, + dwarf2_per_objfile *per_objfile, + sect_offset sect_off, bool is_dwz, + bool for_scanning) { - struct dwarf2_cu *cu = reader->cu; - struct objfile *objfile = cu->per_objfile->objfile; - struct partial_die_info *parent_die, *last_die, *first_die = NULL; - unsigned int bytes_read; - unsigned int load_all = 0; - int nesting_level = 1; - - parent_die = NULL; - last_die = NULL; - - gdb_assert (cu->per_cu != NULL); - if (cu->load_all_dies) - load_all = 1; + /* Lookups for type unit references are always in the CU, and + cross-CU references will crash. */ + if (reader->cu->per_cu->is_dwz == is_dwz + && reader->cu->header.offset_in_cu_p (sect_off)) + return reader; - cu->partial_dies - = htab_create_alloc_ex (cu->header.length / 12, - partial_die_hash, - partial_die_eq, - NULL, - &cu->comp_unit_obstack, - hashtab_obstack_allocate, - dummy_obstack_deallocate); + dwarf2_per_cu_data *per_cu + = dwarf2_find_containing_comp_unit (sect_off, is_dwz, + per_objfile->per_bfd); - while (1) + /* When scanning, we only want to visit a given CU a single time. + Doing this check here avoids self-imports as well. */ + if (for_scanning) { - const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, - &bytes_read); - - /* A NULL abbrev means the end of a series of children. */ - if (abbrev == NULL) - { - if (--nesting_level == 0) - return first_die; - - info_ptr += bytes_read; - last_die = parent_die; - parent_die = parent_die->die_parent; - continue; - } - - /* Check for template arguments. We never save these; if - they're seen, we just mark the parent, and go on our way. */ - if (parent_die != NULL - && cu->per_cu->lang == language_cplus - && (abbrev->tag == DW_TAG_template_type_param - || abbrev->tag == DW_TAG_template_value_param)) - { - parent_die->has_template_arguments = 1; - - if (!load_all) - { - /* We don't need a partial DIE for the template argument. */ - info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev); - continue; - } - } - - /* We only recurse into c++ subprograms looking for template arguments. - Skip their other children. */ - if (!load_all - && cu->per_cu->lang == language_cplus - && parent_die != NULL - && parent_die->tag == DW_TAG_subprogram - && abbrev->tag != DW_TAG_inlined_subroutine) - { - info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev); - continue; - } - - /* Check whether this DIE is interesting enough to save. Normally - we would not be interested in members here, but there may be - later variables referencing them via DW_AT_specification (for - static members). */ - if (!load_all - && !is_type_tag_for_partial (abbrev->tag, cu->per_cu->lang) - && abbrev->tag != DW_TAG_constant - && abbrev->tag != DW_TAG_enumerator - && abbrev->tag != DW_TAG_subprogram - && abbrev->tag != DW_TAG_inlined_subroutine - && abbrev->tag != DW_TAG_lexical_block - && abbrev->tag != DW_TAG_variable - && abbrev->tag != DW_TAG_namespace - && abbrev->tag != DW_TAG_module - && abbrev->tag != DW_TAG_member - && abbrev->tag != DW_TAG_imported_unit - && abbrev->tag != DW_TAG_imported_declaration) - { - /* Otherwise we skip to the next sibling, if any. */ - info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev); - continue; - } - - struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer), - abbrev); - - info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read); - - /* This two-pass algorithm for processing partial symbols has a - high cost in cache pressure. Thus, handle some simple cases - here which cover the majority of C partial symbols. DIEs - which neither have specification tags in them, nor could have - specification tags elsewhere pointing at them, can simply be - processed and discarded. - - This segment is also optional; scan_partial_symbols and - add_partial_symbol will handle these DIEs if we chain - them in normally. When compilers which do not emit large - quantities of duplicate debug information are more common, - this code can probably be removed. */ - - /* Any complete simple types at the top level (pretty much all - of them, for a language without namespaces), can be processed - directly. */ - if (parent_die == NULL - && pdi.has_specification == 0 - && pdi.is_declaration == 0 - && ((pdi.tag == DW_TAG_typedef && !pdi.has_children) - || pdi.tag == DW_TAG_base_type - || pdi.tag == DW_TAG_array_type - || pdi.tag == DW_TAG_subrange_type)) - { - if (building_psymtab && pdi.raw_name != NULL) - add_partial_symbol (&pdi, cu); - - info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr); - continue; - } - - /* The exception for DW_TAG_typedef with has_children above is - a workaround of GCC PR debug/47510. In the case of this complaint - type_name_or_error will error on such types later. - - GDB skipped children of DW_TAG_typedef by the shortcut above and then - it could not find the child DIEs referenced later, this is checked - above. In correct DWARF DW_TAG_typedef should have no children. */ - - if (pdi.tag == DW_TAG_typedef && pdi.has_children) - complaint (_("DW_TAG_typedef has childen - GCC PR debug/47510 bug " - "- DIE at %s [in module %s]"), - sect_offset_str (pdi.sect_off), objfile_name (objfile)); - - /* If we're at the second level, and we're an enumerator, and - our parent has no specification (meaning possibly lives in a - namespace elsewhere), then we can add the partial symbol now - instead of queueing it. */ - if (pdi.tag == DW_TAG_enumerator - && parent_die != NULL - && parent_die->die_parent == NULL - && parent_die->tag == DW_TAG_enumeration_type - && parent_die->has_specification == 0) - { - if (pdi.raw_name == NULL) - complaint (_("malformed enumerator DIE ignored")); - else if (building_psymtab) - add_partial_symbol (&pdi, cu); - - info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr); - continue; - } - - struct partial_die_info *part_die - = new (&cu->comp_unit_obstack) partial_die_info (pdi); - - /* We'll save this DIE so link it in. */ - part_die->die_parent = parent_die; - part_die->die_sibling = NULL; - part_die->die_child = NULL; - - if (last_die && last_die == parent_die) - last_die->die_child = part_die; - else if (last_die) - last_die->die_sibling = part_die; - - last_die = part_die; - - if (first_die == NULL) - first_die = part_die; - - /* Maybe add the DIE to the hash table. Not all DIEs that we - find interesting need to be in the hash table, because we - also have the parent/sibling/child chains; only those that we - might refer to by offset later during partial symbol reading. - - For now this means things that might have be the target of a - DW_AT_specification, DW_AT_abstract_origin, or - DW_AT_extension. DW_AT_extension will refer only to - namespaces; DW_AT_abstract_origin refers to functions (and - many things under the function DIE, but we do not recurse - into function DIEs during partial symbol reading) and - possibly variables as well; DW_AT_specification refers to - declarations. Declarations ought to have the DW_AT_declaration - flag. It happens that GCC forgets to put it in sometimes, but - only for functions, not for types. - - Adding more things than necessary to the hash table is harmless - except for the performance cost. Adding too few will result in - wasted time in find_partial_die, when we reread the compilation - unit with load_all_dies set. */ - - if (load_all - || abbrev->tag == DW_TAG_constant - || abbrev->tag == DW_TAG_subprogram - || abbrev->tag == DW_TAG_variable - || abbrev->tag == DW_TAG_namespace - || part_die->is_declaration) - { - void **slot; - - slot = htab_find_slot_with_hash (cu->partial_dies, part_die, - to_underlying (part_die->sect_off), - INSERT); - *slot = part_die; - } - - /* For some DIEs we want to follow their children (if any). For C - we have no reason to follow the children of structures; for other - languages we have to, so that we can get at method physnames - to infer fully qualified class names, for DW_AT_specification, - and for C++ template arguments. For C++, we also look one level - inside functions to find template arguments (if the name of the - function does not already contain the template arguments). - - For Ada and Fortran, we need to scan the children of subprograms - and lexical blocks as well because these languages allow the - definition of nested entities that could be interesting for the - debugger, such as nested subprograms for instance. */ - if (last_die->has_children - && (load_all - || last_die->tag == DW_TAG_namespace - || last_die->tag == DW_TAG_module - || last_die->tag == DW_TAG_enumeration_type - || (cu->per_cu->lang == language_cplus - && last_die->tag == DW_TAG_subprogram - && (last_die->raw_name == NULL - || strchr (last_die->raw_name, '<') == NULL)) - || (cu->per_cu->lang != language_c - && (last_die->tag == DW_TAG_class_type - || last_die->tag == DW_TAG_interface_type - || last_die->tag == DW_TAG_structure_type - || last_die->tag == DW_TAG_union_type)) - || ((cu->per_cu->lang == language_ada - || cu->per_cu->lang == language_fortran) - && (last_die->tag == DW_TAG_subprogram - || last_die->tag == DW_TAG_lexical_block)))) - { - nesting_level++; - parent_die = last_die; - continue; - } + bool nope = false; + if (!per_cu->scanned.compare_exchange_strong (nope, true)) + return nullptr; + } + if (per_cu == m_per_cu) + return reader; - /* Otherwise we skip to the next sibling, if any. */ - info_ptr = locate_pdi_sibling (reader, last_die, info_ptr); + cutu_reader *result = m_index_storage->get_reader (per_cu); + if (result == nullptr) + { + cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false, + m_index_storage->get_abbrev_cache ()); - /* Back to the top, do it again. */ + prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die, + language_minimal); + std::unique_ptr copy + (new cutu_reader (std::move (new_reader))); + result = m_index_storage->preserve (std::move (copy)); } -} -partial_die_info::partial_die_info (sect_offset sect_off_, - const struct abbrev_info *abbrev) - : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children) -{ -} + if (result->dummy_p || !result->comp_unit_die->has_children) + return nullptr; -/* See class definition. */ + if (for_scanning) + check_bounds (result); -const char * -partial_die_info::name (dwarf2_cu *cu) -{ - if (!canonical_name && raw_name != nullptr) - { - struct objfile *objfile = cu->per_objfile->objfile; - raw_name = dwarf2_canonicalize_name (raw_name, cu, objfile); - canonical_name = 1; - } - - return raw_name; + return result; } -/* Read a minimal amount of information into the minimal die structure. - INFO_PTR should point just after the initial uleb128 of a DIE. */ - const gdb_byte * -partial_die_info::read (const struct die_reader_specs *reader, - const struct abbrev_info &abbrev, const gdb_byte *info_ptr) -{ - struct dwarf2_cu *cu = reader->cu; - dwarf2_per_objfile *per_objfile = cu->per_objfile; - unsigned int i; - int has_low_pc_attr = 0; - int has_high_pc_attr = 0; - int high_pc_relative = 0; - - for (i = 0; i < abbrev.num_attrs; ++i) +cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu, + cutu_reader *reader, + const gdb_byte *watermark_ptr, + const gdb_byte *info_ptr, + const abbrev_info *abbrev, + const char **name, + const char **linkage_name, + cooked_index_flag *flags, + sect_offset *sibling_offset, + const cooked_index_entry **parent_entry, + CORE_ADDR *maybe_defer, + bool for_specification) +{ + bool origin_is_dwz = false; + bool is_declaration = false; + sect_offset origin_offset {}; + + gdb::optional low_pc; + gdb::optional high_pc; + bool high_pc_relative = false; + + for (int i = 0; i < abbrev->num_attrs; ++i) { attribute attr; - info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr); - /* String and address offsets that need to do the reprocessing have - already been read at this point, so there is no need to wait until - the loop terminates to do the reprocessing. */ + info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr); if (attr.requires_reprocessing_p ()) - read_attribute_reprocess (reader, &attr, tag); + read_attribute_reprocess (reader, &attr, abbrev->tag); + /* Store the data if it is of an attribute we want to keep in a partial symbol table. */ switch (attr.name) { case DW_AT_name: - switch (tag) + switch (abbrev->tag) { case DW_TAG_compile_unit: case DW_TAG_partial_unit: case DW_TAG_type_unit: /* Compilation units have a DW_AT_name that is a filename, not a source language identifier. */ - case DW_TAG_enumeration_type: - case DW_TAG_enumerator: - /* These tags always have simple identifiers already; no need - to canonicalize them. */ - canonical_name = 1; - raw_name = attr.as_string (); break; + default: - canonical_name = 0; - raw_name = attr.as_string (); + if (*name == nullptr) + *name = attr.as_string (); break; } break; + case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: /* Note that both forms of linkage name might appear. We assume they will be the same, and we only store the last one we see. */ - linkage_name = attr.as_string (); - break; - case DW_AT_low_pc: - has_low_pc_attr = 1; - lowpc = attr.as_address (); - break; - case DW_AT_high_pc: - has_high_pc_attr = 1; - highpc = attr.as_address (); - if (cu->header.version >= 4 && attr.form_is_constant ()) - high_pc_relative = 1; - break; - case DW_AT_location: - /* Support the .debug_loc offsets. */ - if (attr.form_is_block ()) - { - d.locdesc = attr.as_block (); - } - else if (attr.form_is_section_offset ()) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_location", - "partial symbol information"); - } + if (*linkage_name == nullptr) + *linkage_name = attr.as_string (); break; - case DW_AT_external: - is_external = attr.as_boolean (); + + case DW_AT_main_subprogram: + if (attr.as_boolean ()) + *flags |= IS_MAIN; break; + case DW_AT_declaration: is_declaration = attr.as_boolean (); break; - case DW_AT_type: - has_type = 1; + + case DW_AT_sibling: + if (sibling_offset != nullptr) + *sibling_offset = attr.get_ref_die_offset (); break; - case DW_AT_abstract_origin: + case DW_AT_specification: + case DW_AT_abstract_origin: case DW_AT_extension: - has_specification = 1; - spec_offset = attr.get_ref_die_offset (); - spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt - || cu->per_cu->is_dwz); + origin_offset = attr.get_ref_die_offset (); + origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt; break; - case DW_AT_sibling: - /* Ignore absolute siblings, they might point outside of - the current compile unit. */ - if (attr.form == DW_FORM_ref_addr) - complaint (_("ignoring absolute DW_AT_sibling")); - else - { - const gdb_byte *buffer = reader->buffer; - sect_offset off = attr.get_ref_die_offset (); - const gdb_byte *sibling_ptr = buffer + to_underlying (off); - if (sibling_ptr < info_ptr) - complaint (_("DW_AT_sibling points backwards")); - else if (sibling_ptr > reader->buffer_end) - reader->die_section->overflow_complaint (); - else - sibling = sibling_ptr; - } - break; - case DW_AT_byte_size: - has_byte_size = 1; + case DW_AT_external: + if (attr.as_boolean ()) + *flags &= ~IS_STATIC; break; - case DW_AT_const_value: - has_const_value = 1; + + case DW_AT_enum_class: + if (attr.as_boolean ()) + *flags |= IS_ENUM_CLASS; break; - case DW_AT_calling_convention: - /* DWARF doesn't provide a way to identify a program's source-level - entry point. DW_AT_calling_convention attributes are only meant - to describe functions' calling conventions. - - However, because it's a necessary piece of information in - Fortran, and before DWARF 4 DW_CC_program was the only - piece of debugging information whose definition refers to - a 'main program' at all, several compilers marked Fortran - main programs with DW_CC_program --- even when those - functions use the standard calling conventions. - - Although DWARF now specifies a way to provide this - information, we support this practice for backward - compatibility. */ - if (attr.constant_value (0) == DW_CC_program - && cu->per_cu->lang == language_fortran) - main_subprogram = 1; + + case DW_AT_low_pc: + low_pc = attr.as_address (); break; - case DW_AT_inline: - { - LONGEST value = attr.constant_value (-1); - if (value == DW_INL_inlined - || value == DW_INL_declared_inlined) - may_be_inlined = 1; - } + + case DW_AT_high_pc: + high_pc = attr.as_address (); + if (reader->cu->header.version >= 4 && attr.form_is_constant ()) + high_pc_relative = true; break; - case DW_AT_import: - if (tag == DW_TAG_imported_unit) + case DW_AT_location: + if (!scanning_per_cu->addresses_seen && attr.form_is_block ()) { - d.sect_off = attr.get_ref_die_offset (); - is_dwz = (attr.form == DW_FORM_GNU_ref_alt - || cu->per_cu->is_dwz); + struct dwarf_block *locdesc = attr.as_block (); + CORE_ADDR addr = decode_locdesc (locdesc, reader->cu); + if (addr != 0 + || reader->cu->per_objfile->per_bfd->has_section_at_zero) + { + low_pc = addr; + /* For variables, we don't want to try decoding the + type just to find the size -- for gdb's purposes + we only need the address of a variable. */ + high_pc = addr + 1; + high_pc_relative = false; + } } break; - case DW_AT_main_subprogram: - main_subprogram = attr.as_boolean (); - break; - case DW_AT_ranges: - { - /* Offset in the .debug_ranges or .debug_rnglist section (depending - on DWARF version). */ - ULONGEST ranges_offset = attr.as_unsigned (); - - /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add - this value. */ - if (tag != DW_TAG_compile_unit) - ranges_offset += cu->gnu_ranges_base; - - if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu, - nullptr, tag)) - has_pc_info = 1; - } + if (!scanning_per_cu->addresses_seen) + { + /* Offset in the .debug_ranges or .debug_rnglist section + (depending on DWARF version). */ + ULONGEST ranges_offset = attr.as_unsigned (); + + /* See dwarf2_cu::gnu_ranges_base's doc for why we might + want to add this value. */ + ranges_offset += reader->cu->gnu_ranges_base; + + CORE_ADDR lowpc, highpc; + dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu, + m_index_storage->get_addrmap (), + scanning_per_cu, abbrev->tag); + } break; + } + } - default: - break; + /* We don't want to examine declarations, but if we found a + declaration when handling DW_AT_specification or the like, then + that is ok. Similarly, we allow an external variable without a + location; those are resolved via minimal symbols. */ + if (is_declaration && !for_specification + && (abbrev->tag != DW_TAG_variable + || (*flags & IS_STATIC) != 0)) + { + *linkage_name = nullptr; + *name = nullptr; + } + else if ((*name == nullptr + || (*linkage_name == nullptr + && tag_can_have_linkage_name (abbrev->tag)) + || (*parent_entry == nullptr && m_language != language_c)) + && origin_offset != sect_offset (0)) + { + cutu_reader *new_reader + = ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset, + origin_is_dwz, false); + if (new_reader != nullptr) + { + const gdb_byte *new_info_ptr = (new_reader->buffer + + to_underlying (origin_offset)); + + if (new_reader->cu == reader->cu + && new_info_ptr > watermark_ptr + && maybe_defer != nullptr + && *parent_entry == nullptr) + *maybe_defer = form_addr (origin_offset, origin_is_dwz); + else if (*parent_entry == nullptr) + { + CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz); + *parent_entry + = (cooked_index_entry *) addrmap_find (m_die_range_map, + lookup); + } + + unsigned int bytes_read; + const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader, + new_info_ptr, + &bytes_read); + new_info_ptr += bytes_read; + scan_attributes (scanning_per_cu, new_reader, new_info_ptr, new_info_ptr, + new_abbrev, name, linkage_name, flags, nullptr, + parent_entry, maybe_defer, true); } } - /* For Ada, if both the name and the linkage name appear, we prefer - the latter. This lets "catch exception" work better, regardless - of the order in which the name and linkage name were emitted. - Really, though, this is just a workaround for the fact that gdb - doesn't store both the name and the linkage name. */ - if (cu->per_cu->lang == language_ada && linkage_name != nullptr) - raw_name = linkage_name; + if (!for_specification) + { + if (m_language == language_ada + && *linkage_name == nullptr) + *linkage_name = *name; + + if (!scanning_per_cu->addresses_seen + && low_pc.has_value () + && (reader->cu->per_objfile->per_bfd->has_section_at_zero + || *low_pc != 0) + && high_pc.has_value ()) + { + if (high_pc_relative) + high_pc = *high_pc + *low_pc; + + if (*high_pc > *low_pc) + { + struct objfile *objfile = reader->cu->per_objfile->objfile; + CORE_ADDR baseaddr = objfile->text_section_offset (); + struct gdbarch *gdbarch = objfile->arch (); + CORE_ADDR lo + = (gdbarch_adjust_dwarf2_addr (gdbarch, *low_pc + baseaddr) + - baseaddr); + CORE_ADDR hi + = (gdbarch_adjust_dwarf2_addr (gdbarch, *high_pc + baseaddr) + - baseaddr); + addrmap_set_empty (m_index_storage->get_addrmap (), lo, hi - 1, + scanning_per_cu); + } + } + + if (abbrev->tag == DW_TAG_module || abbrev->tag == DW_TAG_namespace) + *flags &= ~IS_STATIC; + + if (abbrev->tag == DW_TAG_namespace && *name == nullptr) + *name = "(anonymous namespace)"; + + if (m_language == language_cplus + && (abbrev->tag == DW_TAG_class_type + || abbrev->tag == DW_TAG_interface_type + || abbrev->tag == DW_TAG_structure_type + || abbrev->tag == DW_TAG_union_type + || abbrev->tag == DW_TAG_enumeration_type + || abbrev->tag == DW_TAG_enumerator)) + *flags &= ~IS_STATIC; + } + + return info_ptr; +} + +const gdb_byte * +cooked_indexer::index_imported_unit (cutu_reader *reader, + const gdb_byte *info_ptr, + const abbrev_info *abbrev) +{ + sect_offset sect_off {}; + bool is_dwz = false; + + for (int i = 0; i < abbrev->num_attrs; ++i) + { + /* Note that we never need to reprocess attributes here. */ + attribute attr; + info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr); + + if (attr.name == DW_AT_import) + { + sect_off = attr.get_ref_die_offset (); + is_dwz = (attr.form == DW_FORM_GNU_ref_alt + || reader->cu->per_cu->is_dwz); + } + } + + /* Did not find DW_AT_import. */ + if (sect_off == sect_offset (0)) + return info_ptr; + + dwarf2_per_objfile *per_objfile = reader->cu->per_objfile; + cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off, + is_dwz, true); + if (new_reader != nullptr) + { + index_dies (new_reader, new_reader->info_ptr, nullptr, false); + + reader->cu->add_dependence (new_reader->cu->per_cu); + } + + return info_ptr; +} + +const gdb_byte * +cooked_indexer::recurse (cutu_reader *reader, + const gdb_byte *info_ptr, + const cooked_index_entry *parent_entry, + bool fully) +{ + info_ptr = index_dies (reader, info_ptr, parent_entry, fully); + + if (parent_entry != nullptr) + { + CORE_ADDR start = form_addr (parent_entry->die_offset, + reader->cu->per_cu->is_dwz); + CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer), + reader->cu->per_cu->is_dwz); + addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry); + } + + return info_ptr; +} + +const gdb_byte * +cooked_indexer::index_dies (cutu_reader *reader, + const gdb_byte *info_ptr, + const cooked_index_entry *parent_entry, + bool fully) +{ + const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length (); + + while (info_ptr < end_ptr) + { + sect_offset this_die = (sect_offset) (info_ptr - reader->buffer); + unsigned int bytes_read; + const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, + &bytes_read); + info_ptr += bytes_read; + if (abbrev == nullptr) + break; + + if (abbrev->tag == DW_TAG_imported_unit) + { + info_ptr = index_imported_unit (reader, info_ptr, abbrev); + continue; + } + + if (!abbrev->interesting) + { + info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully); + if (fully && abbrev->has_children) + info_ptr = index_dies (reader, info_ptr, parent_entry, fully); + continue; + } + + const char *name = nullptr; + const char *linkage_name = nullptr; + CORE_ADDR defer = 0; + cooked_index_flag flags = IS_STATIC; + sect_offset sibling {}; + const cooked_index_entry *this_parent_entry = parent_entry; + info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr, + info_ptr, abbrev, &name, &linkage_name, + &flags, &sibling, &this_parent_entry, + &defer, false); + + if (abbrev->tag == DW_TAG_namespace + && m_language == language_cplus + && strcmp (name, "::") == 0) + { + /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they + generated bogus DW_TAG_namespace DIEs with a name of "::" + for the global namespace. Work around this problem + here. */ + name = nullptr; + } + + const cooked_index_entry *this_entry = nullptr; + if (name != nullptr) + { + if (defer != 0) + m_deferred_entries.push_back ({ + this_die, name, defer, abbrev->tag, flags + }); + else + this_entry = m_index_storage->add (this_die, abbrev->tag, flags, + name, this_parent_entry, + m_per_cu); + } + + if (linkage_name != nullptr) + { + /* We only want this to be "main" if it has a linkage name + but not an ordinary name. */ + if (name != nullptr) + flags = flags & ~IS_MAIN; + m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE, + linkage_name, nullptr, m_per_cu); + } + + if (abbrev->has_children) + { + switch (abbrev->tag) + { + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + if (m_language != language_c && this_entry != nullptr) + { + info_ptr = recurse (reader, info_ptr, this_entry, fully); + continue; + } + break; + + case DW_TAG_enumeration_type: + /* We need to recurse even for an anonymous enumeration. + Which scope we record as the parent scope depends on + whether we're reading an "enum class". If so, we use + the enum itself as the parent, yielding names like + "enum_class::enumerator"; otherwise we inject the + names into our own parent scope. */ + info_ptr = recurse (reader, info_ptr, + ((flags & IS_ENUM_CLASS) == 0) + ? parent_entry + : this_entry, + fully); + continue; - if (high_pc_relative) - highpc += lowpc; + case DW_TAG_module: + if (this_entry == nullptr) + break; + /* FALLTHROUGH */ + case DW_TAG_namespace: + /* We don't check THIS_ENTRY for a namespace, to handle + the ancient G++ workaround pointed out above. */ + info_ptr = recurse (reader, info_ptr, this_entry, fully); + continue; - if (has_low_pc_attr && has_high_pc_attr) - { - /* When using the GNU linker, .gnu.linkonce. sections are used to - eliminate duplicate copies of functions and vtables and such. - The linker will arbitrarily choose one and discard the others. - The AT_*_pc values for such functions refer to local labels in - these sections. If the section from that file was discarded, the - labels are not in the output, so the relocs get a value of 0. - If this is a discarded function, mark the pc bounds as invalid, - so that GDB will ignore it. */ - if (lowpc == 0 && !per_objfile->per_bfd->has_section_at_zero) - { - struct objfile *objfile = per_objfile->objfile; - struct gdbarch *gdbarch = objfile->arch (); + case DW_TAG_subprogram: + if ((m_language == language_fortran + || m_language == language_ada) + && this_entry != nullptr) + { + info_ptr = recurse (reader, info_ptr, this_entry, true); + continue; + } + break; + } - complaint (_("DW_AT_low_pc %s is zero " - "for DIE at %s [in module %s]"), - paddress (gdbarch, lowpc), - sect_offset_str (sect_off), - objfile_name (objfile)); - } - /* dwarf2_get_pc_bounds has also the strict low < high requirement. */ - else if (lowpc >= highpc) - { - struct objfile *objfile = per_objfile->objfile; - struct gdbarch *gdbarch = objfile->arch (); + if (sibling != sect_offset (0)) + { + const gdb_byte *sibling_ptr + = reader->buffer + to_underlying (sibling); - complaint (_("DW_AT_low_pc %s is not < DW_AT_high_pc %s " - "for DIE at %s [in module %s]"), - paddress (gdbarch, lowpc), - paddress (gdbarch, highpc), - sect_offset_str (sect_off), - objfile_name (objfile)); + if (sibling_ptr < info_ptr) + complaint (_("DW_AT_sibling points backwards")); + else if (sibling_ptr > reader->buffer_end) + reader->die_section->overflow_complaint (); + else + info_ptr = sibling_ptr; + } + else + info_ptr = skip_children (reader, info_ptr); } - else - has_pc_info = 1; } return info_ptr; } -/* Find a cached partial DIE at OFFSET in CU. */ - -struct partial_die_info * -dwarf2_cu::find_partial_die (sect_offset sect_off) +void +cooked_indexer::make_index (cutu_reader *reader) { - struct partial_die_info *lookup_die = NULL; - struct partial_die_info part_die (sect_off); - - lookup_die = ((struct partial_die_info *) - htab_find_with_hash (partial_dies, &part_die, - to_underlying (sect_off))); + check_bounds (reader); + find_file_and_directory (reader->comp_unit_die, reader->cu); + if (!reader->comp_unit_die->has_children) + return; + index_dies (reader, reader->info_ptr, nullptr, false); - return lookup_die; + for (const auto &entry : m_deferred_entries) + { + CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz); + cooked_index_entry *parent + = (cooked_index_entry *) addrmap_find (m_die_range_map, key); + m_index_storage->add (entry.die_offset, entry.tag, entry.flags, + entry.name, parent, m_per_cu); + } } -/* Find a partial DIE at OFFSET, which may or may not be in CU, - except in the case of .debug_types DIEs which do not reference - outside their CU (they do however referencing other types via - DW_FORM_ref_sig8). */ +/* An implementation of quick_symbol_functions for the cooked DWARF + index. */ -static const struct cu_partial_die_info -find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) +struct cooked_index_functions : public dwarf2_base_index_functions { - dwarf2_per_objfile *per_objfile = cu->per_objfile; - struct objfile *objfile = per_objfile->objfile; - struct partial_die_info *pd = NULL; + 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; - if (offset_in_dwz == cu->per_cu->is_dwz - && cu->header.offset_in_cu_p (sect_off)) - { - pd = cu->find_partial_die (sect_off); - if (pd != NULL) - return { cu, pd }; - /* We missed recording what we needed. - Load all dies and try again. */ - } - else - { - /* TUs don't reference other CUs/TUs (except via type signatures). */ - if (cu->per_cu->is_debug_types) - { - error (_("Dwarf Error: Type Unit at offset %s contains" - " external reference to offset %s [in module %s].\n"), - sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off), - bfd_get_filename (objfile->obfd)); - } - dwarf2_per_cu_data *per_cu - = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, - per_objfile); + struct compunit_symtab *find_compunit_symtab_by_address + (struct objfile *objfile, CORE_ADDR address) override; - cu = per_objfile->get_cu (per_cu); - if (cu == NULL || cu->partial_dies == NULL) - load_partial_comp_unit (per_cu, per_objfile, nullptr); + void dump (struct objfile *objfile) override + { + gdb_printf ("Cooked index in use\n"); + } + + void expand_matching_symbols + (struct objfile *, + const lookup_name_info &lookup_name, + domain_enum domain, + int global, + symbol_compare_ftype *ordered_compare) override; - cu = per_objfile->get_cu (per_cu); + bool expand_symtabs_matching + (struct objfile *objfile, + gdb::function_view file_matcher, + const lookup_name_info *lookup_name, + gdb::function_view symbol_matcher, + gdb::function_view expansion_notify, + block_search_flags search_flags, + domain_enum domain, + enum search_domain kind) override; - cu->last_used = 0; - pd = cu->find_partial_die (sect_off); - } + bool can_lazily_read_symbols () override + { + return true; + } - /* If we didn't find it, and not all dies have been loaded, - load them all and try again. */ + void read_partial_symbols (struct objfile *objfile) override + { + if (dwarf2_has_info (objfile, nullptr)) + dwarf2_build_psymtabs (objfile, true); + } +}; - if (pd == NULL && cu->load_all_dies == 0) - { - cu->load_all_dies = 1; +struct compunit_symtab * +cooked_index_functions::find_pc_sect_compunit_symtab + (struct objfile *objfile, + struct bound_minimal_symbol msymbol, + CORE_ADDR pc, + struct obj_section *section, + int warn_if_readin) +{ + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + if (per_objfile->per_bfd->cooked_index_table == nullptr) + return nullptr; - /* This is nasty. When we reread the DIEs, somewhere up the call chain - THIS_CU->cu may already be in use. So we can't just free it and - replace its DIEs with the ones we read in. Instead, we leave those - DIEs alone (which can still be in use, e.g. in scan_partial_symbols), - and clobber THIS_CU->cu->partial_dies with the hash table for the new - set. */ - load_partial_comp_unit (cu->per_cu, per_objfile, cu); + CORE_ADDR baseaddr = objfile->text_section_offset (); + dwarf2_per_cu_data *per_cu + = per_objfile->per_bfd->cooked_index_table->lookup (pc - baseaddr); + if (per_cu == nullptr) + return nullptr; - pd = cu->find_partial_die (sect_off); - } + if (warn_if_readin && per_objfile->symtab_set_p (per_cu)) + warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"), + paddress (objfile->arch (), pc)); - if (pd == NULL) - error (_("Dwarf Error: Cannot find DIE at %s [from module %s]\n"), - sect_offset_str (sect_off), bfd_get_filename (objfile->obfd)); - return { cu, pd }; + compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab + (dw2_instantiate_symtab (per_cu, per_objfile, + false), + pc)); + gdb_assert (result != nullptr); + return result; } -/* See if we can figure out if the class lives in a namespace. We do - this by looking for a member function; its demangled name will - contain namespace info, if there is any. */ - -static void -guess_partial_die_structure_name (struct partial_die_info *struct_pdi, - struct dwarf2_cu *cu) +struct compunit_symtab * +cooked_index_functions::find_compunit_symtab_by_address + (struct objfile *objfile, CORE_ADDR address) { - /* NOTE: carlton/2003-10-07: Getting the info this way changes - what template types look like, because the demangler - frequently doesn't give the same name as the debug info. We - could fix this by only using the demangled name to get the - prefix (but see comment in read_structure_type). */ + if (objfile->sect_index_data == -1) + return nullptr; - struct partial_die_info *real_pdi; - struct partial_die_info *child_pdi; + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + if (per_objfile->per_bfd->cooked_index_table == nullptr) + return nullptr; - /* If this DIE (this DIE's specification, if any) has a parent, then - we should not do this. We'll prepend the parent's fully qualified - name when we create the partial symbol. */ + CORE_ADDR baseaddr = objfile->data_section_offset (); + dwarf2_per_cu_data *per_cu + = per_objfile->per_bfd->cooked_index_table->lookup (address - baseaddr); + if (per_cu == nullptr) + return nullptr; - real_pdi = struct_pdi; - while (real_pdi->has_specification) - { - auto res = find_partial_die (real_pdi->spec_offset, - real_pdi->spec_is_dwz, cu); - real_pdi = res.pdi; - cu = res.cu; - } + return dw2_instantiate_symtab (per_cu, per_objfile, false); +} - if (real_pdi->die_parent != NULL) +void +cooked_index_functions::expand_matching_symbols + (struct objfile *objfile, + const lookup_name_info &lookup_name, + domain_enum domain, + int global, + symbol_compare_ftype *ordered_compare) +{ + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + if (per_objfile->per_bfd->cooked_index_table == nullptr) return; + const block_search_flags search_flags = (global + ? SEARCH_GLOBAL_BLOCK + : SEARCH_STATIC_BLOCK); + const language_defn *lang = language_def (language_ada); + symbol_name_matcher_ftype *name_match + = lang->get_symbol_name_matcher (lookup_name); - for (child_pdi = struct_pdi->die_child; - child_pdi != NULL; - child_pdi = child_pdi->die_sibling) + for (const cooked_index_entry *entry + : per_objfile->per_bfd->cooked_index_table->all_entries ()) { - if (child_pdi->tag == DW_TAG_subprogram - && child_pdi->linkage_name != NULL) - { - gdb::unique_xmalloc_ptr actual_class_name - (cu->language_defn->class_name_from_physname - (child_pdi->linkage_name)); - if (actual_class_name != NULL) - { - struct objfile *objfile = cu->per_objfile->objfile; - struct_pdi->raw_name = objfile->intern (actual_class_name.get ()); - struct_pdi->canonical_name = 1; - } - break; - } - } -} + if (entry->parent_entry != nullptr) + continue; -/* Return true if a DIE with TAG may have the DW_AT_const_value - attribute. */ + if (!entry->matches (search_flags) + || !entry->matches (domain)) + continue; -static bool -can_have_DW_AT_const_value_p (enum dwarf_tag tag) -{ - switch (tag) - { - case DW_TAG_constant: - case DW_TAG_enumerator: - case DW_TAG_formal_parameter: - case DW_TAG_template_value_param: - case DW_TAG_variable: - return true; + if (name_match (entry->canonical, lookup_name, nullptr)) + dw2_instantiate_symtab (entry->per_cu, per_objfile, false); } - - return false; } -void -partial_die_info::fixup (struct dwarf2_cu *cu) +bool +cooked_index_functions::expand_symtabs_matching + (struct objfile *objfile, + gdb::function_view file_matcher, + const lookup_name_info *lookup_name, + gdb::function_view symbol_matcher, + gdb::function_view expansion_notify, + block_search_flags search_flags, + domain_enum domain, + enum search_domain kind) { - /* Once we've fixed up a die, there's no point in doing so again. - This also avoids a memory leak if we were to call - guess_partial_die_structure_name multiple times. */ - if (fixup_called) - return; + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + if (per_objfile->per_bfd->cooked_index_table == nullptr) + return true; - /* If we found a reference attribute and the DIE has no name, try - to find a name in the referred to DIE. */ + dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher); - if (raw_name == NULL && has_specification) + /* This invariant is documented in quick-functions.h. */ + gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); + if (lookup_name == nullptr) { - struct partial_die_info *spec_die; - - auto res = find_partial_die (spec_offset, spec_is_dwz, cu); - spec_die = res.pdi; - cu = res.cu; - - spec_die->fixup (cu); - - if (spec_die->raw_name) + for (dwarf2_per_cu_data *per_cu + : all_comp_units_range (per_objfile->per_bfd)) { - raw_name = spec_die->raw_name; - canonical_name = spec_die->canonical_name; + QUIT; - /* Copy DW_AT_external attribute if it is set. */ - if (spec_die->is_external) - is_external = spec_die->is_external; + if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, + file_matcher, + expansion_notify)) + return false; } + return true; } - if (!has_const_value && has_specification - && can_have_DW_AT_const_value_p (tag)) - { - struct partial_die_info *spec_die; + lookup_name_info lookup_name_without_params + = lookup_name->make_ignore_params (); + bool completing = lookup_name->completion_mode (); - auto res = find_partial_die (spec_offset, spec_is_dwz, cu); - spec_die = res.pdi; - cu = res.cu; + /* Unique styles of language splitting. */ + static const enum language unique_styles[] = + { + /* No splitting is also a style. */ + language_c, + /* This includes Rust. */ + language_cplus, + /* This includes Go. */ + language_d, + language_ada + }; - spec_die->fixup (cu); + for (enum language lang : unique_styles) + { + std::vector name_vec + = lookup_name_without_params.split_name (lang); - if (spec_die->has_const_value) + for (const cooked_index_entry *entry + : per_objfile->per_bfd->cooked_index_table->find (name_vec.back (), + completing)) { - /* Copy DW_AT_const_value attribute if it is set. */ - has_const_value = spec_die->has_const_value; - } - } + /* No need to consider symbols from expanded CUs. */ + if (per_objfile->symtab_set_p (entry->per_cu)) + continue; - /* Set default names for some unnamed DIEs. */ + /* If file-matching was done, we don't need to consider + symbols from unmarked CUs. */ + if (file_matcher != nullptr && !entry->per_cu->mark) + continue; - if (raw_name == NULL && tag == DW_TAG_namespace) - { - raw_name = CP_ANONYMOUS_NAMESPACE_STR; - canonical_name = 1; - } + /* See if the symbol matches the type filter. */ + if (!entry->matches (search_flags) + || !entry->matches (domain) + || !entry->matches (kind)) + continue; - /* If there is no parent die to provide a namespace, and there are - children, see if we can determine the namespace from their linkage - name. */ - if (cu->per_cu->lang == language_cplus - && !cu->per_objfile->per_bfd->types.empty () - && die_parent == NULL - && has_children - && (tag == DW_TAG_class_type - || tag == DW_TAG_structure_type - || tag == DW_TAG_union_type)) - guess_partial_die_structure_name (this, cu); - - /* GCC might emit a nameless struct or union that has a linkage - name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */ - if (raw_name == NULL - && (tag == DW_TAG_class_type - || tag == DW_TAG_interface_type - || tag == DW_TAG_structure_type - || tag == DW_TAG_union_type) - && linkage_name != NULL) - { - gdb::unique_xmalloc_ptr demangled - (gdb_demangle (linkage_name, DMGL_TYPES)); - if (demangled != nullptr) - { - const char *base; - - /* Strip any leading namespaces/classes, keep only the base name. - DW_AT_name for named DIEs does not contain the prefixes. */ - base = strrchr (demangled.get (), ':'); - if (base && base > demangled.get () && base[-1] == ':') - base++; + /* We've found the base name of the symbol; now walk its + parentage chain, ensuring that each component + matches. */ + bool found = true; + + const cooked_index_entry *parent = entry->parent_entry; + for (int i = name_vec.size () - 1; i > 0; --i) + { + /* If we ran out of entries, or if this segment doesn't + match, this did not match. */ + if (parent == nullptr + || strncmp (parent->name, name_vec[i - 1].data (), + name_vec[i - 1].length ()) != 0) + { + found = false; + break; + } + + parent = parent->parent_entry; + } + + if (!found) + continue; + + /* Might have been looking for "a::b" and found + "x::a::b". */ + if (symbol_matcher == nullptr) + { + symbol_name_match_type match_type + = lookup_name_without_params.match_type (); + if ((match_type == symbol_name_match_type::FULL + || (lang != language_ada + && match_type == symbol_name_match_type::EXPRESSION)) + && parent != nullptr) + continue; + } else - base = demangled.get (); + { + auto_obstack temp_storage; + const char *full_name = entry->full_name (&temp_storage); + if (!symbol_matcher (full_name)) + continue; + } - struct objfile *objfile = cu->per_objfile->objfile; - raw_name = objfile->intern (base); - canonical_name = 1; + if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile, + file_matcher, + expansion_notify)) + return false; } } - fixup_called = 1; + return true; +} + +/* Return a new cooked_index_functions object. */ + +static quick_symbol_functions_up +make_cooked_index_funcs () +{ + return quick_symbol_functions_up (new cooked_index_functions); } + + /* Read the .debug_loclists or .debug_rnglists header (they are the same format) contents from the given SECTION in the HEADER. @@ -19846,7 +18967,7 @@ read_attribute_reprocess (const struct die_reader_specs *reader, break; } default: - gdb_assert_not_reached (_("Unexpected DWARF form.")); + gdb_assert_not_reached ("Unexpected DWARF form."); } } @@ -20171,6 +19292,18 @@ read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *abfd, /* See read.h. */ +const char * +dwarf2_per_objfile::read_line_string (const gdb_byte *buf, + unsigned int offset_size) +{ + bfd *abfd = objfile->obfd; + ULONGEST str_offset = read_offset (abfd, buf, offset_size); + + return per_bfd->line_str.read_string (objfile, str_offset, "DW_FORM_line_strp"); +} + +/* See read.h. */ + const char * dwarf2_per_objfile::read_line_string (const gdb_byte *buf, const struct comp_unit_head *cu_header, @@ -20602,30 +19735,28 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu) } /* Subroutine of dwarf_decode_lines to simplify it. - Return the file name of the psymtab for the given file_entry. - COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. + Return the file name for the given file_entry. + CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir. If space for the result is malloc'd, *NAME_HOLDER will be set. - Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */ + Returns NULL if FILE_INDEX should be ignored, i.e., it is + equivalent to CU_INFO. */ static const char * -psymtab_include_file_name (const struct line_header *lh, const file_entry &fe, - const dwarf2_psymtab *pst, - const char *comp_dir, +compute_include_file_name (const struct line_header *lh, const file_entry &fe, + const file_and_directory &cu_info, gdb::unique_xmalloc_ptr *name_holder) { const char *include_name = fe.name; const char *include_name_to_compare = include_name; - const char *pst_filename; - int file_is_pst; const char *dir_name = fe.include_dir (lh); gdb::unique_xmalloc_ptr hold_compare; if (!IS_ABSOLUTE_PATH (include_name) - && (dir_name != NULL || comp_dir != NULL)) + && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr)) { - /* Avoid creating a duplicate psymtab for PST. - We do this by comparing INCLUDE_NAME and PST_FILENAME. + /* Avoid creating a duplicate name for CU_INFO. + We do this by comparing INCLUDE_NAME and CU_INFO. Before we do the comparison, however, we need to account for DIR_NAME and COMP_DIR. First prepend dir_name (if non-NULL). If we still don't @@ -20652,27 +19783,26 @@ psymtab_include_file_name (const struct line_header *lh, const file_entry &fe, include_name = name_holder->get (); include_name_to_compare = include_name; } - if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL) + if (!IS_ABSOLUTE_PATH (include_name) + && cu_info.get_comp_dir () != nullptr) { - hold_compare.reset (concat (comp_dir, SLASH_STRING, + hold_compare.reset (concat (cu_info.get_comp_dir (), SLASH_STRING, include_name, (char *) NULL)); include_name_to_compare = hold_compare.get (); } } - pst_filename = pst->filename; gdb::unique_xmalloc_ptr copied_name; - if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL) + const char *cu_filename = cu_info.get_name (); + if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr) { - copied_name.reset (concat (pst->dirname, SLASH_STRING, - pst_filename, (char *) NULL)); - pst_filename = copied_name.get (); + copied_name.reset (concat (cu_info.get_comp_dir (), SLASH_STRING, + cu_filename, (char *) NULL)); + cu_filename = copied_name.get (); } - file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0; - - if (file_is_pst) - return NULL; + if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0) + return nullptr; return include_name; } @@ -20683,8 +19813,7 @@ class lnp_state_machine public: /* Initialize a machine state for the start of a line number program. */ - lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh, - bool record_lines_p); + lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh); file_entry *current_file () { @@ -20735,7 +19864,7 @@ public: /* Handle DW_LNS_negate_stmt. */ void handle_negate_stmt () { - m_is_stmt = !m_is_stmt; + m_flags ^= LEF_IS_STMT; } /* Handle DW_LNS_const_add_pc. */ @@ -20753,6 +19882,7 @@ public: { record_line (false); m_discriminator = 0; + m_flags &= ~LEF_PROLOGUE_END; } /* Handle DW_LNE_end_sequence. */ @@ -20761,6 +19891,12 @@ public: m_currently_recording_lines = true; } + /* Handle DW_LNS_set_prologue_end. */ + void handle_set_prologue_end () + { + m_flags |= LEF_PROLOGUE_END; + } + private: /* Advance the line by LINE_DELTA. */ void advance_line (int line_delta) @@ -20775,11 +19911,6 @@ private: gdbarch *m_gdbarch; - /* True if we're recording lines. - Otherwise we're building partial symtabs and are just interested in - finding include files mentioned by the line number program. */ - bool m_record_lines_p; - /* The line number header. */ line_header *m_line_header; @@ -20794,7 +19925,7 @@ private: /* These are initialized in the constructor. */ CORE_ADDR m_address; - bool m_is_stmt; + linetable_entry_flags m_flags; unsigned int m_discriminator; /* Additional bits of state we need to track. */ @@ -20809,9 +19940,9 @@ private: CORE_ADDR m_last_address; /* Set to true when a previous line at the same address (using - m_last_address) had m_is_stmt true. This is reset to false when a - line entry at a new address (m_address different to m_last_address) is - processed. */ + m_last_address) had LEF_IS_STMT set in m_flags. This is reset to false + when a line entry at a new address (m_address different to + m_last_address) is processed. */ bool m_stmt_at_address = false; /* When true, record the lines we decode. */ @@ -20852,6 +19983,7 @@ lnp_state_machine::handle_special_opcode (unsigned char op_code) advance_line (line_delta); record_line (false); m_discriminator = 0; + m_flags &= ~LEF_PROLOGUE_END; } void @@ -20862,7 +19994,7 @@ lnp_state_machine::handle_set_file (file_name_index file) const file_entry *fe = current_file (); if (fe == NULL) dwarf2_debug_line_missing_file_complaint (); - else if (m_record_lines_p) + else { const char *dir = fe->include_dir (m_line_header); @@ -20941,21 +20073,22 @@ dwarf_record_line_p (struct dwarf2_cu *cu, static void dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile, - unsigned int line, CORE_ADDR address, bool is_stmt, + unsigned int line, CORE_ADDR address, + linetable_entry_flags flags, struct dwarf2_cu *cu) { CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address); if (dwarf_line_debug) { - fprintf_unfiltered (gdb_stdlog, - "Recording line %u, file %s, address %s\n", - line, lbasename (subfile->name), - paddress (gdbarch, address)); + gdb_printf (gdb_stdlog, + "Recording line %u, file %s, address %s\n", + line, lbasename (subfile->name), + paddress (gdbarch, address)); } if (cu != nullptr) - cu->get_builder ()->record_line (subfile, line, addr, is_stmt); + cu->get_builder ()->record_line (subfile, line, addr, flags); } /* Subroutine of dwarf_decode_lines_1 to simplify it. @@ -20972,13 +20105,13 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile, if (dwarf_line_debug) { - fprintf_unfiltered (gdb_stdlog, - "Finishing current line, file %s, address %s\n", - lbasename (subfile->name), - paddress (gdbarch, address)); + gdb_printf (gdb_stdlog, + "Finishing current line, file %s, address %s\n", + lbasename (subfile->name), + paddress (gdbarch, address)); } - dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu); + dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu); } void @@ -20986,13 +20119,15 @@ lnp_state_machine::record_line (bool end_sequence) { if (dwarf_line_debug) { - fprintf_unfiltered (gdb_stdlog, - "Processing actual line %u: file %u," - " address %s, is_stmt %u, discrim %u%s\n", - m_line, m_file, - paddress (m_gdbarch, m_address), - m_is_stmt, m_discriminator, - (end_sequence ? "\t(end sequence)" : "")); + gdb_printf (gdb_stdlog, + "Processing actual line %u: file %u," + " address %s, is_stmt %u, prologue_end %u, discrim %u%s\n", + m_line, m_file, + paddress (m_gdbarch, m_address), + (m_flags & LEF_IS_STMT) != 0, + (m_flags & LEF_PROLOGUE_END) != 0, + m_discriminator, + (end_sequence ? "\t(end sequence)" : "")); } file_entry *fe = current_file (); @@ -21004,73 +20139,71 @@ lnp_state_machine::record_line (bool end_sequence) previous version of the code. */ else if (m_op_index == 0 || end_sequence) { - fe->included_p = true; - if (m_record_lines_p) - { - /* When we switch files we insert an end maker in the first file, - switch to the second file and add a new line entry. The - problem is that the end marker inserted in the first file will - discard any previous line entries at the same address. If the - line entries in the first file are marked as is-stmt, while - the new line in the second file is non-stmt, then this means - the end marker will discard is-stmt lines so we can have a - non-stmt line. This means that there are less addresses at - which the user can insert a breakpoint. - - To improve this we track the last address in m_last_address, - and whether we have seen an is-stmt at this address. Then - when switching files, if we have seen a stmt at the current - address, and we are switching to create a non-stmt line, then - discard the new line. */ - bool file_changed - = m_last_subfile != m_cu->get_builder ()->get_current_subfile (); - bool ignore_this_line - = ((file_changed && !end_sequence && m_last_address == m_address - && !m_is_stmt && m_stmt_at_address) - || (!end_sequence && m_line == 0)); - - if ((file_changed && !ignore_this_line) || end_sequence) - { - dwarf_finish_line (m_gdbarch, m_last_subfile, m_address, - m_currently_recording_lines ? m_cu : nullptr); - } - - if (!end_sequence && !ignore_this_line) + /* When we switch files we insert an end maker in the first file, + switch to the second file and add a new line entry. The + problem is that the end marker inserted in the first file will + discard any previous line entries at the same address. If the + line entries in the first file are marked as is-stmt, while + the new line in the second file is non-stmt, then this means + the end marker will discard is-stmt lines so we can have a + non-stmt line. This means that there are less addresses at + which the user can insert a breakpoint. + + To improve this we track the last address in m_last_address, + and whether we have seen an is-stmt at this address. Then + when switching files, if we have seen a stmt at the current + address, and we are switching to create a non-stmt line, then + discard the new line. */ + bool file_changed + = m_last_subfile != m_cu->get_builder ()->get_current_subfile (); + bool ignore_this_line + = ((file_changed && !end_sequence && m_last_address == m_address + && ((m_flags & LEF_IS_STMT) == 0) + && m_stmt_at_address) + || (!end_sequence && m_line == 0)); + + if ((file_changed && !ignore_this_line) || end_sequence) + { + dwarf_finish_line (m_gdbarch, m_last_subfile, m_address, + m_currently_recording_lines ? m_cu : nullptr); + } + + if (!end_sequence && !ignore_this_line) + { + linetable_entry_flags lte_flags = m_flags; + if (producer_is_codewarrior (m_cu)) + lte_flags |= LEF_IS_STMT; + + if (dwarf_record_line_p (m_cu, m_line, m_last_line, + m_line_has_non_zero_discriminator, + m_last_subfile)) { - bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt; - - if (dwarf_record_line_p (m_cu, m_line, m_last_line, - m_line_has_non_zero_discriminator, - m_last_subfile)) - { - buildsym_compunit *builder = m_cu->get_builder (); - dwarf_record_line_1 (m_gdbarch, - builder->get_current_subfile (), - m_line, m_address, is_stmt, - m_currently_recording_lines ? m_cu : nullptr); - } - m_last_subfile = m_cu->get_builder ()->get_current_subfile (); - m_last_line = m_line; + buildsym_compunit *builder = m_cu->get_builder (); + dwarf_record_line_1 (m_gdbarch, + builder->get_current_subfile (), + m_line, m_address, lte_flags, + m_currently_recording_lines ? m_cu : nullptr); } + m_last_subfile = m_cu->get_builder ()->get_current_subfile (); + m_last_line = m_line; } } - /* Track whether we have seen any m_is_stmt true at m_address in case we + /* Track whether we have seen any IS_STMT true at m_address in case we have multiple line table entries all at m_address. */ if (m_last_address != m_address) { m_stmt_at_address = false; m_last_address = m_address; } - m_stmt_at_address |= m_is_stmt; + m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0; } lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, - line_header *lh, bool record_lines_p) + line_header *lh) { m_cu = cu; m_gdbarch = arch; - m_record_lines_p = record_lines_p; m_line_header = lh; m_currently_recording_lines = true; @@ -21080,7 +20213,9 @@ lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, and also record it in case it needs it. This is currently used by MIPS code, cf. `mips_adjust_dwarf2_line'. */ m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0); - m_is_stmt = lh->default_is_stmt; + m_flags = 0; + if (lh->default_is_stmt) + m_flags |= LEF_IS_STMT; m_discriminator = 0; m_last_address = m_address; @@ -21115,13 +20250,11 @@ lnp_state_machine::check_line_address (struct dwarf2_cu *cu, } /* Subroutine of dwarf_decode_lines to simplify it. - Process the line number information in LH. - If DECODE_FOR_PST_P is non-zero, all we do is process the line number - program in order to set included_p for every referenced header. */ + Process the line number information in LH. */ static void dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, - const int decode_for_pst_p, CORE_ADDR lowpc) + CORE_ADDR lowpc) { const gdb_byte *line_ptr, *extended_end; const gdb_byte *line_end; @@ -21131,10 +20264,6 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, struct objfile *objfile = cu->per_objfile->objfile; bfd *abfd = objfile->obfd; struct gdbarch *gdbarch = objfile->arch (); - /* True if we're recording line info (as opposed to building partial - symtabs and just interested in finding include files mentioned by - the line number program). */ - bool record_lines_p = !decode_for_pst_p; baseaddr = objfile->text_section_offset (); @@ -21146,18 +20275,15 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, { /* The DWARF line number program state machine. Reset the state machine at the start of each sequence. */ - lnp_state_machine state_machine (cu, gdbarch, lh, record_lines_p); + lnp_state_machine state_machine (cu, gdbarch, lh); bool end_sequence = false; - if (record_lines_p) - { - /* Start a subfile for the current file of the state - machine. */ - const file_entry *fe = state_machine.current_file (); + /* Start a subfile for the current file of the state + machine. */ + const file_entry *fe = state_machine.current_file (); - if (fe != NULL) - dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh)); - } + if (fe != NULL) + dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh)); /* Decode the table. */ while (line_ptr < line_end && !end_sequence) @@ -21308,6 +20434,9 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, state_machine.handle_fixed_advance_pc (addr_adj); } break; + case DW_LNS_set_prologue_end: + state_machine.handle_set_prologue_end (); + break; default: { /* Unknown standard opcode, ignore it. */ @@ -21335,23 +20464,15 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, structure and CU. The actual information extracted and the type of structures created from the LNP depends on the value of PST. - 1. If PST is NULL, then this procedure uses the data from the program - to create all necessary symbol tables, and their linetables. - - 2. If PST is not NULL, this procedure reads the program to determine - the list of files included by the unit represented by PST, and - builds all the associated partial symbol tables. - - COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. + FND holds the CU file name and directory, if known. It is used for relative paths in the line table. - NOTE: When processing partial symtabs (pst != NULL), - comp_dir == pst->dirname. - NOTE: It is important that psymtabs have the same file name (via strcmp) - as the corresponding symtab. Since COMP_DIR is not used in the name of the - symtab we don't use it in the name of the psymtabs we create. - E.g. expand_line_sal requires this when finding psymtabs to expand. - A good testcase for this is mb-inline.exp. + NOTE: It is important that psymtabs have the same file name (via + strcmp) as the corresponding symtab. Since the directory is not + used in the name of the symtab we don't use it in the name of the + psymtabs we create. E.g. expand_line_sal requires this when + finding psymtabs to expand. A good testcase for this is + mb-inline.exp. LOWPC is the lowest address in CU (or 0 if not known). @@ -21360,53 +20481,28 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, table is read in. */ static void -dwarf_decode_lines (struct line_header *lh, const char *comp_dir, - struct dwarf2_cu *cu, dwarf2_psymtab *pst, +dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu, CORE_ADDR lowpc, int decode_mapping) { - struct objfile *objfile = cu->per_objfile->objfile; - const int decode_for_pst_p = (pst != NULL); - if (decode_mapping) - dwarf_decode_lines_1 (lh, cu, decode_for_pst_p, lowpc); + dwarf_decode_lines_1 (lh, cu, lowpc); - if (decode_for_pst_p) - { - /* Now that we're done scanning the Line Header Program, we can - create the psymtab of each included file. */ - for (auto &file_entry : lh->file_names ()) - if (file_entry.included_p) - { - gdb::unique_xmalloc_ptr name_holder; - const char *include_name = - psymtab_include_file_name (lh, file_entry, pst, - comp_dir, &name_holder); - if (include_name != NULL) - dwarf2_create_include_psymtab - (cu->per_objfile->per_bfd, include_name, pst, - cu->per_objfile->per_bfd->partial_symtabs.get (), - objfile->per_bfd); - } - } - else - { - /* Make sure a symtab is created for every file, even files - which contain only variables (i.e. no code with associated - line numbers). */ - buildsym_compunit *builder = cu->get_builder (); - struct compunit_symtab *cust = builder->get_compunit_symtab (); + /* Make sure a symtab is created for every file, even files + which contain only variables (i.e. no code with associated + line numbers). */ + buildsym_compunit *builder = cu->get_builder (); + struct compunit_symtab *cust = builder->get_compunit_symtab (); - for (auto &fe : lh->file_names ()) + for (auto &fe : lh->file_names ()) + { + dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh)); + if (builder->get_current_subfile ()->symtab == NULL) { - dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh)); - if (builder->get_current_subfile ()->symtab == NULL) - { - builder->get_current_subfile ()->symtab - = allocate_symtab (cust, - builder->get_current_subfile ()->name); - } - fe.symtab = builder->get_current_subfile ()->symtab; + builder->get_current_subfile ()->symtab + = allocate_symtab (cust, + builder->get_current_subfile ()->name); } + fe.symtab = builder->get_current_subfile ()->symtab; } } @@ -21476,7 +20572,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym, variable has been optimized away. */ if (attr->form_is_block () && attr->as_block ()->size == 0) { - SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT; + sym->set_aclass_index (LOC_OPTIMIZED_OUT); return; } @@ -21499,19 +20595,16 @@ var_decode_location (struct attribute *attr, struct symbol *sym, unsigned int dummy; if (block->data[0] == DW_OP_addr) - SET_SYMBOL_VALUE_ADDRESS - (sym, cu->header.read_address (objfile->obfd, - block->data + 1, - &dummy)); + sym->set_value_address + (cu->header.read_address (objfile->obfd, block->data + 1, + &dummy)); else - SET_SYMBOL_VALUE_ADDRESS - (sym, read_addr_index_from_leb128 (cu, block->data + 1, - &dummy)); - SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC; + sym->set_value_address + (read_addr_index_from_leb128 (cu, block->data + 1, &dummy)); + sym->set_aclass_index (LOC_STATIC); fixup_symbol_section (sym, objfile); - SET_SYMBOL_VALUE_ADDRESS - (sym, - SYMBOL_VALUE_ADDRESS (sym) + sym->set_value_address + (sym->value_address () + objfile->section_offsets[sym->section_index ()]); return; } @@ -21585,19 +20678,24 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, sym->set_linkage_name (linkagename); } + /* Handle DW_AT_artificial. */ + attr = dwarf2_attr (die, DW_AT_artificial, cu); + if (attr != nullptr) + sym->artificial = attr->as_boolean (); + /* Default assumptions. Use the passed type or decode it from the die. */ - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT; + sym->set_domain (VAR_DOMAIN); + sym->set_aclass_index (LOC_OPTIMIZED_OUT); if (type != NULL) - SYMBOL_TYPE (sym) = type; + sym->set_type (type); else - SYMBOL_TYPE (sym) = die_type (die, cu); + sym->set_type (die_type (die, cu)); attr = dwarf2_attr (die, inlined_func ? DW_AT_call_line : DW_AT_decl_line, cu); if (attr != nullptr) - SYMBOL_LINE (sym) = attr->constant_value (0); + sym->set_line (attr->constant_value (0)); attr = dwarf2_attr (die, inlined_func ? DW_AT_call_file : DW_AT_decl_file, @@ -21629,19 +20727,19 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, addr = attr->as_address (); addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr); - SET_SYMBOL_VALUE_ADDRESS (sym, addr); - SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL; + sym->set_value_address (addr); + sym->set_aclass_index (LOC_LABEL); } else - SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT; - SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr; - SYMBOL_DOMAIN (sym) = LABEL_DOMAIN; + sym->set_aclass_index (LOC_OPTIMIZED_OUT); + sym->set_type (objfile_type (objfile)->builtin_core_addr); + sym->set_domain (LABEL_DOMAIN); add_symbol_to_list (sym, cu->list_in_scope); break; case DW_TAG_subprogram: /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by finish_block. */ - SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK; + sym->set_aclass_index (LOC_BLOCK); attr2 = dwarf2_attr (die, DW_AT_external, cu); if ((attr2 != nullptr && attr2->as_boolean ()) || cu->per_cu->lang == language_ada @@ -21663,8 +20761,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, case DW_TAG_inlined_subroutine: /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by finish_block. */ - SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK; - SYMBOL_INLINED (sym) = 1; + sym->set_aclass_index (LOC_BLOCK); + sym->set_is_inlined (1); list_to_add = cu->list_in_scope; break; case DW_TAG_template_value_param: @@ -21676,8 +20774,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* Compilation with minimal debug info may result in variables with missing type entries. Change the misleading `void' type to something sensible. */ - if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID) - SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int; + if (sym->type ()->code () == TYPE_CODE_VOID) + sym->set_type (objfile_type (objfile)->builtin_int); attr = dwarf2_attr (die, DW_AT_const_value, cu); /* In the case of DW_TAG_member, we should only be called for @@ -21714,8 +20812,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, && die->parent->tag == DW_TAG_common_block) attr2 = NULL; - if (SYMBOL_CLASS (sym) == LOC_STATIC - && SYMBOL_VALUE_ADDRESS (sym) == 0 + if (sym->aclass () == LOC_STATIC + && sym->value_address () == 0 && !per_objfile->per_bfd->has_section_at_zero) { /* When a static variable is eliminated by the linker, @@ -21725,7 +20823,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, } else if (attr2 != nullptr && attr2->as_boolean ()) { - if (SYMBOL_CLASS (sym) == LOC_STATIC + if (sym->aclass () == LOC_STATIC && (objfile->flags & OBJF_MAINLINE) == 0 && per_objfile->per_bfd->can_copy) { @@ -21783,12 +20881,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, ? cu->get_builder ()->get_global_symbols () : cu->list_in_scope); - SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED; + sym->set_aclass_index (LOC_UNRESOLVED); } else if (!die_is_declaration (die, cu)) { /* Use the default LOC_OPTIMIZED_OUT class. */ - gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT); + gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT); if (!suppress_add) list_to_add = cu->list_in_scope; } @@ -21804,7 +20902,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, struct context_stack *curr = cu->get_builder ()->get_current_context_stack (); if (curr != nullptr && curr->name != nullptr) - SYMBOL_IS_ARGUMENT (sym) = 1; + sym->set_is_argument (1); attr = dwarf2_attr (die, DW_AT_location, cu); if (attr != nullptr) { @@ -21833,9 +20931,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, case DW_TAG_union_type: case DW_TAG_set_type: case DW_TAG_enumeration_type: - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; - + case DW_TAG_namelist: + if (die->tag == DW_TAG_namelist) + { + sym->set_aclass_index (LOC_STATIC); + sym->set_domain (VAR_DOMAIN); + } + else + { + sym->set_aclass_index (LOC_TYPEDEF); + sym->set_domain (STRUCT_DOMAIN); + } { /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't really ever be static objects: otherwise, if you try @@ -21864,22 +20970,23 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, /* The symbol's name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ - if (SYMBOL_TYPE (sym)->name () == 0) - SYMBOL_TYPE (sym)->set_name (sym->search_name ()); + if (sym->type ()->name () == 0) + sym->type ()->set_name (sym->search_name ()); } } } break; case DW_TAG_typedef: - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + sym->set_aclass_index (LOC_TYPEDEF); + sym->set_domain (VAR_DOMAIN); list_to_add = cu->list_in_scope; break; case DW_TAG_array_type: case DW_TAG_base_type: case DW_TAG_subrange_type: - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + case DW_TAG_generic_subrange: + sym->set_aclass_index (LOC_TYPEDEF); + sym->set_domain (VAR_DOMAIN); list_to_add = cu->list_in_scope; break; case DW_TAG_enumerator: @@ -21901,17 +21008,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, break; case DW_TAG_imported_declaration: case DW_TAG_namespace: - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; + sym->set_aclass_index (LOC_TYPEDEF); list_to_add = cu->get_builder ()->get_global_symbols (); break; case DW_TAG_module: - SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF; - SYMBOL_DOMAIN (sym) = MODULE_DOMAIN; + sym->set_aclass_index (LOC_TYPEDEF); + sym->set_domain (MODULE_DOMAIN); list_to_add = cu->get_builder ()->get_global_symbols (); break; case DW_TAG_common_block: - SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK; - SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN; + sym->set_aclass_index (LOC_COMMON_BLOCK); + sym->set_domain (COMMON_BLOCK_DOMAIN); add_symbol_to_list (sym, cu->list_in_scope); break; default: @@ -22100,7 +21207,7 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym, const gdb_byte *bytes; struct dwarf2_locexpr_baton *baton; - dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym), + dwarf2_const_value_attr (attr, sym->type (), sym->print_name (), &objfile->objfile_obstack, cu, &value, &bytes, &baton); @@ -22108,17 +21215,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym, if (baton != NULL) { SYMBOL_LOCATION_BATON (sym) = baton; - SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index; + sym->set_aclass_index (dwarf2_locexpr_index); } else if (bytes != NULL) - { - SYMBOL_VALUE_BYTES (sym) = bytes; - SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES; + { + sym->set_value_bytes (bytes); + sym->set_aclass_index (LOC_CONST_BYTES); } else { - SYMBOL_VALUE (sym) = value; - SYMBOL_ACLASS_INDEX (sym) = LOC_CONST; + sym->set_value_longest (value); + sym->set_aclass_index (LOC_CONST); } } @@ -22244,7 +21351,8 @@ lookup_die_type (struct die_info *die, const struct attribute *attr, struct dwarf2_per_cu_data *per_cu; sect_offset sect_off = attr->get_ref_die_offset (); - per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile); + per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, + per_objfile->per_bfd); this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile); } else if (attr->form_is_ref ()) @@ -22370,6 +21478,7 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_typedef: this_type = read_typedef (die, cu); break; + case DW_TAG_generic_subrange: case DW_TAG_subrange_type: this_type = read_subrange_type (die, cu); break; @@ -22771,6 +21880,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) && die->tag != DW_TAG_class_type && die->tag != DW_TAG_interface_type && die->tag != DW_TAG_structure_type + && die->tag != DW_TAG_namelist && die->tag != DW_TAG_union_type) return NULL; @@ -22795,6 +21905,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_interface_type: case DW_TAG_structure_type: case DW_TAG_union_type: + case DW_TAG_namelist: /* Some GCC versions emit spurious DW_AT_name attributes for unnamed structures or unions. These were of the form "._%d" in GCC 4.1, or simply "" or "" in GCC 4.3 @@ -22868,85 +21979,82 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) { unsigned int i; - print_spaces (indent, f); - fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n", - dwarf_tag_name (die->tag), die->abbrev, - sect_offset_str (die->sect_off)); + gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n", + indent, "", + dwarf_tag_name (die->tag), die->abbrev, + sect_offset_str (die->sect_off)); if (die->parent != NULL) - { - print_spaces (indent, f); - fprintf_unfiltered (f, " parent at offset: %s\n", - sect_offset_str (die->parent->sect_off)); - } + gdb_printf (f, "%*s parent at offset: %s\n", + indent, "", + sect_offset_str (die->parent->sect_off)); - print_spaces (indent, f); - fprintf_unfiltered (f, " has children: %s\n", - dwarf_bool_name (die->child != NULL)); + gdb_printf (f, "%*s has children: %s\n", + indent, "", + dwarf_bool_name (die->child != NULL)); - print_spaces (indent, f); - fprintf_unfiltered (f, " attributes:\n"); + gdb_printf (f, "%*s attributes:\n", indent, ""); for (i = 0; i < die->num_attrs; ++i) { - print_spaces (indent, f); - fprintf_unfiltered (f, " %s (%s) ", - dwarf_attr_name (die->attrs[i].name), - dwarf_form_name (die->attrs[i].form)); + gdb_printf (f, "%*s %s (%s) ", + indent, "", + dwarf_attr_name (die->attrs[i].name), + dwarf_form_name (die->attrs[i].form)); switch (die->attrs[i].form) { case DW_FORM_addr: case DW_FORM_addrx: case DW_FORM_GNU_addr_index: - fprintf_unfiltered (f, "address: "); - fputs_filtered (hex_string (die->attrs[i].as_address ()), f); + gdb_printf (f, "address: "); + gdb_puts (hex_string (die->attrs[i].as_address ()), f); break; case DW_FORM_block2: case DW_FORM_block4: case DW_FORM_block: case DW_FORM_block1: - fprintf_unfiltered (f, "block: size %s", - pulongest (die->attrs[i].as_block ()->size)); + gdb_printf (f, "block: size %s", + pulongest (die->attrs[i].as_block ()->size)); break; case DW_FORM_exprloc: - fprintf_unfiltered (f, "expression: size %s", - pulongest (die->attrs[i].as_block ()->size)); + gdb_printf (f, "expression: size %s", + pulongest (die->attrs[i].as_block ()->size)); break; case DW_FORM_data16: - fprintf_unfiltered (f, "constant of 16 bytes"); + gdb_printf (f, "constant of 16 bytes"); break; case DW_FORM_ref_addr: - fprintf_unfiltered (f, "ref address: "); - fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f); + gdb_printf (f, "ref address: "); + gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); break; case DW_FORM_GNU_ref_alt: - fprintf_unfiltered (f, "alt ref address: "); - fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f); + gdb_printf (f, "alt ref address: "); + gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); break; case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)", - (long) (die->attrs[i].as_unsigned ())); + gdb_printf (f, "constant ref: 0x%lx (adjusted)", + (long) (die->attrs[i].as_unsigned ())); break; case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: - fprintf_unfiltered (f, "constant: %s", - pulongest (die->attrs[i].as_unsigned ())); + gdb_printf (f, "constant: %s", + pulongest (die->attrs[i].as_unsigned ())); break; case DW_FORM_sec_offset: - fprintf_unfiltered (f, "section offset: %s", - pulongest (die->attrs[i].as_unsigned ())); + gdb_printf (f, "section offset: %s", + pulongest (die->attrs[i].as_unsigned ())); break; case DW_FORM_ref_sig8: - fprintf_unfiltered (f, "signature: %s", - hex_string (die->attrs[i].as_signature ())); + gdb_printf (f, "signature: %s", + hex_string (die->attrs[i].as_signature ())); break; case DW_FORM_string: case DW_FORM_strp: @@ -22954,37 +22062,37 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) case DW_FORM_strx: case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: - fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)", - die->attrs[i].as_string () - ? die->attrs[i].as_string () : "", - die->attrs[i].canonical_string_p () ? "is" : "not"); + gdb_printf (f, "string: \"%s\" (%s canonicalized)", + die->attrs[i].as_string () + ? die->attrs[i].as_string () : "", + die->attrs[i].canonical_string_p () ? "is" : "not"); break; case DW_FORM_flag: if (die->attrs[i].as_boolean ()) - fprintf_unfiltered (f, "flag: TRUE"); + gdb_printf (f, "flag: TRUE"); else - fprintf_unfiltered (f, "flag: FALSE"); + gdb_printf (f, "flag: FALSE"); break; case DW_FORM_flag_present: - fprintf_unfiltered (f, "flag: TRUE"); + gdb_printf (f, "flag: TRUE"); break; case DW_FORM_indirect: /* The reader will have reduced the indirect form to the "base form" so this form should not occur. */ - fprintf_unfiltered (f, - "unexpected attribute form: DW_FORM_indirect"); + gdb_printf (f, + "unexpected attribute form: DW_FORM_indirect"); break; case DW_FORM_sdata: case DW_FORM_implicit_const: - fprintf_unfiltered (f, "constant: %s", - plongest (die->attrs[i].as_signed ())); + gdb_printf (f, "constant: %s", + plongest (die->attrs[i].as_signed ())); break; default: - fprintf_unfiltered (f, "unsupported attribute form: %d.", - die->attrs[i].form); + gdb_printf (f, "unsupported attribute form: %d.", + die->attrs[i].form); break; } - fprintf_unfiltered (f, "\n"); + gdb_printf (f, "\n"); } } @@ -23008,17 +22116,16 @@ dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) if (die->child != NULL) { - print_spaces (indent, f); - fprintf_unfiltered (f, " Children:"); + gdb_printf (f, "%*s Children:", indent, ""); if (level + 1 < max_level) { - fprintf_unfiltered (f, "\n"); + gdb_printf (f, "\n"); dump_die_1 (f, level + 1, max_level, die->child); } else { - fprintf_unfiltered (f, - " [not printed, max nesting level reached]\n"); + gdb_printf (f, + " [not printed, max nesting level reached]\n"); } } @@ -23110,7 +22217,7 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, struct dwarf2_per_cu_data *per_cu; per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, - per_objfile); + per_objfile->per_bfd); dwarf_read_debug_printf_v ("target CU offset: %s, " "target CU DIEs loaded: %d", @@ -23133,7 +22240,6 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz, else if (cu->dies == NULL) { /* We're loading full DIEs during partial symbol reading. */ - gdb_assert (per_objfile->per_bfd->reading_partial_symbols); load_full_comp_unit (cu->per_cu, per_objfile, cu, false, language_minimal); } @@ -23675,9 +22781,6 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu, { struct signatured_type *sig_type; - /* Caller is responsible for ensuring type_unit_groups don't get here. */ - gdb_assert (! per_cu->type_unit_group_p ()); - /* We have the per_cu, but we need the signatured_type. Fortunately this is an easy translation. */ gdb_assert (per_cu->is_debug_types); @@ -24097,7 +23200,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, struct dwarf2_section_info *str_offsets_section; struct dwarf2_section_info *str_section; - ULONGEST str_offsets_base; + gdb::optional str_offsets_base; if (cu->dwo_unit != nullptr) { @@ -24110,7 +23213,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, { str_offsets_section = &per_objfile->per_bfd->str_offsets; str_section = &per_objfile->per_bfd->str; - str_offsets_base = *cu->str_offsets_base; + str_offsets_base = cu->str_offsets_base; } dwarf_decode_macros (per_objfile, builder, section, lh, @@ -24214,9 +23317,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, complaint (_("Location list used without " "specifying the CU base address.")); - SYMBOL_ACLASS_INDEX (sym) = (is_block - ? dwarf2_loclist_block_index - : dwarf2_loclist_index); + sym->set_aclass_index ((is_block + ? dwarf2_loclist_block_index + : dwarf2_loclist_index)); SYMBOL_LOCATION_BATON (sym) = baton; } else @@ -24246,9 +23349,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, baton->size = 0; } - SYMBOL_ACLASS_INDEX (sym) = (is_block - ? dwarf2_locexpr_block_index - : dwarf2_locexpr_index); + sym->set_aclass_index ((is_block + ? dwarf2_locexpr_block_index + : dwarf2_locexpr_index)); SYMBOL_LOCATION_BATON (sym) = baton; } } @@ -24342,12 +23445,11 @@ dwarf2_find_containing_comp_unit static struct dwarf2_per_cu_data * dwarf2_find_containing_comp_unit (sect_offset sect_off, unsigned int offset_in_dwz, - dwarf2_per_objfile *per_objfile) + dwarf2_per_bfd *per_bfd) { int low = dwarf2_find_containing_comp_unit - (sect_off, offset_in_dwz, per_objfile->per_bfd->all_comp_units); - dwarf2_per_cu_data *this_cu - = per_objfile->per_bfd->all_comp_units[low].get (); + (sect_off, offset_in_dwz, per_bfd->all_comp_units); + dwarf2_per_cu_data *this_cu = per_bfd->all_comp_units[low].get (); if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off) { @@ -24355,15 +23457,15 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off, error (_("Dwarf Error: could not find partial DIE containing " "offset %s [in module %s]"), sect_offset_str (sect_off), - bfd_get_filename (per_objfile->objfile->obfd)); + bfd_get_filename (per_bfd->obfd)); - gdb_assert (per_objfile->per_bfd->all_comp_units[low-1]->sect_off + gdb_assert (per_bfd->all_comp_units[low-1]->sect_off <= sect_off); - return per_objfile->per_bfd->all_comp_units[low - 1].get (); + return per_bfd->all_comp_units[low - 1].get (); } else { - if (low == per_objfile->per_bfd->all_comp_units.size () - 1 + if (low == per_bfd->all_comp_units.size () - 1 && sect_off >= this_cu->sect_off + this_cu->length) error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off)); gdb_assert (sect_off < this_cu->sect_off + this_cu->length); @@ -24656,6 +23758,15 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu, type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop); } + /* Read DW_AT_rank and set in type. */ + attr = dwarf2_attr (die, DW_AT_rank, cu); + if (attr != NULL) + { + struct type *prop_type = cu->addr_sized_int_type (false); + if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type)) + type->add_dyn_prop (DYN_PROP_RANK, prop); + } + /* Read DW_AT_data_location and set in type. */ if (!skip_data_location) { @@ -24717,32 +23828,6 @@ get_die_type (struct die_info *die, struct dwarf2_cu *cu) return get_die_type_at_offset (die->sect_off, cu->per_cu, cu->per_objfile); } -/* Trivial hash function for partial_die_info: the hash value of a DIE - is its offset in .debug_info for this objfile. */ - -static hashval_t -partial_die_hash (const void *item) -{ - const struct partial_die_info *part_die - = (const struct partial_die_info *) item; - - return to_underlying (part_die->sect_off); -} - -/* Trivial comparison function for partial_die_info structures: two DIEs - are equal if they have the same offset. */ - -static int -partial_die_eq (const void *item_lhs, const void *item_rhs) -{ - const struct partial_die_info *part_die_lhs - = (const struct partial_die_info *) item_lhs; - const struct partial_die_info *part_die_rhs - = (const struct partial_die_info *) item_rhs; - - return part_die_lhs->sect_off == part_die_rhs->sect_off; -} - struct cmd_list_element *set_dwarf_cmdlist; struct cmd_list_element *show_dwarf_cmdlist; @@ -24750,26 +23835,24 @@ static void show_check_physname (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, - _("Whether to check \"physname\" is %s.\n"), - value); + gdb_printf (file, + _("Whether to check \"physname\" is %s.\n"), + value); } void _initialize_dwarf2_read (); void _initialize_dwarf2_read () { - add_basic_prefix_cmd ("dwarf", class_maintenance, _("\ + add_setshow_prefix_cmd ("dwarf", class_maintenance, + _("\ Set DWARF specific variables.\n\ Configure DWARF variables such as the cache size."), - &set_dwarf_cmdlist, - 0/*allow-unknown*/, &maintenance_set_cmdlist); - - add_show_prefix_cmd ("dwarf", class_maintenance, _("\ + _("\ Show DWARF specific variables.\n\ Show DWARF variables such as the cache size."), - &show_dwarf_cmdlist, - 0/*allow-unknown*/, &maintenance_show_cmdlist); + &set_dwarf_cmdlist, &show_dwarf_cmdlist, + &maintenance_set_cmdlist, &maintenance_show_cmdlist); add_setshow_zinteger_cmd ("max-cache-age", class_obscure, &dwarf_max_cache_age, _("\