mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2026-08-27 00:26:02 -04:00
gdb/dwarf: make abbrev_table_cache read-through, make it mandatory
This patch implements some performance improvements initially sent as
part of this series [1], but now as a single patch. There was some push
back from Tom regarding the increased memory usage, but I think that my
solution is still desirable: it makes the code simpler, and I think that
the memory usage it not an issue (the usage is transient and the amount
of memory used by the abbrev tables is relatively low).
As a reminder, here is the problem I'm looking to solve: when using
split DWARF (.dwo files) plus type units, all units inside a .dwo file
(generally one compile unit plus many type units) share the same abbrev
table. So we end up re-reading that same abbrev tables many times, and
its gets very noticeable in function process_skeletonless_type_units.
cooked_index_worker_debug_info::process_type_units does some work to
avoid this problem, but it only works when everything is in the main
file (not using split DWARF).
Right now, we cache abbrev tables only in specific cases during
indexing, like when one CU imports things from another CU. My previous
series changed cutu_reader so that it would add any abbrev table it
would read to the abbrev table cache (if it was passed one as a
parameter). This allowed using a cache in
process_skeletonless_type_units and cut the time down significantly.
This patch goes a bit further in order to simplify cutu_reader even
further:
- It makes the abbrev table cache read-through, meaning that when you
request an abbrev table and it's not in the cache, it will go read
it (and cache it).
- It makes passing an abbrev table cache to the constructors mandatory
(even when we wouldn't benefit from using a cache).
The result is that cutu_reader doesn't need to manage multiple cases of
how to obtain an abbrev table, and it doesn't need to manage adding
abbrev tables to the cache. It no longer needs to manage the ownership
of the abbrev tables either: the abbrev tables are always owned by the
cache. And the cases of abbrev table sharing are well handled
transparently.
This means that we pay a small price when we don't necessarily need to
(sometimes building and destroying an abbrev_table_cache for just one
cutu_reader), but I think that this price is not significant and the
code simplification is welcome.
In concrete terms, this patch:
- changes abbrev_table_cache::find to become abbrev_table_cache::get,
making it read-through
- removes abbrev_table_cache::add
- removes the abbrev_table parameter from the main cutu_reader
constructor
- makes the abbrev_table_cache parameter mandatory (a reference) in the
main cutu_reader constructor, adds it to the alternative constructor,
and passes it down to a few methods
- adjusts the cutu_reader code obtaining an abbrev table to just call
abbrev_table_cache::get
- adjusts all the cutu_reader users to pass an abbrev_table_cache (if
not already)
- removes the code in
cooked_index_worker_debug_info::process_type_units meant to
efficiently handle TUs that share abbrev tables - the cache now does
this
The specific split DWARF + type units performance problem at the origin
of this work gets fixed by the fact that
cooked_index_worker_debug_info::process_skeletonless_type_unit now
passes an abbrev table cache to cutu_reader, and
cutu_reader::read_cutu_die_from_dwo uses it.
As a test, I'm using a build of Blender compiled with -gsplit-dwarf and
-fdebug-types-section. I run this:
$ ./gdb -nx -q --data-directory=data-directory -ex 'maint set dwarf sync on' -ex 'maintenance set per-command time on' -ex "file /data1/smarchi/blender-build/relwithdebinfo-clang-debugtypes-splitdwarf/bin/blender" -batch
and look at the time taken by the "DWARF skeletonless type units"
step. Before looks like:
Time for "DWARF skeletonless type units": wall 11.131, user 10.699, sys 0.431, user+sys 11.130, 100.0 % CPU
and after looks like:
Time for "DWARF skeletonless type units": wall 1.751, user 1.221, sys 0.518, user+sys 1.739, 99.3 % CPU
The total run time (wall clock time) of the command goes from about 18.5
seconds to about 9.5 seconds.
I removed this assert in cutu_reader, because it relies on abbrev_cache
as a flag for whether we're in the indexer:
/* If an existing_cu is provided, a dwarf2_cu must not exist for
this_cu in per_objfile yet. Here, CACHE doubles as a flag to
let us know that the CU is being scanned using the parallel
indexer. This assert is avoided in this case because (1) it
is irrelevant, and (2) the get_cu method is not
thread-safe. */
gdb_assert (abbrev_cache != nullptr
|| per_objfile.get_cu (&this_cu) == nullptr);
It's not clear to me if this assert is important or how to implement it
differently.
[1] https://inbox.sourceware.org/gdb-patches/20250326200002.136200-4-simon.marchi@efficios.com/
Change-Id: Idf8a514326fb35be8bda0d7ebe3cee4b7304941a
Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
parent
cfea0e5e80
commit
c019c04618
7 changed files with 81 additions and 204 deletions
|
|
@ -2006,7 +2006,6 @@ TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
|
|||
# Files that are used to support certain debuginfo formats
|
||||
DWARF2_SRCS = \
|
||||
dwarf2/abbrev.c \
|
||||
dwarf2/abbrev-table-cache.c \
|
||||
dwarf2/ada-imported.c \
|
||||
dwarf2/aranges.c \
|
||||
dwarf2/attribute.c \
|
||||
|
|
|
|||
|
|
@ -34,27 +34,19 @@ public:
|
|||
abbrev_table_cache &operator= (abbrev_table_cache &&) = default;
|
||||
|
||||
/* Find an abbrev table coming from the abbrev section SECTION at
|
||||
offset OFFSET. Return the table, or nullptr if it has not yet
|
||||
been registered. */
|
||||
const abbrev_table *find (dwarf2_section_info *section,
|
||||
sect_offset offset) const
|
||||
offset OFFSET. Read it in if necessary. */
|
||||
const abbrev_table &get (dwarf2_section_info *section, sect_offset offset)
|
||||
{
|
||||
abbrev_table_search_key key {section, offset};
|
||||
|
||||
if (auto iter = m_tables.find (key);
|
||||
iter != m_tables.end ())
|
||||
return iter->get ();
|
||||
return **iter;
|
||||
|
||||
return nullptr;
|
||||
auto table = abbrev_table::read (section, offset);
|
||||
return **m_tables.insert (std::move (table)).first;
|
||||
}
|
||||
|
||||
/* Add TABLE to this cache. Ownership of TABLE is transferred to
|
||||
the cache. Note that a table at a given section+offset may only
|
||||
be registered once -- a violation of this will cause an assert.
|
||||
To avoid this, call the 'find' method first, to see if the table
|
||||
has already been read. */
|
||||
void add (abbrev_table_up table);
|
||||
|
||||
private:
|
||||
/* Key used to search for an existing abbrev table in M_TABLES. */
|
||||
struct abbrev_table_search_key
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ cooked_index_worker_result::get_reader (dwarf2_per_cu *per_cu)
|
|||
cutu_reader *
|
||||
cooked_index_worker_result::preserve (cutu_reader_up reader)
|
||||
{
|
||||
m_abbrev_table_cache.add (reader->release_abbrev_table ());
|
||||
|
||||
auto [it, inserted] = m_reader_hash.insert (std::move (reader));
|
||||
gdb_assert (inserted);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ public:
|
|||
cooked_index_worker_result &operator= (cooked_index_worker_result &&)
|
||||
= default;
|
||||
|
||||
/* Return the current abbrev table_cache. */
|
||||
abbrev_table_cache &get_abbrev_table_cache ()
|
||||
{ return m_abbrev_table_cache; }
|
||||
|
||||
/* Return the current abbrev table_cache. */
|
||||
const abbrev_table_cache &get_abbrev_table_cache () const
|
||||
{ return m_abbrev_table_cache; }
|
||||
|
|
|
|||
|
|
@ -110,12 +110,11 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader,
|
|||
cutu_reader *result = m_index_storage->get_reader (per_cu);
|
||||
if (result == nullptr)
|
||||
{
|
||||
const abbrev_table_cache &abbrev_table_cache
|
||||
abbrev_table_cache &abbrev_table_cache
|
||||
= m_index_storage->get_abbrev_table_cache ();
|
||||
auto new_reader
|
||||
= std::make_unique<cutu_reader> (*per_cu, *per_objfile, nullptr,
|
||||
nullptr, false, m_language,
|
||||
&abbrev_table_cache);
|
||||
= std::make_unique<cutu_reader> (*per_cu, *per_objfile, nullptr, false,
|
||||
m_language, abbrev_table_cache);
|
||||
|
||||
if (new_reader->is_dummy ())
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -704,9 +704,6 @@ static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
|
|||
static unrelocated_addr read_addr_index (struct dwarf2_cu *cu,
|
||||
unsigned int addr_index);
|
||||
|
||||
static sect_offset read_abbrev_offset (dwarf2_per_objfile *per_objfile,
|
||||
dwarf2_section_info *, sect_offset);
|
||||
|
||||
static const char *read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *,
|
||||
const gdb_byte *, const unit_head *,
|
||||
unsigned int *);
|
||||
|
|
@ -1850,9 +1847,9 @@ dw2_get_file_names (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile)
|
|||
if (this_cu->files_read)
|
||||
return this_cu->file_names;
|
||||
|
||||
cutu_reader reader (*this_cu, *per_objfile, nullptr,
|
||||
per_objfile->get_cu (this_cu), true, std::nullopt,
|
||||
nullptr);
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader reader (*this_cu, *per_objfile, per_objfile->get_cu (this_cu),
|
||||
true, std::nullopt, abbrev_table_cache);
|
||||
if (reader.is_dummy ())
|
||||
{
|
||||
/* Make sure we don't re-read the dummy CU. */
|
||||
|
|
@ -2444,35 +2441,6 @@ all_units_less_than (const dwarf2_per_cu &lhs, const section_and_offset &rhs)
|
|||
return lhs.sect_off () < rhs.offset;
|
||||
}
|
||||
|
||||
/* Fetch the abbreviation table offset from a comp or type unit header. */
|
||||
|
||||
static sect_offset
|
||||
read_abbrev_offset (dwarf2_per_objfile *per_objfile,
|
||||
struct dwarf2_section_info *section,
|
||||
sect_offset sect_off)
|
||||
{
|
||||
bfd *abfd = section->get_bfd_owner ();
|
||||
const gdb_byte *info_ptr;
|
||||
unsigned int initial_length_size, offset_size;
|
||||
uint16_t version;
|
||||
|
||||
section->read (per_objfile->objfile);
|
||||
info_ptr = section->buffer + to_underlying (sect_off);
|
||||
read_initial_length (abfd, info_ptr, &initial_length_size);
|
||||
offset_size = initial_length_size == 4 ? 4 : 8;
|
||||
info_ptr += initial_length_size;
|
||||
|
||||
version = read_2_bytes (abfd, info_ptr);
|
||||
info_ptr += 2;
|
||||
if (version >= 5)
|
||||
{
|
||||
/* Skip unit type and address size. */
|
||||
info_ptr += 2;
|
||||
}
|
||||
|
||||
return (sect_offset) read_offset (abfd, info_ptr, offset_size);
|
||||
}
|
||||
|
||||
/* Add an entry for signature SIG to per_bfd->signatured_types.
|
||||
|
||||
This functions leaves PER_BFD::ALL_UNITS unsorted. The caller must call
|
||||
|
|
@ -2667,7 +2635,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
|
|||
void
|
||||
cutu_reader::init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section,
|
||||
struct dwo_file *dwo_file,
|
||||
const struct abbrev_table *abbrev_table)
|
||||
const abbrev_table &abbrev_table)
|
||||
{
|
||||
gdb_assert (section->read_in && section->buffer != NULL);
|
||||
m_abfd = section->get_bfd_owner ();
|
||||
|
|
@ -2676,7 +2644,7 @@ cutu_reader::init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section,
|
|||
m_die_section = section;
|
||||
m_buffer = section->buffer;
|
||||
m_buffer_end = section->buffer + section->size;
|
||||
m_abbrev_table = abbrev_table;
|
||||
m_abbrev_table = &abbrev_table;
|
||||
}
|
||||
|
||||
/* Subroutine of cutu_reader to simplify it.
|
||||
|
|
@ -2702,7 +2670,8 @@ cutu_reader::init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section,
|
|||
void
|
||||
cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
|
||||
die_info *stub_comp_unit_die,
|
||||
const char *stub_comp_dir)
|
||||
const char *stub_comp_dir,
|
||||
abbrev_table_cache &abbrev_table_cache)
|
||||
{
|
||||
dwarf2_per_cu *per_cu = cu->per_cu;
|
||||
struct objfile *objfile = cu->per_objfile->objfile;
|
||||
|
|
@ -2826,11 +2795,9 @@ cutu_reader::read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
|
|||
? cu->header.addr_size
|
||||
: cu->header.offset_size);
|
||||
|
||||
dwo_abbrev_section->read (objfile);
|
||||
m_dwo_abbrev_table
|
||||
= abbrev_table::read (dwo_abbrev_section, cu->header.abbrev_sect_off);
|
||||
this->init_cu_die_reader (cu, section, dwo_unit->dwo_file,
|
||||
m_dwo_abbrev_table.get ());
|
||||
const abbrev_table &abbrev_table
|
||||
= abbrev_table_cache.get (dwo_abbrev_section, cu->header.abbrev_sect_off);
|
||||
this->init_cu_die_reader (cu, section, dwo_unit->dwo_file, abbrev_table);
|
||||
|
||||
/* Skip dummy compilation units. */
|
||||
if (m_info_ptr >= begin_info_ptr + dwo_unit->length
|
||||
|
|
@ -2910,7 +2877,8 @@ void
|
|||
cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu,
|
||||
dwarf2_per_objfile *per_objfile,
|
||||
dwarf2_cu *existing_cu,
|
||||
std::optional<language> pretend_language)
|
||||
std::optional<language> pretend_language,
|
||||
abbrev_table_cache &abbrev_table_cache)
|
||||
{
|
||||
signatured_type *sig_type = this_cu->as_signatured_type ();
|
||||
|
||||
|
|
@ -2941,7 +2909,8 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu,
|
|||
could share abbrev tables. */
|
||||
|
||||
read_cutu_die_from_dwo (cu, sig_type->dwo_unit, NULL /* stub_comp_unit_die */,
|
||||
sig_type->dwo_unit->dwo_file->comp_dir);
|
||||
sig_type->dwo_unit->dwo_file->comp_dir,
|
||||
abbrev_table_cache);
|
||||
prepare_one_comp_unit (cu, pretend_language);
|
||||
}
|
||||
|
||||
|
|
@ -2957,11 +2926,10 @@ cutu_reader::init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu,
|
|||
|
||||
cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
||||
dwarf2_per_objfile &per_objfile,
|
||||
const struct abbrev_table *abbrev_table,
|
||||
dwarf2_cu *existing_cu,
|
||||
bool skip_partial,
|
||||
std::optional<language> pretend_language,
|
||||
const abbrev_table_cache *abbrev_cache)
|
||||
abbrev_table_cache &abbrev_table_cache)
|
||||
{
|
||||
struct objfile *objfile = per_objfile.objfile;
|
||||
struct dwarf2_section_info *section = this_cu.section ();
|
||||
|
|
@ -2984,9 +2952,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
{
|
||||
/* Narrow down the scope of possibilities to have to understand. */
|
||||
gdb_assert (this_cu.is_debug_types ());
|
||||
gdb_assert (abbrev_table == NULL);
|
||||
init_tu_and_read_dwo_dies (&this_cu, &per_objfile, existing_cu,
|
||||
pretend_language);
|
||||
pretend_language, abbrev_table_cache);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3014,14 +2981,6 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* If an existing_cu is provided, a dwarf2_cu must not exist for
|
||||
this_cu in per_objfile yet. Here, CACHE doubles as a flag to
|
||||
let us know that the CU is being scanned using the parallel
|
||||
indexer. This assert is avoided in this case because (1) it
|
||||
is irrelevant, and (2) the get_cu method is not
|
||||
thread-safe. */
|
||||
gdb_assert (abbrev_cache != nullptr
|
||||
|| per_objfile.get_cu (&this_cu) == nullptr);
|
||||
m_new_cu = std::make_unique<dwarf2_cu> (&this_cu, &per_objfile);
|
||||
cu = m_new_cu.get ();
|
||||
}
|
||||
|
|
@ -3081,25 +3040,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
m_dummy_p = true;
|
||||
else
|
||||
{
|
||||
/* If we don't have them yet, read the abbrevs for this
|
||||
compilation unit. And if we need to read them now, make sure
|
||||
they're freed when we're done. */
|
||||
if (abbrev_table != NULL)
|
||||
gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
|
||||
else
|
||||
{
|
||||
if (abbrev_cache != nullptr)
|
||||
abbrev_table = abbrev_cache->find (abbrev_section,
|
||||
cu->header.abbrev_sect_off);
|
||||
if (abbrev_table == nullptr)
|
||||
{
|
||||
abbrev_section->read (objfile);
|
||||
m_abbrev_table_holder
|
||||
= abbrev_table::read (abbrev_section,
|
||||
cu->header.abbrev_sect_off);
|
||||
abbrev_table = m_abbrev_table_holder.get ();
|
||||
}
|
||||
}
|
||||
abbrev_section->read (objfile);
|
||||
const abbrev_table &abbrev_table
|
||||
= abbrev_table_cache.get (abbrev_section, cu->header.abbrev_sect_off);
|
||||
|
||||
/* Read the top level CU/TU die. */
|
||||
this->init_cu_die_reader (cu, section, NULL, abbrev_table);
|
||||
|
|
@ -3134,7 +3077,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
|
||||
dwo_unit = lookup_dwo_unit (cu, m_top_level_die, dwo_name);
|
||||
if (dwo_unit != NULL)
|
||||
read_cutu_die_from_dwo (cu, dwo_unit, m_top_level_die, nullptr);
|
||||
read_cutu_die_from_dwo (cu, dwo_unit, m_top_level_die, nullptr,
|
||||
abbrev_table_cache);
|
||||
else
|
||||
{
|
||||
/* Yikes, we couldn't find the rest of the DIE, we only have
|
||||
|
|
@ -3179,7 +3123,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
dwarf2_per_objfile &per_objfile,
|
||||
std::optional<language> pretend_language,
|
||||
dwarf2_cu &parent_cu,
|
||||
dwo_file &dwo_file)
|
||||
dwo_file &dwo_file,
|
||||
abbrev_table_cache &abbrev_table_cache)
|
||||
{
|
||||
struct objfile *objfile = per_objfile.objfile;
|
||||
struct dwarf2_section_info *section = this_cu.section ();
|
||||
|
|
@ -3218,13 +3163,12 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu,
|
|||
m_dummy_p = true;
|
||||
else
|
||||
{
|
||||
abbrev_section->read (objfile);
|
||||
m_abbrev_table_holder
|
||||
= abbrev_table::read (abbrev_section,
|
||||
m_new_cu->header.abbrev_sect_off);
|
||||
const abbrev_table &abbrev_table
|
||||
= abbrev_table_cache.get (abbrev_section,
|
||||
m_new_cu->header.abbrev_sect_off);
|
||||
|
||||
this->init_cu_die_reader (m_new_cu.get (), section, &dwo_file,
|
||||
m_abbrev_table_holder.get ());
|
||||
abbrev_table);
|
||||
m_top_level_die = this->read_toplevel_die ();
|
||||
}
|
||||
|
||||
|
|
@ -3364,8 +3308,6 @@ private:
|
|||
|
||||
dwarf_read_debug_printf ("Type unit statistics:");
|
||||
dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units);
|
||||
dwarf_read_debug_printf (" %d uniq abbrev tables",
|
||||
tu_stats->nr_uniq_abbrev_tables);
|
||||
dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
|
||||
tu_stats->nr_symtabs);
|
||||
dwarf_read_debug_printf (" %d symtab sharers",
|
||||
|
|
@ -3433,12 +3375,10 @@ cooked_index_worker_debug_info::process_unit
|
|||
cutu_reader *reader = storage->get_reader (this_cu);
|
||||
if (reader == nullptr)
|
||||
{
|
||||
const abbrev_table_cache &abbrev_table_cache
|
||||
= storage->get_abbrev_table_cache ();
|
||||
auto new_reader = std::make_unique<cutu_reader> (*this_cu, *per_objfile,
|
||||
nullptr, nullptr, false,
|
||||
std::nullopt,
|
||||
&abbrev_table_cache);
|
||||
auto new_reader
|
||||
= std::make_unique<cutu_reader> (*this_cu, *per_objfile, nullptr,
|
||||
false, std::nullopt,
|
||||
storage->get_abbrev_table_cache ());
|
||||
|
||||
if (new_reader->is_dummy ())
|
||||
return;
|
||||
|
|
@ -3503,74 +3443,23 @@ void
|
|||
cooked_index_worker_debug_info::process_type_units
|
||||
(dwarf2_per_objfile *per_objfile, cooked_index_worker_result *storage)
|
||||
{
|
||||
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
|
||||
abbrev_table_up abbrev_table;
|
||||
|
||||
if (per_objfile->per_bfd->num_type_units == 0)
|
||||
return;
|
||||
|
||||
/* TUs typically share abbrev tables, and there can be way more TUs than
|
||||
abbrev tables. Sort by abbrev table to reduce the number of times we
|
||||
read each abbrev table in.
|
||||
Alternatives are to punt or to maintain a cache of abbrev tables.
|
||||
This is simpler and efficient enough for now.
|
||||
|
||||
Later we group TUs by their DW_AT_stmt_list value (as this defines the
|
||||
symtab to use). Typically TUs with the same abbrev offset have the same
|
||||
stmt_list value too so in practice this should work well.
|
||||
|
||||
The basic algorithm here is:
|
||||
|
||||
sort TUs by abbrev table
|
||||
for each TU with same abbrev table:
|
||||
read abbrev table if first user
|
||||
read TU top level DIE
|
||||
[IWBN if DWO skeletons had DW_AT_stmt_list]
|
||||
call FUNC */
|
||||
|
||||
dwarf_read_debug_printf ("Building type unit groups ...");
|
||||
|
||||
/* Sort in a separate table to maintain the order of all_units
|
||||
for .gdb_index: TU indices directly index all_type_units. */
|
||||
std::vector<tu_abbrev_offset> sorted_by_abbrev;
|
||||
sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units);
|
||||
|
||||
for (const auto &cu : per_objfile->per_bfd->all_units)
|
||||
if (signatured_type *sig_type = cu->as_signatured_type ();
|
||||
sig_type != nullptr)
|
||||
{
|
||||
sect_offset abbrev_offset
|
||||
= read_abbrev_offset (per_objfile, sig_type->section (),
|
||||
sig_type->sect_off ());
|
||||
sorted_by_abbrev.emplace_back (sig_type, abbrev_offset);
|
||||
cutu_reader reader (*sig_type, *per_objfile, nullptr, false,
|
||||
std::nullopt,
|
||||
storage->get_abbrev_table_cache ());
|
||||
|
||||
if (!reader.is_dummy ())
|
||||
storage->catch_error ([&] ()
|
||||
{
|
||||
process_type_unit (&reader, storage);
|
||||
});
|
||||
}
|
||||
|
||||
std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end ());
|
||||
|
||||
sect_offset abbrev_offset = (sect_offset) ~(unsigned) 0;
|
||||
|
||||
for (const tu_abbrev_offset &tu : sorted_by_abbrev)
|
||||
{
|
||||
/* Switch to the next abbrev table if necessary. */
|
||||
if (abbrev_table == NULL
|
||||
|| tu.abbrev_offset != abbrev_offset)
|
||||
{
|
||||
abbrev_offset = tu.abbrev_offset;
|
||||
per_objfile->per_bfd->abbrev.read (per_objfile->objfile);
|
||||
abbrev_table =
|
||||
abbrev_table::read (&per_objfile->per_bfd->abbrev, abbrev_offset);
|
||||
++tu_stats->nr_uniq_abbrev_tables;
|
||||
}
|
||||
|
||||
cutu_reader reader (*tu.sig_type, *per_objfile,
|
||||
abbrev_table.get (), nullptr, false,
|
||||
std::nullopt);
|
||||
if (!reader.is_dummy ())
|
||||
storage->catch_error ([&] ()
|
||||
{
|
||||
process_type_unit (&reader, storage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3597,8 +3486,8 @@ cooked_index_worker_debug_info::process_skeletonless_type_unit
|
|||
fill_in_sig_entry_from_dwo_entry (per_objfile, *sig_type_it, dwo_unit);
|
||||
|
||||
/* This does the job that build_type_psymtabs would have done. */
|
||||
cutu_reader reader (**sig_type_it, *per_objfile, nullptr, nullptr, false,
|
||||
std::nullopt);
|
||||
cutu_reader reader (**sig_type_it, *per_objfile, nullptr, false,
|
||||
std::nullopt, storage->get_abbrev_table_cache ());
|
||||
if (!reader.is_dummy ())
|
||||
process_type_unit (&reader, storage);
|
||||
}
|
||||
|
|
@ -4182,8 +4071,9 @@ load_full_comp_unit (dwarf2_per_cu *this_cu, dwarf2_per_objfile *per_objfile,
|
|||
gdb_assert (!this_cu->is_debug_types ());
|
||||
gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
|
||||
|
||||
cutu_reader reader (*this_cu, *per_objfile, nullptr, nullptr, skip_partial,
|
||||
pretend_language);
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader reader (*this_cu, *per_objfile, nullptr, skip_partial,
|
||||
pretend_language, abbrev_table_cache);
|
||||
if (reader.is_dummy ())
|
||||
return;
|
||||
|
||||
|
|
@ -6322,6 +6212,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
|
|||
section.get_file_name ());
|
||||
|
||||
const gdb_byte *end_ptr = info_ptr + section.size;
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
|
||||
while (info_ptr < end_ptr)
|
||||
{
|
||||
|
|
@ -6362,7 +6253,7 @@ cutu_reader::create_dwo_unit_hash_tables (dwo_file &dwo_file,
|
|||
dwarf2_per_cu per_cu (&per_bfd, §ion, sect_off, length,
|
||||
false /* is_dwz */);
|
||||
cutu_reader reader (per_cu, per_objfile, std::nullopt,
|
||||
skeleton_cu, dwo_file);
|
||||
skeleton_cu, dwo_file, abbrev_table_cache);
|
||||
|
||||
std::optional<ULONGEST> opt_signature
|
||||
= lookup_dwo_id (reader.cu (), reader.top_level_die ());
|
||||
|
|
@ -14975,8 +14866,9 @@ dwarf2_read_addr_index (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile,
|
|||
}
|
||||
else
|
||||
{
|
||||
cutu_reader reader (*per_cu, *per_objfile, nullptr, nullptr, false,
|
||||
std::nullopt);
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader reader (*per_cu, *per_objfile, nullptr, false,
|
||||
std::nullopt, abbrev_table_cache);
|
||||
addr_base = reader.cu ()->addr_base;
|
||||
addr_size = reader.cu ()->header.addr_size;
|
||||
}
|
||||
|
|
@ -17576,8 +17468,9 @@ read_signatured_type (signatured_type *sig_type,
|
|||
gdb_assert (sig_type->is_debug_types ());
|
||||
gdb_assert (per_objfile->get_cu (sig_type) == nullptr);
|
||||
|
||||
cutu_reader reader (*sig_type, *per_objfile, nullptr, nullptr, false,
|
||||
std::nullopt);
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader reader (*sig_type, *per_objfile, nullptr, false,
|
||||
std::nullopt, abbrev_table_cache);
|
||||
|
||||
if (!reader.is_dummy ())
|
||||
{
|
||||
|
|
@ -18045,8 +17938,9 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile)
|
|||
|
||||
/* Constructing this object will set the language as a side
|
||||
effect. */
|
||||
cutu_reader reader (*this, *per_objfile, nullptr, per_objfile->get_cu (this),
|
||||
true, std::nullopt, nullptr);
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader reader (*this, *per_objfile, per_objfile->get_cu (this),
|
||||
true, std::nullopt, abbrev_table_cache);
|
||||
}
|
||||
|
||||
/* Return the unit from ALL_UNITS that potentially contains TARGET.
|
||||
|
|
@ -18126,8 +18020,11 @@ dwarf2_find_containing_unit (const section_and_offset &target,
|
|||
Even though it should happen too often, it could be replaced with
|
||||
something more lightweight that has the same effect. */
|
||||
if (!per_cu->length_is_set ())
|
||||
cutu_reader (*per_cu, *per_objfile, nullptr, nullptr, false,
|
||||
std::nullopt);
|
||||
{
|
||||
abbrev_table_cache abbrev_table_cache;
|
||||
cutu_reader (*per_cu, *per_objfile, nullptr, false, std::nullopt,
|
||||
abbrev_table_cache);
|
||||
}
|
||||
|
||||
/* Now we can check if the target section offset is within PER_CU's range. */
|
||||
if (target.offset < per_cu->sect_off ()
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ extern struct cmd_list_element *show_dwarf_cmdlist;
|
|||
|
||||
struct tu_stats
|
||||
{
|
||||
int nr_uniq_abbrev_tables = 0;
|
||||
int nr_symtabs = 0;
|
||||
int nr_symtab_sharers = 0;
|
||||
int nr_stmt_less_type_units = 0;
|
||||
|
|
@ -1016,17 +1015,17 @@ public:
|
|||
|
||||
cutu_reader (dwarf2_per_cu &this_cu,
|
||||
dwarf2_per_objfile &per_objfile,
|
||||
const struct abbrev_table *abbrev_table,
|
||||
dwarf2_cu *existing_cu,
|
||||
bool skip_partial,
|
||||
std::optional<language> pretend_language,
|
||||
const abbrev_table_cache *abbrev_cache = nullptr);
|
||||
abbrev_table_cache &abbrev_cache);
|
||||
|
||||
cutu_reader (dwarf2_per_cu &this_cu,
|
||||
dwarf2_per_objfile &per_objfile,
|
||||
std::optional<language> pretend_language,
|
||||
struct dwarf2_cu &parent_cu,
|
||||
struct dwo_file &dwo_file);
|
||||
struct dwo_file &dwo_file,
|
||||
abbrev_table_cache &abbrev_table_cache);
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (cutu_reader);
|
||||
|
||||
|
|
@ -1054,13 +1053,6 @@ public:
|
|||
/* Release the CU created by this cutu_reader. */
|
||||
dwarf2_cu_up release_cu ();
|
||||
|
||||
/* Release the abbrev table, transferring ownership to the
|
||||
caller. */
|
||||
abbrev_table_up release_abbrev_table ()
|
||||
{
|
||||
return std::move (m_abbrev_table_holder);
|
||||
}
|
||||
|
||||
/* Read all DIES of the debug info section in memory. */
|
||||
void read_all_dies ();
|
||||
|
||||
|
|
@ -1085,16 +1077,18 @@ private:
|
|||
|
||||
void init_cu_die_reader (dwarf2_cu *cu, dwarf2_section_info *section,
|
||||
struct dwo_file *dwo_file,
|
||||
const struct abbrev_table *abbrev_table);
|
||||
const abbrev_table &abbrev_table);
|
||||
|
||||
void init_tu_and_read_dwo_dies (dwarf2_per_cu *this_cu,
|
||||
dwarf2_per_objfile *per_objfile,
|
||||
dwarf2_cu *existing_cu,
|
||||
std::optional<language> pretend_language);
|
||||
std::optional<language> pretend_language,
|
||||
abbrev_table_cache &abbrev_table_cache);
|
||||
|
||||
void read_cutu_die_from_dwo (dwarf2_cu *cu, dwo_unit *dwo_unit,
|
||||
die_info *stub_comp_unit_die,
|
||||
const char *stub_comp_dir);
|
||||
const char *stub_comp_dir,
|
||||
abbrev_table_cache &abbrev_table_cache);
|
||||
|
||||
void prepare_one_comp_unit (struct dwarf2_cu *cu,
|
||||
std::optional<language> pretend_language);
|
||||
|
|
@ -1171,12 +1165,6 @@ private:
|
|||
bool m_dummy_p = false;
|
||||
|
||||
dwarf2_cu_up m_new_cu;
|
||||
|
||||
/* The ordinary abbreviation table. */
|
||||
abbrev_table_up m_abbrev_table_holder;
|
||||
|
||||
/* The DWO abbreviation table. */
|
||||
abbrev_table_up m_dwo_abbrev_table;
|
||||
};
|
||||
|
||||
/* Converts DWARF language names to GDB language names. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue