The new DWARF indexer

This patch adds the code to index DWARF.  This is just the scanner; it
reads the DWARF and constructs the index, but nothing calls it yet.

The indexer is split into two parts: a storage object and an indexer
object.  This is done to support the parallelization of this code -- a
future patch will create a single storage object per thread.
This commit is contained in:
Tom Tromey
2021-05-22 07:51:24 -06:00
parent 51f5a4b8e9
commit 2e57de7c84
2 changed files with 818 additions and 2 deletions

View File

@ -89,6 +89,8 @@
#include "gdbsupport/pathstuff.h"
#include "count-one-bits.h"
#include <unordered_set>
#include "dwarf2/abbrev-cache.h"
#include "cooked-index.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
@ -800,6 +802,8 @@ public:
DISABLE_COPY_AND_ASSIGN (cutu_reader);
cutu_reader (cutu_reader &&) = default;
const gdb_byte *info_ptr = nullptr;
struct die_info *comp_unit_die = nullptr;
bool dummy_p = false;
@ -808,6 +812,13 @@ public:
for dummy CUs. */
void keep ();
/* Release the abbrev table, transferring ownership to the
caller. */
abbrev_table_up release_abbrev_table ()
{
return std::move (m_abbrev_table_holder);
}
private:
void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
dwarf2_per_objfile *per_objfile,
@ -7021,6 +7032,238 @@ create_partial_symtab (dwarf2_per_cu_data *per_cu,
return pst;
}
/* An instance of this is created when scanning DWARF to create a
cooked index. */
class cooked_index_storage
{
public:
cooked_index_storage ()
: m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
eq_cutu_reader,
htab_delete_entry<cutu_reader>,
xcalloc, xfree)),
m_index (new cooked_index),
m_addrmap_storage (),
m_addrmap (addrmap_create_mutable (&m_addrmap_storage))
{
}
DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
/* Return the current abbrev cache. */
abbrev_cache *get_abbrev_cache ()
{
return &m_abbrev_cache;
}
/* Return the DIE reader corresponding to PER_CU. If no such reader
has been registered, return NULL. */
cutu_reader *get_reader (dwarf2_per_cu_data *per_cu)
{
int index = per_cu->index;
return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
&index, index);
}
/* Preserve READER by storing it in the local hash table. */
cutu_reader *preserve (std::unique_ptr<cutu_reader> reader)
{
m_abbrev_cache.add (reader->release_abbrev_table ());
int index = reader->cu->per_cu->index;
void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
index, INSERT);
gdb_assert (*slot == nullptr);
cutu_reader *result = reader.get ();
*slot = reader.release ();
return result;
}
/* Add an entry to the index. The arguments describe the entry; see
cooked-index.h. The new entry is returned. */
const cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
cooked_index_flag flags,
const char *name,
const cooked_index_entry *parent_entry,
dwarf2_per_cu_data *per_cu)
{
return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu);
}
/* Install the current addrmap into the index being constructed,
then transfer ownership of the index to the caller. */
std::unique_ptr<cooked_index> release ()
{
m_index->install_addrmap (m_addrmap);
return std::move (m_index);
}
/* Return the mutable addrmap that is currently being created. */
addrmap *get_addrmap ()
{
return m_addrmap;
}
private:
/* Hash function for a cutu_reader. */
static hashval_t hash_cutu_reader (const void *a)
{
const cutu_reader *reader = (const cutu_reader *) a;
return reader->cu->per_cu->index;
}
/* Equality function for cutu_reader. */
static int eq_cutu_reader (const void *a, const void *b)
{
const cutu_reader *ra = (const cutu_reader *) a;
const int *rb = (const int *) b;
return ra->cu->per_cu->index == *rb;
}
/* The abbrev cache used by this indexer. */
abbrev_cache m_abbrev_cache;
/* A hash table of cutu_reader objects. */
htab_up m_reader_hash;
/* The index that is being constructed. */
std::unique_ptr<cooked_index> m_index;
/* Storage for the writeable addrmap. */
auto_obstack m_addrmap_storage;
/* A writeable addrmap being constructed by this scanner. */
addrmap *m_addrmap;
};
/* An instance of this is created to index a CU. */
class cooked_indexer
{
public:
cooked_indexer (cooked_index_storage *storage,
dwarf2_per_cu_data *per_cu,
enum language language)
: m_index_storage (storage),
m_per_cu (per_cu),
m_language (language),
m_obstack (),
m_die_range_map (addrmap_create_mutable (&m_obstack))
{
}
DISABLE_COPY_AND_ASSIGN (cooked_indexer);
/* Index the given CU. */
void make_index (cutu_reader *reader);
private:
/* A helper function to turn a section offset into an address that
can be used in an addrmap. */
CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
{
CORE_ADDR value = to_underlying (offset);
if (is_dwz)
value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
return value;
}
/* A helper function to scan the PC bounds of READER and record them
in the storage's addrmap. */
void check_bounds (cutu_reader *reader);
/* Ensure that the indicated CU exists. The cutu_reader for it is
returned. FOR_SCANNING is true if the caller intends to scan all
the DIEs in the CU; when false, this use is assumed to be to look
up just a single DIE. */
cutu_reader *ensure_cu_exists (cutu_reader *reader,
dwarf2_per_objfile *per_objfile,
sect_offset sect_off,
bool is_dwz,
bool for_scanning);
/* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is
the entry for the enclosing scope (nullptr at top level). FULLY
is true when a full scan must be done -- in some languages,
function scopes must be fully explored in order to find nested
functions. This returns a pointer to just after the spot where
reading stopped. */
const gdb_byte *index_dies (cutu_reader *reader,
const gdb_byte *info_ptr,
const cooked_index_entry *parent_entry,
bool fully);
/* Scan the attributes for a given DIE and update the out
parameters. Returns a pointer to the byte after the DIE. */
const gdb_byte *scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
cutu_reader *reader,
const gdb_byte *watermark_ptr,
const gdb_byte *info_ptr,
const abbrev_info *abbrev,
const char **name,
const char **linkage_name,
cooked_index_flag *flags,
sect_offset *sibling_offset,
const cooked_index_entry **parent_entry,
CORE_ADDR *maybe_defer,
bool for_specification);
/* Handle DW_TAG_imported_unit, by scanning the DIE to find
DW_AT_import, and then scanning the referenced CU. Returns a
pointer to the byte after the DIE. */
const gdb_byte *index_imported_unit (cutu_reader *reader,
const gdb_byte *info_ptr,
const abbrev_info *abbrev);
/* Recursively read DIEs, recording the section offsets in
m_die_range_map and then calling index_dies. */
const gdb_byte *recurse (cutu_reader *reader,
const gdb_byte *info_ptr,
const cooked_index_entry *parent_entry,
bool fully);
/* The storage object, where the results are kept. */
cooked_index_storage *m_index_storage;
/* The CU that we are reading on behalf of. This object might be
asked to index one CU but to treat the results as if they come
from some including CU; in this case the including CU would be
recorded here. */
dwarf2_per_cu_data *m_per_cu;
/* The language that we're assuming when reading. */
enum language m_language;
/* Temporary storage. */
auto_obstack m_obstack;
/* An addrmap that maps from section offsets (see the form_addr
method) to newly-created entries. See m_deferred_entries to
understand this. */
addrmap *m_die_range_map;
/* A single deferred entry. */
struct deferred_entry
{
sect_offset die_offset;
const char *name;
CORE_ADDR spec_offset;
dwarf_tag tag;
cooked_index_flag flags;
};
/* The generated DWARF can sometimes have the declaration for a
method in a class (or perhaps namespace) scope, with the
definition appearing outside this scope... just one of the many
bad things about DWARF. In order to handle this situation, we
defer certain entries until the end of scanning, at which point
we'll know the containing context of all the DIEs that we might
have scanned. This vector stores these deferred entries. */
std::vector<deferred_entry> m_deferred_entries;
};
/* DIE reader function for process_psymtab_comp_unit. */
@ -8398,7 +8641,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
/* We only handle DW_FORM_ref4 here. */
const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
unsigned int offset = read_4_bytes (abfd, sibling_data);
const gdb_byte *sibling_ptr = buffer + offset;
const gdb_byte *sibling_ptr
= buffer + to_underlying (cu->header.sect_off) + offset;
if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
return sibling_ptr;
/* Fall through to the slow way. */
@ -19069,6 +19313,573 @@ read_full_die (const struct die_reader_specs *reader,
}
void
cooked_indexer::check_bounds (cutu_reader *reader)
{
if (reader->cu->per_cu->addresses_seen)
return;
dwarf2_cu *cu = reader->cu;
CORE_ADDR best_lowpc = 0, best_highpc = 0;
/* Possibly set the default values of LOWPC and HIGHPC from
`DW_AT_ranges'. */
dwarf2_find_base_address (reader->comp_unit_die, cu);
enum pc_bounds_kind cu_bounds_kind
= dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc,
cu, m_index_storage->get_addrmap (), cu->per_cu);
if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
{
struct objfile *objfile = cu->per_objfile->objfile;
CORE_ADDR baseaddr = objfile->text_section_offset ();
struct gdbarch *gdbarch = objfile->arch ();
CORE_ADDR low
= (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
- baseaddr);
CORE_ADDR high
= (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
- baseaddr - 1);
/* Store the contiguous range if it is not empty; it can be
empty for CUs with no code. */
addrmap_set_empty (m_index_storage->get_addrmap (), low, high,
cu->per_cu);
cu->per_cu->addresses_seen = true;
}
}
/* Helper function that returns true if TAG can have a linkage
name. */
static bool
tag_can_have_linkage_name (enum dwarf_tag tag)
{
switch (tag)
{
/* We include types here because an anonymous C++ type might
have a name for linkage purposes. */
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_variable:
case DW_TAG_subprogram:
return true;
default:
return false;
}
}
cutu_reader *
cooked_indexer::ensure_cu_exists (cutu_reader *reader,
dwarf2_per_objfile *per_objfile,
sect_offset sect_off, bool is_dwz,
bool for_scanning)
{
/* Lookups for type unit references are always in the CU, and
cross-CU references will crash. */
if (reader->cu->per_cu->is_dwz == is_dwz
&& reader->cu->header.offset_in_cu_p (sect_off))
return reader;
dwarf2_per_cu_data *per_cu
= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
per_objfile->per_bfd);
/* When scanning, we only want to visit a given CU a single time.
Doing this check here avoids self-imports as well. */
if (for_scanning)
{
if (per_cu->scanned)
return nullptr;
per_cu->scanned = true;
}
if (per_cu == m_per_cu)
return reader;
cutu_reader *result = m_index_storage->get_reader (per_cu);
if (result == nullptr)
{
cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false);
prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die,
language_minimal);
std::unique_ptr<cutu_reader> copy
(new cutu_reader (std::move (new_reader)));
result = m_index_storage->preserve (std::move (copy));
}
if (result->dummy_p || !result->comp_unit_die->has_children)
return nullptr;
if (for_scanning)
check_bounds (result);
return result;
}
const gdb_byte *
cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
cutu_reader *reader,
const gdb_byte *watermark_ptr,
const gdb_byte *info_ptr,
const abbrev_info *abbrev,
const char **name,
const char **linkage_name,
cooked_index_flag *flags,
sect_offset *sibling_offset,
const cooked_index_entry **parent_entry,
CORE_ADDR *maybe_defer,
bool for_specification)
{
bool origin_is_dwz = false;
bool is_declaration = false;
sect_offset origin_offset {};
gdb::optional<CORE_ADDR> low_pc;
gdb::optional<CORE_ADDR> high_pc;
bool high_pc_relative = false;
for (int i = 0; i < abbrev->num_attrs; ++i)
{
attribute attr;
info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
if (attr.requires_reprocessing_p ())
read_attribute_reprocess (reader, &attr, abbrev->tag);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
{
case DW_AT_name:
switch (abbrev->tag)
{
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
case DW_TAG_type_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
break;
default:
if (*name == nullptr)
*name = attr.as_string ();
break;
}
break;
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
/* Note that both forms of linkage name might appear. We
assume they will be the same, and we only store the last
one we see. */
if (*linkage_name == nullptr)
*linkage_name = attr.as_string ();
break;
case DW_AT_main_subprogram:
if (attr.as_boolean ())
*flags |= IS_MAIN;
break;
case DW_AT_declaration:
is_declaration = attr.as_boolean ();
break;
case DW_AT_sibling:
if (sibling_offset != nullptr)
*sibling_offset = attr.get_ref_die_offset ();
break;
case DW_AT_specification:
case DW_AT_abstract_origin:
case DW_AT_extension:
origin_offset = attr.get_ref_die_offset ();
origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
break;
case DW_AT_external:
if (attr.as_boolean ())
*flags &= ~IS_STATIC;
break;
case DW_AT_enum_class:
if (attr.as_boolean ())
*flags |= IS_ENUM_CLASS;
break;
case DW_AT_low_pc:
low_pc = attr.as_address ();
break;
case DW_AT_high_pc:
high_pc = attr.as_address ();
if (reader->cu->header.version >= 4 && attr.form_is_constant ())
high_pc_relative = true;
break;
case DW_AT_location:
if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
{
struct dwarf_block *locdesc = attr.as_block ();
CORE_ADDR addr = decode_locdesc (locdesc, reader->cu);
if (addr != 0
|| reader->cu->per_objfile->per_bfd->has_section_at_zero)
{
low_pc = addr;
/* For variables, we don't want to try decoding the
type just to find the size -- for gdb's purposes
we only need the address of a variable. */
high_pc = addr + 1;
high_pc_relative = false;
}
}
break;
case DW_AT_ranges:
if (!scanning_per_cu->addresses_seen)
{
/* Offset in the .debug_ranges or .debug_rnglist section
(depending on DWARF version). */
ULONGEST ranges_offset = attr.as_unsigned ();
/* See dwarf2_cu::gnu_ranges_base's doc for why we might
want to add this value. */
ranges_offset += reader->cu->gnu_ranges_base;
CORE_ADDR lowpc, highpc;
dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu,
m_index_storage->get_addrmap (),
scanning_per_cu, abbrev->tag);
}
break;
}
}
/* We don't want to examine declarations, but if we found a
declaration when handling DW_AT_specification or the like, then
that is ok. Similarly, we allow an external variable without a
location; those are resolved via minimal symbols. */
if (is_declaration && !for_specification
&& (abbrev->tag != DW_TAG_variable
|| (*flags & IS_STATIC) != 0))
{
*linkage_name = nullptr;
*name = nullptr;
}
else if ((*name == nullptr
|| (*linkage_name == nullptr
&& tag_can_have_linkage_name (abbrev->tag))
|| (*parent_entry == nullptr && m_language != language_c))
&& origin_offset != sect_offset (0))
{
cutu_reader *new_reader
= ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
origin_is_dwz, false);
if (new_reader != nullptr)
{
const gdb_byte *new_info_ptr = (new_reader->buffer
+ to_underlying (origin_offset));
if (new_reader->cu == reader->cu
&& new_info_ptr > watermark_ptr
&& maybe_defer != nullptr
&& *parent_entry == nullptr)
*maybe_defer = form_addr (origin_offset, origin_is_dwz);
else if (*parent_entry == nullptr)
{
CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
*parent_entry
= (cooked_index_entry *) addrmap_find (m_die_range_map,
lookup);
}
unsigned int bytes_read;
const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
new_info_ptr,
&bytes_read);
new_info_ptr += bytes_read;
scan_attributes (scanning_per_cu, new_reader, new_info_ptr, new_info_ptr,
new_abbrev, name, linkage_name, flags, nullptr,
parent_entry, maybe_defer, true);
}
}
if (!for_specification)
{
if (m_language == language_ada
&& *linkage_name == nullptr)
*linkage_name = *name;
if (!scanning_per_cu->addresses_seen
&& low_pc.has_value ()
&& (reader->cu->per_objfile->per_bfd->has_section_at_zero
|| *low_pc != 0)
&& high_pc.has_value ())
{
if (high_pc_relative)
high_pc = *high_pc + *low_pc;
if (*high_pc > *low_pc)
{
struct objfile *objfile = reader->cu->per_objfile->objfile;
CORE_ADDR baseaddr = objfile->text_section_offset ();
struct gdbarch *gdbarch = objfile->arch ();
CORE_ADDR lo
= (gdbarch_adjust_dwarf2_addr (gdbarch, *low_pc + baseaddr)
- baseaddr);
CORE_ADDR hi
= (gdbarch_adjust_dwarf2_addr (gdbarch, *high_pc + baseaddr)
- baseaddr);
addrmap_set_empty (m_index_storage->get_addrmap (), lo, hi - 1,
scanning_per_cu);
}
}
if (abbrev->tag == DW_TAG_module || abbrev->tag == DW_TAG_namespace)
*flags &= ~IS_STATIC;
if (abbrev->tag == DW_TAG_namespace && *name == nullptr)
*name = "(anonymous namespace)";
if (m_language == language_cplus
&& (abbrev->tag == DW_TAG_class_type
|| abbrev->tag == DW_TAG_interface_type
|| abbrev->tag == DW_TAG_structure_type
|| abbrev->tag == DW_TAG_union_type
|| abbrev->tag == DW_TAG_enumeration_type
|| abbrev->tag == DW_TAG_enumerator))
*flags &= ~IS_STATIC;
}
return info_ptr;
}
const gdb_byte *
cooked_indexer::index_imported_unit (cutu_reader *reader,
const gdb_byte *info_ptr,
const abbrev_info *abbrev)
{
sect_offset sect_off {};
bool is_dwz = false;
for (int i = 0; i < abbrev->num_attrs; ++i)
{
/* Note that we never need to reprocess attributes here. */
attribute attr;
info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
if (attr.name == DW_AT_import)
{
sect_off = attr.get_ref_die_offset ();
is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| reader->cu->per_cu->is_dwz);
}
}
/* Did not find DW_AT_import. */
if (sect_off == sect_offset (0))
return info_ptr;
dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off,
is_dwz, true);
if (new_reader != nullptr)
{
index_dies (new_reader, new_reader->info_ptr, nullptr, false);
reader->cu->add_dependence (new_reader->cu->per_cu);
}
return info_ptr;
}
const gdb_byte *
cooked_indexer::recurse (cutu_reader *reader,
const gdb_byte *info_ptr,
const cooked_index_entry *parent_entry,
bool fully)
{
info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
if (parent_entry != nullptr)
{
CORE_ADDR start = form_addr (parent_entry->die_offset,
reader->cu->per_cu->is_dwz);
CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
reader->cu->per_cu->is_dwz);
addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry);
}
return info_ptr;
}
const gdb_byte *
cooked_indexer::index_dies (cutu_reader *reader,
const gdb_byte *info_ptr,
const cooked_index_entry *parent_entry,
bool fully)
{
const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length ();
while (info_ptr < end_ptr)
{
sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
unsigned int bytes_read;
const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
&bytes_read);
info_ptr += bytes_read;
if (abbrev == nullptr)
break;
if (abbrev->tag == DW_TAG_imported_unit)
{
info_ptr = index_imported_unit (reader, info_ptr, abbrev);
continue;
}
if (!abbrev->interesting)
{
info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
if (fully && abbrev->has_children)
info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
continue;
}
const char *name = nullptr;
const char *linkage_name = nullptr;
CORE_ADDR defer = 0;
cooked_index_flag flags = IS_STATIC;
sect_offset sibling {};
const cooked_index_entry *this_parent_entry = parent_entry;
info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr,
info_ptr, abbrev, &name, &linkage_name,
&flags, &sibling, &this_parent_entry,
&defer, false);
if (abbrev->tag == DW_TAG_namespace
&& m_language == language_cplus
&& strcmp (name, "::") == 0)
{
/* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they
generated bogus DW_TAG_namespace DIEs with a name of "::"
for the global namespace. Work around this problem
here. */
name = nullptr;
}
const cooked_index_entry *this_entry = nullptr;
if (name != nullptr)
{
if (defer != 0)
m_deferred_entries.push_back ({
this_die, name, defer, abbrev->tag, flags
});
else
this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
name, this_parent_entry,
m_per_cu);
}
if (linkage_name != nullptr)
{
/* We only want this to be "main" if it has a linkage name
but not an ordinary name. */
if (name != nullptr)
flags = flags & ~IS_MAIN;
m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE,
linkage_name, nullptr, m_per_cu);
}
if (abbrev->has_children)
{
switch (abbrev->tag)
{
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
if (m_language != language_c && this_entry != nullptr)
{
info_ptr = recurse (reader, info_ptr, this_entry, fully);
continue;
}
break;
case DW_TAG_enumeration_type:
/* We need to recurse even for an anonymous enumeration.
Which scope we record as the parent scope depends on
whether we're reading an "enum class". If so, we use
the enum itself as the parent, yielding names like
"enum_class::enumerator"; otherwise we inject the
names into our own parent scope. */
info_ptr = recurse (reader, info_ptr,
((flags & IS_ENUM_CLASS) == 0)
? parent_entry
: this_entry,
fully);
continue;
case DW_TAG_module:
if (this_entry == nullptr)
break;
/* FALLTHROUGH */
case DW_TAG_namespace:
/* We don't check THIS_ENTRY for a namespace, to handle
the ancient G++ workaround pointed out above. */
info_ptr = recurse (reader, info_ptr, this_entry, fully);
continue;
case DW_TAG_subprogram:
if ((m_language == language_fortran
|| m_language == language_ada)
&& this_entry != nullptr)
{
info_ptr = recurse (reader, info_ptr, this_entry, true);
continue;
}
break;
}
if (sibling != sect_offset (0))
{
const gdb_byte *sibling_ptr
= reader->buffer + to_underlying (sibling);
if (sibling_ptr < info_ptr)
complaint (_("DW_AT_sibling points backwards"));
else if (sibling_ptr > reader->buffer_end)
reader->die_section->overflow_complaint ();
else
info_ptr = sibling_ptr;
}
else
info_ptr = skip_children (reader, info_ptr);
}
}
return info_ptr;
}
void
cooked_indexer::make_index (cutu_reader *reader)
{
check_bounds (reader);
find_file_and_directory (reader->comp_unit_die, reader->cu);
if (!reader->comp_unit_die->has_children)
return;
index_dies (reader, reader->info_ptr, nullptr, false);
for (const auto &entry : m_deferred_entries)
{
CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
cooked_index_entry *parent
= (cooked_index_entry *) addrmap_find (m_die_range_map, key);
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
entry.name, parent, m_per_cu);
}
}
/* Returns nonzero if TAG represents a type that we might generate a partial
symbol for. */

View File

@ -106,7 +106,8 @@ struct dwarf2_per_cu_data
m_header_read_in (false),
addresses_seen (false),
unit_type {},
lang (language_unknown)
lang (language_unknown),
scanned (false)
{
}
@ -165,6 +166,10 @@ struct dwarf2_per_cu_data
/* The language of this CU. */
ENUM_BITFIELD (language) lang : LANGUAGE_BITS;
/* True if this CU has been scanned by the indexer; false if
not. */
bool scanned : 1;
/* Our index in the unshared "symtabs" vector. */
unsigned index = 0;