From: simon.marchi@polymtl.ca
To: gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: [PATCH v2 1/2] gdb/testsuite: add .debug_frame support in DWARF assembler
Date: Wed, 18 Mar 2026 16:27:22 -0400 [thread overview]
Message-ID: <20260318202801.2030268-1-simon.marchi@polymtl.ca> (raw)
In-Reply-To: <20260316172239.349677-2-simon.marchi@efficios.com>
From: Simon Marchi <simon.marchi@efficios.com>
Add support to the DWARF assembler for generating .debug_frame sections.
My initial use case is to reproduce a crash happening when encountering
an empty FDE, but I suppose that other use cases will pop up in the
future.
- Generate procs for the `DW_CFA_*` constants, similar to how the
DW_OP_* constants are handled. These `DW_CFA_*` procs are expected
to be used in the CIE and FDE bodies, described below.
- Add handlers for `DW_CFA_*` operations that take arguments. I tried
to cover everything that is in DWARF 5.
- Add the `frame` proc, used to generate one .debug_frame section.
- Add the `_frame_CIE` proc (available as `CIE` in the context of the
frame proc), used to generate one Common Information Entry.
- Add the `_frame_FDE` proc (available as `FDE` in the context of the
frame proc), used to generate one Frame Description Entry.
Due to the nature of the .debug_frame contents (it describes how
specific machine registers get saved), I expect that most of
the tests written using this will be arch-specific. But I think it
will still be useful, as it will let us craft .debug_frame sections to
look exactly how we want.
I included a test (gdb.dwarf2/debug-frame.exp), which is more like a
proof that we can build something useful using this, and can serve as an
example for whoever wants to write a test case using this in the future.
Change-Id: I048568ded53883abf52d70139e5cd3e7b4ac3841
---
gdb/testsuite/gdb.dwarf2/debug-frame.S | 101 ++++++
gdb/testsuite/gdb.dwarf2/debug-frame.exp | 130 ++++++++
gdb/testsuite/lib/dwarf.exp | 394 ++++++++++++++++++++++-
3 files changed, 624 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.dwarf2/debug-frame.S
create mode 100644 gdb/testsuite/gdb.dwarf2/debug-frame.exp
diff --git a/gdb/testsuite/gdb.dwarf2/debug-frame.S b/gdb/testsuite/gdb.dwarf2/debug-frame.S
new file mode 100644
index 000000000000..231e2dc23704
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/debug-frame.S
@@ -0,0 +1,101 @@
+/* Copyright 2026 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 <http://www.gnu.org/licenses/>. */
+
+/* Hand-written x86-64 assembly with no .cfi directives. The .debug_frame
+ section is supplied by the companion -dw.S file, generated by the DWARF
+ assembler.
+
+ The call chain: main -> caller -> callee.
+
+ caller sets some known register values, and callee saves those registers in
+ different way. */
+
+ .text
+
+/* main */
+ .globl main
+ .type main, @function
+main:
+ pushq %rbp
+ .globl main_after_push_rbp
+main_after_push_rbp:
+ movq %rsp, %rbp
+ .globl main_after_set_rbp
+main_after_set_rbp:
+ call caller
+ xorl %eax, %eax
+ popq %rbp
+ ret
+ .size main, . - main
+ .globl main_end
+main_end:
+ .globl main_len
+ .set main_len, main_end - main
+
+/* caller */
+ .globl caller
+ .type caller, @function
+caller:
+ pushq %rbp
+ .globl caller_after_push_rbp
+caller_after_push_rbp:
+ movq %rsp, %rbp
+ .globl caller_after_set_rbp
+caller_after_set_rbp:
+ movq $0x11223344, %r12
+ movq $0x55667788, %r13
+ .globl caller_call_callee
+caller_call_callee:
+ call callee
+ popq %rbp
+ ret
+ .size caller, . - caller
+ .globl caller_end
+caller_end:
+ .globl caller_len
+ .set caller_len, caller_end - caller
+
+/* callee */
+ .globl callee
+ .type callee, @function
+callee:
+ pushq %rbp
+ .globl callee_after_push_rbp
+callee_after_push_rbp:
+ movq %rsp, %rbp
+ .globl callee_after_set_rbp
+callee_after_set_rbp:
+ /* Save r12 in the stack, then clobber it. */
+ pushq %r12
+ xorq %r12, %r12
+ /* Save r13 in rax, then clobber it. */
+ movq %r13, %rax
+ xorq %r13, %r13
+ /* Clobber r14. This one is described with a DWARF expression. */
+ xorq %r14, %r14
+ .globl callee_body
+callee_body:
+ nop
+ movq %rax, %r13
+ popq %r12
+ popq %rbp
+ ret
+ .size callee, . - callee
+ .globl callee_end
+callee_end:
+ .globl callee_len
+ .set callee_len, callee_end - callee
+
+ .section .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/debug-frame.exp b/gdb/testsuite/gdb.dwarf2/debug-frame.exp
new file mode 100644
index 000000000000..ddadab7566ef
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/debug-frame.exp
@@ -0,0 +1,130 @@
+# Copyright 2026 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 <http://www.gnu.org/licenses/>.
+
+# Test that GDB can unwind using a .debug_frame section generated by
+# the DWARF assembler.
+#
+# This test is amd64-specific, but could be ported to other
+# architectures if needed.
+
+load_lib dwarf.exp
+
+require dwarf2_support is_x86_64_m64_target
+
+standard_testfile .S -dw.S
+
+# AMD64 DWARF register numbers.
+set rax 0
+set rbp 6
+set rsp 7
+set r12 12
+set r13 13
+set r14 14
+set rip 16
+
+foreach_with_prefix is_64 { false true } {
+ set asm_file [standard_output_file ${testfile}-${is_64}-dw.S]
+
+ Dwarf::assemble $asm_file {
+ frame {
+ declare_labels cie_label
+
+ cie_label: CIE {
+ return_address_register $::rip
+ data_alignment_factor -8
+ is_64 $::is_64
+ } {
+ DW_CFA_def_cfa $::rsp 8
+ DW_CFA_offset $::rip 1
+ }
+
+ # FDE for main
+ FDE $cie_label main main_len {
+ is_64 $::is_64
+ } {
+ DW_CFA_set_loc main_after_push_rbp
+ DW_CFA_def_cfa_offset 16
+ DW_CFA_offset $::rbp 2
+ DW_CFA_set_loc main_after_set_rbp
+ DW_CFA_def_cfa_register $::rbp
+ }
+
+ # FDE for caller
+ FDE $cie_label caller caller_len {
+ is_64 $::is_64
+ } {
+ DW_CFA_set_loc caller_after_push_rbp
+ DW_CFA_def_cfa_offset 16
+ DW_CFA_offset $::rbp 2
+ DW_CFA_set_loc caller_after_set_rbp
+ DW_CFA_def_cfa_register $::rbp
+ }
+
+ # FDE for callee
+ FDE $cie_label callee callee_len {
+ is_64 $::is_64
+ } {
+ DW_CFA_set_loc callee_after_push_rbp
+ DW_CFA_def_cfa_offset 16
+ DW_CFA_offset $::rbp 2
+ DW_CFA_set_loc callee_after_set_rbp
+ DW_CFA_def_cfa_register $::rbp
+
+ DW_CFA_set_loc callee_body
+ DW_CFA_offset $::r12 3
+ DW_CFA_register $::r13 $::rax
+
+ # r14's value is computed by an arbitrary expression.
+ DW_CFA_val_expression $::r14 {
+ DW_OP_constu 0x99aabbcc
+ }
+ }
+ }
+ }
+
+ if { [prepare_for_testing "failed to prepare" ${testfile}-${is_64} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ continue
+ }
+
+ # Stop in caller before the call, to capture rbp.
+ if { ![runto caller_call_callee] } {
+ continue
+ }
+
+ set caller_rbp [get_hexadecimal_valueof "\$rbp" "UNKNOWN"]
+
+ # Stop inside callee.
+ gdb_breakpoint callee_body
+ gdb_continue_to_breakpoint "callee_body"
+
+ # Verify backtrace shows the full call chain.
+ gdb_test "bt" "#0.*callee.*\r\n#1.*caller.*\r\n#2.*main.*"
+
+ # Select caller's frame and check saved registers.
+ gdb_test "frame 1" "#1.*caller.*"
+
+ # r12 was saved on the stack by callee.
+ gdb_test "p/x \$r12" "= 0x11223344"
+
+ # r13 was saved in rax by callee.
+ gdb_test "p/x \$r13" "= 0x55667788"
+
+ # r14's value is computed by a DWARF expression.
+ gdb_test "p/x \$r14" "= 0x99aabbcc"
+
+ # rbp should match what caller had.
+ gdb_test "p/x \$rbp" "= ${caller_rbp}"
+}
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 9fa5c4e297da..e545019e065b 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -602,6 +602,10 @@ namespace eval Dwarf {
variable _loc_addr_size
variable _loc_offset_size
+ # Variables used when generating a .debug_frame section.
+ variable _frame_addr_size
+ variable _frame_offset_size
+
proc _process_one_constant {name value} {
variable _constants
variable _FORM
@@ -618,7 +622,6 @@ namespace eval Dwarf {
}
# We only try to shorten some very common things.
- # FIXME: CFA?
switch -exact -- $prefix {
TAG {
# Create two procedures for the tag. These call
@@ -667,6 +670,57 @@ namespace eval Dwarf {
} $name $name $handler]
}
+ CFA {
+ # Create procs for DW_CFA_* instructions, used in
+ # .debug_frame CIE/FDE bodies.
+
+ # DW_CFA_advance_loc, DW_CFA_offset and
+ # DW_CFA_restore encode the operand in the low 6
+ # bits of the opcode byte. They need special
+ # handling.
+ switch -exact -- $name {
+ DW_CFA_advance_loc {
+ proc DW_CFA_advance_loc {delta} {
+ _op .byte \
+ "$Dwarf::_constants(DW_CFA_advance_loc) + $delta" \
+ DW_CFA_advance_loc
+ }
+ }
+
+ DW_CFA_offset {
+ proc DW_CFA_offset {register offset} {
+ _op .byte \
+ "$Dwarf::_constants(DW_CFA_offset) + $register" \
+ DW_CFA_offset
+ _op .uleb128 $offset "offset"
+ }
+ }
+
+ DW_CFA_restore {
+ proc DW_CFA_restore {register} {
+ _op .byte \
+ "$Dwarf::_constants(DW_CFA_restore) + $register" \
+ DW_CFA_restore
+ }
+ }
+
+ default {
+ # Standard CFA instruction: emit opcode
+ # byte then delegate to handler.
+ set handler _handle_default_CFA
+ if {[llength [info procs _handle_$name]] > 0} {
+ set handler _handle_$name
+ }
+
+ # tclint-disable-next-line command-args
+ proc $name {args} [format {
+ _op .byte $Dwarf::_constants(%s) %s
+ %s {*}$args
+ } $name $name $handler]
+ }
+ }
+ }
+
default {
return
}
@@ -1456,6 +1510,127 @@ namespace eval Dwarf {
# error.
}
+ # Helper to emit a DWARF expression block (ULEB128 length followed
+ # by the expression bytes) inside a .debug_frame CIE or FDE body.
+ # BODY is a Tcl code containing DW_OP_* calls.
+ proc _emit_cfa_expression {body} {
+ set start [new_label "cfa_expr_start"]
+ set end [new_label "cfa_expr_end"]
+ _op .uleb128 "$end - $start" "expression length"
+ define_label $start
+
+ # Pass 5 as the DWARF version, since we need to pass something, but it
+ # doesn't matter. The DWARF version is checked only for DW_OP_* ops
+ # that don't make sense in CFI.
+ _location $body 5 $Dwarf::_frame_addr_size $Dwarf::_frame_offset_size
+ define_label $end
+ }
+
+ #
+ # Handlers for DW_CFA_* instructions.
+ #
+ # A handler is only needed if the instruction requires operands.
+ # Generic code handles emitting the opcode byte itself, so a
+ # handler should not do this.
+ #
+ # Handlers are found by name when processing the .def file. If a
+ # handler isn't found, the default (_handle_default_CFA) is used.
+ #
+
+ proc _handle_default_CFA {} {
+ # Do nothing; if arguments are passed, Tcl will cause an
+ # error.
+ }
+
+ proc _handle_DW_CFA_set_loc {address} {
+ _op .${Dwarf::_frame_addr_size}byte $address "address"
+ }
+
+ proc _handle_DW_CFA_advance_loc1 {delta} {
+ _op .byte $delta "delta"
+ }
+
+ proc _handle_DW_CFA_advance_loc2 {delta} {
+ _op .2byte $delta "delta"
+ }
+
+ proc _handle_DW_CFA_advance_loc4 {delta} {
+ _op .4byte $delta "delta"
+ }
+
+ proc _handle_DW_CFA_offset_extended {register offset} {
+ _op .uleb128 $register "register"
+ _op .uleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_restore_extended {register} {
+ _op .uleb128 $register "register"
+ }
+
+ proc _handle_DW_CFA_undefined {register} {
+ _op .uleb128 $register "register"
+ }
+
+ proc _handle_DW_CFA_same_value {register} {
+ _op .uleb128 $register "register"
+ }
+
+ proc _handle_DW_CFA_register {register1 register2} {
+ _op .uleb128 $register1 "register"
+ _op .uleb128 $register2 "register"
+ }
+
+ proc _handle_DW_CFA_def_cfa {register offset} {
+ _op .uleb128 $register "register"
+ _op .uleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_def_cfa_register {register} {
+ _op .uleb128 $register "register"
+ }
+
+ proc _handle_DW_CFA_def_cfa_offset {offset} {
+ _op .uleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_def_cfa_expression {body} {
+ _emit_cfa_expression $body
+ }
+
+ proc _handle_DW_CFA_expression {register body} {
+ _op .uleb128 $register "register"
+ _emit_cfa_expression $body
+ }
+
+ proc _handle_DW_CFA_offset_extended_sf {register offset} {
+ _op .uleb128 $register "register"
+ _op .sleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_def_cfa_sf {register offset} {
+ _op .uleb128 $register "register"
+ _op .sleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_def_cfa_offset_sf {offset} {
+ _op .sleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_val_offset {register offset} {
+ _op .uleb128 $register "register"
+ _op .uleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_val_offset_sf {register offset} {
+ _op .uleb128 $register "register"
+ _op .sleb128 $offset "offset"
+ }
+
+ proc _handle_DW_CFA_val_expression {register body} {
+ _op .uleb128 $register "register"
+ _emit_cfa_expression $body
+ }
+
# This is a miniature assembler for location expressions. It is
# suitable for use in the attributes to a DIE.
#
@@ -3554,6 +3729,223 @@ namespace eval Dwarf {
debug_str_offsets_end:
}
+ # Emit a DWARF .debug_frame section.
+ #
+ # BODY is Tcl code that emits the CIEs and FDEs which make up the
+ # section. It is evaluated in the caller's context.
+ #
+ # Within BODY, the following commands are available:
+ #
+ # CIE options body
+ # -- emit a Common Information Entry. See _frame_CIE for details.
+ #
+ # FDE cie_label initial_location address_range body
+ # -- emit a Frame Description Entry. See _frame_FDE for details.
+ proc frame { body } {
+ _section .debug_frame
+
+ with_override Dwarf::CIE Dwarf::_frame_CIE {
+ with_override Dwarf::FDE Dwarf::_frame_FDE {
+ uplevel $Dwarf::_level $body
+ }
+ }
+ }
+
+ # Available as proc CIE when in the body of proc debug_frame.
+ #
+ # OPTIONS is a list of option-name/option-value pairs. Supported
+ # options are (default values are shown in parentheses):
+ #
+ # is_64 (false)
+ # -- if true, emit a 64-bit CIE.
+ #
+ # cie_id (default)
+ # -- the CIE id value. When "default", uses 0xffffffff for
+ # 32-bit and 0xffffffffffffffff for 64-bit. Should typically not be
+ # used unless trying to craft an invalid CIE.
+ #
+ # version (4)
+ # -- the CIE version number. Note that this is version independent
+ # from the DWARF version. DWARF 4 and 5 both use .debug_frame
+ # version 4.
+ #
+ # augmentation ("")
+ # -- the augmentation string.
+ #
+ # addr_size (default)
+ # -- the address size in bytes. When "default", use 8 for 64-bit
+ # targets and 4 for 32-bit targets.
+ #
+ # segment_selector_size (0)
+ # -- the segment selector size in bytes.
+ #
+ # code_alignment_factor (1)
+ # -- the code alignment factor.
+ #
+ # data_alignment_factor (1)
+ # -- the data alignment factor.
+ #
+ # return_address_register (0)
+ # -- the number of the "column" containing the return address.
+ #
+ # BODY is Tcl code that emits the CIE's initial instructions using
+ # DW_CFA_* operations. It is evaluated in the caller's context.
+ proc _frame_CIE {options body} {
+ parse_options {
+ { is_64 false }
+ { cie_id default }
+ { version 4 }
+ { augmentation "" }
+ { addr_size default }
+ { segment_selector_size 0 }
+ { code_alignment_factor 1 }
+ { data_alignment_factor 1 }
+ { return_address_register 0 }
+ }
+
+ if { $is_64 } {
+ set Dwarf::_frame_offset_size 8
+ } else {
+ set Dwarf::_frame_offset_size 4
+ }
+
+ if { $cie_id == "default" } {
+ if { $is_64 } {
+ set cie_id 0xffffffffffffffff
+ } else {
+ set cie_id 0xffffffff
+ }
+ }
+
+ if {$addr_size == "default"} {
+ if {[is_64_target]} {
+ set Dwarf::_frame_addr_size 8
+ } else {
+ set Dwarf::_frame_addr_size 4
+ }
+ } else {
+ set Dwarf::_frame_addr_size $addr_size
+ }
+
+ declare_labels cie_post_length cie_end
+
+ # Length.
+ if { $is_64 } {
+ _op .4byte 0xffffffff "length 1/2"
+ _op .8byte "$cie_end - $cie_post_length" "length 2/2"
+ } else {
+ _op .4byte "$cie_end - $cie_post_length" "length"
+ }
+
+ define_label $cie_post_length
+
+ # CIE_id
+ _op .${Dwarf::_frame_offset_size}byte $cie_id "CIE_id"
+
+ # Version.
+ _op .byte $version "version"
+
+ # Augmentation string.
+ _op .ascii [_quote $augmentation] "augmentation"
+
+ # Address size.
+ _op .byte $Dwarf::_frame_addr_size "address_size"
+
+ # Segment selector size.
+ _op .byte 0 "segment_size"
+
+ # Code alignment factor.
+ _op .uleb128 $code_alignment_factor "code_alignment_factor"
+
+ # Data alignment factor.
+ _op .sleb128 $data_alignment_factor "data_alignment_factor"
+
+ # Return address register.
+ _op .uleb128 $return_address_register "return_address_register"
+
+ # Initial instructions.
+ uplevel $Dwarf::_level $body
+
+ # Padding up to the address size. Fill with DW_CFA_nop (zeroes).
+ _op .align $Dwarf::_frame_addr_size "padding"
+
+ define_label $cie_end
+ }
+
+ # Available as proc FDE when in the body of proc debug_frame.
+ #
+ # CIE_LABEL is the label of the CIE this FDE refers to.
+ #
+ # INITIAL_LOCATION is the address of the first instruction covered
+ # by this FDE.
+ #
+ # ADDRESS_RANGE is the number of bytes of instructions covered by
+ # this FDE.
+ #
+ # OPTIONS is a list of option-name/option-value pairs. Supported
+ # options are (default values are shown in parentheses):
+ #
+ # is_64 (false)
+ # -- if true, emit a 64-bit CIE.
+ #
+ # addr_size (default)
+ # -- the address size in bytes. When "default", use 8 for 64-bit
+ # targets and 4 for 32-bit targets.
+ #
+ # BODY is Tcl code that emits the FDE's call frame instructions using
+ # DW_CFA_* operations. It is evaluated in the caller's context.
+ proc _frame_FDE { cie_label initial_location address_range options
+ body } {
+ parse_options {
+ { is_64 false }
+ { addr_size default }
+ }
+
+ if { $is_64 } {
+ set Dwarf::_frame_offset_size 8
+ } else {
+ set Dwarf::_frame_offset_size 4
+ }
+
+ if {$addr_size == "default"} {
+ if {[is_64_target]} {
+ set Dwarf::_frame_addr_size 8
+ } else {
+ set Dwarf::_frame_addr_size 4
+ }
+ } else {
+ set Dwarf::_frame_addr_size $addr_size
+ }
+
+ declare_labels fde_post_length fde_end
+
+ # Length.
+ if { $is_64 } {
+ _op .4byte 0xffffffff "length 1/2"
+ _op .8byte "$fde_end - $fde_post_length" "length 2/2"
+ } else {
+ _op .4byte "$fde_end - $fde_post_length" "length"
+ }
+ define_label $fde_post_length
+
+ # CIE pointer, offset of the CIE into the .debug_frame section.
+ _op .${Dwarf::_frame_offset_size}byte $cie_label "CIE pointer"
+
+ # Initial location.
+ _op .${Dwarf::_frame_addr_size}byte $initial_location "initial_location"
+
+ # Address range.
+ _op .${Dwarf::_frame_addr_size}byte $address_range "address_range"
+
+ # Instructions.
+ uplevel $Dwarf::_level $body
+
+ # Padding up to the address size. Fill with DW_CFA_nop (zeroes).
+ _op .align $Dwarf::_frame_addr_size "padding"
+
+ define_label $fde_end
+ }
+
# The top-level interface to the DWARF assembler.
# OPTIONS is a list with an even number of elements containing
# option-name and option-value pairs.
base-commit: bd40fc073ae0c30f8ad40623e9f40da1be09b0e5
--
2.53.0
next prev parent reply other threads:[~2026-03-18 20:29 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-16 17:22 [PATCH " Simon Marchi
2026-03-16 17:22 ` [PATCH 2/2] gdb/dwarf: fix internal error when FDEs do not describe the CFA Simon Marchi
2026-03-17 19:33 ` Simon Marchi
2026-03-18 20:27 ` simon.marchi [this message]
2026-03-18 20:27 ` [PATCH v2 " simon.marchi
2026-04-06 18:10 ` Tom Tromey
2026-04-11 2:47 ` Simon Marchi
2026-04-04 1:25 ` [PATCH v2 1/2] gdb/testsuite: add .debug_frame support in DWARF assembler Simon Marchi
2026-04-06 17:45 ` Tom Tromey
2026-04-11 2:46 ` Simon Marchi
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=20260318202801.2030268-1-simon.marchi@polymtl.ca \
--to=simon.marchi@polymtl.ca \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
/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