forked from Imagelibrary/binutils-gdb
Correctly handle forward DIE references in scanner
The cooked index scanner has special code to handle forward DIE references. However, a bug report lead to the discovery that this code does not work -- the "deferred_entry::spec_offset" field is written to but never used, i.e., the lookup is done using the wrong key. This patch fixes the bug and adds a regression test. The test in the bug itself used a thread_local variable, which provoked a failure at runtime. This test instead uses "maint print objfiles" and then inspects to ensure that the entry in question has a parent. This lets us avoid a clang dependency in the test. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30271
This commit is contained in:
@@ -16641,9 +16641,8 @@ cooked_indexer::make_index (cutu_reader *reader)
|
|||||||
|
|
||||||
for (const auto &entry : m_deferred_entries)
|
for (const auto &entry : m_deferred_entries)
|
||||||
{
|
{
|
||||||
CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
|
void *obj = m_die_range_map.find (entry.spec_offset);
|
||||||
void *obj = m_die_range_map.find (key);
|
cooked_index_entry *parent = static_cast<cooked_index_entry *> (obj);
|
||||||
cooked_index_entry *parent = static_cast <cooked_index_entry *> (obj);
|
|
||||||
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||||
entry.name, parent, m_per_cu);
|
entry.name, parent, m_per_cu);
|
||||||
}
|
}
|
||||||
|
|||||||
102
gdb/testsuite/gdb.dwarf2/forward-spec.exp
Normal file
102
gdb/testsuite/gdb.dwarf2/forward-spec.exp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
# Copyright 2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Check that the DWARF reader works with a a DW_AT_specification that
|
||||||
|
# refers to a later DIE.
|
||||||
|
|
||||||
|
load_lib dwarf.exp
|
||||||
|
|
||||||
|
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||||
|
require dwarf2_support
|
||||||
|
|
||||||
|
standard_testfile main.c -debug.S
|
||||||
|
|
||||||
|
# Set up the DWARF for the test.
|
||||||
|
set asm_file [standard_output_file $srcfile2]
|
||||||
|
Dwarf::assemble $asm_file {
|
||||||
|
global srcfile
|
||||||
|
|
||||||
|
cu {} {
|
||||||
|
DW_TAG_compile_unit {
|
||||||
|
{DW_AT_language @DW_LANG_C_plus_plus}
|
||||||
|
{DW_AT_name $srcfile}
|
||||||
|
{DW_AT_comp_dir /tmp}
|
||||||
|
|
||||||
|
} {
|
||||||
|
declare_labels spec myint
|
||||||
|
|
||||||
|
# The new indexer has special code to compute the full
|
||||||
|
# name of an object that uses a specification that appears
|
||||||
|
# later in the DWARF.
|
||||||
|
DW_TAG_variable {
|
||||||
|
{DW_AT_specification :$spec}
|
||||||
|
{DW_AT_location {
|
||||||
|
DW_OP_const1u 23
|
||||||
|
DW_OP_stack_value
|
||||||
|
} SPECIAL_expr}
|
||||||
|
}
|
||||||
|
|
||||||
|
myint: DW_TAG_base_type {
|
||||||
|
{DW_AT_byte_size 4 DW_FORM_sdata}
|
||||||
|
{DW_AT_encoding @DW_ATE_signed}
|
||||||
|
{DW_AT_name myint}
|
||||||
|
}
|
||||||
|
|
||||||
|
DW_TAG_namespace {
|
||||||
|
{DW_AT_name ns}
|
||||||
|
} {
|
||||||
|
spec: DW_TAG_variable {
|
||||||
|
{DW_AT_name v}
|
||||||
|
{DW_AT_type :$myint}
|
||||||
|
{DW_AT_declaration 1 DW_FORM_flag_present}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing "failed to prepare" ${testfile} \
|
||||||
|
[list $srcfile $asm_file] {nodebug}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
set in_v 0
|
||||||
|
gdb_test_multiple "maint print objfiles" "v has a parent" {
|
||||||
|
-re "^ *\\\[\[0-9\]\\\] *..cooked_index_entry\[^\r\n\]*" {
|
||||||
|
set in_v 0
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
-re "^ *name: *v\[\r\n\]*" {
|
||||||
|
set in_v 1
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
-re "^ *parent: *..cooked_index_entry .. (0|$hex)." {
|
||||||
|
if {$in_v} {
|
||||||
|
if {$expect_out(1,string) == "0"} {
|
||||||
|
fail $gdb_test_name
|
||||||
|
} else {
|
||||||
|
pass $gdb_test_name
|
||||||
|
}
|
||||||
|
set in_v 0
|
||||||
|
}
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
-re "^\[^\r\n\]*\[\r\n\]+" {
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
-re "$gdb_prompt " {
|
||||||
|
# Done.
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user