From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id +NhNGPcB7WJkMCEAWB0awg (envelope-from ) for ; Fri, 05 Aug 2022 07:41:43 -0400 Received: by simark.ca (Postfix, from userid 112) id 5FDB71EA05; Fri, 5 Aug 2022 07:41:43 -0400 (EDT) Authentication-Results: simark.ca; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=MgStOJcz; dkim-atps=neutral X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 8FD0F1EA04 for ; Fri, 5 Aug 2022 07:41:41 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 78FF23856DD7 for ; Fri, 5 Aug 2022 11:41:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 78FF23856DD7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1659699699; bh=I/rZ0qKrgMNOqF5JiQ9H3LHkFsojTbLWMUsS8WuWZYo=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=MgStOJcz5hh5SezCMYXvrhDxPDKavhMPdslrJ96wZ1aQ0xS5kEN/iJRbn2/IlMPDo 0nOSkDDem95fKer20AhYGKqV01VzlHbsFkdC7GjR+xnKpXQ8KIqBpugseeZ1ot6Yg3 PsbCRRPtPu4JcVfIhjYc4eMIrAVqKfRuqPdWkY/M= Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id 2954D3858C53 for ; Fri, 5 Aug 2022 11:41:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2954D3858C53 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 41C2833C1F for ; Fri, 5 Aug 2022 11:41:17 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 2A665133B5 for ; Fri, 5 Aug 2022 11:41:17 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id RV4cCd0B7WIlBwAAMHmgww (envelope-from ) for ; Fri, 05 Aug 2022 11:41:17 +0000 To: gdb-patches@sourceware.org Subject: [PATCH 1/2] [gdb/testsuite] Add support for .debug_names in dwarf assembler Date: Fri, 5 Aug 2022 13:41:15 +0200 Message-Id: <20220805114116.8338-1-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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: , From: Tom de Vries via Gdb-patches Reply-To: Tom de Vries Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" Add: - support for a per-module .debug_names section in the dwarf assembler, and - a test-case excercising this new functionality. 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. I've kept things simple by having the test-case specify the hash value, rather than adding that functionality in the dwarf assembler. 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 the hash value modulo bucket_count". The readelf dump of the .debug_names section from the test-case looks like: ... Version 5 Augmentation string: 47 44 42 00 ("GDB") CU table: [ 0] 0x0 TU table: Foreign TU table: Used 1 of 1 bucket. Out of 2 items there are 1 bucket clashes (longest of 1 entries). Symbol table: [ 0] #eddb6232 _start: <1> DW_TAG_subprogram DW_IDX_compile_unit=0 [ 1] #0b888030 int: <2> DW_TAG_base_type DW_IDX_compile_unit=0 ... Tested on x86_64-linux. --- gdb/testsuite/gdb.dwarf2/_start.c | 27 +++ gdb/testsuite/gdb.dwarf2/debug-names.exp | 81 +++++++++ gdb/testsuite/lib/dwarf.exp | 214 ++++++++++++++++++++++- 3 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/_start.c create mode 100644 gdb/testsuite/gdb.dwarf2/debug-names.exp 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.dwarf2/debug-names.exp new file mode 100644 index 00000000000..30b48bd3fc3 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/debug-names.exp @@ -0,0 +1,81 @@ +# 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=-nostartfiles]] + +save_vars { Dwarf::_add_dummy_cus } { + + set Dwarf::_add_dummy_cus 0 + + # Create the DWARF. + set asm_file [standard_output_file $srcfile2] + Dwarf::assemble $asm_file { + 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} ${srcfile}" \ + [list additional_flags=-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 symtab" diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 356451bcaac..172180279a7 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -2925,6 +2925,208 @@ namespace eval Dwarf { } } + # 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 = 0 (32-bit) + # version n - section version. + # default = 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 _add_dummy_cus + if { $_add_dummy_cus } { + error "Don't add dummy CUs when generating .debug_names section" + } + + variable _debug_names_offset_size + if { $is_64 == 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] + set tag [lindex $idx 1] + set cu [lindex $idx 2] + + 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) + _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 == $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. @@ -2955,11 +3157,15 @@ namespace eval Dwarf { variable _line_header_end_label variable _debug_ranges_64_bit variable _debug_addr_index + variable _add_dummy_cus if {!$_initialized} { _read_constants set _initialized 1 } + if { ![info exists _add_dummy_cus] } { + set _add_dummy_cus 1 + } set _output_file [open $filename w] set _cu_count -1 @@ -2975,7 +3181,9 @@ namespace eval Dwarf { # 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 + } with_shared_gdb { # Not "uplevel" here, because we want to evaluate in this @@ -2986,7 +3194,9 @@ namespace eval Dwarf { # 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 + } _write_deferred_output base-commit: 37c59664adcb87bdf3279a5919940785057fe565 -- 2.35.3