aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/lib
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2022-08-07 08:31:36 +0200
committerTom de Vries <tdevries@suse.de>2022-08-07 08:31:36 +0200
commitf4cbdf0b6857069d42477e06f0077f4c03bb4c82 (patch)
tree8e25cccc31cd591bdf59119f9e2776dbe99d1f2b /gdb/testsuite/lib
parent3ba7b1551b810b9613e11889111406138f10f208 (diff)
downloadgdb-f4cbdf0b6857069d42477e06f0077f4c03bb4c82.zip
gdb-f4cbdf0b6857069d42477e06f0077f4c03bb4c82.tar.gz
gdb-f4cbdf0b6857069d42477e06f0077f4c03bb4c82.tar.bz2
[gdb/testsuite] Add support for .debug_names in dwarf assembler
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.
Diffstat (limited to 'gdb/testsuite/lib')
-rw-r--r--gdb/testsuite/lib/dwarf.exp229
1 files changed, 224 insertions, 5 deletions
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 356451b..3d833e5 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -2925,9 +2925,215 @@ 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 <cu-label>
+ # -- add a CU.
+ #
+ # name <name> <tag> <cu> <hash>
+ # -- add a name.
+
+ proc debug_names { options body } {
+ parse_options {
+ { is_64 0 }
+ { version 5 }
+ }
+
+ 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]
+
+ 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 == $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 <string>
+ # - the name of the file where the generated assembly
+ # code is written.
+ # default = "".
+ # add_dummy_cus <0|1>
+ # - Whether to add dummy CUs before and after the CUs
+ # added in the BODY.
+ # default = 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
+ if { [llength $options] == 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 {
# 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 +3203,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