aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2020-04-28 06:12:35 +0200
committerTom de Vries <tdevries@suse.de>2020-04-28 06:12:35 +0200
commit15cd93d05e8e84644acc8bbeaa3d5f4280cc5159 (patch)
tree400712532427c91f20a7757055e25f3a6e420819 /gdb
parent30b57e1bea5b4bb2b0430e444db3848694d342b3 (diff)
downloadbinutils-15cd93d05e8e84644acc8bbeaa3d5f4280cc5159.zip
binutils-15cd93d05e8e84644acc8bbeaa3d5f4280cc5159.tar.gz
binutils-15cd93d05e8e84644acc8bbeaa3d5f4280cc5159.tar.bz2
[gdb/symtab] Handle struct decl with DW_AT_signature
Consider a test-case with sources 36.c: ... struct s { int i; }; extern void f (void); int main (void) { struct s a; f (); return 0; } ... and 36b.c: ... struct s { int j; }; void f (void) { struct s b; } ... compiled like this: ... $ gcc 36.c 36b.c -g ... It contains DWARF like this: ... <0><d2>: Abbrev Number: 1 (DW_TAG_compile_unit) <d8> DW_AT_name : 36.c <1><f4>: Abbrev Number: 2 (DW_TAG_structure_type) <f5> DW_AT_name : s <2><fe>: Abbrev Number: 3 (DW_TAG_member) <ff> DW_AT_name : i <1><110>: Abbrev Number: 5 (DW_TAG_subprogram) <111> DW_AT_name : main <2><12d>: Abbrev Number: 6 (DW_TAG_variable) <12e> DW_AT_name : a <132> DW_AT_type : <0xf4> <0><146>: Abbrev Number: 1 (DW_TAG_compile_unit) <14c> DW_AT_name : 36b.c <1><168>: Abbrev Number: 2 (DW_TAG_structure_type) <169> DW_AT_name : s <2><172>: Abbrev Number: 3 (DW_TAG_member) <173> DW_AT_name : j <1><184>: Abbrev Number: 5 (DW_TAG_subprogram) <185> DW_AT_name : f <2><19b>: Abbrev Number: 6 (DW_TAG_variable) <19c> DW_AT_name : b <1a0> DW_AT_type : <0x168> ... And when printing "struct s", we get first a random one (with int j), and then context-specific ones (with int i in main, and int j in f): ... $ gdb -batch a.out \ -ex "ptype struct s" \ -ex start \ -ex "ptype struct s" \ -ex "break f" -ex continue \ -ex "ptype struct s" \ | grep "int [ij];" int j; int i; int j; ... Same for -readnow. However, if we use -fdebug-types-section: ... $ gcc 36.c 36b.c -g -fdebug-types-section ... we get: ... $ gdb ... | grep "int [ij];" int j; int i; int i; $ gdb -readnow ... | grep "int [ij];" int j; int j; int j; ... This is due to the fact that both "struct s" DIEs have been moved to the .debug_types section: ... Compilation Unit @ offset 0x0: Signature: 0xfd1462823bb6f7b7 <0><17>: Abbrev Number: 1 (DW_TAG_type_unit) <1><1d>: Abbrev Number: 2 (DW_TAG_structure_type) <1e> DW_AT_name : s <2><27>: Abbrev Number: 3 (DW_TAG_member) <28> DW_AT_name : i Compilation Unit @ offset 0x3a: Signature: 0x534310fbefba324d <0><51>: Abbrev Number: 1 (DW_TAG_type_unit) <1><57>: Abbrev Number: 2 (DW_TAG_structure_type) <58> DW_AT_name : s <2><61>: Abbrev Number: 3 (DW_TAG_member) <62> DW_AT_name : j ... and there's no longer a "struct s" DIE in the 36.c and and 36b.c CUs to specify which "struct s" belongs in the CU. This is gcc PR90232. However, using a tentative patch for gcc that adds these DIEs (according to DWARF standard: If the complete declaration of a type has been placed in a separate type unit, an incomplete declaration of that type in the compilation unit may provide the unique 64-bit signature of the type using a DW_AT_signature attribute): ... <0><d2>: Abbrev Number: 5 (DW_TAG_compile_unit) <d8> DW_AT_name : 36.c + <1><f4>: Abbrev Number: 6 (DW_TAG_structure_type) + <f5> DW_AT_name : s + <f7> DW_AT_signature : signature: 0xfd1462823bb6f7b7 + <ff> DW_AT_declaration : 1 <0><13c>: Abbrev Number: 5 (DW_TAG_compile_unit) <142> DW_AT_name : 36b.c + <1><15e>: Abbrev Number: 6 (DW_TAG_structure_type) + <15f> DW_AT_name : s + <161> DW_AT_signature : signature: 0x534310fbefba324d + <169> DW_AT_declaration : 1 ... still does not help, because they're declarations, so new_symbol is not called for them in process_structure_scope. Fix this by calling new_symbol for these decls. Build and tested on x86_64-linux. Also tested with target board enabling by default -fdebug-types-section -gdwarf-4, and with gcc with aforementioned tentative patch. In this configuration, the patch reduces number of FAILs from 2888 to 238. gdb/ChangeLog: 2020-04-28 Tom de Vries <tdevries@suse.de> * dwarf2/read.c (process_structure_scope): Add symbol for struct decl with DW_AT_signature. gdb/testsuite/ChangeLog: 2020-04-28 Tom de Vries <tdevries@suse.de> * gdb.dwarf2/main-foo.c: New test. * gdb.dwarf2/struct-with-sig.exp: New file.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/dwarf2/read.c3
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.dwarf2/main-foo.c34
-rw-r--r--gdb/testsuite/gdb.dwarf2/struct-with-sig.exp141
5 files changed, 187 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 78b3ed8..76f6cf7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2020-04-28 Tom de Vries <tdevries@suse.de>
+
+ * dwarf2/read.c (process_structure_scope): Add symbol for struct decl
+ with DW_AT_signature.
+
2020-04-27 Simon Marchi <simon.marchi@efficios.com>
* configure.ac: Remove check for fs_base/gs_base in
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 9762613..82564ed 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -15748,7 +15748,8 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
these DIEs are identified by the fact that they have no byte_size
attribute, and a declaration attribute. */
if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
- || !die_is_declaration (die, cu))
+ || !die_is_declaration (die, cu)
+ || dwarf2_attr (die, DW_AT_signature, cu) != NULL)
{
struct symbol *sym = new_symbol (die, type, cu);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 366ecc2..2fef7c5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-04-28 Tom de Vries <tdevries@suse.de>
+
+ * gdb.dwarf2/main-foo.c: New test.
+ * gdb.dwarf2/struct-with-sig.exp: New file.
+
2020-04-25 Tom de Vries <tdevries@suse.de>
* boards/debug-types.exp: New file.
diff --git a/gdb/testsuite/gdb.dwarf2/main-foo.c b/gdb/testsuite/gdb.dwarf2/main-foo.c
new file mode 100644
index 0000000..82d7b1f
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/main-foo.c
@@ -0,0 +1,34 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2020 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/>. */
+
+/* Dummy foo function. */
+
+void
+foo (void)
+{
+ asm ("foo_label: .globl foo_label");
+}
+
+/* Dummy main function. */
+
+int
+main()
+{
+ asm ("main_label: .globl main_label");
+ foo ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/struct-with-sig.exp b/gdb/testsuite/gdb.dwarf2/struct-with-sig.exp
new file mode 100644
index 0000000..1ce013d
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/struct-with-sig.exp
@@ -0,0 +1,141 @@
+# Copyright 2020 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/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile main-foo.c .S
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile
+
+ lassign [function_range main ${srcdir}/${subdir}/${srcfile}] \
+ main_start main_length
+
+ lassign [function_range foo ${srcdir}/${subdir}/${srcfile}] \
+ foo_start foo_length
+
+ cu {} {
+ compile_unit {
+ {DW_AT_language @DW_LANG_C}
+ {DW_AT_name main.c}
+ } {
+ structure_type {
+ {name s}
+ {signature 0x0000000000000001 ref_sig8}
+ {declaration 1 flag}
+ }
+ DW_TAG_subprogram {
+ {name "main"}
+ {low_pc $main_start addr}
+ {high_pc "$main_start + $main_length" addr}
+ }
+ }
+ }
+
+ cu {} {
+ compile_unit {
+ {DW_AT_language @DW_LANG_C}
+ {DW_AT_name foo.c}
+ } {
+ structure_type {
+ {name s}
+ {signature 0x0000000000000002 ref_sig8}
+ {declaration 1 flag}
+ }
+ DW_TAG_subprogram {
+ {name "foo"}
+ {low_pc $foo_start addr}
+ {high_pc "$foo_start + $foo_length" addr}
+ }
+ }
+ }
+
+ tu {} 0x0000000000000001 the_type_i {
+ type_unit {} {
+ declare_labels int_type
+
+ the_type_i: structure_type {
+ {name s}
+ {byte_size 4 sdata}
+ } {
+ member {
+ {name i}
+ {type :$int_type}
+ }
+ }
+ int_type: base_type {
+ {name int}
+ {encoding @DW_ATE_signed}
+ {byte_size 4 sdata}
+ }
+ }
+ }
+
+ tu {} 0x0000000000000002 the_type_j {
+ type_unit {} {
+ declare_labels int_type
+
+ the_type_j: structure_type {
+ {name s}
+ {byte_size 4 sdata}
+ } {
+ member {
+ {name j}
+ {type :$int_type}
+ }
+ }
+ int_type: base_type {
+ {name int}
+ {encoding @DW_ATE_signed}
+ {byte_size 4 sdata}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+set struct_s_i_re \
+ [multi_line \
+ "type = struct s {" \
+ " int i;" \
+ "}"]
+set struct_s_j_re \
+ [multi_line \
+ "type = struct s {" \
+ " int j;" \
+ "}"]
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test "ptype struct s" $struct_s_i_re \
+ "struct s with int i"
+
+gdb_breakpoint "foo"
+gdb_continue_to_breakpoint "foo"
+
+gdb_test "ptype struct s" $struct_s_j_re \
+ "struct s with int j"