diff options
author | Tom de Vries <tdevries@suse.de> | 2024-08-22 10:00:27 +0200 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2024-08-22 10:00:27 +0200 |
commit | 573d8bb08bfff4638405add40a6a61868af1f2a4 (patch) | |
tree | fa3096151384d4b1ea98550b76b9e81af788c340 /gdb/dwarf2 | |
parent | 50f8a39878d6c8cf4dfcb1d3333aa2a20daada0c (diff) | |
download | gdb-573d8bb08bfff4638405add40a6a61868af1f2a4.zip gdb-573d8bb08bfff4638405add40a6a61868af1f2a4.tar.gz gdb-573d8bb08bfff4638405add40a6a61868af1f2a4.tar.bz2 |
[gdb/symtab] Return correct reader for top-level CU in cooked_indexer::ensure_cu_exists
With the test-case included in this patch, we run into:
...
$ gdb -q -batch $exec
Dwarf Error: Could not find abbrev number 3 in CU at offset 0xdb \
[in module $exec]
...
The debug info consists of two CUs:
...
Compilation Unit @ offset 0xb2:
Length: 0x25 (32-bit)
Version: 4
Abbrev Offset: 0x6c
Pointer Size: 8
<0><bd>: Abbrev Number: 1 (DW_TAG_compile_unit)
<be> DW_AT_language : 2 (non-ANSI C)
<1><bf>: Abbrev Number: 2 (DW_TAG_subprogram)
<c0> DW_AT_low_pc : 0x4004a7
<c8> DW_AT_high_pc : 0x4004b2
<d0> DW_AT_specification: <0xe8>
<1><d4>: Abbrev Number: 3 (DW_TAG_subprogram)
<d5> DW_AT_name : main
<1><da>: Abbrev Number: 0
Compilation Unit @ offset 0xdb:
Length: 0xf (32-bit)
Version: 4
Abbrev Offset: 0x86
Pointer Size: 8
<0><e6>: Abbrev Number: 1 (DW_TAG_compile_unit)
<e7> DW_AT_language : 2 (non-ANSI C)
<1><e8>: Abbrev Number: 2 (DW_TAG_subprogram)
<e9> DW_AT_specification: <0xd4>
<1><ed>: Abbrev Number: 0
...
where:
- DIE 0xbf in CU@0xb2 contains an inter-CU reference to
- DIE 0xe8 in CU@0xdb, which contains an inter-CU reference to
- DIE 0xd4 back in CU@0xb2.
The dwarf error is caused by this bit of code in
cooked_indexer::ensure_cu_exists:
...
if (per_cu == m_per_cu)
return reader;
...
The dwarf error happens as follows:
- a cutu_reader A is created for CU@0xb2
- using cutu_reader A, the cooked index reader starts indexing dies, with
m_per_cu set to CU@0xb2
- while indexing it scans the attributes of DIE 0xbf and encounters the
inter-CU reference to DIE 0xe8
- it calls cooked_indexer::ensure_cu_exists, which creates a cutu_reader B for
CU@0xdb and returns it
- using cutu_reader B, it continues scanning attributes of DIE 0xe8 and
encounters the inter-CU reference to DIE 0xd4
- it calls cooked_indexer::ensure_cu_exists, the problematic bit is triggered
and cutu_reader B is returned
- using cutu_reader B, it continues scanning attributes of DIE 0xd4
- this goes wrong because:
- the attributes of the DIE are encoded using the abbreviation table at
offset 0x6c, while
- the decoding is done using cutu_reader B which uses the abbreviation table
at offset 0x86.
Fix this by removing the problematic if clause.
Since cutu_reader A is not preserved in m_index_storage,
cooked_indexer::ensure_cu_exists cannot find it there and creates a duplicate
cutu_reader C for CU@0xb2. Fix this in process_psymtab_comp_unit by preserving
the cutu_reader A as well in m_index_storage.
Tested on x86_64-linux and aarch64-linux.
PR symtab/32081
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32081
Approved-By: Tom Tromey <tom@tromey.com>
Reported-By: Andreas Schwab <schwab@linux-m68k.org>
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r-- | gdb/dwarf2/read.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index f9f34fd..04a5398 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -4532,28 +4532,35 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, dwarf2_per_objfile *per_objfile, cooked_index_storage *storage) { - cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false, - storage->get_abbrev_cache ()); + cutu_reader *reader = storage->get_reader (this_cu); + if (reader == nullptr) + { + cutu_reader new_reader (this_cu, per_objfile, nullptr, nullptr, false, + storage->get_abbrev_cache ()); - if (reader.comp_unit_die == nullptr) - return; + if (new_reader.comp_unit_die == nullptr || new_reader.dummy_p) + return; - if (reader.dummy_p) - { - /* Nothing. */ + std::unique_ptr<cutu_reader> copy + (new cutu_reader (std::move (new_reader))); + reader = storage->preserve (std::move (copy)); } - else if (this_cu->is_debug_types) - build_type_psymtabs_reader (&reader, storage); - else if (reader.comp_unit_die->tag != DW_TAG_partial_unit) + + if (reader->comp_unit_die == nullptr || reader->dummy_p) + return; + + if (this_cu->is_debug_types) + build_type_psymtabs_reader (reader, storage); + else if (reader->comp_unit_die->tag != DW_TAG_partial_unit) { bool nope = false; if (this_cu->scanned.compare_exchange_strong (nope, true)) { - prepare_one_comp_unit (reader.cu, reader.comp_unit_die, + prepare_one_comp_unit (reader->cu, reader->comp_unit_die, language_minimal); gdb_assert (storage != nullptr); - cooked_indexer indexer (storage, this_cu, reader.cu->lang ()); - indexer.make_index (&reader); + cooked_indexer indexer (storage, this_cu, reader->cu->lang ()); + indexer.make_index (reader); } } } @@ -16030,8 +16037,6 @@ cooked_indexer::ensure_cu_exists (cutu_reader *reader, if (!per_cu->scanned.compare_exchange_strong (nope, true)) return nullptr; } - if (per_cu == m_per_cu) - return reader; cutu_reader *result = m_index_storage->get_reader (per_cu); if (result == nullptr) |