#include "defs.h"
#include "read-debug-names.h"
#include "dwarf2/aranges.h"
+#include "dwarf2/cooked-index.h"
#include "complaints.h"
#include "cp-support.h"
#include "read.h"
#include "stringify.h"
-/* A description of the mapped .debug_names.
- Uninitialized map has CU_COUNT 0. */
+/* This is just like cooked_index_functions, but overrides a single
+ method so the test suite can distinguish the .debug_names case from
+ the ordinary case. */
+struct dwarf2_debug_names_index : public cooked_index_functions
+{
+ /* This dumps minimal information about .debug_names. It is called
+ via "mt print objfiles". The gdb.dwarf2/gdb-index.exp testcase
+ uses this to verify that .debug_names has been loaded. */
+ void dump (struct objfile *objfile) override
+ {
+ gdb_printf (".debug_names: exists\n");
+ /* This could call the superclass method if that's useful. */
+ }
+};
+
+/* This is like a cooked index, but as it has been ingested from
+ .debug_names, it can't be used to write out an index. */
+class debug_names_index : public cooked_index
+{
+public:
+
+ using cooked_index::cooked_index;
+
+ cooked_index *index_for_writing () override
+ { return nullptr; }
+
+ quick_symbol_functions_up make_quick_functions () const override
+ { return quick_symbol_functions_up (new dwarf2_debug_names_index); }
+};
+
+/* A description of the mapped .debug_names. */
-struct mapped_debug_names final : public mapped_index_base
+struct mapped_debug_names_reader
{
- bfd_endian dwarf5_byte_order;
- bool dwarf5_is_dwarf64;
- bool augmentation_is_gdb;
- uint8_t offset_size;
+ const gdb_byte *scan_one_entry (const char *name,
+ const gdb_byte *entry,
+ cooked_index_entry **result,
+ std::optional<ULONGEST> &parent);
+ void scan_entries (uint32_t index, const char *name, const gdb_byte *entry);
+ void scan_all_names ();
+
+ dwarf2_per_objfile *per_objfile = nullptr;
+ bfd *abfd = nullptr;
+ bfd_endian dwarf5_byte_order {};
+ bool dwarf5_is_dwarf64 = false;
+ bool augmentation_is_gdb = false;
+ uint8_t offset_size = 0;
uint32_t cu_count = 0;
- uint32_t tu_count, bucket_count, name_count;
- const gdb_byte *cu_table_reordered, *tu_table_reordered;
- const uint32_t *bucket_table_reordered, *hash_table_reordered;
- const gdb_byte *name_table_string_offs_reordered;
- const gdb_byte *name_table_entry_offs_reordered;
- const gdb_byte *entry_pool;
+ uint32_t tu_count = 0, bucket_count = 0, name_count = 0;
+ const gdb_byte *cu_table_reordered = nullptr;
+ const gdb_byte *tu_table_reordered = nullptr;
+ const uint32_t *bucket_table_reordered = nullptr;
+ const uint32_t *hash_table_reordered = nullptr;
+ const gdb_byte *name_table_string_offs_reordered = nullptr;
+ const gdb_byte *name_table_entry_offs_reordered = nullptr;
+ const gdb_byte *entry_pool = nullptr;
struct index_val
{
std::unordered_map<ULONGEST, index_val> abbrev_map;
- const char *namei_to_name
- (uint32_t namei, dwarf2_per_objfile *per_objfile) const;
+ std::unique_ptr<cooked_index_shard> shard;
+ std::vector<std::pair<cooked_index_entry *, ULONGEST>> needs_parent;
+ std::vector<std::vector<cooked_index_entry *>> all_entries;
+};
- /* Implementation of the mapped_index_base virtual interface, for
- the name_components cache. */
+/* Scan a single entry from the entries table. Set *RESULT and PARENT
+ (if needed) and return the updated pointer on success, or return
+ nullptr on error, or at the end of the table. */
- const char *symbol_name_at
- (offset_type idx, dwarf2_per_objfile *per_objfile) const override
- { return namei_to_name (idx, per_objfile); }
+const gdb_byte *
+mapped_debug_names_reader::scan_one_entry (const char *name,
+ const gdb_byte *entry,
+ cooked_index_entry **result,
+ std::optional<ULONGEST> &parent)
+{
+ unsigned int bytes_read;
+ const ULONGEST abbrev = read_unsigned_leb128 (abfd, entry, &bytes_read);
+ entry += bytes_read;
+ if (abbrev == 0)
+ return nullptr;
- size_t symbol_name_count () const override
- { return this->name_count; }
+ const auto indexval_it = abbrev_map.find (abbrev);
+ if (indexval_it == abbrev_map.cend ())
+ {
+ complaint (_("Wrong .debug_names undefined abbrev code %s "
+ "[in module %s]"),
+ pulongest (abbrev), bfd_get_filename (abfd));
+ return nullptr;
+ }
- quick_symbol_functions_up make_quick_functions () const override;
-};
+ const auto &indexval = indexval_it->second;
+ cooked_index_flag flags = 0;
+ sect_offset die_offset {};
+ enum language lang = language_unknown;
+ dwarf2_per_cu_data *per_cu = nullptr;
+ for (const auto &attr : indexval.attr_vec)
+ {
+ ULONGEST ull;
+ switch (attr.form)
+ {
+ case DW_FORM_implicit_const:
+ ull = attr.implicit_const;
+ break;
+ case DW_FORM_flag_present:
+ ull = 1;
+ break;
+ case DW_FORM_udata:
+ ull = read_unsigned_leb128 (abfd, entry, &bytes_read);
+ entry += bytes_read;
+ break;
+ case DW_FORM_ref4:
+ ull = read_4_bytes (abfd, entry);
+ entry += 4;
+ break;
+ case DW_FORM_ref8:
+ ull = read_8_bytes (abfd, entry);
+ entry += 8;
+ break;
+ case DW_FORM_ref_sig8:
+ ull = read_8_bytes (abfd, entry);
+ entry += 8;
+ break;
+ default:
+ complaint (_("Unsupported .debug_names form %s [in module %s]"),
+ dwarf_form_name (attr.form),
+ bfd_get_filename (abfd));
+ return nullptr;
+ }
+ switch (attr.dw_idx)
+ {
+ case DW_IDX_compile_unit:
+ {
+ /* Don't crash on bad data. */
+ if (ull >= per_objfile->per_bfd->all_comp_units.size ())
+ {
+ complaint (_(".debug_names entry has bad CU index %s"
+ " [in module %s]"),
+ pulongest (ull),
+ bfd_get_filename (abfd));
+ continue;
+ }
+ }
+ per_cu = per_objfile->per_bfd->get_cu (ull);
+ break;
+ case DW_IDX_type_unit:
+ /* Don't crash on bad data. */
+ if (ull >= per_objfile->per_bfd->all_type_units.size ())
+ {
+ complaint (_(".debug_names entry has bad TU index %s"
+ " [in module %s]"),
+ pulongest (ull),
+ bfd_get_filename (abfd));
+ continue;
+ }
+ {
+ int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
+ per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull);
+ }
+ break;
+ case DW_IDX_die_offset:
+ die_offset = sect_offset (ull);
+ /* In a per-CU index (as opposed to a per-module index), index
+ entries without CU attribute implicitly refer to the single CU. */
+ if (per_cu == NULL)
+ per_cu = per_objfile->per_bfd->get_cu (0);
+ break;
+ case DW_IDX_parent:
+ parent = ull;
+ break;
+ case DW_IDX_GNU_internal:
+ if (augmentation_is_gdb && ull != 0)
+ flags |= IS_STATIC;
+ break;
+ case DW_IDX_GNU_main:
+ if (augmentation_is_gdb && ull != 0)
+ flags |= IS_MAIN;
+ break;
+ case DW_IDX_GNU_language:
+ if (augmentation_is_gdb)
+ lang = dwarf_lang_to_enum_language (ull);
+ break;
+ case DW_IDX_GNU_linkage_name:
+ if (augmentation_is_gdb && ull != 0)
+ flags |= IS_LINKAGE;
+ break;
+ }
+ }
+
+ /* Skip if we couldn't find a valid CU/TU index. */
+ if (per_cu != nullptr)
+ *result = shard->add (die_offset, (dwarf_tag) indexval.dwarf_tag, flags,
+ lang, name, nullptr, per_cu);
+ return entry;
+}
+
+/* Scan all the entries for NAME, at name slot INDEX. */
-struct dwarf2_debug_names_index : public dwarf2_base_index_functions
+void
+mapped_debug_names_reader::scan_entries (uint32_t index,
+ const char *name,
+ const gdb_byte *entry)
{
- void dump (struct objfile *objfile) 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;
+ std::vector<cooked_index_entry *> these_entries;
+
+ while (true)
+ {
+ std::optional<ULONGEST> parent;
+ cooked_index_entry *this_entry;
+ entry = scan_one_entry (name, entry, &this_entry, parent);
+
+ if (entry == nullptr)
+ break;
+
+ these_entries.push_back (this_entry);
+ if (parent.has_value ())
+ needs_parent.emplace_back (this_entry, *parent);
+ }
+
+ all_entries[index] = std::move (these_entries);
+}
+
+/* Scan the name table and create all the entries. */
+
+void
+mapped_debug_names_reader::scan_all_names ()
+{
+ all_entries.resize (name_count);
+
+ /* In the first pass, create all the entries. */
+ for (uint32_t i = 0; i < name_count; ++i)
+ {
+ const ULONGEST namei_string_offs
+ = extract_unsigned_integer ((name_table_string_offs_reordered
+ + i * offset_size),
+ offset_size, dwarf5_byte_order);
+ const char *name = read_indirect_string_at_offset (per_objfile,
+ namei_string_offs);
+
+ const ULONGEST namei_entry_offs
+ = extract_unsigned_integer ((name_table_entry_offs_reordered
+ + i * offset_size),
+ offset_size, dwarf5_byte_order);
+ const gdb_byte *entry = entry_pool + namei_entry_offs;
+
+ scan_entries (i, name, entry);
+ }
+
+ /* Now update the parent pointers for all entries. This has to be
+ done in a funny way because DWARF specifies the parent entry to
+ point to a name -- but we don't know which specific one. */
+ for (auto [entry, parent_idx] : needs_parent)
+ {
+ /* Name entries are indexed from 1 in DWARF. */
+ std::vector<cooked_index_entry *> &entries = all_entries[parent_idx - 1];
+ for (const auto &parent : entries)
+ if (parent->lang == entry->lang)
+ {
+ entry->set_parent (parent);
+ break;
+ }
+ }
+}
+
+/* A reader for .debug_names. */
+
+struct cooked_index_debug_names : public cooked_index_worker
+{
+ cooked_index_debug_names (dwarf2_per_objfile *per_objfile,
+ mapped_debug_names_reader &&map)
+ : cooked_index_worker (per_objfile),
+ m_map (std::move (map))
+ { }
+
+ void do_reading () override;
+
+ mapped_debug_names_reader m_map;
};
-quick_symbol_functions_up
-mapped_debug_names::make_quick_functions () const
+void
+cooked_index_debug_names::do_reading ()
{
- return quick_symbol_functions_up (new dwarf2_debug_names_index);
+ complaint_interceptor complaint_handler;
+ std::vector<gdb_exception> exceptions;
+ try
+ {
+ m_map.scan_all_names ();
+ }
+ catch (const gdb_exception &exc)
+ {
+ exceptions.push_back (std::move (exc));
+ }
+
+ dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
+ per_bfd->quick_file_names_table
+ = create_quick_file_names_table (per_bfd->all_units.size ());
+ m_results.emplace_back (nullptr,
+ complaint_handler.release (),
+ std::move (exceptions));
+ std::vector<std::unique_ptr<cooked_index_shard>> indexes;
+ indexes.push_back (std::move (m_map.shard));
+ cooked_index *table
+ = (gdb::checked_static_cast<cooked_index *>
+ (per_bfd->index_table.get ()));
+ table->set_contents (std::move (indexes));
+
+ bfd_thread_cleanup ();
}
/* Check the signatured type hash table from .debug_names. */
static bool
check_signatured_type_table_from_debug_names
(dwarf2_per_objfile *per_objfile,
- const mapped_debug_names &map,
+ const mapped_debug_names_reader &map,
struct dwarf2_section_info *section)
{
struct objfile *objfile = per_objfile->objfile;
return true;
}
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
- populate the index_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;
-
- addrmap_mutable mutable_map;
- deferred_warnings warnings;
-
- section->read (per_objfile->objfile);
- if (read_addrmap_from_aranges (per_objfile, section, &mutable_map,
- &warnings))
- per_bfd->index_addrmap
- = new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack,
- &mutable_map);
-
- warnings.emit ();
-}
-
/* DWARF-5 debug_names reader. */
-/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension. */
-static const gdb_byte dwarf5_augmentation[] = { 'G', 'D', 'B', 0 };
+/* The old, no-longer-supported GDB augmentation. */
+static const gdb_byte old_gdb_augmentation[]
+ = { 'G', 'D', 'B', 0 };
+static_assert (sizeof (old_gdb_augmentation) % 4 == 0);
+
+/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension. This
+ must have a size that is a multiple of 4. */
+static const gdb_byte dwarf5_augmentation[]
+ = { 'G', 'D', 'B', '2', 0, 0, 0, 0 };
+static_assert (sizeof (dwarf5_augmentation) % 4 == 0);
/* A helper function that reads the .debug_names section in SECTION
and fills in MAP. FILENAME is the name of the file containing the
Returns true if all went well, false otherwise. */
static bool
-read_debug_names_from_section (struct objfile *objfile,
+read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
const char *filename,
struct dwarf2_section_info *section,
- mapped_debug_names &map)
+ mapped_debug_names_reader &map)
{
+ struct objfile *objfile = per_objfile->objfile;
+
if (section->empty ())
return false;
section->read (objfile);
+ map.per_objfile = per_objfile;
map.dwarf5_byte_order = gdbarch_byte_order (objfile->arch ());
const gdb_byte *addr = section->buffer;
- bfd *const abfd = section->get_bfd_owner ();
+ bfd *abfd = section->get_bfd_owner ();
+ map.abfd = abfd;
unsigned int bytes_read;
LONGEST length = read_initial_length (abfd, addr, &bytes_read);
string. This value is rounded up to a multiple of 4. */
uint32_t augmentation_string_size = read_4_bytes (abfd, addr);
addr += 4;
+ augmentation_string_size += (-augmentation_string_size) & 3;
+
+ if (augmentation_string_size == sizeof (old_gdb_augmentation)
+ && memcmp (addr, old_gdb_augmentation,
+ sizeof (old_gdb_augmentation)) == 0)
+ {
+ warning (_(".debug_names created by an old version of gdb; ignoring"));
+ return false;
+ }
+
map.augmentation_is_gdb = ((augmentation_string_size
== sizeof (dwarf5_augmentation))
&& memcmp (addr, dwarf5_augmentation,
sizeof (dwarf5_augmentation)) == 0);
- augmentation_string_size += (-augmentation_string_size) & 3;
+
+ if (!map.augmentation_is_gdb)
+ {
+ warning (_(".debug_names not created by gdb; ignoring"));
+ return false;
+ }
+
addr += augmentation_string_size;
/* List of CUs */
break;
const auto insertpair
- = map.abbrev_map.emplace (index_num, mapped_debug_names::index_val ());
+ = map.abbrev_map.emplace (index_num, mapped_debug_names_reader::index_val ());
if (!insertpair.second)
{
warning (_("Section .debug_names in %s has duplicate index %s, "
filename, pulongest (index_num));
return false;
}
- mapped_debug_names::index_val &indexval = insertpair.first->second;
+ mapped_debug_names_reader::index_val &indexval = insertpair.first->second;
indexval.dwarf_tag = read_unsigned_leb128 (abfd, addr, &bytes_read);
addr += bytes_read;
for (;;)
{
- mapped_debug_names::index_val::attr attr;
+ mapped_debug_names_reader::index_val::attr attr;
attr.dw_idx = read_unsigned_leb128 (abfd, addr, &bytes_read);
addr += bytes_read;
attr.form = read_unsigned_leb128 (abfd, addr, &bytes_read);
static bool
check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names &map,
- dwarf2_section_info §ion,
- bool is_dwz)
+ const mapped_debug_names_reader &map,
+ dwarf2_section_info §ion,
+ bool is_dwz)
{
int nr_cus = per_bfd->all_comp_units.size ();
static bool
check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
- const mapped_debug_names &map,
- const mapped_debug_names &dwz_map)
+ const mapped_debug_names_reader &map,
+ const mapped_debug_names_reader &dwz_map)
{
if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->info,
false /* is_dwz */))
true /* is_dwz */);
}
-/* See read-debug-names.h. */
+/* This does all the work for dwarf2_read_debug_names, but putting it
+ into a separate function makes some cleanup a bit simpler. */
-bool
-dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
+static bool
+do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
{
- auto map = std::make_unique<mapped_debug_names> ();
- mapped_debug_names dwz_map;
+ mapped_debug_names_reader map;
+ mapped_debug_names_reader dwz_map;
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
- if (!read_debug_names_from_section (objfile, objfile_name (objfile),
- &per_bfd->debug_names, *map))
+ if (!read_debug_names_from_section (per_objfile, objfile_name (objfile),
+ &per_bfd->debug_names, map))
return false;
/* Don't use the index if it's empty. */
- if (map->name_count == 0)
+ if (map.name_count == 0)
return false;
/* If there is a .dwz file, read it so we can get its CU list as
dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
if (dwz != NULL)
{
- if (!read_debug_names_from_section (objfile,
+ if (!read_debug_names_from_section (per_objfile,
bfd_get_filename (dwz->dwz_bfd.get ()),
&dwz->debug_names, dwz_map))
{
}
create_all_units (per_objfile);
- if (!check_cus_from_debug_names (per_bfd, *map, dwz_map))
- {
- per_bfd->all_units.clear ();
- return false;
- }
+ if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
+ return false;
- if (map->tu_count != 0)
+ if (map.tu_count != 0)
{
/* 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 false;
- }
+ return false;
dwarf2_section_info *section
= (per_bfd->types.size () == 1
? &per_bfd->types[0]
: &per_bfd->info);
- if (!check_signatured_type_table_from_debug_names
- (per_objfile, *map, section))
- {
- per_bfd->all_units.clear ();
- return false;
- }
- }
-
- create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges);
-
- per_bfd->index_table = std::move (map);
- per_bfd->quick_file_names_table =
- create_quick_file_names_table (per_bfd->all_units.size ());
-
- return true;
-}
-
-/* Type used to manage iterating over all CUs looking for a symbol for
- .debug_names. */
-
-class dw2_debug_names_iterator
-{
-public:
- dw2_debug_names_iterator (const mapped_debug_names &map,
- block_search_flags block_index,
- domain_enum domain,
- const char *name, dwarf2_per_objfile *per_objfile)
- : m_map (map), m_block_index (block_index), m_domain (domain),
- m_addr (find_vec_in_debug_names (map, name, per_objfile)),
- m_per_objfile (per_objfile)
- {}
-
- dw2_debug_names_iterator (const mapped_debug_names &map,
- search_domain search, uint32_t namei,
- dwarf2_per_objfile *per_objfile,
- domain_enum domain = UNDEF_DOMAIN)
- : m_map (map),
- m_domain (domain),
- m_search (search),
- m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
- m_per_objfile (per_objfile)
- {}
-
- dw2_debug_names_iterator (const mapped_debug_names &map,
- block_search_flags block_index, domain_enum domain,
- uint32_t namei, dwarf2_per_objfile *per_objfile)
- : m_map (map), m_block_index (block_index), m_domain (domain),
- m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
- m_per_objfile (per_objfile)
- {}
-
- /* Return the next matching CU or NULL if there are no more. */
- dwarf2_per_cu_data *next ();
-
-private:
- static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
- const char *name,
- dwarf2_per_objfile *per_objfile);
- static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
- uint32_t namei,
- dwarf2_per_objfile *per_objfile);
-
- /* The internalized form of .debug_names. */
- const mapped_debug_names &m_map;
-
- /* Restrict the search to these blocks. */
- block_search_flags m_block_index = (SEARCH_GLOBAL_BLOCK
- | SEARCH_STATIC_BLOCK);
-
- /* The kind of symbol we're looking for. */
- const domain_enum m_domain = UNDEF_DOMAIN;
- const search_domain m_search = ALL_DOMAIN;
-
- /* The list of CUs from the index entry of the symbol, or NULL if
- not found. */
- const gdb_byte *m_addr;
-
- dwarf2_per_objfile *m_per_objfile;
-};
-
-const char *
-mapped_debug_names::namei_to_name
- (uint32_t namei, dwarf2_per_objfile *per_objfile) const
-{
- const ULONGEST namei_string_offs
- = extract_unsigned_integer ((name_table_string_offs_reordered
- + namei * offset_size),
- offset_size,
- dwarf5_byte_order);
- return read_indirect_string_at_offset (per_objfile, namei_string_offs);
-}
-
-/* Find a slot in .debug_names for the object named NAME. If NAME is
- found, return pointer to its pool data. If NAME cannot be found,
- return NULL. */
-
-const gdb_byte *
-dw2_debug_names_iterator::find_vec_in_debug_names
- (const mapped_debug_names &map, const char *name,
- dwarf2_per_objfile *per_objfile)
-{
- int (*cmp) (const char *, const char *);
-
- gdb::unique_xmalloc_ptr<char> without_params;
- if (current_language->la_language == language_cplus
- || current_language->la_language == language_fortran
- || current_language->la_language == language_d)
- {
- /* NAME is already canonical. Drop any qualifiers as
- .debug_names does not contain any. */
-
- if (strchr (name, '(') != NULL)
- {
- without_params = cp_remove_params (name);
- if (without_params != NULL)
- name = without_params.get ();
- }
- }
-
- cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
-
- const uint32_t full_hash = dwarf5_djb_hash (name);
- uint32_t namei
- = extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
- (map.bucket_table_reordered
- + (full_hash % map.bucket_count)), 4,
- map.dwarf5_byte_order);
- if (namei == 0)
- return NULL;
- --namei;
- if (namei >= map.name_count)
- {
- complaint (_("Wrong .debug_names with name index %u but name_count=%u "
- "[in module %s]"),
- namei, map.name_count,
- objfile_name (per_objfile->objfile));
- return NULL;
- }
-
- for (;;)
- {
- const uint32_t namei_full_hash
- = extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
- (map.hash_table_reordered + namei), 4,
- map.dwarf5_byte_order);
- if (full_hash % map.bucket_count != namei_full_hash % map.bucket_count)
- return NULL;
-
- if (full_hash == namei_full_hash)
- {
- const char *const namei_string = map.namei_to_name (namei, per_objfile);
-
-#if 0 /* An expensive sanity check. */
- if (namei_full_hash != dwarf5_djb_hash (namei_string))
- {
- complaint (_("Wrong .debug_names hash for string at index %u "
- "[in module %s]"),
- namei, objfile_name (dwarf2_per_objfile->objfile));
- return NULL;
- }
-#endif
-
- if (cmp (namei_string, name) == 0)
- {
- const ULONGEST namei_entry_offs
- = extract_unsigned_integer ((map.name_table_entry_offs_reordered
- + namei * map.offset_size),
- map.offset_size, map.dwarf5_byte_order);
- return map.entry_pool + namei_entry_offs;
- }
- }
-
- ++namei;
- if (namei >= map.name_count)
- return NULL;
+ if (!check_signatured_type_table_from_debug_names (per_objfile,
+ map, section))
+ return false;
}
-}
-
-const gdb_byte *
-dw2_debug_names_iterator::find_vec_in_debug_names
- (const mapped_debug_names &map, uint32_t namei, dwarf2_per_objfile *per_objfile)
-{
- if (namei >= map.name_count)
- {
- complaint (_("Wrong .debug_names with name index %u but name_count=%u "
- "[in module %s]"),
- namei, map.name_count,
- objfile_name (per_objfile->objfile));
- return NULL;
- }
-
- const ULONGEST namei_entry_offs
- = extract_unsigned_integer ((map.name_table_entry_offs_reordered
- + namei * map.offset_size),
- map.offset_size, map.dwarf5_byte_order);
- return map.entry_pool + namei_entry_offs;
-}
-
-/* See dw2_debug_names_iterator. */
-
-dwarf2_per_cu_data *
-dw2_debug_names_iterator::next ()
-{
- if (m_addr == NULL)
- return NULL;
-
- dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
- struct objfile *objfile = m_per_objfile->objfile;
- bfd *const abfd = objfile->obfd.get ();
- again:
-
- unsigned int bytes_read;
- const ULONGEST abbrev = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
- m_addr += bytes_read;
- if (abbrev == 0)
- return NULL;
-
- const auto indexval_it = m_map.abbrev_map.find (abbrev);
- if (indexval_it == m_map.abbrev_map.cend ())
- {
- complaint (_("Wrong .debug_names undefined abbrev code %s "
- "[in module %s]"),
- pulongest (abbrev), objfile_name (objfile));
- return NULL;
- }
- const mapped_debug_names::index_val &indexval = indexval_it->second;
- enum class symbol_linkage {
- unknown,
- static_,
- extern_,
- } symbol_linkage_ = symbol_linkage::unknown;
- dwarf2_per_cu_data *per_cu = NULL;
- for (const mapped_debug_names::index_val::attr &attr : indexval.attr_vec)
- {
- ULONGEST ull;
- switch (attr.form)
- {
- case DW_FORM_implicit_const:
- ull = attr.implicit_const;
- break;
- case DW_FORM_flag_present:
- ull = 1;
- break;
- case DW_FORM_udata:
- ull = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
- m_addr += bytes_read;
- break;
- case DW_FORM_ref4:
- ull = read_4_bytes (abfd, m_addr);
- m_addr += 4;
- break;
- case DW_FORM_ref8:
- ull = read_8_bytes (abfd, m_addr);
- m_addr += 8;
- break;
- case DW_FORM_ref_sig8:
- ull = read_8_bytes (abfd, m_addr);
- m_addr += 8;
- break;
- default:
- complaint (_("Unsupported .debug_names form %s [in module %s]"),
- dwarf_form_name (attr.form),
- objfile_name (objfile));
- return NULL;
- }
- switch (attr.dw_idx)
- {
- case DW_IDX_compile_unit:
- {
- /* Don't crash on bad data. */
- if (ull >= per_bfd->all_comp_units.size ())
- {
- complaint (_(".debug_names entry has bad CU index %s"
- " [in module %s]"),
- pulongest (ull),
- objfile_name (objfile));
- continue;
- }
- }
- per_cu = per_bfd->get_index_cu (ull);
- break;
- case DW_IDX_type_unit:
- /* Don't crash on bad data. */
- if (ull >= per_bfd->all_type_units.size ())
- {
- complaint (_(".debug_names entry has bad TU index %s"
- " [in module %s]"),
- pulongest (ull),
- objfile_name (objfile));
- continue;
- }
- {
- per_cu = per_bfd->get_index_tu (ull);
- }
- break;
- case DW_IDX_die_offset:
- /* In a per-CU index (as opposed to a per-module index), index
- entries without CU attribute implicitly refer to the single CU. */
- if (per_cu == NULL)
- per_cu = per_bfd->get_index_cu (0);
- break;
- case DW_IDX_GNU_internal:
- if (!m_map.augmentation_is_gdb)
- break;
- symbol_linkage_ = symbol_linkage::static_;
- break;
- case DW_IDX_GNU_external:
- if (!m_map.augmentation_is_gdb)
- break;
- symbol_linkage_ = symbol_linkage::extern_;
- break;
- }
- }
-
- /* Skip if we couldn't find a valid CU/TU index. */
- if (per_cu == nullptr)
- goto again;
-
- /* Skip if already read in. */
- if (m_per_objfile->symtab_set_p (per_cu))
- goto again;
+ per_bfd->debug_aranges.read (per_objfile->objfile);
+ addrmap_mutable addrmap;
+ deferred_warnings warnings;
+ read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+ &addrmap, &warnings);
+ warnings.emit ();
- /* Check static vs global. */
- if (symbol_linkage_ != symbol_linkage::unknown)
- {
- if (symbol_linkage_ == symbol_linkage::static_)
- {
- if ((m_block_index & SEARCH_STATIC_BLOCK) == 0)
- goto again;
- }
- else
- {
- if ((m_block_index & SEARCH_GLOBAL_BLOCK) == 0)
- goto again;
- }
- }
+ map.shard = std::make_unique<cooked_index_shard> ();
+ map.shard->install_addrmap (&addrmap);
- /* Match dw2_symtab_iter_next, symbol_kind
- and debug_names::psymbol_tag. */
- switch (m_domain)
- {
- case VAR_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_variable:
- case DW_TAG_subprogram:
- /* Some types are also in VAR_DOMAIN. */
- case DW_TAG_typedef:
- case DW_TAG_structure_type:
- break;
- default:
- goto again;
- }
- break;
- case STRUCT_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_typedef:
- case DW_TAG_structure_type:
- break;
- default:
- goto again;
- }
- break;
- case LABEL_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case 0:
- case DW_TAG_variable:
- break;
- default:
- goto again;
- }
- break;
- case MODULE_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_module:
- break;
- default:
- goto again;
- }
- break;
- default:
- break;
- }
+ cooked_index *idx
+ = new debug_names_index (per_objfile,
+ (std::make_unique<cooked_index_debug_names>
+ (per_objfile, std::move (map))));
+ per_bfd->index_table.reset (idx);
- /* Match dw2_expand_symtabs_matching, symbol_kind and
- debug_names::psymbol_tag. */
- switch (m_search)
- {
- case VARIABLES_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_variable:
- break;
- default:
- goto again;
- }
- break;
- case FUNCTIONS_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_subprogram:
- break;
- default:
- goto again;
- }
- break;
- case TYPES_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_typedef:
- case DW_TAG_structure_type:
- break;
- default:
- goto again;
- }
- break;
- case MODULES_DOMAIN:
- switch (indexval.dwarf_tag)
- {
- case DW_TAG_module:
- break;
- default:
- goto again;
- }
- default:
- break;
- }
+ idx->start_reading ();
- return per_cu;
+ return true;
}
-/* This dumps minimal information about .debug_names. It is called
- via "mt print objfiles". The gdb.dwarf2/gdb-index.exp testcase
- uses this to verify that .debug_names has been loaded. */
-
-void
-dwarf2_debug_names_index::dump (struct objfile *objfile)
-{
- gdb_printf (".debug_names: exists\n");
-}
+/* See read-debug-names.h. */
bool
-dwarf2_debug_names_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_read_debug_names (dwarf2_per_objfile *per_objfile)
{
- 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_debug_names &map
- = *(gdb::checked_static_cast<mapped_debug_names *>
- (per_objfile->per_bfd->index_table.get ()));
-
- bool result
- = dw2_expand_symtabs_matching_symbol (map, *lookup_name,
- symbol_matcher,
- [&] (offset_type namei)
- {
- /* The name was matched, now expand corresponding CUs that were
- marked. */
- dw2_debug_names_iterator iter (map, kind, namei, per_objfile, domain);
-
- struct dwarf2_per_cu_data *per_cu;
- while ((per_cu = iter.next ()) != NULL)
- if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
- file_matcher,
- expansion_notify))
- return false;
- return true;
- }, per_objfile);
-
+ bool result = do_dwarf2_read_debug_names (per_objfile);
+ if (!result)
+ per_objfile->per_bfd->all_units.clear ();
return result;
}