aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2024-08-22 10:00:27 +0200
committerTom de Vries <tdevries@suse.de>2024-08-22 10:00:27 +0200
commit573d8bb08bfff4638405add40a6a61868af1f2a4 (patch)
treefa3096151384d4b1ea98550b76b9e81af788c340 /gdb/dwarf2
parent50f8a39878d6c8cf4dfcb1d3333aa2a20daada0c (diff)
downloadgdb-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.c35
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)