diff options
Diffstat (limited to 'gdb/dwarf2/index-write.c')
-rw-r--r-- | gdb/dwarf2/index-write.c | 433 |
1 files changed, 135 insertions, 298 deletions
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index 7a6bc24a3e6..dfa74ddad8e 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -36,8 +36,8 @@ #include "gdb/gdb-index.h" #include "gdbcmd.h" #include "objfiles.h" -#include "psympriv.h" #include "ada-lang.h" +#include "dwarf2/tag.h" #include <algorithm> #include <cmath> @@ -189,7 +189,7 @@ struct mapped_symtab offset_type n_elements = 0; std::vector<symtab_index_entry> data; - /* Temporary storage for Ada names. */ + /* Temporary storage for names. */ auto_obstack m_string_obstack; }; @@ -407,17 +407,18 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool) } } -typedef std::unordered_map<partial_symtab *, unsigned int> psym_index_map; +typedef std::unordered_map<dwarf2_per_cu_data *, unsigned int> cu_index_map; /* Helper struct for building the address table. */ struct addrmap_index_data { - addrmap_index_data (data_buf &addr_vec_, psym_index_map &cu_index_htab_) - : addr_vec (addr_vec_), cu_index_htab (cu_index_htab_) + addrmap_index_data (data_buf &addr_vec_, cu_index_map &cu_index_htab_) + : addr_vec (addr_vec_), + cu_index_htab (cu_index_htab_) {} data_buf &addr_vec; - psym_index_map &cu_index_htab; + cu_index_map &cu_index_htab; int operator() (CORE_ADDR start_addr, void *obj); @@ -447,7 +448,7 @@ add_address_entry (data_buf &addr_vec, int addrmap_index_data::operator() (CORE_ADDR start_addr, void *obj) { - partial_symtab *pst = (partial_symtab *) obj; + dwarf2_per_cu_data *per_cu = (dwarf2_per_cu_data *) obj; if (previous_valid) add_address_entry (addr_vec, @@ -455,9 +456,9 @@ addrmap_index_data::operator() (CORE_ADDR start_addr, void *obj) previous_cu_index); previous_cu_start = start_addr; - if (pst != NULL) + if (per_cu != NULL) { - const auto it = cu_index_htab.find (pst); + const auto it = cu_index_htab.find (per_cu); gdb_assert (it != cu_index_htab.cend ()); previous_cu_index = it->second; previous_valid = true; @@ -473,13 +474,12 @@ addrmap_index_data::operator() (CORE_ADDR start_addr, void *obj) in the index file. */ static void -write_address_map (dwarf2_per_bfd *per_bfd, data_buf &addr_vec, - psym_index_map &cu_index_htab) +write_address_map (struct addrmap *addrmap, data_buf &addr_vec, + cu_index_map &cu_index_htab) { struct addrmap_index_data addrmap_index_data (addr_vec, cu_index_htab); - addrmap_foreach (per_bfd->partial_symtabs->psymtabs_addrmap, - addrmap_index_data); + addrmap_foreach (addrmap, addrmap_index_data); /* It's highly unlikely the last entry (end address = 0xff...ff) is valid, but we should still handle it. @@ -492,142 +492,6 @@ write_address_map (dwarf2_per_bfd *per_bfd, data_buf &addr_vec, addrmap_index_data.previous_cu_index); } -/* Return the symbol kind of PSYM. */ - -static gdb_index_symbol_kind -symbol_kind (struct partial_symbol *psym) -{ - domain_enum domain = psym->domain; - enum address_class aclass = psym->aclass; - - switch (domain) - { - case VAR_DOMAIN: - switch (aclass) - { - case LOC_BLOCK: - return GDB_INDEX_SYMBOL_KIND_FUNCTION; - case LOC_TYPEDEF: - return GDB_INDEX_SYMBOL_KIND_TYPE; - case LOC_COMPUTED: - case LOC_CONST_BYTES: - case LOC_OPTIMIZED_OUT: - case LOC_STATIC: - return GDB_INDEX_SYMBOL_KIND_VARIABLE; - case LOC_CONST: - /* Note: It's currently impossible to recognize psyms as enum values - short of reading the type info. For now punt. */ - return GDB_INDEX_SYMBOL_KIND_VARIABLE; - default: - /* There are other LOC_FOO values that one might want to classify - as variables, but dwarf2read.c doesn't currently use them. */ - return GDB_INDEX_SYMBOL_KIND_OTHER; - } - case STRUCT_DOMAIN: - return GDB_INDEX_SYMBOL_KIND_TYPE; - default: - return GDB_INDEX_SYMBOL_KIND_OTHER; - } -} - -/* Add a list of partial symbols to SYMTAB. */ - -static void -write_psymbols (struct mapped_symtab *symtab, - std::unordered_set<partial_symbol *> &psyms_seen, - const std::vector<partial_symbol *> &symbols, - offset_type cu_index, - int is_static) -{ - for (partial_symbol *psym : symbols) - { - const char *name = psym->ginfo.search_name (); - - if (psym->ginfo.language () == language_ada) - { - /* We want to ensure that the Ada main function's name appears - verbatim in the index. However, this name will be of the - form "_ada_mumble", and will be rewritten by ada_decode. - So, recognize it specially here and add it to the index by - hand. */ - if (strcmp (main_name (), name) == 0) - { - gdb_index_symbol_kind kind = symbol_kind (psym); - - add_index_entry (symtab, name, is_static, kind, cu_index); - } - - /* In order for the index to work when read back into gdb, it - has to supply a funny form of the name: it should be the - encoded name, with any suffixes stripped. Using the - ordinary encoded name will not work properly with the - searching logic in find_name_components_bounds; nor will - using the decoded name. Furthermore, an Ada "verbatim" - name (of the form "<MumBle>") must be entered without the - angle brackets. Note that the current index is unusual, - see PR symtab/24820 for details. */ - std::string decoded = ada_decode (name); - if (decoded[0] == '<') - name = (char *) obstack_copy0 (&symtab->m_string_obstack, - decoded.c_str () + 1, - decoded.length () - 2); - else - name = obstack_strdup (&symtab->m_string_obstack, - ada_encode (decoded.c_str ())); - } - - /* Only add a given psymbol once. */ - if (psyms_seen.insert (psym).second) - { - gdb_index_symbol_kind kind = symbol_kind (psym); - - add_index_entry (symtab, name, is_static, kind, cu_index); - } - } -} - -/* Recurse into all "included" dependencies and count their symbols as - if they appeared in this psymtab. */ - -static void -recursively_count_psymbols (partial_symtab *psymtab, - size_t &psyms_seen) -{ - for (int i = 0; i < psymtab->number_of_dependencies; ++i) - if (psymtab->dependencies[i]->user != NULL) - recursively_count_psymbols (psymtab->dependencies[i], - psyms_seen); - - psyms_seen += psymtab->global_psymbols.size (); - psyms_seen += psymtab->static_psymbols.size (); -} - -/* Recurse into all "included" dependencies and write their symbols as - if they appeared in this psymtab. */ - -static void -recursively_write_psymbols (struct objfile *objfile, - partial_symtab *psymtab, - struct mapped_symtab *symtab, - std::unordered_set<partial_symbol *> &psyms_seen, - offset_type cu_index) -{ - int i; - - for (i = 0; i < psymtab->number_of_dependencies; ++i) - if (psymtab->dependencies[i]->user != NULL) - recursively_write_psymbols (objfile, - psymtab->dependencies[i], - symtab, psyms_seen, cu_index); - - write_psymbols (symtab, psyms_seen, - psymtab->global_psymbols, cu_index, - 0); - write_psymbols (symtab, psyms_seen, - psymtab->static_psymbols, cu_index, - 1); -} - /* DWARF-5 .debug_names builder. */ class debug_names { @@ -655,15 +519,10 @@ public: enum class unit_kind { cu, tu }; /* Insert one symbol. */ - void insert (const partial_symbol *psym, int cu_index, bool is_static, - unit_kind kind) + void insert (int dwarf_tag, const char *name, int cu_index, bool is_static, + unit_kind kind, enum language lang) { - const int dwarf_tag = psymbol_tag (psym); - if (dwarf_tag == 0) - return; - const char *name = psym->ginfo.search_name (); - - if (psym->ginfo.language () == language_ada) + if (lang == language_ada) { /* We want to ensure that the Ada main function's name appears verbatim in the index. However, this name will be of the @@ -706,6 +565,27 @@ public: value_set.emplace (symbol_value (dwarf_tag, cu_index, is_static, kind)); } + void insert (const cooked_index_entry *entry) + { + const auto it = m_cu_index_htab.find (entry->per_cu); + gdb_assert (it != m_cu_index_htab.cend ()); + const char *name = entry->full_name (&m_string_obstack); + + /* This is incorrect but it mirrors gdb's historical behavior; and + because the current .debug_names generation is also incorrect, + it seems better to follow what was done before, rather than + introduce a mismatch between the newer and older gdb. */ + dwarf_tag tag = entry->tag; + if (tag != DW_TAG_typedef && tag_is_type (tag)) + tag = DW_TAG_structure_type; + else if (tag == DW_TAG_enumerator || tag == DW_TAG_constant) + tag = DW_TAG_variable; + + insert (tag, name, it->second, (entry->flags & IS_STATIC) != 0, + entry->per_cu->is_debug_types ? unit_kind::tu : unit_kind::cu, + entry->per_cu->lang); + } + /* Build all the tables. All symbols must be already inserted. This function does not call file_write, caller has to do it afterwards. */ @@ -837,25 +717,6 @@ public: return m_abbrev_table.size (); } - /* Recurse into all "included" dependencies and store their symbols - as if they appeared in this psymtab. */ - void recursively_write_psymbols - (struct objfile *objfile, - partial_symtab *psymtab, - std::unordered_set<partial_symbol *> &psyms_seen, - int cu_index) - { - for (int i = 0; i < psymtab->number_of_dependencies; ++i) - if (psymtab->dependencies[i]->user != NULL) - recursively_write_psymbols - (objfile, psymtab->dependencies[i], psyms_seen, cu_index); - - write_psymbols (psyms_seen, psymtab->global_psymbols, - cu_index, false, unit_kind::cu); - write_psymbols (psyms_seen, psymtab->static_psymbols, - cu_index, true, unit_kind::cu); - } - /* Return number of bytes the .debug_names section will have. This must be called only after calling the build method. */ size_t bytes () const @@ -888,6 +749,11 @@ public: m_debugstrlookup.file_write (file_str); } + void add_cu (dwarf2_per_cu_data *per_cu, offset_type index) + { + m_cu_index_htab.emplace (per_cu, index); + } + private: /* Storage for symbol names mapping them to their .debug_str section @@ -1117,59 +983,6 @@ private: offset_vec_tmpl<OffsetSize> m_name_table_entry_offs; }; - /* Try to reconstruct original DWARF tag for given partial_symbol. - This function is not DWARF-5 compliant but it is sufficient for - GDB as a DWARF-5 index consumer. */ - static int psymbol_tag (const struct partial_symbol *psym) - { - domain_enum domain = psym->domain; - enum address_class aclass = psym->aclass; - - switch (domain) - { - case VAR_DOMAIN: - switch (aclass) - { - case LOC_BLOCK: - return DW_TAG_subprogram; - case LOC_TYPEDEF: - return DW_TAG_typedef; - case LOC_COMPUTED: - case LOC_CONST_BYTES: - case LOC_OPTIMIZED_OUT: - case LOC_STATIC: - return DW_TAG_variable; - case LOC_CONST: - /* Note: It's currently impossible to recognize psyms as enum values - short of reading the type info. For now punt. */ - return DW_TAG_variable; - default: - /* There are other LOC_FOO values that one might want to classify - as variables, but dwarf2read.c doesn't currently use them. */ - return DW_TAG_variable; - } - case STRUCT_DOMAIN: - return DW_TAG_structure_type; - case MODULE_DOMAIN: - return DW_TAG_module; - default: - return 0; - } - } - - /* Call insert for all partial symbols and mark them in PSYMS_SEEN. */ - void write_psymbols (std::unordered_set<partial_symbol *> &psyms_seen, - const std::vector<partial_symbol *> &symbols, - int cu_index, bool is_static, unit_kind kind) - { - for (partial_symbol *psym : symbols) - { - /* Only add a given psymbol once. */ - if (psyms_seen.insert (psym).second) - insert (psym, cu_index, is_static, kind); - } - } - /* Store value of each symbol. */ std::unordered_map<c_str_view, std::set<symbol_value>, c_str_view_hasher> m_name_to_value_set; @@ -1202,6 +1015,8 @@ private: /* Temporary storage for Ada names. */ auto_obstack m_string_obstack; + + cu_index_map m_cu_index_htab; }; /* Return iff any of the needed offsets does not fit into 32-bit @@ -1219,28 +1034,6 @@ check_dwarf64_offsets (dwarf2_per_objfile *per_objfile) return false; } -/* The psyms_seen set is potentially going to be largish (~40k - elements when indexing a -g3 build of GDB itself). Estimate the - number of elements in order to avoid too many rehashes, which - require rebuilding buckets and thus many trips to - malloc/free. */ - -static size_t -psyms_seen_size (dwarf2_per_objfile *per_objfile) -{ - size_t psyms_count = 0; - for (const auto &per_cu : per_objfile->per_bfd->all_comp_units) - { - partial_symtab *psymtab = per_cu->v.psymtab; - - if (psymtab != NULL && psymtab->user == NULL) - recursively_count_psymbols (psymtab, psyms_count); - } - /* Generating an index for gdb itself shows a ratio of - TOTAL_SEEN_SYMS/UNIQUE_SYMS or ~5. 4 seems like a good bet. */ - return psyms_count / 4; -} - /* Assert that FILE's size is EXPECTED_SIZE. Assumes file's seek position is at the end of the file. */ @@ -1303,25 +1096,86 @@ write_gdbindex_1 (FILE *out_file, assert_file_size (out_file, total_len); } +/* Write the contents of the internal "cooked" index. */ + +static void +write_cooked_index (cooked_index_vector *table, + const cu_index_map &cu_index_htab, + struct mapped_symtab *symtab) +{ + /* We track type names and only enter a given type once. */ + htab_up type_names (htab_create_alloc (10, htab_hash_string, htab_eq_string, + nullptr, xcalloc, xfree)); + /* Same with variable names. However, if a type and variable share + a name, we want both, which is why there are two hash tables + here. */ + htab_up var_names (htab_create_alloc (10, htab_hash_string, htab_eq_string, + nullptr, xcalloc, xfree)); + + for (const cooked_index_entry *entry : table->all_entries ()) + { + /* GDB never put linkage names into .gdb_index. The theory here + is that a linkage name will normally be in the minimal + symbols anyway, so including it in the index is usually + redundant -- and the cases where it would not be redundant + are rare and not worth supporting. */ + if ((entry->flags & IS_LINKAGE) != 0) + continue; + + const auto it = cu_index_htab.find (entry->per_cu); + gdb_assert (it != cu_index_htab.cend ()); + + const char *name = entry->full_name (&symtab->m_string_obstack); + + gdb_index_symbol_kind kind; + if (entry->tag == DW_TAG_subprogram) + kind = GDB_INDEX_SYMBOL_KIND_FUNCTION; + else if (entry->tag == DW_TAG_variable + || entry->tag == DW_TAG_constant + || entry->tag == DW_TAG_enumerator) + { + kind = GDB_INDEX_SYMBOL_KIND_VARIABLE; + void **slot = htab_find_slot (var_names.get (), name, INSERT); + if (*slot != nullptr) + continue; + *slot = (void *) name; + } + else if (entry->tag == DW_TAG_module + || entry->tag == DW_TAG_common_block) + kind = GDB_INDEX_SYMBOL_KIND_OTHER; + else + { + kind = GDB_INDEX_SYMBOL_KIND_TYPE; + void **slot = htab_find_slot (type_names.get (), name, INSERT); + if (*slot != nullptr) + continue; + *slot = (void *) name; + } + + add_index_entry (symtab, name, (entry->flags & IS_STATIC) != 0, + kind, it->second); + } +} + /* Write contents of a .gdb_index section for OBJFILE into OUT_FILE. If OBJFILE has an associated dwz file, write contents of a .gdb_index section for that dwz file into DWZ_OUT_FILE. If OBJFILE does not have an associated dwz file, DWZ_OUT_FILE must be NULL. */ static void -write_gdbindex (dwarf2_per_objfile *per_objfile, FILE *out_file, - FILE *dwz_out_file) +write_gdbindex (dwarf2_per_objfile *per_objfile, + cooked_index_vector *table, + FILE *out_file, FILE *dwz_out_file) { - struct objfile *objfile = per_objfile->objfile; mapped_symtab symtab; data_buf objfile_cu_list; data_buf dwz_cu_list; - /* While we're scanning CU's create a table that maps a psymtab pointer + /* While we're scanning CU's create a table that maps a dwarf2_per_cu_data (which is what addrmap records) to its index (which is what is recorded in the index file). This will later be needed to write the address table. */ - psym_index_map cu_index_htab; + cu_index_map cu_index_htab; cu_index_htab.reserve (per_objfile->per_bfd->all_comp_units.size ()); /* Store out the .debug_type CUs, if any. */ @@ -1331,28 +1185,17 @@ write_gdbindex (dwarf2_per_objfile *per_objfile, FILE *out_file, work here. Also, the debug_types entries do not appear in all_comp_units, but only in their own hash table. */ - std::unordered_set<partial_symbol *> psyms_seen - (psyms_seen_size (per_objfile)); int counter = 0; int types_counter = 0; for (int i = 0; i < per_objfile->per_bfd->all_comp_units.size (); ++i) { dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->all_comp_units[i].get (); - partial_symtab *psymtab = per_cu->v.psymtab; int &this_counter = per_cu->is_debug_types ? types_counter : counter; - if (psymtab != NULL) - { - if (psymtab->user == NULL) - recursively_write_psymbols (objfile, psymtab, &symtab, - psyms_seen, this_counter); - - const auto insertpair = cu_index_htab.emplace (psymtab, - this_counter); - gdb_assert (insertpair.second); - } + const auto insertpair = cu_index_htab.emplace (per_cu, this_counter); + gdb_assert (insertpair.second); /* The all_comp_units list contains CUs read from the objfile as well as from the eventual dwz file. We need to place the entry in the @@ -1376,9 +1219,12 @@ write_gdbindex (dwarf2_per_objfile *per_objfile, FILE *out_file, ++this_counter; } + write_cooked_index (table, cu_index_htab, &symtab); + /* Dump the address map. */ data_buf addr_vec; - write_address_map (per_objfile->per_bfd, addr_vec, cu_index_htab); + for (auto map : table->get_addrmaps ()) + write_address_map (map, addr_vec, cu_index_htab); /* Now that we've processed all symbols we can shrink their cu_indices lists. */ @@ -1408,6 +1254,7 @@ static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 }; static void write_debug_names (dwarf2_per_objfile *per_objfile, + cooked_index_vector *table, FILE *out_file, FILE *out_file_str) { const bool dwarf5_is_dwarf64 = check_dwarf64_offsets (per_objfile); @@ -1421,23 +1268,17 @@ write_debug_names (dwarf2_per_objfile *per_objfile, data_buf cu_list; data_buf types_cu_list; debug_names nametable (per_objfile, dwarf5_is_dwarf64, dwarf5_byte_order); - std::unordered_set<partial_symbol *> - psyms_seen (psyms_seen_size (per_objfile)); int counter = 0; int types_counter = 0; for (int i = 0; i < per_objfile->per_bfd->all_comp_units.size (); ++i) { - const dwarf2_per_cu_data *per_cu + dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->all_comp_units[i].get (); - partial_symtab *psymtab = per_cu->v.psymtab; int &this_counter = per_cu->is_debug_types ? types_counter : counter; data_buf &this_list = per_cu->is_debug_types ? types_cu_list : cu_list; - if (psymtab != nullptr && psymtab->user == nullptr) - nametable.recursively_write_psymbols (objfile, psymtab, psyms_seen, - this_counter); - + nametable.add_cu (per_cu, this_counter); this_list.append_uint (nametable.dwarf5_offset_size (), dwarf5_byte_order, to_underlying (per_cu->sect_off)); @@ -1449,6 +1290,9 @@ write_debug_names (dwarf2_per_objfile *per_objfile, - per_objfile->per_bfd->tu_stats.nr_tus)); gdb_assert (types_counter == per_objfile->per_bfd->tu_stats.nr_tus); + for (const cooked_index_entry *entry : table->all_entries ()) + nametable.insert (entry); + nametable.build (); /* No addr_vec - DWARF-5 uses .debug_aranges generated by GCC. */ @@ -1577,27 +1421,22 @@ struct index_wip_file /* See dwarf-index-write.h. */ void -write_psymtabs_to_index (dwarf2_per_objfile *per_objfile, const char *dir, - const char *basename, const char *dwz_basename, - dw_index_kind index_kind) +write_dwarf_index (dwarf2_per_objfile *per_objfile, const char *dir, + const char *basename, const char *dwz_basename, + dw_index_kind index_kind) { - dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; struct objfile *objfile = per_objfile->objfile; - if (per_objfile->per_bfd->using_index) - error (_("Cannot use an index to create the index")); + if (per_objfile->per_bfd->index_table == nullptr) + error (_("No debugging symbols")); + cooked_index_vector *table + = per_objfile->per_bfd->index_table->index_for_writing (); if (per_objfile->per_bfd->types.size () > 1) error (_("Cannot make an index when the file has multiple .debug_types sections")); - if (per_bfd->partial_symtabs == nullptr - || !per_bfd->partial_symtabs->psymtabs - || !per_bfd->partial_symtabs->psymtabs_addrmap) - return; - struct stat st; - if (stat (objfile_name (objfile), &st) < 0) - perror_with_name (objfile_name (objfile)); + gdb_assert ((objfile->flags & OBJF_NOT_FILENAME) == 0); const char *index_suffix = (index_kind == dw_index_kind::DEBUG_NAMES ? INDEX5_SUFFIX : INDEX4_SUFFIX); @@ -1612,13 +1451,13 @@ write_psymtabs_to_index (dwarf2_per_objfile *per_objfile, const char *dir, { index_wip_file str_wip_file (dir, basename, DEBUG_STR_SUFFIX); - write_debug_names (per_objfile, objfile_index_wip.out_file.get (), + write_debug_names (per_objfile, table, objfile_index_wip.out_file.get (), str_wip_file.out_file.get ()); str_wip_file.finalize (); } else - write_gdbindex (per_objfile, objfile_index_wip.out_file.get (), + write_gdbindex (per_objfile, table, objfile_index_wip.out_file.get (), (dwz_index_wip.has_value () ? dwz_index_wip->out_file.get () : NULL)); @@ -1656,10 +1495,8 @@ save_gdb_index_command (const char *arg, int from_tty) for (objfile *objfile : current_program_space->objfiles ()) { - struct stat st; - /* If the objfile does not correspond to an actual file, skip it. */ - if (stat (objfile_name (objfile), &st) < 0) + if ((objfile->flags & OBJF_NOT_FILENAME) != 0) continue; dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); @@ -1675,8 +1512,8 @@ save_gdb_index_command (const char *arg, int from_tty) if (dwz != NULL) dwz_basename = lbasename (dwz->filename ()); - write_psymtabs_to_index (per_objfile, arg, basename, dwz_basename, - index_kind); + write_dwarf_index (per_objfile, arg, basename, dwz_basename, + index_kind); } catch (const gdb_exception_error &except) { |