[v2,1/4] gdb/testsuite: add support for DWARF 5 .debug_addr sections to DWARF assembler
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
The DWARF assembler knows how to emit .debug_addr as they were in the
DWARF 4 GNU extensions days. This patch adds proper DWARF 5 .debug_addr
support.
The only difference is that the GNU extensions .debug_addr does not have
a header. It is just an array of addresses (concatenated from all the
contributions). The DW_AT_GNU_addr_base attributes of the various units
point at different places in it. The DWARF 5 version of the section has
a header, similar to other sections.
The changes are:
- Add a version parameter to the debug_addr_label proc.
- Make the debug_addr_label proc emit a header if it's version 5 or
higher. Otherwise, it's understood to be a GNU extensions
.debug_addr section and does not emit a header. A call to the
debug_addr_label proc now marks the beginning of a .debug_addr
contribution.
- Make the debug_addr_label proc end the previous .debug_addr
contribution, if there is one. To end a contribution, we emit a
label that is referred to in the unit_length computation. Track this
label name through a new _debug_addr_end_label namespace variable.
- When using a form or operator that appends to .debug_addr, verify
that a .debug_addr contribution is open. This is just to help catch
programmer mistakes where one would forget to call the
debug_addr_label proc before using DW_FORM_addrx, for example.
However, if building multiple CUs that use .debug_addr, it does not
protect against forgetting to call the debug_addr_label proc to begin
the contribution of the second CU.
- Add support for DW_FORM_addrx and DW_AT_addr_base, synonymous for
their GNU extensions counterpart.
Change-Id: I2226cc57d91317de111a2468269122ff87be5c70
---
gdb/testsuite/lib/dwarf.exp | 118 ++++++++++++++++++++++++++++++++----
1 file changed, 106 insertions(+), 12 deletions(-)
@@ -580,10 +580,14 @@ namespace eval Dwarf {
# The address size for debug ranges section.
variable _debug_ranges_64_bit
- # The index into the .debug_addr section (used for fission
- # generation).
+ # The index of the next entry in the currently open .debug_addr
+ # contribution, or the empty string if no contribution is open.
variable _debug_addr_index
+ # The label marking the end of the currently open .debug_addr
+ # contribution, or the empty string if no contribution is open.
+ variable _debug_addr_end_label
+
# Flag, true if the current CU is contains fission information,
# otherwise false.
variable _cu_is_fission
@@ -808,10 +812,13 @@ namespace eval Dwarf {
_op .${_cu_addr_size}byte $value
}
+ DW_FORM_addrx -
DW_FORM_GNU_addr_index {
variable _debug_addr_index
variable _cu_addr_size
+ _debug_addr_check_open
+
_op .uleb128 ${_debug_addr_index}
incr _debug_addr_index
@@ -948,6 +955,7 @@ namespace eval Dwarf {
DW_AT_name {
return DW_FORM_string
}
+ DW_AT_addr_base -
DW_AT_GNU_addr_base {
return DW_FORM_sec_offset
}
@@ -1323,6 +1331,8 @@ namespace eval Dwarf {
variable _debug_addr_index
variable _cu_addr_size
+ _debug_addr_check_open
+
_op .uleb128 ${_debug_addr_index}
incr _debug_addr_index
@@ -1658,20 +1668,99 @@ namespace eval Dwarf {
uplevel $_level $body
}
- # Return a label that references the current position in the
- # .debug_addr table. When a user is creating split DWARF they
- # will define two CUs, the first will be the split DWARF content,
- # and the second will be the non-split stub CU. The split DWARF
- # CU fills in the .debug_addr section, but the non-split CU
- # includes a reference to the start of the section. The label
- # returned by this proc provides that reference.
- proc debug_addr_label {} {
+ # Verify that a .debug_addr contribution is open, that is that the
+ # debug_addr_label proc was called.
+ proc _debug_addr_check_open {} {
variable _debug_addr_index
- set lbl [new_label "debug_addr_idx_${_debug_addr_index}_"]
+ if { $_debug_addr_index == "" } {
+ error "no .debug_addr contribution is open, call the addr proc first"
+ }
+ }
+
+ # Terminate the currently open .debug_addr contribution, if any, by
+ # defining its end label.
+ proc _debug_addr_end_contribution {} {
+ variable _debug_addr_end_label
+
+ if { $_debug_addr_end_label == "" } {
+ return
+ }
+
+ _defer_output .debug_addr {
+ define_label $_debug_addr_end_label
+ }
+
+ set _debug_addr_end_label ""
+ }
+
+ # Start this unit's contribution to the .debug_addr section and return a
+ # label referencing its first entry.
+ #
+ # When a user is creating split DWARF they will define two CUs, the first will
+ # be the split DWARF content, and the second will be the non-split stub
+ # CU. The split DWARF CU fills in the .debug_addr section with addresses,
+ # but the non-split CU includes a reference to the start of the address
+ # array section (through DW_AT_addr_base for DWARF 5, DW_AT_GNU_addr_base
+ # for DWARF 4 GNU extensions).
+ #
+ # This proc must be called from within a cu or tu body, before any
+ # use of DW_FORM_addrx, or any operator that appends an address to
+ # .debug_addr.
+ #
+ # The `version` option gives the version of the .debug_addr section to
+ # emit. If the version is >= 5, start the contribution with a header.
+ # The offset and address sizes are obtained from the current unit.
+ #
+ # If the version is < 5, then the contribution is understood to be in the
+ # format of DWARF 4 GNU extension, which does not use a header (in which
+ # case the version isn't written anywhere).
+ #
+ # Calling this proc again terminates the previous contribution, starts a
+ # new one, and restarts entry indices at zero.
+ proc debug_addr_label { {options {}} } {
+ variable _debug_addr_index
+ variable _debug_addr_end_label
+ variable _cu_addr_size
+ variable _cu_offset_size
+
+ parse_options {
+ {version 4}
+ }
+
+ _debug_addr_end_contribution
+
+ if { $version >= 5 } {
+ set _debug_addr_end_label [new_label "debug_addr_end_"]
+ set post_unit_len_label [new_label "debug_addr_post_unit_len_"]
+
+ _defer_output .debug_addr {
+ if { $_cu_offset_size == 8 } {
+ _op .4byte 0xffffffff "unit length 1/2"
+ _op .8byte \
+ "$_debug_addr_end_label - $post_unit_len_label" \
+ "unit length 2/2"
+ } else {
+ _op .4byte \
+ "$_debug_addr_end_label - $post_unit_len_label" \
+ "unit length"
+ }
+
+ define_label $post_unit_len_label
+
+ _op .2byte $version "version"
+ _op .byte $_cu_addr_size "address size"
+ _op .byte 0 "segment selector size"
+ }
+ }
+
+ set lbl [new_label "debug_addr_base_"]
_defer_output .debug_addr {
define_label $lbl
}
+
+ set _debug_addr_index 0
+
return $lbl
}
@@ -3988,6 +4077,7 @@ namespace eval Dwarf {
variable _line_header_end_label
variable _debug_ranges_64_bit
variable _debug_addr_index
+ variable _debug_addr_end_label
variable _level
variable _dwo_abbrev_num
@@ -4022,7 +4112,8 @@ namespace eval Dwarf {
set _line_count 0
set _debug_ranges_64_bit [is_64_target]
- set _debug_addr_index 0
+ set _debug_addr_index ""
+ set _debug_addr_end_label ""
set _dwo_abbrev_num 1
# Dummy CU at the start to ensure that the first CU in $body is not
@@ -4053,6 +4144,9 @@ namespace eval Dwarf {
}
}
+ # Terminate the last .debug_addr contribution, if any.
+ _debug_addr_end_contribution
+
_write_deferred_output
_section .note.GNU-stack {