diff options
author | Simon Marchi <simon.marchi@efficios.com> | 2023-02-14 14:55:57 -0500 |
---|---|---|
committer | Simon Marchi <simon.marchi@efficios.com> | 2023-02-15 15:12:01 -0500 |
commit | be932484aacb329459f96dd1811fb33d935af29f (patch) | |
tree | 7751af1c108e4caa362f79f8e7f51b22f7f02c9c /gdb | |
parent | 6acd95be6a5c12006466e4d545ea5816f65004ad (diff) | |
download | binutils-be932484aacb329459f96dd1811fb33d935af29f.zip binutils-be932484aacb329459f96dd1811fb33d935af29f.tar.gz binutils-be932484aacb329459f96dd1811fb33d935af29f.tar.bz2 |
gdb/dwarf2: split .gdb_index reading code to own file
Move everything related to reading .gdb_index from read.c to
read-gdb-index.c. The only entry point exposed by read-gdb-index.{c,h}
is dwarf2_read_gdb_index.
Change-Id: I1e32c8f0720086538de8d2f612f27545377099bc
Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/Makefile.in | 2 | ||||
-rw-r--r-- | gdb/dwarf2/read-gdb-index.c | 874 | ||||
-rw-r--r-- | gdb/dwarf2/read-gdb-index.h | 47 | ||||
-rw-r--r-- | gdb/dwarf2/read.c | 847 |
4 files changed, 925 insertions, 845 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index dac5a66..5a0b3c8 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1082,6 +1082,7 @@ COMMON_SFILES = \ dwarf2/loc.c \ dwarf2/macro.c \ dwarf2/read.c \ + dwarf2/read-gdb-index.c \ dwarf2/section.c \ dwarf2/stringify.c \ eval.c \ @@ -1325,6 +1326,7 @@ HFILES_NO_SRCDIR = \ dwarf2/index-common.h \ dwarf2/loc.h \ dwarf2/read.h \ + dwarf2/read-gdb-index.h \ event-top.h \ exceptions.h \ exec.h \ diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c new file mode 100644 index 0000000..1006386 --- /dev/null +++ b/gdb/dwarf2/read-gdb-index.c @@ -0,0 +1,874 @@ +/* Reading code for .gdb_index + + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "read-gdb-index.h" + +#include "cli/cli-cmds.h" +#include "complaints.h" +#include "dwz.h" +#include "gdb/gdb-index.h" +#include "gdbsupport/gdb-checked-static-cast.h" +#include "mapped-index.h" +#include "read.h" + +/* When true, do not reject deprecated .gdb_index sections. */ +static bool use_deprecated_index_sections = false; + +/* This is a view into the index that converts from bytes to an + offset_type, and allows indexing. Unaligned bytes are specifically + allowed here, and handled via unpacking. */ + +class offset_view +{ +public: + offset_view () = default; + + explicit offset_view (gdb::array_view<const gdb_byte> bytes) + : m_bytes (bytes) + { + } + + /* Extract the INDEXth offset_type from the array. */ + offset_type operator[] (size_t index) const + { + const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)]; + return (offset_type) extract_unsigned_integer (bytes, + sizeof (offset_type), + BFD_ENDIAN_LITTLE); + } + + /* Return the number of offset_types in this array. */ + size_t size () const + { + return m_bytes.size () / sizeof (offset_type); + } + + /* Return true if this view is empty. */ + bool empty () const + { + return m_bytes.empty (); + } + +private: + /* The underlying bytes. */ + gdb::array_view<const gdb_byte> m_bytes; +}; + +/* A description of .gdb_index index. The file format is described in + a comment by the code that writes the index. */ + +struct mapped_gdb_index final : public mapped_index_base +{ + /* Index data format version. */ + int version = 0; + + /* The address table data. */ + gdb::array_view<const gdb_byte> address_table; + + /* The symbol table, implemented as a hash table. */ + offset_view symbol_table; + + /* A pointer to the constant pool. */ + gdb::array_view<const gdb_byte> constant_pool; + + /* Return the index into the constant pool of the name of the IDXth + symbol in the symbol table. */ + offset_type symbol_name_index (offset_type idx) const + { + return symbol_table[2 * idx]; + } + + /* Return the index into the constant pool of the CU vector of the + IDXth symbol in the symbol table. */ + offset_type symbol_vec_index (offset_type idx) const + { + return symbol_table[2 * idx + 1]; + } + + bool symbol_name_slot_invalid (offset_type idx) const override + { + return (symbol_name_index (idx) == 0 + && symbol_vec_index (idx) == 0); + } + + /* Convenience method to get at the name of the symbol at IDX in the + symbol table. */ + const char *symbol_name_at + (offset_type idx, dwarf2_per_objfile *per_objfile) const override + { + return (const char *) (this->constant_pool.data () + + symbol_name_index (idx)); + } + + size_t symbol_name_count () const override + { return this->symbol_table.size () / 2; } + + quick_symbol_functions_up make_quick_functions () const override; + + bool version_check () const override + { + return version >= 8; + } +}; + +struct dwarf2_gdb_index : public dwarf2_base_index_functions +{ + /* This dumps minimal information about the index. + It is called via "mt print objfiles". + One use is to verify .gdb_index has been loaded by the + gdb.dwarf2/gdb-index.exp testcase. */ + void dump (struct objfile *objfile) override; + + void expand_matching_symbols + (struct objfile *, + const lookup_name_info &lookup_name, + domain_enum domain, + int global, + symbol_compare_ftype *ordered_compare) override; + + bool expand_symtabs_matching + (struct objfile *objfile, + gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, + const lookup_name_info *lookup_name, + gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, + gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, + block_search_flags search_flags, + domain_enum domain, + enum search_domain kind) override; +}; + +/* This dumps minimal information about the index. + It is called via "mt print objfiles". + One use is to verify .gdb_index has been loaded by the + gdb.dwarf2/gdb-index.exp testcase. */ + +void +dwarf2_gdb_index::dump (struct objfile *objfile) +{ + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + + mapped_gdb_index *index = (gdb::checked_static_cast<mapped_gdb_index *> + (per_objfile->per_bfd->index_table.get ())); + gdb_printf (".gdb_index: version %d\n", index->version); + gdb_printf ("\n"); +} + +/* Struct used to manage iterating over all CUs looking for a symbol. */ + +struct dw2_symtab_iterator +{ + /* The dwarf2_per_objfile owning the CUs we are iterating on. */ + dwarf2_per_objfile *per_objfile; + /* If set, only look for symbols that match that block. Valid values are + GLOBAL_BLOCK and STATIC_BLOCK. */ + gdb::optional<block_enum> block_index; + /* The kind of symbol we're looking for. */ + domain_enum domain; + /* The list of CUs from the index entry of the symbol, + or NULL if not found. */ + offset_view vec; + /* The next element in VEC to look at. */ + int next; + /* The number of elements in VEC, or zero if there is no match. */ + int length; + /* Have we seen a global version of the symbol? + If so we can ignore all further global instances. + This is to work around gold/15646, inefficient gold-generated + indices. */ + int global_seen; +}; + +/* Initialize the index symtab iterator ITER, offset_type NAMEI variant. */ + +static void +dw2_symtab_iter_init (struct dw2_symtab_iterator *iter, + dwarf2_per_objfile *per_objfile, + gdb::optional<block_enum> block_index, + domain_enum domain, offset_type namei, + mapped_gdb_index &index) +{ + iter->per_objfile = per_objfile; + iter->block_index = block_index; + iter->domain = domain; + iter->next = 0; + iter->global_seen = 0; + iter->vec = {}; + iter->length = 0; + + gdb_assert (!index.symbol_name_slot_invalid (namei)); + offset_type vec_idx = index.symbol_vec_index (namei); + + iter->vec = offset_view (index.constant_pool.slice (vec_idx)); + iter->length = iter->vec[0]; +} + +/* Return the next matching CU or NULL if there are no more. */ + +static struct dwarf2_per_cu_data * +dw2_symtab_iter_next (struct dw2_symtab_iterator *iter, + mapped_gdb_index &index) +{ + dwarf2_per_objfile *per_objfile = iter->per_objfile; + + for ( ; iter->next < iter->length; ++iter->next) + { + offset_type cu_index_and_attrs = iter->vec[iter->next + 1]; + offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs); + gdb_index_symbol_kind symbol_kind = + GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs); + /* Only check the symbol attributes if they're present. + Indices prior to version 7 don't record them, + and indices >= 7 may elide them for certain symbols + (gold does this). */ + int attrs_valid = (index.version >= 7 + && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE); + + /* Don't crash on bad data. */ + if (cu_index >= per_objfile->per_bfd->all_units.size ()) + { + complaint (_(".gdb_index entry has bad CU index" + " [in module %s]"), objfile_name (per_objfile->objfile)); + continue; + } + + dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index); + + /* Skip if already read in. */ + if (per_objfile->symtab_set_p (per_cu)) + continue; + + /* Check static vs global. */ + if (attrs_valid) + { + bool is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs); + + if (iter->block_index.has_value ()) + { + bool want_static = *iter->block_index == STATIC_BLOCK; + + if (is_static != want_static) + continue; + } + + /* Work around gold/15646. */ + if (!is_static + && symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE) + { + if (iter->global_seen) + continue; + + iter->global_seen = 1; + } + } + + /* Only check the symbol's kind if it has one. */ + if (attrs_valid) + { + switch (iter->domain) + { + case VAR_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE + && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION + /* Some types are also in VAR_DOMAIN. */ + && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) + continue; + break; + case STRUCT_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) + continue; + break; + case LABEL_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) + continue; + break; + case MODULE_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) + continue; + break; + default: + break; + } + } + + ++iter->next; + return per_cu; + } + + return NULL; +} + +void +dwarf2_gdb_index::expand_matching_symbols + (struct objfile *objfile, + const lookup_name_info &name, domain_enum domain, + int global, + symbol_compare_ftype *ordered_compare) +{ + /* Used for Ada. */ + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + + const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK; + + mapped_gdb_index &index + = *(gdb::checked_static_cast<mapped_gdb_index *> + (per_objfile->per_bfd->index_table.get ())); + + const char *match_name = name.ada ().lookup_name ().c_str (); + auto matcher = [&] (const char *symname) + { + if (ordered_compare == nullptr) + return true; + return ordered_compare (symname, match_name) == 0; + }; + + dw2_expand_symtabs_matching_symbol (index, name, matcher, + [&] (offset_type namei) + { + struct dw2_symtab_iterator iter; + struct dwarf2_per_cu_data *per_cu; + + dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain, namei, + index); + while ((per_cu = dw2_symtab_iter_next (&iter, index)) != NULL) + dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr, + nullptr); + return true; + }, per_objfile); +} + +/* Helper for dw2_expand_matching symtabs. Called on each symbol + matched, to expand corresponding CUs that were marked. IDX is the + index of the symbol name that matched. */ + +static bool +dw2_expand_marked_cus + (dwarf2_per_objfile *per_objfile, offset_type idx, + gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, + gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, + block_search_flags search_flags, + search_domain kind) +{ + offset_type vec_len, vec_idx; + bool global_seen = false; + mapped_gdb_index &index + = *(gdb::checked_static_cast<mapped_gdb_index *> + (per_objfile->per_bfd->index_table.get ())); + + offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx))); + vec_len = vec[0]; + for (vec_idx = 0; vec_idx < vec_len; ++vec_idx) + { + offset_type cu_index_and_attrs = vec[vec_idx + 1]; + /* This value is only valid for index versions >= 7. */ + int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs); + gdb_index_symbol_kind symbol_kind = + GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs); + int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs); + /* Only check the symbol attributes if they're present. + Indices prior to version 7 don't record them, + and indices >= 7 may elide them for certain symbols + (gold does this). */ + int attrs_valid = + (index.version >= 7 + && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE); + + /* Work around gold/15646. */ + if (attrs_valid + && !is_static + && symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE) + { + if (global_seen) + continue; + + global_seen = true; + } + + /* Only check the symbol's kind if it has one. */ + if (attrs_valid) + { + if (is_static) + { + if ((search_flags & SEARCH_STATIC_BLOCK) == 0) + continue; + } + else + { + if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0) + continue; + } + + switch (kind) + { + case VARIABLES_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE) + continue; + break; + case FUNCTIONS_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION) + continue; + break; + case TYPES_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) + continue; + break; + case MODULES_DOMAIN: + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) + continue; + break; + default: + break; + } + } + + /* Don't crash on bad data. */ + if (cu_index >= per_objfile->per_bfd->all_units.size ()) + { + complaint (_(".gdb_index entry has bad CU index" + " [in module %s]"), objfile_name (per_objfile->objfile)); + continue; + } + + dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index); + if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, + expansion_notify)) + return false; + } + + return true; +} + +bool +dwarf2_gdb_index::expand_symtabs_matching + (struct objfile *objfile, + gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, + const lookup_name_info *lookup_name, + gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, + gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, + block_search_flags search_flags, + domain_enum domain, + enum search_domain kind) +{ + dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); + + dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher); + + /* This invariant is documented in quick-functions.h. */ + gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); + if (lookup_name == nullptr) + { + for (dwarf2_per_cu_data *per_cu + : all_units_range (per_objfile->per_bfd)) + { + QUIT; + + if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, + file_matcher, + expansion_notify)) + return false; + } + return true; + } + + mapped_gdb_index &index + = *(gdb::checked_static_cast<mapped_gdb_index *> + (per_objfile->per_bfd->index_table.get ())); + + bool result + = dw2_expand_symtabs_matching_symbol (index, *lookup_name, + symbol_matcher, + [&] (offset_type idx) + { + if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher, + expansion_notify, search_flags, kind)) + return false; + return true; + }, per_objfile); + + return result; +} + +quick_symbol_functions_up +mapped_gdb_index::make_quick_functions () const +{ + return quick_symbol_functions_up (new dwarf2_gdb_index); +} + +/* A helper function that reads the .gdb_index from BUFFER and fills + in MAP. FILENAME is the name of the file containing the data; + it is used for error reporting. DEPRECATED_OK is true if it is + ok to use deprecated sections. + + CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are + out parameters that are filled in with information about the CU and + TU lists in the section. + + Returns true if all went well, false otherwise. */ + +static bool +read_gdb_index_from_buffer (const char *filename, + bool deprecated_ok, + gdb::array_view<const gdb_byte> buffer, + mapped_gdb_index *map, + const gdb_byte **cu_list, + offset_type *cu_list_elements, + const gdb_byte **types_list, + offset_type *types_list_elements) +{ + const gdb_byte *addr = &buffer[0]; + offset_view metadata (buffer); + + /* Version check. */ + offset_type version = metadata[0]; + /* Versions earlier than 3 emitted every copy of a psymbol. This + causes the index to behave very poorly for certain requests. Version 3 + contained incomplete addrmap. So, it seems better to just ignore such + indices. */ + if (version < 4) + { + static int warning_printed = 0; + if (!warning_printed) + { + warning (_("Skipping obsolete .gdb_index section in %s."), + filename); + warning_printed = 1; + } + return 0; + } + /* Index version 4 uses a different hash function than index version + 5 and later. + + Versions earlier than 6 did not emit psymbols for inlined + functions. Using these files will cause GDB not to be able to + set breakpoints on inlined functions by name, so we ignore these + indices unless the user has done + "set use-deprecated-index-sections on". */ + if (version < 6 && !deprecated_ok) + { + static int warning_printed = 0; + if (!warning_printed) + { + warning (_("\ +Skipping deprecated .gdb_index section in %s.\n\ +Do \"set use-deprecated-index-sections on\" before the file is read\n\ +to use the section anyway."), + filename); + warning_printed = 1; + } + return 0; + } + /* Version 7 indices generated by gold refer to the CU for a symbol instead + of the TU (for symbols coming from TUs), + http://sourceware.org/bugzilla/show_bug.cgi?id=15021. + Plus gold-generated indices can have duplicate entries for global symbols, + http://sourceware.org/bugzilla/show_bug.cgi?id=15646. + These are just performance bugs, and we can't distinguish gdb-generated + indices from gold-generated ones, so issue no warning here. */ + + /* Indexes with higher version than the one supported by GDB may be no + longer backward compatible. */ + if (version > 8) + return 0; + + map->version = version; + + int i = 1; + *cu_list = addr + metadata[i]; + *cu_list_elements = (metadata[i + 1] - metadata[i]) / 8; + ++i; + + *types_list = addr + metadata[i]; + *types_list_elements = (metadata[i + 1] - metadata[i]) / 8; + ++i; + + const gdb_byte *address_table = addr + metadata[i]; + const gdb_byte *address_table_end = addr + metadata[i + 1]; + map->address_table + = gdb::array_view<const gdb_byte> (address_table, address_table_end); + ++i; + + const gdb_byte *symbol_table = addr + metadata[i]; + const gdb_byte *symbol_table_end = addr + metadata[i + 1]; + map->symbol_table + = offset_view (gdb::array_view<const gdb_byte> (symbol_table, + symbol_table_end)); + + ++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<const gdb_byte> (symbol_table, + symbol_table)); + } + + return 1; +} + +/* A helper for create_cus_from_gdb_index that handles a given list of + CUs. */ + +static void +create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd, + const gdb_byte *cu_list, offset_type n_elements, + struct dwarf2_section_info *section, + int is_dwz) +{ + for (offset_type i = 0; i < n_elements; i += 2) + { + gdb_static_assert (sizeof (ULONGEST) >= 8); + + sect_offset sect_off + = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); + ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); + cu_list += 2 * 8; + + dwarf2_per_cu_data_up per_cu + = create_cu_from_index_list (per_bfd, section, is_dwz, sect_off, + length); + per_bfd->all_units.push_back (std::move (per_cu)); + } +} + +/* Read the CU list from the mapped index, and use it to create all + the CU objects for PER_BFD. */ + +static void +create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd, + const gdb_byte *cu_list, offset_type cu_list_elements, + const gdb_byte *dwz_list, offset_type dwz_elements) +{ + gdb_assert (per_bfd->all_units.empty ()); + per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2); + + create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements, + &per_bfd->info, 0); + + if (dwz_elements == 0) + return; + + dwz_file *dwz = dwarf2_get_dwz_file (per_bfd); + create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements, + &dwz->info, 1); +} + +/* Create the signatured type hash table from the index. */ + +static void +create_signatured_type_table_from_gdb_index + (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section, + const gdb_byte *bytes, offset_type elements) +{ + htab_up sig_types_hash = allocate_signatured_type_table (); + + for (offset_type i = 0; i < elements; i += 3) + { + signatured_type_up sig_type; + ULONGEST signature; + void **slot; + cu_offset type_offset_in_tu; + + gdb_static_assert (sizeof (ULONGEST) >= 8); + sect_offset sect_off + = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); + type_offset_in_tu + = (cu_offset) extract_unsigned_integer (bytes + 8, 8, + BFD_ENDIAN_LITTLE); + signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); + bytes += 3 * 8; + + sig_type = per_bfd->allocate_signatured_type (signature); + sig_type->type_offset_in_tu = type_offset_in_tu; + sig_type->section = section; + sig_type->sect_off = sect_off; + + slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); + *slot = sig_type.get (); + + per_bfd->all_units.emplace_back (sig_type.release ()); + } + + per_bfd->signatured_types = std::move (sig_types_hash); +} + +/* Read the address map data from the mapped GDB index, and use it to + populate the index_addrmap. */ + +static void +create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile, + mapped_gdb_index *index) +{ + struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + struct gdbarch *gdbarch = objfile->arch (); + const gdb_byte *iter, *end; + CORE_ADDR baseaddr; + + addrmap_mutable mutable_map; + + iter = index->address_table.data (); + end = iter + index->address_table.size (); + + baseaddr = objfile->text_section_offset (); + + while (iter < end) + { + ULONGEST hi, lo, cu_index; + lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); + iter += 8; + hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); + iter += 8; + cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); + iter += 4; + + if (lo > hi) + { + complaint (_(".gdb_index address table has invalid range (%s - %s)"), + hex_string (lo), hex_string (hi)); + continue; + } + + if (cu_index >= per_bfd->all_units.size ()) + { + complaint (_(".gdb_index address table has invalid CU number %u"), + (unsigned) cu_index); + continue; + } + + lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr; + hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr; + mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index)); + } + + per_bfd->index_addrmap + = new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack, &mutable_map); +} + +/* See read-gdb-index.h. */ + +int +dwarf2_read_gdb_index + (dwarf2_per_objfile *per_objfile, + get_gdb_index_contents_ftype get_gdb_index_contents, + get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz) +{ + const gdb_byte *cu_list, *types_list, *dwz_list = NULL; + offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; + struct dwz_file *dwz; + struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; + + gdb::array_view<const gdb_byte> main_index_contents + = get_gdb_index_contents (objfile, per_bfd); + + if (main_index_contents.empty ()) + return 0; + + std::unique_ptr<mapped_gdb_index> map (new mapped_gdb_index); + if (!read_gdb_index_from_buffer (objfile_name (objfile), + use_deprecated_index_sections, + main_index_contents, map.get (), &cu_list, + &cu_list_elements, &types_list, + &types_list_elements)) + return 0; + + /* Don't use the index if it's empty. */ + if (map->symbol_table.empty ()) + return 0; + + /* If there is a .dwz file, read it so we can get its CU list as + well. */ + dwz = dwarf2_get_dwz_file (per_bfd); + if (dwz != NULL) + { + mapped_gdb_index dwz_map; + const gdb_byte *dwz_types_ignore; + offset_type dwz_types_elements_ignore; + + gdb::array_view<const gdb_byte> dwz_index_content + = get_gdb_index_contents_dwz (objfile, dwz); + + if (dwz_index_content.empty ()) + return 0; + + if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.get ()), + 1, dwz_index_content, &dwz_map, + &dwz_list, &dwz_list_elements, + &dwz_types_ignore, + &dwz_types_elements_ignore)) + { + warning (_("could not read '.gdb_index' section from %s; skipping"), + bfd_get_filename (dwz->dwz_bfd.get ())); + return 0; + } + } + + create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list, + dwz_list_elements); + + if (types_list_elements) + { + /* We can only handle a single .debug_types when we have an + index. */ + if (per_bfd->types.size () > 1) + { + per_bfd->all_units.clear (); + return 0; + } + + dwarf2_section_info *section + = (per_bfd->types.size () == 1 + ? &per_bfd->types[0] + : &per_bfd->info); + + create_signatured_type_table_from_gdb_index (per_bfd, section, types_list, + types_list_elements); + } + + finalize_all_units (per_bfd); + + create_addrmap_from_gdb_index (per_objfile, map.get ()); + + per_bfd->index_table = std::move (map); + per_bfd->quick_file_names_table = + create_quick_file_names_table (per_bfd->all_units.size ()); + + return 1; +} + +void _initialize_read_gdb_index (); + +void +_initialize_read_gdb_index () +{ + add_setshow_boolean_cmd ("use-deprecated-index-sections", + no_class, &use_deprecated_index_sections, _("\ +Set whether to use deprecated gdb_index sections."), _("\ +Show whether to use deprecated gdb_index sections."), _("\ +When enabled, deprecated .gdb_index sections are used anyway.\n\ +Normally they are ignored either because of a missing feature or\n\ +performance issue.\n\ +Warning: This option must be enabled before gdb reads the file."), + NULL, + NULL, + &setlist, &showlist); +} diff --git a/gdb/dwarf2/read-gdb-index.h b/gdb/dwarf2/read-gdb-index.h new file mode 100644 index 0000000..b69de4a --- /dev/null +++ b/gdb/dwarf2/read-gdb-index.h @@ -0,0 +1,47 @@ +/* Reading code for .gdb_index + + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef DWARF2_READ_GDB_INDEX_H +#define DWARF2_READ_GDB_INDEX_H + +#include "gdbsupport/function-view.h" + +struct dwarf2_per_bfd; +struct dwarf2_per_objfile; +struct dwz_file; +struct objfile; + +/* Callback types for dwarf2_read_gdb_index. */ + +typedef gdb::function_view + <gdb::array_view<const gdb_byte>(objfile *, dwarf2_per_bfd *)> + get_gdb_index_contents_ftype; +typedef gdb::function_view + <gdb::array_view<const gdb_byte>(objfile *, dwz_file *)> + get_gdb_index_contents_dwz_ftype; + +/* Read .gdb_index. If everything went ok, initialize the "quick" + elements of all the CUs and return 1. Otherwise, return 0. */ + +int dwarf2_read_gdb_index + (dwarf2_per_objfile *per_objfile, + get_gdb_index_contents_ftype get_gdb_index_contents, + get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz); + +#endif /* DWARF2_READ_GDB_INDEX_H */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 96e907b..77ebd95 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -41,6 +41,7 @@ #include "dwarf2/dwz.h" #include "dwarf2/macro.h" #include "dwarf2/die.h" +#include "dwarf2/read-gdb-index.h" #include "dwarf2/sect-names.h" #include "dwarf2/stringify.h" #include "dwarf2/public.h" @@ -120,9 +121,6 @@ unsigned int dwarf_line_debug = 0; /* When true, cross-check physname against demangler. */ static bool check_physname = false; -/* When true, do not reject deprecated .gdb_index sections. */ -static bool use_deprecated_index_sections = false; - /* This is used to store the data that is always per objfile. */ static const registry<objfile>::key<dwarf2_per_objfile> dwarf2_objfile_data_key; @@ -158,103 +156,6 @@ static int dwarf2_loclist_block_index; /* Size of .debug_rnglists section header for 64-bit DWARF format. */ #define RNGLIST_HEADER_SIZE64 20 -/* This is a view into the index that converts from bytes to an - offset_type, and allows indexing. Unaligned bytes are specifically - allowed here, and handled via unpacking. */ - -class offset_view -{ -public: - offset_view () = default; - - explicit offset_view (gdb::array_view<const gdb_byte> bytes) - : m_bytes (bytes) - { - } - - /* Extract the INDEXth offset_type from the array. */ - offset_type operator[] (size_t index) const - { - const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)]; - return (offset_type) extract_unsigned_integer (bytes, - sizeof (offset_type), - BFD_ENDIAN_LITTLE); - } - - /* Return the number of offset_types in this array. */ - size_t size () const - { - return m_bytes.size () / sizeof (offset_type); - } - - /* Return true if this view is empty. */ - bool empty () const - { - return m_bytes.empty (); - } - -private: - /* The underlying bytes. */ - gdb::array_view<const gdb_byte> m_bytes; -}; - -/* A description of .gdb_index index. The file format is described in - a comment by the code that writes the index. */ - -struct mapped_gdb_index final : public mapped_index_base -{ - /* Index data format version. */ - int version = 0; - - /* The address table data. */ - gdb::array_view<const gdb_byte> address_table; - - /* The symbol table, implemented as a hash table. */ - offset_view symbol_table; - - /* A pointer to the constant pool. */ - gdb::array_view<const gdb_byte> constant_pool; - - /* Return the index into the constant pool of the name of the IDXth - symbol in the symbol table. */ - offset_type symbol_name_index (offset_type idx) const - { - return symbol_table[2 * idx]; - } - - /* Return the index into the constant pool of the CU vector of the - IDXth symbol in the symbol table. */ - offset_type symbol_vec_index (offset_type idx) const - { - return symbol_table[2 * idx + 1]; - } - - bool symbol_name_slot_invalid (offset_type idx) const override - { - return (symbol_name_index (idx) == 0 - && symbol_vec_index (idx) == 0); - } - - /* Convenience method to get at the name of the symbol at IDX in the - symbol table. */ - const char *symbol_name_at - (offset_type idx, dwarf2_per_objfile *per_objfile) const override - { - return (const char *) (this->constant_pool.data () - + symbol_name_index (idx)); - } - - size_t symbol_name_count () const override - { return this->symbol_table.size () / 2; } - - quick_symbol_functions_up make_quick_functions () const override; - - bool version_check () const override - { - return version >= 8; - } -}; - /* A description of the mapped .debug_names. Uninitialized map has CU_COUNT 0. */ struct mapped_debug_names final : public mapped_index_base @@ -1763,28 +1664,6 @@ struct readnow_functions : public dwarf2_base_index_functions } }; -struct dwarf2_gdb_index : public dwarf2_base_index_functions -{ - void dump (struct objfile *objfile) override; - - void expand_matching_symbols - (struct objfile *, - const lookup_name_info &lookup_name, - domain_enum domain, - int global, - symbol_compare_ftype *ordered_compare) override; - - bool expand_symtabs_matching - (struct objfile *objfile, - gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, - const lookup_name_info *lookup_name, - gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, - gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, - block_search_flags search_flags, - domain_enum domain, - enum search_domain kind) override; -}; - struct dwarf2_debug_names_index : public dwarf2_base_index_functions { void dump (struct objfile *objfile) override; @@ -1808,12 +1687,6 @@ struct dwarf2_debug_names_index : public dwarf2_base_index_functions }; quick_symbol_functions_up -mapped_gdb_index::make_quick_functions () const -{ - return quick_symbol_functions_up (new dwarf2_gdb_index); -} - -quick_symbol_functions_up mapped_debug_names::make_quick_functions () const { return quick_symbol_functions_up (new dwarf2_debug_names_index); @@ -1985,8 +1858,7 @@ dwarf2_per_bfd::allocate_signatured_type (ULONGEST signature) return result; } -/* Return a new dwarf2_per_cu_data allocated on the per-bfd - obstack, and constructed with the specified field values. */ +/* See read.h. */ dwarf2_per_cu_data_up create_cu_from_index_list (dwarf2_per_bfd *per_bfd, @@ -2002,92 +1874,6 @@ create_cu_from_index_list (dwarf2_per_bfd *per_bfd, return the_cu; } -/* A helper for create_cus_from_index that handles a given list of - CUs. */ - -static void -create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd, - const gdb_byte *cu_list, offset_type n_elements, - struct dwarf2_section_info *section, - int is_dwz) -{ - for (offset_type i = 0; i < n_elements; i += 2) - { - gdb_static_assert (sizeof (ULONGEST) >= 8); - - sect_offset sect_off - = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); - ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); - cu_list += 2 * 8; - - dwarf2_per_cu_data_up per_cu - = create_cu_from_index_list (per_bfd, section, is_dwz, sect_off, - length); - per_bfd->all_units.push_back (std::move (per_cu)); - } -} - -/* Read the CU list from the mapped index, and use it to create all - the CU objects for PER_BFD. */ - -static void -create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd, - const gdb_byte *cu_list, offset_type cu_list_elements, - const gdb_byte *dwz_list, offset_type dwz_elements) -{ - gdb_assert (per_bfd->all_units.empty ()); - per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2); - - create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements, - &per_bfd->info, 0); - - if (dwz_elements == 0) - return; - - dwz_file *dwz = dwarf2_get_dwz_file (per_bfd); - create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements, - &dwz->info, 1); -} - -/* Create the signatured type hash table from the index. */ - -static void -create_signatured_type_table_from_gdb_index - (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section, - const gdb_byte *bytes, offset_type elements) -{ - htab_up sig_types_hash = allocate_signatured_type_table (); - - for (offset_type i = 0; i < elements; i += 3) - { - signatured_type_up sig_type; - ULONGEST signature; - void **slot; - cu_offset type_offset_in_tu; - - gdb_static_assert (sizeof (ULONGEST) >= 8); - sect_offset sect_off - = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); - type_offset_in_tu - = (cu_offset) extract_unsigned_integer (bytes + 8, 8, - BFD_ENDIAN_LITTLE); - signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); - bytes += 3 * 8; - - sig_type = per_bfd->allocate_signatured_type (signature); - sig_type->type_offset_in_tu = type_offset_in_tu; - sig_type->section = section; - sig_type->sect_off = sect_off; - - slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); - *slot = sig_type.get (); - - per_bfd->all_units.emplace_back (sig_type.release ()); - } - - per_bfd->signatured_types = std::move (sig_types_hash); -} - /* Create the signatured type hash table from .debug_names. */ static void @@ -2136,59 +1922,6 @@ create_signatured_type_table_from_debug_names per_objfile->per_bfd->signatured_types = std::move (sig_types_hash); } -/* Read the address map data from the mapped GDB index, and use it to - populate the index_addrmap. */ - -static void -create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile, - mapped_gdb_index *index) -{ - struct objfile *objfile = per_objfile->objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - struct gdbarch *gdbarch = objfile->arch (); - const gdb_byte *iter, *end; - CORE_ADDR baseaddr; - - addrmap_mutable mutable_map; - - iter = index->address_table.data (); - end = iter + index->address_table.size (); - - baseaddr = objfile->text_section_offset (); - - while (iter < end) - { - ULONGEST hi, lo, cu_index; - lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); - iter += 8; - hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); - iter += 8; - cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); - iter += 4; - - if (lo > hi) - { - complaint (_(".gdb_index address table has invalid range (%s - %s)"), - hex_string (lo), hex_string (hi)); - continue; - } - - if (cu_index >= per_bfd->all_units.size ()) - { - complaint (_(".gdb_index address table has invalid CU number %u"), - (unsigned) cu_index); - continue; - } - - lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr; - hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr; - mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index)); - } - - per_bfd->index_addrmap - = new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack, &mutable_map); -} - /* Read the address map data from DWARF-5 .debug_aranges, and use it to populate given addrmap. Returns true on success, false on failure. */ @@ -2389,222 +2122,6 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, &mutable_map); } -/* A helper function that reads the .gdb_index from BUFFER and fills - in MAP. FILENAME is the name of the file containing the data; - it is used for error reporting. DEPRECATED_OK is true if it is - ok to use deprecated sections. - - CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are - out parameters that are filled in with information about the CU and - TU lists in the section. - - Returns true if all went well, false otherwise. */ - -static bool -read_gdb_index_from_buffer (const char *filename, - bool deprecated_ok, - gdb::array_view<const gdb_byte> buffer, - mapped_gdb_index *map, - const gdb_byte **cu_list, - offset_type *cu_list_elements, - const gdb_byte **types_list, - offset_type *types_list_elements) -{ - const gdb_byte *addr = &buffer[0]; - offset_view metadata (buffer); - - /* Version check. */ - offset_type version = metadata[0]; - /* Versions earlier than 3 emitted every copy of a psymbol. This - causes the index to behave very poorly for certain requests. Version 3 - contained incomplete addrmap. So, it seems better to just ignore such - indices. */ - if (version < 4) - { - static int warning_printed = 0; - if (!warning_printed) - { - warning (_("Skipping obsolete .gdb_index section in %s."), - filename); - warning_printed = 1; - } - return 0; - } - /* Index version 4 uses a different hash function than index version - 5 and later. - - Versions earlier than 6 did not emit psymbols for inlined - functions. Using these files will cause GDB not to be able to - set breakpoints on inlined functions by name, so we ignore these - indices unless the user has done - "set use-deprecated-index-sections on". */ - if (version < 6 && !deprecated_ok) - { - static int warning_printed = 0; - if (!warning_printed) - { - warning (_("\ -Skipping deprecated .gdb_index section in %s.\n\ -Do \"set use-deprecated-index-sections on\" before the file is read\n\ -to use the section anyway."), - filename); - warning_printed = 1; - } - return 0; - } - /* Version 7 indices generated by gold refer to the CU for a symbol instead - of the TU (for symbols coming from TUs), - http://sourceware.org/bugzilla/show_bug.cgi?id=15021. - Plus gold-generated indices can have duplicate entries for global symbols, - http://sourceware.org/bugzilla/show_bug.cgi?id=15646. - These are just performance bugs, and we can't distinguish gdb-generated - indices from gold-generated ones, so issue no warning here. */ - - /* Indexes with higher version than the one supported by GDB may be no - longer backward compatible. */ - if (version > 8) - return 0; - - map->version = version; - - int i = 1; - *cu_list = addr + metadata[i]; - *cu_list_elements = (metadata[i + 1] - metadata[i]) / 8; - ++i; - - *types_list = addr + metadata[i]; - *types_list_elements = (metadata[i + 1] - metadata[i]) / 8; - ++i; - - const gdb_byte *address_table = addr + metadata[i]; - const gdb_byte *address_table_end = addr + metadata[i + 1]; - map->address_table - = gdb::array_view<const gdb_byte> (address_table, address_table_end); - ++i; - - const gdb_byte *symbol_table = addr + metadata[i]; - const gdb_byte *symbol_table_end = addr + metadata[i + 1]; - map->symbol_table - = offset_view (gdb::array_view<const gdb_byte> (symbol_table, - symbol_table_end)); - - ++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<const gdb_byte> (symbol_table, - symbol_table)); - } - - return 1; -} - -/* Callback types for dwarf2_read_gdb_index. */ - -typedef gdb::function_view - <gdb::array_view<const gdb_byte>(objfile *, dwarf2_per_bfd *)> - get_gdb_index_contents_ftype; -typedef gdb::function_view - <gdb::array_view<const gdb_byte>(objfile *, dwz_file *)> - get_gdb_index_contents_dwz_ftype; - -/* Read .gdb_index. If everything went ok, initialize the "quick" - elements of all the CUs and return 1. Otherwise, return 0. */ - -static int -dwarf2_read_gdb_index - (dwarf2_per_objfile *per_objfile, - get_gdb_index_contents_ftype get_gdb_index_contents, - get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz) -{ - const gdb_byte *cu_list, *types_list, *dwz_list = NULL; - offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; - struct dwz_file *dwz; - struct objfile *objfile = per_objfile->objfile; - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; - - gdb::array_view<const gdb_byte> main_index_contents - = get_gdb_index_contents (objfile, per_bfd); - - if (main_index_contents.empty ()) - return 0; - - std::unique_ptr<mapped_gdb_index> map (new mapped_gdb_index); - if (!read_gdb_index_from_buffer (objfile_name (objfile), - use_deprecated_index_sections, - main_index_contents, map.get (), &cu_list, - &cu_list_elements, &types_list, - &types_list_elements)) - return 0; - - /* Don't use the index if it's empty. */ - if (map->symbol_table.empty ()) - return 0; - - /* If there is a .dwz file, read it so we can get its CU list as - well. */ - dwz = dwarf2_get_dwz_file (per_bfd); - if (dwz != NULL) - { - mapped_gdb_index dwz_map; - const gdb_byte *dwz_types_ignore; - offset_type dwz_types_elements_ignore; - - gdb::array_view<const gdb_byte> dwz_index_content - = get_gdb_index_contents_dwz (objfile, dwz); - - if (dwz_index_content.empty ()) - return 0; - - if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.get ()), - 1, dwz_index_content, &dwz_map, - &dwz_list, &dwz_list_elements, - &dwz_types_ignore, - &dwz_types_elements_ignore)) - { - warning (_("could not read '.gdb_index' section from %s; skipping"), - bfd_get_filename (dwz->dwz_bfd.get ())); - return 0; - } - } - - create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list, - dwz_list_elements); - - if (types_list_elements) - { - /* We can only handle a single .debug_types when we have an - index. */ - if (per_bfd->types.size () > 1) - { - per_bfd->all_units.clear (); - return 0; - } - - dwarf2_section_info *section - = (per_bfd->types.size () == 1 - ? &per_bfd->types[0] - : &per_bfd->info); - - create_signatured_type_table_from_gdb_index (per_bfd, section, types_list, - types_list_elements); - } - - finalize_all_units (per_bfd); - - create_addrmap_from_gdb_index (per_objfile, map.get ()); - - per_bfd->index_table = std::move (map); - per_bfd->quick_file_names_table = - create_quick_file_names_table (per_bfd->all_units.size ()); - - return 1; -} - /* die_reader_func for dw2_get_file_names. */ static void @@ -2796,150 +2313,6 @@ dwarf2_base_index_functions::forget_cached_source_info per_cu->free_cached_file_names (); } -/* Struct used to manage iterating over all CUs looking for a symbol. */ - -struct dw2_symtab_iterator -{ - /* The dwarf2_per_objfile owning the CUs we are iterating on. */ - dwarf2_per_objfile *per_objfile; - /* If set, only look for symbols that match that block. Valid values are - GLOBAL_BLOCK and STATIC_BLOCK. */ - gdb::optional<block_enum> block_index; - /* The kind of symbol we're looking for. */ - domain_enum domain; - /* The list of CUs from the index entry of the symbol, - or NULL if not found. */ - offset_view vec; - /* The next element in VEC to look at. */ - int next; - /* The number of elements in VEC, or zero if there is no match. */ - int length; - /* Have we seen a global version of the symbol? - If so we can ignore all further global instances. - This is to work around gold/15646, inefficient gold-generated - indices. */ - int global_seen; -}; - -/* Initialize the index symtab iterator ITER, offset_type NAMEI variant. */ - -static void -dw2_symtab_iter_init (struct dw2_symtab_iterator *iter, - dwarf2_per_objfile *per_objfile, - gdb::optional<block_enum> block_index, - domain_enum domain, offset_type namei, - mapped_gdb_index &index) -{ - iter->per_objfile = per_objfile; - iter->block_index = block_index; - iter->domain = domain; - iter->next = 0; - iter->global_seen = 0; - iter->vec = {}; - iter->length = 0; - - gdb_assert (!index.symbol_name_slot_invalid (namei)); - offset_type vec_idx = index.symbol_vec_index (namei); - - iter->vec = offset_view (index.constant_pool.slice (vec_idx)); - iter->length = iter->vec[0]; -} - -/* Return the next matching CU or NULL if there are no more. */ - -static struct dwarf2_per_cu_data * -dw2_symtab_iter_next (struct dw2_symtab_iterator *iter, - mapped_gdb_index &index) -{ - dwarf2_per_objfile *per_objfile = iter->per_objfile; - - for ( ; iter->next < iter->length; ++iter->next) - { - offset_type cu_index_and_attrs = iter->vec[iter->next + 1]; - offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs); - gdb_index_symbol_kind symbol_kind = - GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs); - /* Only check the symbol attributes if they're present. - Indices prior to version 7 don't record them, - and indices >= 7 may elide them for certain symbols - (gold does this). */ - int attrs_valid = (index.version >= 7 - && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE); - - /* Don't crash on bad data. */ - if (cu_index >= per_objfile->per_bfd->all_units.size ()) - { - complaint (_(".gdb_index entry has bad CU index" - " [in module %s]"), objfile_name (per_objfile->objfile)); - continue; - } - - dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index); - - /* Skip if already read in. */ - if (per_objfile->symtab_set_p (per_cu)) - continue; - - /* Check static vs global. */ - if (attrs_valid) - { - bool is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs); - - if (iter->block_index.has_value ()) - { - bool want_static = *iter->block_index == STATIC_BLOCK; - - if (is_static != want_static) - continue; - } - - /* Work around gold/15646. */ - if (!is_static - && symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE) - { - if (iter->global_seen) - continue; - - iter->global_seen = 1; - } - } - - /* Only check the symbol's kind if it has one. */ - if (attrs_valid) - { - switch (iter->domain) - { - case VAR_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE - && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION - /* Some types are also in VAR_DOMAIN. */ - && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) - continue; - break; - case STRUCT_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) - continue; - break; - case LABEL_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) - continue; - break; - case MODULE_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) - continue; - break; - default: - break; - } - } - - ++iter->next; - return per_cu; - } - - return NULL; -} - void dwarf2_base_index_functions::print_stats (struct objfile *objfile, bool print_bcache) @@ -2962,22 +2335,6 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile, gdb_printf (_(" Number of unread CUs: %d\n"), count); } -/* This dumps minimal information about the index. - It is called via "mt print objfiles". - One use is to verify .gdb_index has been loaded by the - gdb.dwarf2/gdb-index.exp testcase. */ - -void -dwarf2_gdb_index::dump (struct objfile *objfile) -{ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - - mapped_gdb_index *index = (gdb::checked_static_cast<mapped_gdb_index *> - (per_objfile->per_bfd->index_table.get ())); - gdb_printf (".gdb_index: version %d\n", index->version); - gdb_printf ("\n"); -} - void dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile) { @@ -2997,44 +2354,6 @@ dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile) } } -void -dwarf2_gdb_index::expand_matching_symbols - (struct objfile *objfile, - const lookup_name_info &name, domain_enum domain, - int global, - symbol_compare_ftype *ordered_compare) -{ - /* Used for Ada. */ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - - const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK; - - mapped_gdb_index &index - = *(gdb::checked_static_cast<mapped_gdb_index *> - (per_objfile->per_bfd->index_table.get ())); - - const char *match_name = name.ada ().lookup_name ().c_str (); - auto matcher = [&] (const char *symname) - { - if (ordered_compare == nullptr) - return true; - return ordered_compare (symname, match_name) == 0; - }; - - dw2_expand_symtabs_matching_symbol (index, name, matcher, - [&] (offset_type namei) - { - struct dw2_symtab_iterator iter; - struct dwarf2_per_cu_data *per_cu; - - dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain, namei, - index); - while ((per_cu = dw2_symtab_iter_next (&iter, index)) != NULL) - dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr, - nullptr); - return true; - }, per_objfile); -} /* Starting from a search name, return the string that finds the upper bound of all strings that start with SEARCH_NAME in a sorted name @@ -3837,107 +3156,6 @@ dw2_expand_symtabs_matching_one return true; } -/* Helper for dw2_expand_matching symtabs. Called on each symbol - matched, to expand corresponding CUs that were marked. IDX is the - index of the symbol name that matched. */ - -static bool -dw2_expand_marked_cus - (dwarf2_per_objfile *per_objfile, offset_type idx, - gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, - gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, - block_search_flags search_flags, - search_domain kind) -{ - offset_type vec_len, vec_idx; - bool global_seen = false; - mapped_gdb_index &index - = *(gdb::checked_static_cast<mapped_gdb_index *> - (per_objfile->per_bfd->index_table.get ())); - - offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx))); - vec_len = vec[0]; - for (vec_idx = 0; vec_idx < vec_len; ++vec_idx) - { - offset_type cu_index_and_attrs = vec[vec_idx + 1]; - /* This value is only valid for index versions >= 7. */ - int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs); - gdb_index_symbol_kind symbol_kind = - GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs); - int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs); - /* Only check the symbol attributes if they're present. - Indices prior to version 7 don't record them, - and indices >= 7 may elide them for certain symbols - (gold does this). */ - int attrs_valid = - (index.version >= 7 - && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE); - - /* Work around gold/15646. */ - if (attrs_valid - && !is_static - && symbol_kind == GDB_INDEX_SYMBOL_KIND_TYPE) - { - if (global_seen) - continue; - - global_seen = true; - } - - /* Only check the symbol's kind if it has one. */ - if (attrs_valid) - { - if (is_static) - { - if ((search_flags & SEARCH_STATIC_BLOCK) == 0) - continue; - } - else - { - if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0) - continue; - } - - switch (kind) - { - case VARIABLES_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE) - continue; - break; - case FUNCTIONS_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION) - continue; - break; - case TYPES_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE) - continue; - break; - case MODULES_DOMAIN: - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER) - continue; - break; - default: - break; - } - } - - /* Don't crash on bad data. */ - if (cu_index >= per_objfile->per_bfd->all_units.size ()) - { - complaint (_(".gdb_index entry has bad CU index" - " [in module %s]"), objfile_name (per_objfile->objfile)); - continue; - } - - dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index); - if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher, - expansion_notify)) - return false; - } - - return true; -} - /* See read.h. */ void @@ -4037,55 +3255,6 @@ dw_expand_symtabs_matching_file_matcher } } -bool -dwarf2_gdb_index::expand_symtabs_matching - (struct objfile *objfile, - gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, - const lookup_name_info *lookup_name, - gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, - gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, - block_search_flags search_flags, - domain_enum domain, - enum search_domain kind) -{ - dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); - - dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher); - - /* This invariant is documented in quick-functions.h. */ - gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr); - if (lookup_name == nullptr) - { - for (dwarf2_per_cu_data *per_cu - : all_units_range (per_objfile->per_bfd)) - { - QUIT; - - if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, - file_matcher, - expansion_notify)) - return false; - } - return true; - } - - mapped_gdb_index &index - = *(gdb::checked_static_cast<mapped_gdb_index *> - (per_objfile->per_bfd->index_table.get ())); - - bool result - = dw2_expand_symtabs_matching_symbol (index, *lookup_name, - symbol_matcher, - [&] (offset_type idx) - { - if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher, - expansion_notify, search_flags, kind)) - return false; - return true; - }, per_objfile); - - return result; -} /* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific symtab. */ @@ -23778,18 +22947,6 @@ the demangler."), NULL, show_check_physname, &setdebuglist, &showdebuglist); - add_setshow_boolean_cmd ("use-deprecated-index-sections", - no_class, &use_deprecated_index_sections, _("\ -Set whether to use deprecated gdb_index sections."), _("\ -Show whether to use deprecated gdb_index sections."), _("\ -When enabled, deprecated .gdb_index sections are used anyway.\n\ -Normally they are ignored either because of a missing feature or\n\ -performance issue.\n\ -Warning: This option must be enabled before gdb reads the file."), - NULL, - NULL, - &setlist, &showlist); - dwarf2_locexpr_index = register_symbol_computed_impl (LOC_COMPUTED, &dwarf2_locexpr_funcs); dwarf2_loclist_index = register_symbol_computed_impl (LOC_COMPUTED, |