From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 1A035385DC0C for ; Thu, 23 Apr 2020 13:09:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 1A035385DC0C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 73A13AC5B; Thu, 23 Apr 2020 13:09:31 +0000 (UTC) Date: Thu, 23 Apr 2020 15:09:29 +0200 From: Tom de Vries To: gdb-patches@sourceware.org Cc: Tom Tromey , Simon Marchi Subject: [PATCH][gdb/symtab] Handle struct decl with DW_AT_signature Message-ID: <20200423130928.GA4247@delia> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-29.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Apr 2020 13:09:35 -0000 Hi, 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>: Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_name : 36.c <1>: Abbrev Number: 2 (DW_TAG_structure_type) DW_AT_name : s <2>: Abbrev Number: 3 (DW_TAG_member) 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>: Abbrev Number: 5 (DW_TAG_compile_unit) DW_AT_name : 36.c + <1>: Abbrev Number: 6 (DW_TAG_structure_type) + DW_AT_name : s + DW_AT_signature : signature: 0xfd1462823bb6f7b7 + 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. Any comments? Thanks, - Tom [gdb/symtab] Handle struct decl with DW_AT_signature gdb/ChangeLog: 2020-04-21 Tom de Vries * dwarf2/read.c (process_structure_scope): Add symbol for struct decl with DW_AT_signature. gdb/testsuite/ChangeLog: 2020-04-21 Tom de Vries * gdb.dwarf2/main-foo.c: New test. * gdb.dwarf2/struct-with-sig.exp: New file. --- gdb/dwarf2/read.c | 3 +- gdb/testsuite/gdb.dwarf2/main-foo.c | 34 +++++++ gdb/testsuite/gdb.dwarf2/struct-with-sig.exp | 141 +++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index c2a9103510f..e61e6670344 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -15464,7 +15464,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/gdb.dwarf2/main-foo.c b/gdb/testsuite/gdb.dwarf2/main-foo.c new file mode 100644 index 00000000000..82d7b1f40ed --- /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 . */ + +/* 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 00000000000..1ce013dfea6 --- /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 . +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"