Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@efficios.com>
To: gdb-patches@sourceware.org, binutils@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: [PATCH v2 1/4] gdb/testsuite: add support for DWARF 5 .debug_addr sections to DWARF assembler
Date: Mon, 21 Sep 2026 13:39:41 -0400	[thread overview]
Message-ID: <20260921173951.688121-2-simon.marchi@efficios.com> (raw)
In-Reply-To: <20260921173951.688121-1-simon.marchi@efficios.com>

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(-)

diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 839c51742650..351903242f98 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -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 {
-- 
2.55.0


  reply	other threads:[~2026-09-21 17:41 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-21 17:39 [PATCH v2 0/4] Fix reading DW_FORM_addrx with address size of 2 Simon Marchi
2026-09-21 17:39 ` Simon Marchi [this message]
2026-09-21 17:39 ` [PATCH v2 2/4] gdb/dwarf: validate address sizes when reading DWARF headers Simon Marchi
2026-09-21 17:39 ` [PATCH v2 3/4] gdb/dwarf: don't store segment_collector_size (sic) Simon Marchi
2026-09-21 17:39 ` [PATCH v2 4/4] gdb/dwarf: fix reading DW_FORM_addrx with address size of 2 Simon Marchi
2026-09-23 15:13   ` Tom Tromey
2026-09-24 15:59     ` Simon Marchi
2026-09-23 15:49 ` [PATCH v2 0/4] Fix " Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260921173951.688121-2-simon.marchi@efficios.com \
    --to=simon.marchi@efficios.com \
    --cc=binutils@sourceware.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox