* [PATCH] Update dwarf.exp assembler from gdb.
@ 2020-12-14 21:19 Mark Wielaard
2020-12-20 8:33 ` Tom de Vries
0 siblings, 1 reply; 2+ messages in thread
From: Mark Wielaard @ 2020-12-14 21:19 UTC (permalink / raw)
To: dwz; +Cc: Mark Wielaard
Includes various fixes and features. Specifically it won't emit a block
for a DWARF expression when the version is >= 4.
The DWARF Assembler is used by invalid-dw-at-stmt-list-encoding.exp
(pr24171.sh) and no-multifile-prop.exp (pr25109.sh)
Also fix up the generated varval.S (pr24823.sh) to use DW_FORM_exprloc.
---
testsuite/dwz.tests/varval.S | 26 ++--
testsuite/lib/dwarf.exp | 242 +++++++++++++++++++++++------------
2 files changed, 176 insertions(+), 92 deletions(-)
diff --git a/testsuite/dwz.tests/varval.S b/testsuite/dwz.tests/varval.S
index be62e8b..126768c 100644
--- a/testsuite/dwz.tests/varval.S
+++ b/testsuite/dwz.tests/varval.S
@@ -241,7 +241,7 @@
.uleb128 0x3f /* DW_AT_external */
.uleb128 0x0c /* DW_FORM_flag */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 6 /* Abbrev start */
@@ -263,7 +263,7 @@
.uleb128 0x3f /* DW_AT_external */
.uleb128 0x0c /* DW_FORM_flag */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 8 /* Abbrev start */
@@ -289,7 +289,7 @@
.uleb128 0x3f /* DW_AT_external */
.uleb128 0x0c /* DW_FORM_flag */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 10 /* Abbrev start */
@@ -397,7 +397,7 @@
.uleb128 0x3f /* DW_AT_external */
.uleb128 0x0c /* DW_FORM_flag */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 20 /* Abbrev start */
@@ -408,7 +408,7 @@
.uleb128 0x3f /* DW_AT_external */
.uleb128 0x0c /* DW_FORM_flag */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 21 /* Abbrev start */
@@ -434,7 +434,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 23 /* Abbrev start */
@@ -445,7 +445,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 24 /* Abbrev start */
@@ -454,7 +454,7 @@
.uleb128 0x31 /* DW_AT_abstract_origin */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 25 /* Abbrev start */
@@ -465,7 +465,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 26 /* Abbrev start */
@@ -476,7 +476,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 27 /* Abbrev start */
@@ -487,7 +487,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 28 /* Abbrev start */
@@ -498,7 +498,7 @@
.uleb128 0x49 /* DW_AT_type */
.uleb128 0x13 /* DW_FORM_ref4 */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.uleb128 29 /* Abbrev start */
@@ -507,7 +507,7 @@
.uleb128 0x03 /* DW_AT_name */
.uleb128 0x08 /* DW_FORM_string */
.uleb128 0x02 /* DW_AT_location */
- .uleb128 0x09 /* SPECIAL_expr */
+ .uleb128 0x18 /* DW_FORM_exprloc */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
diff --git a/testsuite/lib/dwarf.exp b/testsuite/lib/dwarf.exp
index d722982..8fc6da6 100644
--- a/testsuite/lib/dwarf.exp
+++ b/testsuite/lib/dwarf.exp
@@ -1,4 +1,4 @@
-# Copyright 2010-2019 Free Software Foundation, Inc.
+# Copyright 2010-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
@@ -117,12 +117,12 @@ proc build_executable_from_fission_assembler { testname executable sources optio
# static void func (void) {}
#
-proc function_range { func src } {
+proc function_range { func src {options {debug}} } {
global decimal gdb_prompt
set exe [standard_temp_file func_addr[pid].x]
- gdb_compile $src $exe executable {debug}
+ gdb_compile $src $exe executable $options
gdb_exit
gdb_start
@@ -167,6 +167,22 @@ proc function_range { func src } {
return [list "${func}_label - $func_label_offset" $func_length]
}
+# Extract the start, length, and end for function called NAME and
+# create suitable variables in the callers scope.
+proc get_func_info { name {options {debug}} } {
+ global srcdir subdir srcfile
+
+ upvar 1 "${name}_start" func_start
+ upvar 1 "${name}_len" func_len
+ upvar 1 "${name}_end" func_end
+
+ lassign [function_range ${name} \
+ [list ${srcdir}/${subdir}/$srcfile] \
+ ${options}] \
+ func_start func_len
+ set func_end "$func_start + $func_len"
+}
+
# A DWARF assembler.
#
# All the variables in this namespace are private to the
@@ -206,11 +222,11 @@ proc function_range { func src } {
# which will be substituted by one or more standard or macro attributes.
# supported macro attributes are:
#
-# - MACRO_AT_range { FUNC FILE }
+# - MACRO_AT_range { FUNC }
# It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and
-# end address of function FUNC in file FILE.
+# end address of function FUNC in file $srcdir/$subdir/$srcfile.
#
-# - MACRO_AT_func { FUNC FILE }
+# - MACRO_AT_func { FUNC }
# It is substituted by DW_AT_name with FUNC and MACRO_AT_range.
#
# If FORM is given, it should name a DW_FORM_ constant.
@@ -221,8 +237,9 @@ proc function_range { func src } {
# section automatically.
#
# If FORM is 'SPECIAL_expr', then VALUE is treated as a location
-# expression. The effective form is then DW_FORM_block, and VALUE
-# is passed to the (internal) '_location' proc to be translated.
+# expression. The effective form is then DW_FORM_block or DW_FORM_exprloc
+# for DWARF version >= 4, and VALUE is passed to the (internal)
+# '_location' proc to be translated.
# This proc implements a miniature DW_OP_ assembler.
#
# If FORM is not given, it is guessed:
@@ -234,11 +251,10 @@ proc function_range { func src } {
# and DW_FORM_ref4 is used. See 'new_label' and 'define_label'.
# * If VALUE starts with the "%" character, then it is a label
# reference too, but DW_FORM_ref_addr is used.
-# * Otherwise, VALUE is taken to be a string and DW_FORM_string is
-# used. In order to prevent bugs where a numeric value is given but
-# no form is specified, it is an error if the value looks like a number
-# (using Tcl's "string is integer") and no form is provided.
-# More form-guessing functionality may be added.
+# * Otherwise, if the attribute name has a default form (f.i. DW_FORM_addr for
+# DW_AT_low_pc), then that one is used.
+# * Otherwise, an error is reported. Either specify a form explicitly, or
+# add a default for the the attribute name in _default_form.
#
# CHILDREN is just Tcl code that can be used to define child DIEs. It
# is evaluated in the caller's context.
@@ -377,7 +393,6 @@ namespace eval Dwarf {
proc _read_constants {} {
global srcdir hex decimal
- variable _constants
# DWARF name-matching regexp.
set dwrx "DW_\[a-zA-Z0-9_\]+"
@@ -404,8 +419,6 @@ namespace eval Dwarf {
}
}
close $fd
-
- set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
}
proc _quote {string} {
@@ -577,9 +590,25 @@ namespace eval Dwarf {
}
default {
+ return ""
+ }
+ }
+ }
+
+ proc _default_form { attr } {
+ switch -exact -- $attr {
+ DW_AT_low_pc {
+ return DW_FORM_addr
+ }
+ DW_AT_producer -
+ DW_AT_comp_dir -
+ DW_AT_linkage_name -
+ DW_AT_MIPS_linkage_name -
+ DW_AT_name {
return DW_FORM_string
}
}
+ return ""
}
# Map NAME to its canonical form.
@@ -596,24 +625,35 @@ namespace eval Dwarf {
proc _handle_attribute { attr_name attr_value attr_form } {
variable _abbrev_section
variable _constants
+ variable _cu_version
_handle_DW_FORM $attr_form $attr_value
_defer_output $_abbrev_section {
+ if { $attr_form eq "SPECIAL_expr" } {
+ if { $_cu_version < 4 } {
+ set attr_form_comment "DW_FORM_block"
+ } else {
+ set attr_form_comment "DW_FORM_exprloc"
+ }
+ } else {
+ set attr_form_comment $attr_form
+ }
_op .uleb128 $_constants($attr_name) $attr_name
- _op .uleb128 $_constants($attr_form) $attr_form
+ _op .uleb128 $_constants($attr_form) $attr_form_comment
}
}
# Handle macro attribute MACRO_AT_range.
proc _handle_macro_at_range { attr_value } {
- if {[llength $attr_value] != 2} {
- error "usage: MACRO_AT_range { func file }"
+ if {[llength $attr_value] != 1} {
+ error "usage: MACRO_AT_range { func }"
}
set func [lindex $attr_value 0]
- set src [lindex $attr_value 1]
+ global srcdir subdir srcfile
+ set src ${srcdir}/${subdir}/${srcfile}
set result [function_range $func $src]
_handle_attribute DW_AT_low_pc [lindex $result 0] \
@@ -625,7 +665,7 @@ namespace eval Dwarf {
# Handle macro attribute MACRO_AT_func.
proc _handle_macro_at_func { attr_value } {
- if {[llength $attr_value] != 2} {
+ if {[llength $attr_value] != 1} {
error "usage: MACRO_AT_func { func file }"
}
_handle_attribute DW_AT_name [lindex $attr_value 0] DW_FORM_string
@@ -678,11 +718,13 @@ namespace eval Dwarf {
_guess_form $attr_value attr_value
}
} else {
- # If the value looks like an integer, a form is required.
- if [string is integer $attr_value] {
- error "Integer value requires a form"
- }
set attr_form [_guess_form $attr_value attr_value]
+ if { $attr_form eq "" } {
+ set attr_form [_default_form $attr_name]
+ }
+ if { $attr_form eq "" } {
+ error "No form for $attr_name $attr_value"
+ }
}
set attr_form [_map_name $attr_form _FORM]
@@ -692,8 +734,8 @@ namespace eval Dwarf {
_defer_output $_abbrev_section {
# Terminator.
- _op .byte 0x0 Terminator
- _op .byte 0x0 Terminator
+ _op .byte 0x0 "DW_AT - Terminator"
+ _op .byte 0x0 "DW_FORM - Terminator"
}
if {$has_children} {
@@ -809,15 +851,6 @@ namespace eval Dwarf {
_emit "${name}:"
}
- # Declare a global label. This is typically used to refer to
- # labels defined in other files, for example a function defined in
- # a .c file.
- proc extern {args} {
- foreach name $args {
- _op .global $name
- }
- }
-
# A higher-level interface to label handling.
#
# ARGS is a list of label descriptors. Each one is either a
@@ -841,13 +874,13 @@ namespace eval Dwarf {
set name [lindex $arg 0]
set text [lindex $arg 1]
- upvar $name label_var
- if {$text == ""} {
- set label_var [new_label]
- } else {
- set label_var [new_label $text]
+ if { $text == "" } {
+ set text $name
}
+ upvar $name label_var
+ set label_var [new_label $text]
+
proc ${name}: {args} [format {
define_label %s
uplevel $args
@@ -1013,13 +1046,14 @@ namespace eval Dwarf {
# default = 0 (32-bit)
# version n - DWARF version number to emit
# default = 4
- # addr_size n - the size of addresses, 32, 64, or default
+ # addr_size n - the size of addresses in bytes: 4, 8, or default
# default = default
# fission 0|1 - boolean indicating if generating Fission debug info
# default = 0
# BODY is Tcl code that emits the DIEs which make up the body of
# the CU. It is evaluated in the caller's context.
proc cu {options body} {
+ variable _constants
variable _cu_count
variable _abbrev_section
variable _abbrev_num
@@ -1059,6 +1093,12 @@ namespace eval Dwarf {
set _abbrev_section ".debug_abbrev.dwo"
}
+ if {$_cu_version < 4} {
+ set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
+ } else {
+ set _constants(SPECIAL_expr) $_constants(DW_FORM_exprloc)
+ }
+
_section $section
set cu_num [incr _cu_count]
@@ -1089,8 +1129,7 @@ namespace eval Dwarf {
_defer_output $_abbrev_section {
# Emit the terminator.
- _op .byte 0x0 Terminator
- _op .byte 0x0 Terminator
+ _op .byte 0x0 "Abbrev end - Terminator"
}
define_label $end_label
@@ -1104,7 +1143,7 @@ namespace eval Dwarf {
# default = 0 (32-bit)
# version n - DWARF version number to emit
# default = 4
- # addr_size n - the size of addresses, 32, 64, or default
+ # addr_size n - the size of addresses in bytes: 4, 8, or default
# default = default
# fission 0|1 - boolean indicating if generating Fission debug info
# default = 0
@@ -1198,8 +1237,7 @@ namespace eval Dwarf {
_defer_output $_abbrev_section {
# Emit the terminator.
- _op .byte 0x0 Terminator
- _op .byte 0x0 Terminator
+ _op .byte 0x0 "Abbrev end - Terminator"
}
define_label $end_label
@@ -1227,42 +1265,37 @@ namespace eval Dwarf {
set section ".debug_ranges"
_section $section
- proc sequence {{ranges {}}} {
+ proc sequence { body } {
variable _debug_ranges_64_bit
# Emit the sequence of addresses.
- set base ""
- foreach range $ranges {
- set range [uplevel 1 "subst \"$range\""]
- set type [lindex $range 0]
- switch -exact -- $type {
- base {
- set base [lrange $range 1 end]
-
- if { $_debug_ranges_64_bit } then {
- _op .8byte 0xffffffffffffffff "Base Marker"
- _op .8byte $base "Base Address"
- } else {
- _op .4byte 0xffffffff "Base Marker"
- _op .4byte $base "Base Address"
- }
- }
- range {
- set start [lindex $range 1]
- set end [lrange $range 2 end]
-
- if { $_debug_ranges_64_bit } then {
- _op .8byte $start "Start Address"
- _op .8byte $end "End Address"
- } else {
- _op .4byte $start "Start Address"
- _op .4byte $end "End Address"
- }
- }
- default { error "unknown range type: $type " }
+
+ proc base { addr } {
+ variable _debug_ranges_64_bit
+
+ if { $_debug_ranges_64_bit } then {
+ _op .8byte 0xffffffffffffffff "Base Marker"
+ _op .8byte $addr "Base Address"
+ } else {
+ _op .4byte 0xffffffff "Base Marker"
+ _op .4byte $addr "Base Address"
}
}
+ proc range { start end } {
+ variable _debug_ranges_64_bit
+
+ if { $_debug_ranges_64_bit } then {
+ _op .8byte $start "Start Address"
+ _op .8byte $end "End Address"
+ } else {
+ _op .4byte $start "Start Address"
+ _op .4byte $end "End Address"
+ }
+ }
+
+ uplevel $body
+
# End of the sequence.
if { $_debug_ranges_64_bit } then {
_op .8byte 0x0 "End of Sequence Marker (Part 1)"
@@ -1285,7 +1318,7 @@ namespace eval Dwarf {
# default = 0 (32-bit)
# version n - DWARF version number to emit
# default = 4
- # addr_size n - the size of addresses, 32, 64, or default
+ # addr_size n - the size of addresses in bytes: 4, 8, or default
# default = default
#
# LABEL is the label of the current unit (which is probably
@@ -1312,12 +1345,16 @@ namespace eval Dwarf {
set is_64 0
set _unit_version 4
set _unit_addr_size default
+ set _line_saw_program 0
+ set _line_saw_file 0
+ set _default_is_stmt 1
foreach { name value } $options {
switch -exact -- $name {
is_64 { set is_64 $value }
version { set _unit_version $value }
addr_size { set _unit_addr_size $value }
+ default_is_stmt { set _default_is_stmt $value }
default { error "unknown option $name" }
}
}
@@ -1364,7 +1401,7 @@ namespace eval Dwarf {
define_label $header_len_label
_op .byte 1 "minimum_instruction_length"
- _op .byte 1 "default_is_stmt"
+ _op .byte $_default_is_stmt "default_is_stmt"
_op .byte 1 "line_base"
_op .byte 1 "line_range"
_op .byte 10 "opcode_base"
@@ -1406,6 +1443,9 @@ namespace eval Dwarf {
proc program {statements} {
variable _line_saw_program
variable _line_header_end_label
+ variable _line
+
+ set _line 1
if "! $_line_saw_program" {
# Terminate the file list.
@@ -1430,23 +1470,67 @@ namespace eval Dwarf {
}
proc DW_LNE_end_sequence {} {
+ variable _line
_op .byte 0
_op .uleb128 1
_op .byte 1
+ set _line 1
+ }
+
+ proc DW_LNE_user { len opcode } {
+ set DW_LNE_lo_usr 0x80
+ set DW_LNE_hi_usr 0xff
+ if { $DW_LNE_lo_usr <= $opcode
+ && $opcode <= $DW_LNE_hi_usr } {
+ _op .byte 0
+ _op .uleb128 $len
+ _op .byte $opcode
+ for {set i 1} {$i < $len} {incr i} {
+ _op .byte 0
+ }
+ } else {
+ error "unknown vendor specific extended opcode: $opcode"
+ }
}
proc DW_LNS_copy {} {
_op .byte 1
}
+ proc DW_LNS_negate_stmt {} {
+ _op .byte 6
+ }
+
proc DW_LNS_advance_pc {offset} {
_op .byte 2
_op .uleb128 ${offset}
}
proc DW_LNS_advance_line {offset} {
+ variable _line
_op .byte 3
_op .sleb128 ${offset}
+ set _line [expr $_line + $offset]
+ }
+
+ # A pseudo line number program instruction, that can be used instead
+ # of DW_LNS_advance_line. Rather than writing:
+ # {DW_LNS_advance_line [expr $line1 - 1]}
+ # {DW_LNS_advance_line [expr $line2 - $line1]}
+ # {DW_LNS_advance_line [expr $line3 - $line2]}
+ # we can just write:
+ # {line $line1}
+ # {line $line2}
+ # {line $line3}
+ proc line {line} {
+ variable _line
+ set offset [expr $line - $_line]
+ DW_LNS_advance_line $offset
+ }
+
+ proc DW_LNS_set_file {num} {
+ _op .byte 4
+ _op .sleb128 ${num}
}
foreach statement $statements {
--
2.18.4
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] Update dwarf.exp assembler from gdb.
2020-12-14 21:19 [PATCH] Update dwarf.exp assembler from gdb Mark Wielaard
@ 2020-12-20 8:33 ` Tom de Vries
0 siblings, 0 replies; 2+ messages in thread
From: Tom de Vries @ 2020-12-20 8:33 UTC (permalink / raw)
To: Mark Wielaard, dwz
On 12/14/20 10:19 PM, Mark Wielaard wrote:
> Includes various fixes and features. Specifically it won't emit a block
> for a DWARF expression when the version is >= 4.
> The DWARF Assembler is used by invalid-dw-at-stmt-list-encoding.exp
> (pr24171.sh) and no-multifile-prop.exp (pr25109.sh)
>
Thanks for the update.
> Also fix up the generated varval.S (pr24823.sh) to use DW_FORM_exprloc.
Yeah, that's from the time we didn't have the DWARF assembler in dwz
sources yet, I think eventually we want that test-case rewritting to use
dwarf assembly. Anyway, this is fine for now.
LGTM, please commit.
Thanks,
- Tom
> ---
> testsuite/dwz.tests/varval.S | 26 ++--
> testsuite/lib/dwarf.exp | 242 +++++++++++++++++++++++------------
> 2 files changed, 176 insertions(+), 92 deletions(-)
>
> diff --git a/testsuite/dwz.tests/varval.S b/testsuite/dwz.tests/varval.S
> index be62e8b..126768c 100644
> --- a/testsuite/dwz.tests/varval.S
> +++ b/testsuite/dwz.tests/varval.S
> @@ -241,7 +241,7 @@
> .uleb128 0x3f /* DW_AT_external */
> .uleb128 0x0c /* DW_FORM_flag */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 6 /* Abbrev start */
> @@ -263,7 +263,7 @@
> .uleb128 0x3f /* DW_AT_external */
> .uleb128 0x0c /* DW_FORM_flag */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 8 /* Abbrev start */
> @@ -289,7 +289,7 @@
> .uleb128 0x3f /* DW_AT_external */
> .uleb128 0x0c /* DW_FORM_flag */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 10 /* Abbrev start */
> @@ -397,7 +397,7 @@
> .uleb128 0x3f /* DW_AT_external */
> .uleb128 0x0c /* DW_FORM_flag */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 20 /* Abbrev start */
> @@ -408,7 +408,7 @@
> .uleb128 0x3f /* DW_AT_external */
> .uleb128 0x0c /* DW_FORM_flag */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 21 /* Abbrev start */
> @@ -434,7 +434,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 23 /* Abbrev start */
> @@ -445,7 +445,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 24 /* Abbrev start */
> @@ -454,7 +454,7 @@
> .uleb128 0x31 /* DW_AT_abstract_origin */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 25 /* Abbrev start */
> @@ -465,7 +465,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 26 /* Abbrev start */
> @@ -476,7 +476,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 27 /* Abbrev start */
> @@ -487,7 +487,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 28 /* Abbrev start */
> @@ -498,7 +498,7 @@
> .uleb128 0x49 /* DW_AT_type */
> .uleb128 0x13 /* DW_FORM_ref4 */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .uleb128 29 /* Abbrev start */
> @@ -507,7 +507,7 @@
> .uleb128 0x03 /* DW_AT_name */
> .uleb128 0x08 /* DW_FORM_string */
> .uleb128 0x02 /* DW_AT_location */
> - .uleb128 0x09 /* SPECIAL_expr */
> + .uleb128 0x18 /* DW_FORM_exprloc */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> .byte 0x0 /* Terminator */
> diff --git a/testsuite/lib/dwarf.exp b/testsuite/lib/dwarf.exp
> index d722982..8fc6da6 100644
> --- a/testsuite/lib/dwarf.exp
> +++ b/testsuite/lib/dwarf.exp
> @@ -1,4 +1,4 @@
> -# Copyright 2010-2019 Free Software Foundation, Inc.
> +# Copyright 2010-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
> @@ -117,12 +117,12 @@ proc build_executable_from_fission_assembler { testname executable sources optio
> # static void func (void) {}
> #
>
> -proc function_range { func src } {
> +proc function_range { func src {options {debug}} } {
> global decimal gdb_prompt
>
> set exe [standard_temp_file func_addr[pid].x]
>
> - gdb_compile $src $exe executable {debug}
> + gdb_compile $src $exe executable $options
>
> gdb_exit
> gdb_start
> @@ -167,6 +167,22 @@ proc function_range { func src } {
> return [list "${func}_label - $func_label_offset" $func_length]
> }
>
> +# Extract the start, length, and end for function called NAME and
> +# create suitable variables in the callers scope.
> +proc get_func_info { name {options {debug}} } {
> + global srcdir subdir srcfile
> +
> + upvar 1 "${name}_start" func_start
> + upvar 1 "${name}_len" func_len
> + upvar 1 "${name}_end" func_end
> +
> + lassign [function_range ${name} \
> + [list ${srcdir}/${subdir}/$srcfile] \
> + ${options}] \
> + func_start func_len
> + set func_end "$func_start + $func_len"
> +}
> +
> # A DWARF assembler.
> #
> # All the variables in this namespace are private to the
> @@ -206,11 +222,11 @@ proc function_range { func src } {
> # which will be substituted by one or more standard or macro attributes.
> # supported macro attributes are:
> #
> -# - MACRO_AT_range { FUNC FILE }
> +# - MACRO_AT_range { FUNC }
> # It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and
> -# end address of function FUNC in file FILE.
> +# end address of function FUNC in file $srcdir/$subdir/$srcfile.
> #
> -# - MACRO_AT_func { FUNC FILE }
> +# - MACRO_AT_func { FUNC }
> # It is substituted by DW_AT_name with FUNC and MACRO_AT_range.
> #
> # If FORM is given, it should name a DW_FORM_ constant.
> @@ -221,8 +237,9 @@ proc function_range { func src } {
> # section automatically.
> #
> # If FORM is 'SPECIAL_expr', then VALUE is treated as a location
> -# expression. The effective form is then DW_FORM_block, and VALUE
> -# is passed to the (internal) '_location' proc to be translated.
> +# expression. The effective form is then DW_FORM_block or DW_FORM_exprloc
> +# for DWARF version >= 4, and VALUE is passed to the (internal)
> +# '_location' proc to be translated.
> # This proc implements a miniature DW_OP_ assembler.
> #
> # If FORM is not given, it is guessed:
> @@ -234,11 +251,10 @@ proc function_range { func src } {
> # and DW_FORM_ref4 is used. See 'new_label' and 'define_label'.
> # * If VALUE starts with the "%" character, then it is a label
> # reference too, but DW_FORM_ref_addr is used.
> -# * Otherwise, VALUE is taken to be a string and DW_FORM_string is
> -# used. In order to prevent bugs where a numeric value is given but
> -# no form is specified, it is an error if the value looks like a number
> -# (using Tcl's "string is integer") and no form is provided.
> -# More form-guessing functionality may be added.
> +# * Otherwise, if the attribute name has a default form (f.i. DW_FORM_addr for
> +# DW_AT_low_pc), then that one is used.
> +# * Otherwise, an error is reported. Either specify a form explicitly, or
> +# add a default for the the attribute name in _default_form.
> #
> # CHILDREN is just Tcl code that can be used to define child DIEs. It
> # is evaluated in the caller's context.
> @@ -377,7 +393,6 @@ namespace eval Dwarf {
>
> proc _read_constants {} {
> global srcdir hex decimal
> - variable _constants
>
> # DWARF name-matching regexp.
> set dwrx "DW_\[a-zA-Z0-9_\]+"
> @@ -404,8 +419,6 @@ namespace eval Dwarf {
> }
> }
> close $fd
> -
> - set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
> }
>
> proc _quote {string} {
> @@ -577,9 +590,25 @@ namespace eval Dwarf {
> }
>
> default {
> + return ""
> + }
> + }
> + }
> +
> + proc _default_form { attr } {
> + switch -exact -- $attr {
> + DW_AT_low_pc {
> + return DW_FORM_addr
> + }
> + DW_AT_producer -
> + DW_AT_comp_dir -
> + DW_AT_linkage_name -
> + DW_AT_MIPS_linkage_name -
> + DW_AT_name {
> return DW_FORM_string
> }
> }
> + return ""
> }
>
> # Map NAME to its canonical form.
> @@ -596,24 +625,35 @@ namespace eval Dwarf {
> proc _handle_attribute { attr_name attr_value attr_form } {
> variable _abbrev_section
> variable _constants
> + variable _cu_version
>
> _handle_DW_FORM $attr_form $attr_value
>
> _defer_output $_abbrev_section {
> + if { $attr_form eq "SPECIAL_expr" } {
> + if { $_cu_version < 4 } {
> + set attr_form_comment "DW_FORM_block"
> + } else {
> + set attr_form_comment "DW_FORM_exprloc"
> + }
> + } else {
> + set attr_form_comment $attr_form
> + }
> _op .uleb128 $_constants($attr_name) $attr_name
> - _op .uleb128 $_constants($attr_form) $attr_form
> + _op .uleb128 $_constants($attr_form) $attr_form_comment
> }
> }
>
> # Handle macro attribute MACRO_AT_range.
>
> proc _handle_macro_at_range { attr_value } {
> - if {[llength $attr_value] != 2} {
> - error "usage: MACRO_AT_range { func file }"
> + if {[llength $attr_value] != 1} {
> + error "usage: MACRO_AT_range { func }"
> }
>
> set func [lindex $attr_value 0]
> - set src [lindex $attr_value 1]
> + global srcdir subdir srcfile
> + set src ${srcdir}/${subdir}/${srcfile}
> set result [function_range $func $src]
>
> _handle_attribute DW_AT_low_pc [lindex $result 0] \
> @@ -625,7 +665,7 @@ namespace eval Dwarf {
> # Handle macro attribute MACRO_AT_func.
>
> proc _handle_macro_at_func { attr_value } {
> - if {[llength $attr_value] != 2} {
> + if {[llength $attr_value] != 1} {
> error "usage: MACRO_AT_func { func file }"
> }
> _handle_attribute DW_AT_name [lindex $attr_value 0] DW_FORM_string
> @@ -678,11 +718,13 @@ namespace eval Dwarf {
> _guess_form $attr_value attr_value
> }
> } else {
> - # If the value looks like an integer, a form is required.
> - if [string is integer $attr_value] {
> - error "Integer value requires a form"
> - }
> set attr_form [_guess_form $attr_value attr_value]
> + if { $attr_form eq "" } {
> + set attr_form [_default_form $attr_name]
> + }
> + if { $attr_form eq "" } {
> + error "No form for $attr_name $attr_value"
> + }
> }
> set attr_form [_map_name $attr_form _FORM]
>
> @@ -692,8 +734,8 @@ namespace eval Dwarf {
>
> _defer_output $_abbrev_section {
> # Terminator.
> - _op .byte 0x0 Terminator
> - _op .byte 0x0 Terminator
> + _op .byte 0x0 "DW_AT - Terminator"
> + _op .byte 0x0 "DW_FORM - Terminator"
> }
>
> if {$has_children} {
> @@ -809,15 +851,6 @@ namespace eval Dwarf {
> _emit "${name}:"
> }
>
> - # Declare a global label. This is typically used to refer to
> - # labels defined in other files, for example a function defined in
> - # a .c file.
> - proc extern {args} {
> - foreach name $args {
> - _op .global $name
> - }
> - }
> -
> # A higher-level interface to label handling.
> #
> # ARGS is a list of label descriptors. Each one is either a
> @@ -841,13 +874,13 @@ namespace eval Dwarf {
> set name [lindex $arg 0]
> set text [lindex $arg 1]
>
> - upvar $name label_var
> - if {$text == ""} {
> - set label_var [new_label]
> - } else {
> - set label_var [new_label $text]
> + if { $text == "" } {
> + set text $name
> }
>
> + upvar $name label_var
> + set label_var [new_label $text]
> +
> proc ${name}: {args} [format {
> define_label %s
> uplevel $args
> @@ -1013,13 +1046,14 @@ namespace eval Dwarf {
> # default = 0 (32-bit)
> # version n - DWARF version number to emit
> # default = 4
> - # addr_size n - the size of addresses, 32, 64, or default
> + # addr_size n - the size of addresses in bytes: 4, 8, or default
> # default = default
> # fission 0|1 - boolean indicating if generating Fission debug info
> # default = 0
> # BODY is Tcl code that emits the DIEs which make up the body of
> # the CU. It is evaluated in the caller's context.
> proc cu {options body} {
> + variable _constants
> variable _cu_count
> variable _abbrev_section
> variable _abbrev_num
> @@ -1059,6 +1093,12 @@ namespace eval Dwarf {
> set _abbrev_section ".debug_abbrev.dwo"
> }
>
> + if {$_cu_version < 4} {
> + set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
> + } else {
> + set _constants(SPECIAL_expr) $_constants(DW_FORM_exprloc)
> + }
> +
> _section $section
>
> set cu_num [incr _cu_count]
> @@ -1089,8 +1129,7 @@ namespace eval Dwarf {
>
> _defer_output $_abbrev_section {
> # Emit the terminator.
> - _op .byte 0x0 Terminator
> - _op .byte 0x0 Terminator
> + _op .byte 0x0 "Abbrev end - Terminator"
> }
>
> define_label $end_label
> @@ -1104,7 +1143,7 @@ namespace eval Dwarf {
> # default = 0 (32-bit)
> # version n - DWARF version number to emit
> # default = 4
> - # addr_size n - the size of addresses, 32, 64, or default
> + # addr_size n - the size of addresses in bytes: 4, 8, or default
> # default = default
> # fission 0|1 - boolean indicating if generating Fission debug info
> # default = 0
> @@ -1198,8 +1237,7 @@ namespace eval Dwarf {
>
> _defer_output $_abbrev_section {
> # Emit the terminator.
> - _op .byte 0x0 Terminator
> - _op .byte 0x0 Terminator
> + _op .byte 0x0 "Abbrev end - Terminator"
> }
>
> define_label $end_label
> @@ -1227,42 +1265,37 @@ namespace eval Dwarf {
> set section ".debug_ranges"
> _section $section
>
> - proc sequence {{ranges {}}} {
> + proc sequence { body } {
> variable _debug_ranges_64_bit
>
> # Emit the sequence of addresses.
> - set base ""
> - foreach range $ranges {
> - set range [uplevel 1 "subst \"$range\""]
> - set type [lindex $range 0]
> - switch -exact -- $type {
> - base {
> - set base [lrange $range 1 end]
> -
> - if { $_debug_ranges_64_bit } then {
> - _op .8byte 0xffffffffffffffff "Base Marker"
> - _op .8byte $base "Base Address"
> - } else {
> - _op .4byte 0xffffffff "Base Marker"
> - _op .4byte $base "Base Address"
> - }
> - }
> - range {
> - set start [lindex $range 1]
> - set end [lrange $range 2 end]
> -
> - if { $_debug_ranges_64_bit } then {
> - _op .8byte $start "Start Address"
> - _op .8byte $end "End Address"
> - } else {
> - _op .4byte $start "Start Address"
> - _op .4byte $end "End Address"
> - }
> - }
> - default { error "unknown range type: $type " }
> +
> + proc base { addr } {
> + variable _debug_ranges_64_bit
> +
> + if { $_debug_ranges_64_bit } then {
> + _op .8byte 0xffffffffffffffff "Base Marker"
> + _op .8byte $addr "Base Address"
> + } else {
> + _op .4byte 0xffffffff "Base Marker"
> + _op .4byte $addr "Base Address"
> }
> }
>
> + proc range { start end } {
> + variable _debug_ranges_64_bit
> +
> + if { $_debug_ranges_64_bit } then {
> + _op .8byte $start "Start Address"
> + _op .8byte $end "End Address"
> + } else {
> + _op .4byte $start "Start Address"
> + _op .4byte $end "End Address"
> + }
> + }
> +
> + uplevel $body
> +
> # End of the sequence.
> if { $_debug_ranges_64_bit } then {
> _op .8byte 0x0 "End of Sequence Marker (Part 1)"
> @@ -1285,7 +1318,7 @@ namespace eval Dwarf {
> # default = 0 (32-bit)
> # version n - DWARF version number to emit
> # default = 4
> - # addr_size n - the size of addresses, 32, 64, or default
> + # addr_size n - the size of addresses in bytes: 4, 8, or default
> # default = default
> #
> # LABEL is the label of the current unit (which is probably
> @@ -1312,12 +1345,16 @@ namespace eval Dwarf {
> set is_64 0
> set _unit_version 4
> set _unit_addr_size default
> + set _line_saw_program 0
> + set _line_saw_file 0
> + set _default_is_stmt 1
>
> foreach { name value } $options {
> switch -exact -- $name {
> is_64 { set is_64 $value }
> version { set _unit_version $value }
> addr_size { set _unit_addr_size $value }
> + default_is_stmt { set _default_is_stmt $value }
> default { error "unknown option $name" }
> }
> }
> @@ -1364,7 +1401,7 @@ namespace eval Dwarf {
> define_label $header_len_label
>
> _op .byte 1 "minimum_instruction_length"
> - _op .byte 1 "default_is_stmt"
> + _op .byte $_default_is_stmt "default_is_stmt"
> _op .byte 1 "line_base"
> _op .byte 1 "line_range"
> _op .byte 10 "opcode_base"
> @@ -1406,6 +1443,9 @@ namespace eval Dwarf {
> proc program {statements} {
> variable _line_saw_program
> variable _line_header_end_label
> + variable _line
> +
> + set _line 1
>
> if "! $_line_saw_program" {
> # Terminate the file list.
> @@ -1430,23 +1470,67 @@ namespace eval Dwarf {
> }
>
> proc DW_LNE_end_sequence {} {
> + variable _line
> _op .byte 0
> _op .uleb128 1
> _op .byte 1
> + set _line 1
> + }
> +
> + proc DW_LNE_user { len opcode } {
> + set DW_LNE_lo_usr 0x80
> + set DW_LNE_hi_usr 0xff
> + if { $DW_LNE_lo_usr <= $opcode
> + && $opcode <= $DW_LNE_hi_usr } {
> + _op .byte 0
> + _op .uleb128 $len
> + _op .byte $opcode
> + for {set i 1} {$i < $len} {incr i} {
> + _op .byte 0
> + }
> + } else {
> + error "unknown vendor specific extended opcode: $opcode"
> + }
> }
>
> proc DW_LNS_copy {} {
> _op .byte 1
> }
>
> + proc DW_LNS_negate_stmt {} {
> + _op .byte 6
> + }
> +
> proc DW_LNS_advance_pc {offset} {
> _op .byte 2
> _op .uleb128 ${offset}
> }
>
> proc DW_LNS_advance_line {offset} {
> + variable _line
> _op .byte 3
> _op .sleb128 ${offset}
> + set _line [expr $_line + $offset]
> + }
> +
> + # A pseudo line number program instruction, that can be used instead
> + # of DW_LNS_advance_line. Rather than writing:
> + # {DW_LNS_advance_line [expr $line1 - 1]}
> + # {DW_LNS_advance_line [expr $line2 - $line1]}
> + # {DW_LNS_advance_line [expr $line3 - $line2]}
> + # we can just write:
> + # {line $line1}
> + # {line $line2}
> + # {line $line3}
> + proc line {line} {
> + variable _line
> + set offset [expr $line - $_line]
> + DW_LNS_advance_line $offset
> + }
> +
> + proc DW_LNS_set_file {num} {
> + _op .byte 4
> + _op .sleb128 ${num}
> }
>
> foreach statement $statements {
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-12-20 8:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-14 21:19 [PATCH] Update dwarf.exp assembler from gdb Mark Wielaard
2020-12-20 8:33 ` Tom de Vries
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).