[binutils-gdb] Use fully-qualified name in var_decl_name
Tom Tromey via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0586465daf276a2313f9eb0d2812f171a9ea28fb commit 0586465daf276a2313f9eb0d2812f171a9ea28fb Author: Tom Tromey <[email protected]> Date: Thu Apr 23 06:22:43 2026 -0600 Use fully-qualified name in var_decl_name While testing gdb against a version of gnat-llvm that emits unqualified names (in a hierarchical structure), I found that gdb.ada/array_of_symbolic_length.exp would fail. The DWARF in question looks like this: <1><11a1>: Abbrev Number: 2 (DW_TAG_module) <11a2> DW_AT_name : (indirect string, offset: 0xe65): pck <2><11a6>: Abbrev Number: 3 (DW_TAG_variable) <11a7> DW_AT_name : (indirect string, offset: 0xe69): my_length_LAST [...] <3><11df>: Abbrev Number: 5 (DW_TAG_subrange_type) <11e0> DW_AT_type : <0x12ab> <11e4> DW_AT_upper_bound : <0x11a6> That is, an array's upper bound refers to my_length_LAST. gdb represents this as a PROP_VARIABLE_NAME -- but only the local name of the variable was used in this case. This patch changes var_decl_name to use the correct full name for the variable. Co-Authored-By: Andrew Burgess <[email protected]> Approved-By: Andrew Burgess <[email protected]> Diff: --- gdb/dwarf2/read.c | 5 +- gdb/testsuite/gdb.dwarf2/ada-var-in-module.c | 24 ++++ gdb/testsuite/gdb.dwarf2/ada-var-in-module.exp | 151 +++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 4 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 7b5e1b65554..58646cff54b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -13397,10 +13397,7 @@ var_decl_name (struct die_info *die, struct dwarf2_cu *cu) if (attr == nullptr || !attr->as_boolean ()) return nullptr; - attr = dwarf2_attr (die, DW_AT_name, cu); - if (attr == nullptr) - return nullptr; - return attr->as_string (); + return dwarf2_full_name (nullptr, die, cu); } /* Parse dwarf attribute if it's a block, reference or constant and put the diff --git a/gdb/testsuite/gdb.dwarf2/ada-var-in-module.c b/gdb/testsuite/gdb.dwarf2/ada-var-in-module.c new file mode 100644 index 00000000000..cbc388b0346 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/ada-var-in-module.c @@ -0,0 +1,24 @@ +/* Copyright 2026 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/>. */ + +int the_length = 5; +int wrong_length = 9; +int global_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/ada-var-in-module.exp b/gdb/testsuite/gdb.dwarf2/ada-var-in-module.exp new file mode 100644 index 00000000000..b97e81b65c2 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/ada-var-in-module.exp @@ -0,0 +1,151 @@ +# Copyright 2026 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/>. + +# Test that an array whose upper bound references a variable +# declaration inside a DW_TAG_module gets the correct fully qualified +# name. This tests that var_decl_name returns the fully qualified +# name. +# +# Without the var_decl_name fix, only the non-qualified name was being +# returned, GDB would then lookup based on this partial name, and +# could find the wrong variable. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +require dwarf2_support + +standard_testfile .c -dw.S + +# Make some DWARF for the test. +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + cu {} { + DW_TAG_compile_unit { + DW_AT_language @DW_LANG_Ada95 + DW_AT_name foo.adb + DW_AT_comp_dir /tmp + } { + declare_labels integer_label array_label \ + length_label + + # Basic integer type. + integer_label: DW_TAG_base_type { + DW_AT_byte_size 4 DW_FORM_sdata + DW_AT_encoding @DW_ATE_signed + DW_AT_name integer + } + + # A module with a variable called 'my_length', this does + # not point at the array length though. This exists to + # confuse Ada's wild card variable lookup. + DW_TAG_module { + DW_AT_name aaa + } { + DW_TAG_variable { + DW_AT_name my_length + DW_AT_type :$integer_label + DW_AT_external 1 flag + DW_AT_location { + DW_OP_addr [gdb_target_symbol wrong_length] + } SPECIAL_expr + } + } + + # The 'bbb' module contains the variable that holds the + # array length (the array itself is defined below). There + # MUST be a separate declaration and definition for the + # variable, the bug we are testing for is when the array + # bound points at the declaration. + DW_TAG_module { + DW_AT_name bbb + } { + length_label: DW_TAG_variable { + DW_AT_name my_length + DW_AT_type :$integer_label + DW_AT_declaration 1 flag + } + + DW_TAG_variable { + DW_AT_name my_length + DW_AT_type :$integer_label + DW_AT_external 1 flag + DW_AT_location { + DW_OP_addr [gdb_target_symbol the_length] + } SPECIAL_expr + } + } + + # Another module with a variable called 'my_length', this + # also does not point at the array length. As with the + # 'aaa' module, this exists to confuse Ada's wild card + # variable lookup. + DW_TAG_module { + DW_AT_name ccc + } { + DW_TAG_variable { + DW_AT_name my_length + DW_AT_type :$integer_label + DW_AT_external 1 flag + DW_AT_location { + DW_OP_addr [gdb_target_symbol wrong_length] + } SPECIAL_expr + } + } + + # Global array type. The upper bound is held in the + # 'bbb.my_length' variable. The upper bound MUST + # reference the variable declaration in order to test the + # bug we are interested in. + array_label: DW_TAG_array_type { + DW_AT_name the_array_type + DW_AT_type :$integer_label + } { + DW_TAG_subrange_type { + DW_AT_type :$integer_label + DW_AT_lower_bound 1 DW_FORM_sdata + DW_AT_upper_bound :$length_label + } + } + + # Global array variable. + DW_TAG_variable { + DW_AT_name the_array + DW_AT_type :$array_label + DW_AT_location { + DW_OP_addr [gdb_target_symbol global_array] + } SPECIAL_expr + DW_AT_external 1 flag + } + } + } +} + +if {[prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}]} { + return +} + +# Print 'the_array'. To establish the upper bound GDB must lookup the +# correct variable by name. With the bug fix in place GDB should look +# for 'bbb.my_length' and find the correct variable. Without the fix +# GDB would look for just 'my_length' which is ambiguous. The hope of +# this test is that by having an 'aaa.my_length' and 'ccc.my_length' +# that, without the fix, GDB will find the wrong length and use that. +gdb_test_no_output "set language ada" +gdb_test "print aaa.my_length" " = 9" +gdb_test "print bbb.my_length" " = 5" +gdb_test "print ccc.my_length" " = 9" +gdb_test "print the_array" " = \\(1, 2, 3, 4, 5\\)"