From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id 66BAB385842B; Sun, 7 Aug 2022 06:31:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 66BAB385842B Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/testsuite] Add support for .debug_names in dwarf assembler X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: 3ba7b1551b810b9613e11889111406138f10f208 X-Git-Newrev: f4cbdf0b6857069d42477e06f0077f4c03bb4c82 Message-Id: <20220807063142.66BAB385842B@sourceware.org> Date: Sun, 7 Aug 2022 06:31:42 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Aug 2022 06:31:42 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Df4cbdf0b6857= 069d42477e06f0077f4c03bb4c82 commit f4cbdf0b6857069d42477e06f0077f4c03bb4c82 Author: Tom de Vries Date: Sun Aug 7 08:31:36 2022 +0200 [gdb/testsuite] Add support for .debug_names in dwarf assembler =20 Add: - support for a per-module .debug_names section in the dwarf assembler,= and - a test-case excercising this new functionality. =20 A per-module .debug_names section needs to have an entry in the CU list= for each CU in the module, which is made more difficult by two things: - linking in other objects, which may contain additional CUs (typically the case on openSUSE), and - adding dummy CUs in the dwarf assembler. We handle this by: - compiling with -nostartfiles (so the test-case contains _start rather= than main), and - disabling the dummy CU generation for the test-case. =20 I've kept things simple by having the test-case specify the hash value,= rather than adding that functionality in the dwarf assembler. =20 Also I've kept the bucket count to 1, which makes it trivial to satisfy= the requirement that "the symbol is entered into a bucket whose index is th= e hash value modulo bucket_count". =20 The readelf dump of the .debug_names section from the test-case looks l= ike: ... Version 5 Augmentation string: 47 44 42 00 ("GDB") CU table: [ 0] 0x0 =20 TU table: =20 Foreign TU table: =20 Used 1 of 1 bucket. Out of 2 items there are 1 bucket clashes (longest of 1 entries). =20 Symbol table: [ 0] #eddb6232 _start: <1> DW_TAG_subprogram DW_IDX_compile_unit=3D0 [ 1] #0b888030 int: <2> DW_TAG_base_type DW_IDX_compile_unit=3D0 ... =20 Tested on x86_64-linux. Diff: --- gdb/testsuite/gdb.dwarf2/_start.c | 27 ++++ gdb/testsuite/gdb.dwarf2/debug-names.exp | 79 +++++++++++ gdb/testsuite/lib/dwarf.exp | 229 +++++++++++++++++++++++++++= +++- 3 files changed, 330 insertions(+), 5 deletions(-) diff --git a/gdb/testsuite/gdb.dwarf2/_start.c b/gdb/testsuite/gdb.dwarf2/_= start.c new file mode 100644 index 00000000000..cf74fe0b42f --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/_start.c @@ -0,0 +1,27 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 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 _start function, to be used with -nostartfile. */ + +#include + +void +_start (void) +{ + asm ("_start_label: .globl _start_label"); + exit (0); +} diff --git a/gdb/testsuite/gdb.dwarf2/debug-names.exp b/gdb/testsuite/gdb.d= warf2/debug-names.exp new file mode 100644 index 00000000000..0af5a93bea8 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/debug-names.exp @@ -0,0 +1,79 @@ +# Copyright 2022 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 _start.c debug-names.S + +set func_info_vars \ + [get_func_info _start [list debug additional_flags=3D-nostartfiles]] + +# Create the DWARF. +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble { + filename $asm_file + add_dummy_cus 0 +} { + global func_info_vars + foreach var $func_info_vars { + global $var + } + + cu { label cu_label } { + compile_unit {{language @DW_LANG_C}} { + subprogram { + {DW_AT_name _start} + {DW_AT_low_pc $_start_start DW_FORM_addr} + {DW_AT_high_pc $_start_end DW_FORM_addr} + } + base_type { + {name int} + {byte_size 4 sdata} + {encoding @DW_ATE_signed} + } + } + } + + debug_names {} { + cu cu_label + name _start subprogram cu_label 0xEDDB6232 + name int base_type cu_label 0xB888030 + } +} + +if [prepare_for_testing "failed to prepare" $testfile "${asm_file} ${srcfi= le}" \ + [list additional_flags=3D-nostartfiles]] { + return -1 +} + +# Verify that .debug_names section is not ignored. +set index [have_index $binfile] +gdb_assert { [string equal $index "debug_names"] } ".debug_names used" + +# Verify that initially no symtab is expanded. +gdb_test_no_output "maint info symtabs" + +if ![runto _start] { + return -1 +} + +# Verify that breaking on _start actually expanded a symtab, rather than +# falling back on minimal symbols. +gdb_test "maint info symtabs" "name .*" "break _start expanded sy= mtab" diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 356451bcaac..3d833e5cd58 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -2925,9 +2925,215 @@ namespace eval Dwarf { } } =20 + # Emit a DWARF .debug_names section. + # + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # is_64 0|1 - boolean indicating if the section contains 64-bit DWARF. + # default =3D 0 (32-bit) + # version n - section version. + # default =3D 5. + # + # BODY is Tcl code that emits the parts which make up the body of + # the .debug_names section. It is evaluated in the caller's context. + # The following commands are available for the BODY section: + # + # cu + # -- add a CU. + # + # name + # -- add a name. + + proc debug_names { options body } { + parse_options { + { is_64 0 } + { version 5 } + } + + variable _debug_names_offset_size + if { $is_64 =3D=3D 1 } { + set _debug_names_offset_size 8 + } else { + set _debug_names_offset_size 4 + } + + # Section start. + set section ".debug_names" + _section $section + + # Header - initial length. + declare_labels debug_names_start debug_names_end + set length "$debug_names_end - $debug_names_start" + set comment "Initial_length" + if { $is_64 } { + _op .4byte 0xffffffff + _op .8byte $length $comment + } else { + _op .4byte $length $comment + } + + # Header - start label. + debug_names_start: + + # Header - version + padding. + _op .2byte $version "Version" + _op .2byte 0 "Padding" + + # Parse the body. + variable _debug_names_cus + set _debug_names_cus [] + proc _debug_names_cu { cu } { + variable _debug_names_cus + lappend _debug_names_cus $cu + } + variable _debug_names + set _debug_names [] + proc _debug_names_name { name tag cu hash } { + variable _debug_names + declare_labels entry_pool_offset + lappend _debug_names [list $name $tag $cu $hash $entry_pool_offset] + } + with_override Dwarf::cu Dwarf::_debug_names_cu { + with_override Dwarf::name Dwarf::_debug_names_name { + uplevel $body + }} + + # Header - CU / TU / foreign TU count. + _op .4byte [llength $_debug_names_cus] "Comp_unit_count" + _op .4byte 0 "Local_type_unit_count" + _op .4byte 0 "Foreign_type_unit_count" + + # Header - bucket count. + _op .4byte 1 "Bucket_count" + + # Header - name count. + _op .4byte [llength $_debug_names] "Name_count" + + # Header - abbreviation table size. + declare_labels debug_names_abbrev_table_start \ + debug_names_abbrev_table_end + set abbrev_table_size \ + "$debug_names_abbrev_table_end - $debug_names_abbrev_table_start" + _op .4byte $abbrev_table_size "Abbrev_table_size" + + # Header - augmentation string. + _op .4byte 4 "Augmentation_string_size" + _op .ascii [_quote GDB] "Augmentation_string" + + # List of CUs. + set comment "CU offset" + foreach cu $_debug_names_cus { + upvar $cu tmp + if { $is_64 } { + _op .8byte $tmp $comment + } else { + _op .4byte $tmp $comment + } + } + + # List of Local TUs. + # + + # List of Foreign TUs. + # + + # Hash Lookup Table - array of buckets. + _op .4byte 1 "bucket: hash array index 1" + + # Hash Lookup Table - array of hashes. + foreach idx $_debug_names { + set name [lindex $idx 0] + set hash [lindex $idx 3] + _op .4byte $hash "hash: $name" + } + + # Name Table - array of string offsets. + foreach idx $_debug_names { + set name [lindex $idx 0] + + variable _strings + if {![info exists _strings($name)]} { + set _strings($name) [new_label strp] + _defer_output .debug_str { + define_label $_strings($name) + _op .ascii [_quote $name] + } + } + + _op_offset $_debug_names_offset_size $_strings($name) "name: $name" + } + + # Name Table - array of entry offsets. + set base_label "" + foreach idx $_debug_names { + set name [lindex $idx 0] + set label [lindex $idx 4] + if { [string equal $base_label ""]} { + set base_label $label + } + _op_offset $_debug_names_offset_size "$label - $base_label" \ + "entry pool offset: $name" + } + + # Abbreviations Table. + debug_names_abbrev_table_start: + set abbrev 1 + variable _constants + foreach idx $_debug_names { + set name [lindex $idx 0] + set tag [lindex $idx 1] + _op .byte $abbrev "abbrev $abbrev" + _op .uleb128 $_constants(DW_TAG_$tag) "DW_TAG_$tag" + _op .byte 1 "DW_IDX_compile_unit (attribute)" + _op .byte 0x0f "DW_FORM_udata (form)" + _op .byte 0 "abbrev terminator (attribute)" + _op .byte 0 "abbrev terminator (form)" + incr abbrev + } + _op .byte 0 "Abbreviations Table terminator" + debug_names_abbrev_table_end: + + # Entry Pool + set abbrev 1 + foreach idx $_debug_names { + set name [lindex $idx 0] + set cu [lindex $idx 2] + set label [lindex $idx 4] + + set cu_index 0 + foreach idx2 $_debug_names_cus { + if { $idx2 =3D=3D $cu } { + break + } + incr cu_index + } + + define_label $label + _op .byte $abbrev "$name: abbrev" + _op .uleb128 $cu_index "$name: CU index" + _op .byte 0 "$name: terminator" + incr abbrev + } + + # Section end. + debug_names_end: + } + # The top-level interface to the DWARF assembler. - # FILENAME is the name of the file where the generated assembly - # code is written. + # OPTIONS is a list with an even number of elements containing + # option-name and option-value pairs. + # Current options are: + # filename + # - the name of the file where the generated assembly + # code is written. + # default =3D "". + # add_dummy_cus <0|1> + # - Whether to add dummy CUs before and after the CUs + # added in the BODY. + # default =3D 1. + # As a special case, if OPTIONS is a list of length 1, it's + # interpreted as specifing the filename. # BODY is Tcl code to emit the assembly. It is evaluated via # "eval" -- not uplevel as you might expect, because it is # important to run the body in the Dwarf namespace. @@ -2943,7 +3149,7 @@ namespace eval Dwarf { # ... # } # } - proc assemble {filename body} { + proc assemble {options body} { variable _initialized variable _output_file variable _deferred_output @@ -2956,6 +3162,15 @@ namespace eval Dwarf { variable _debug_ranges_64_bit variable _debug_addr_index =20 + if { [llength $options] =3D=3D 1 } { + set options [list filename [lindex $options 0]] + } + + parse_options { + { filename "" } + { add_dummy_cus 1 } + } + if {!$_initialized} { _read_constants set _initialized 1 @@ -2975,7 +3190,9 @@ namespace eval Dwarf { =20 # Dummy CU at the start to ensure that the first CU in $body is not # the first in .debug_info. - dummy_cu + if { $add_dummy_cus } { + dummy_cu + } =20 with_shared_gdb { # Not "uplevel" here, because we want to evaluate in this @@ -2986,7 +3203,9 @@ namespace eval Dwarf { =20 # Dummy CU at the end to ensure that the last CU in $body is not # the last in .debug_info. - dummy_cu + if { $add_dummy_cus } { + dummy_cu + } =20 _write_deferred_output