[PATCH v3 3/3] sframe: Add tests for PR ld/32769
Indu Bhagat
indu.bhagat@oracle.com
Fri Jan 23 06:27:02 GMT 2026
On 1/22/26 12:00 AM, claudiu.zissulescu-ianculescu@oracle.com wrote:
> From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
>
> Add a simple tests which tests if sframe section is removed or not
> while performing garbage collection durring linking.
>
> x86_64-specific tests:
> - sframe-gc-sections-1.d checks that none of the functions get
> discarded with --gc-sections
> - sframe-gc-sections-2a.d checks the behavior of --gc-sections with two
> distinct .text.* sections (similar to -ffunction-sections compiler
> option)
I wish there was a way to add these comments somehow in the test
infrastructure.
> - sframe-gc-sections-2b.d checks the same behaviour as
> sframe-gc-sections-2a.d, but with a linker script that discards
> .eh_frame sections. This testcase is keep it ensured that the two
> section's GC behaviours are not unnecessarily inter-twined.
>
We could leave this comment at least I think in the
sframe-gc-sections-2b.t linker script fragment file. WDYT ?
> ld/
> PR ld/32769
> * testsuite/ld-sframe/pr32769.rd: New file.
> * testsuite/ld-sframe/pr32769.s: Likewise.
> * testsuite/ld-sframe/pr32769-2.d: Likewise.
> * testsuite/ld-sframe/pr32769-2.s: Likewise.
> * testsuite/ld-sframe/pr32769-3.d: Likewise.
> * testsuite/ld-sframe/pr32769-3.s: Likewise.
> * testsuite/ld-sframe/sframe.exp: Add pr32769 test.
> * testsuite/ld-x86-64/sframe-baz.s: New file.
> * testsuite/ld-x86-64/sframe-gc-sections-1.d: Likewise.
> * testsuite/ld-x86-64/sframe-gc-sections-2.s: Likewise.
> * testsuite/ld-x86-64/sframe-gc-sections-2a.d: Likewise.
> * testsuite/ld-x86-64/sframe-gc-sections-2b.d: Likewise.
> * testsuite/ld-x86-64/sframe-gc-sections-2b.t: Likewise.
> * testsuite/ld-x86-64/x86-64.exp: Add new sframe gc tests.
>
> Co-authored-by: Indu Bhagat <indu.bhagat@oracle.com>
> Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
> ---
> ld/testsuite/ld-sframe/pr32769-2.d | 9 +++++
> ld/testsuite/ld-sframe/pr32769-2.s | 19 ++++++++++
> ld/testsuite/ld-sframe/pr32769-3.d | 10 ++++++
> ld/testsuite/ld-sframe/pr32769-3.s | 21 +++++++++++
> ld/testsuite/ld-sframe/pr32769.rd | 14 ++++++++
> ld/testsuite/ld-sframe/pr32769.s | 8 +++++
> ld/testsuite/ld-sframe/sframe.exp | 9 +++++
> ld/testsuite/ld-x86-64/sframe-baz.s | 36 +++++++++++++++++++
> ld/testsuite/ld-x86-64/sframe-gc-sections-1.d | 20 +++++++++++
> ld/testsuite/ld-x86-64/sframe-gc-sections-2.s | 35 ++++++++++++++++++
> .../ld-x86-64/sframe-gc-sections-2a.d | 17 +++++++++
> .../ld-x86-64/sframe-gc-sections-2b.d | 30 ++++++++++++++++
> .../ld-x86-64/sframe-gc-sections-2b.t | 11 ++++++
> ld/testsuite/ld-x86-64/x86-64.exp | 3 ++
> 14 files changed, 242 insertions(+)
> create mode 100644 ld/testsuite/ld-sframe/pr32769-2.d
> create mode 100644 ld/testsuite/ld-sframe/pr32769-2.s
> create mode 100644 ld/testsuite/ld-sframe/pr32769-3.d
> create mode 100644 ld/testsuite/ld-sframe/pr32769-3.s
> create mode 100644 ld/testsuite/ld-sframe/pr32769.rd
> create mode 100644 ld/testsuite/ld-sframe/pr32769.s
> create mode 100644 ld/testsuite/ld-x86-64/sframe-baz.s
> create mode 100644 ld/testsuite/ld-x86-64/sframe-gc-sections-1.d
> create mode 100644 ld/testsuite/ld-x86-64/sframe-gc-sections-2.s
> create mode 100644 ld/testsuite/ld-x86-64/sframe-gc-sections-2a.d
> create mode 100644 ld/testsuite/ld-x86-64/sframe-gc-sections-2b.d
> create mode 100644 ld/testsuite/ld-x86-64/sframe-gc-sections-2b.t
>
> diff --git a/ld/testsuite/ld-sframe/pr32769-2.d b/ld/testsuite/ld-sframe/pr32769-2.d
> new file mode 100644
> index 00000000000..f0708f5c283
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769-2.d
> @@ -0,0 +1,9 @@
> +#as: --gsframe
> +#source: pr32769-2.s
> +#readelf: --sframe
> +#ld: --gc-section -shared
> +#name: GC Multiple .text sections, remove unused
> +
> +#...
> +\s+Num FDEs: 1
> +#...
I think there is value in running this test with and wihout -r, and
checking relas are as expected. WDYT ?
> diff --git a/ld/testsuite/ld-sframe/pr32769-2.s b/ld/testsuite/ld-sframe/pr32769-2.s
> new file mode 100644
> index 00000000000..df4eab0bc3a
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769-2.s
> @@ -0,0 +1,19 @@
> + .section .text.foo
> + .globl foo
> + .type foo, @function
> +foo:
> + .cfi_startproc
> + .byte 0
> +
> + .section .text.foo.cold
> +coldx:
> + .cfi_startproc
> + .cfi_def_cfa_offset 16
> + .byte 0
> + .cfi_endproc
> +
> + .section .text.foo
> + .byte 0
> + .cfi_def_cfa_offset 16
> + .cfi_endproc
> + .size foo, .-foo
> diff --git a/ld/testsuite/ld-sframe/pr32769-3.d b/ld/testsuite/ld-sframe/pr32769-3.d
> new file mode 100644
> index 00000000000..0c33f95fed8
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769-3.d
> @@ -0,0 +1,10 @@
> +#as: --gsframe
> +#source: pr32769-3.s
> +#readelf: --sframe
> +#ld: --gc-section -e foo
> +#name: GC Multiple .text sections, keep all
> +
> +#...
> +\s+Num FDEs: 2
> +\s+Num FREs: 3
> +#...
> diff --git a/ld/testsuite/ld-sframe/pr32769-3.s b/ld/testsuite/ld-sframe/pr32769-3.s
> new file mode 100644
> index 00000000000..181eb1305b9
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769-3.s
> @@ -0,0 +1,21 @@
> + .section .text.foo
> + .globl foo
> + .type foo, @function
> +foo:
> + .cfi_startproc
> + .byte 0
> + .long coldx
> +
> + .section .text.foo.cold
> + .type coldx, @function
> +coldx:
> + .cfi_startproc
> + .cfi_def_cfa_offset 16
> + .byte 0
> + .cfi_endproc
> +
> + .section .text.foo
> +1: .byte 0
> + .cfi_def_cfa_offset 16
> + .cfi_endproc
> + .size foo, .-foo
> diff --git a/ld/testsuite/ld-sframe/pr32769.rd b/ld/testsuite/ld-sframe/pr32769.rd
> new file mode 100644
> index 00000000000..1190c58fb1e
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769.rd
> @@ -0,0 +1,14 @@
> +Contents of the SFrame section .sframe:
> + Header :
> +
> + Version: SFRAME_VERSION_\d+
> +#...
> + Num FDEs: 1
> + Num FREs: 1
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x[0-9a-f]+, size = 1 bytes
> + STARTPC\s+CFA\s+FP\s+RA\s+
> + [0-9a-f]+\s+sp.*
> +#pass
> diff --git a/ld/testsuite/ld-sframe/pr32769.s b/ld/testsuite/ld-sframe/pr32769.s
> new file mode 100644
> index 00000000000..0518fff68a6
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr32769.s
> @@ -0,0 +1,8 @@
> + .text
> + .globl foo
> + .type foo, @function
> +foo:
> + .cfi_startproc
> + .byte 0
> + .cfi_endproc
> + .size foo, .-foo
> diff --git a/ld/testsuite/ld-sframe/sframe.exp b/ld/testsuite/ld-sframe/sframe.exp
> index ef946193c32..60ecbb08096 100644
> --- a/ld/testsuite/ld-sframe/sframe.exp
> +++ b/ld/testsuite/ld-sframe/sframe.exp
> @@ -170,6 +170,15 @@ if { [check_compiler_available] } {
> ]
> }
>
> +set sframe_link_tests {
> + { "pr32769"
> + "--gc-section -e foo" "" "--gsframe" {pr32769.s}
> + {{readelf --sframe pr32769.rd}}
> + "pr32769.x" }
> +}
> +
> +run_ld_link_tests $sframe_link_tests
> +
> if {[info exists old_lc_all]} {
> set env(LC_ALL) $old_lc_all
> } else {
> diff --git a/ld/testsuite/ld-x86-64/sframe-baz.s b/ld/testsuite/ld-x86-64/sframe-baz.s
> new file mode 100644
> index 00000000000..b0142ac6b43
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-baz.s
> @@ -0,0 +1,36 @@
> + .text
> + .globl baz
> + .type baz, @function
> +baz:
> + .cfi_startproc
> + pushq %rbp
> + .cfi_def_cfa_offset 16
> + .cfi_offset 6, -16
> + movq %rsp, %rbp
> + .cfi_def_cfa_register 6
> + call foo
> + popq %rbp
> + .cfi_def_cfa 7, 8
> + ret
> + .cfi_endproc
> + .size baz, .-baz
> +
> + .global qux
> + .type qux, @function
> +qux:
> + .cfi_startproc
> + nop
> + ret
> + .cfi_endproc
> + .size qux, .-qux
> +
> + .global _start
> + .type _start,%function
> +_start:
> + .cfi_startproc
> + mov bar@GOTPCREL(%rip), %rax
> + mov foo@GOTPCREL(%rip), %rax
> + .cfi_endproc
> + .size _start, . - _start
> +
> + .section .note.GNU-stack,"",@progbits
> diff --git a/ld/testsuite/ld-x86-64/sframe-gc-sections-1.d b/ld/testsuite/ld-x86-64/sframe-gc-sections-1.d
> new file mode 100644
> index 00000000000..23b06225b99
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-gc-sections-1.d
> @@ -0,0 +1,20 @@
> +#as: --gsframe
> +#source: sframe-foo.s
> +#source: sframe-bar.s
> +#source: sframe-baz.s
> +#objdump: --sframe=.sframe
> +#ld: --gc-sections -e _start
> +#name: SFrame gc sections
> +
> +.*: +file format .*
> +
> +Contents of the SFrame section .sframe:
> + Header :
> +
> + Version: SFRAME_VERSION_\d+
> + Flags: SFRAME_F_FDE_SORTED,
> + SFRAME_F_FDE_FUNC_START_PCREL
> + CFA fixed RA offset: -8
> + Num FDEs: 5
> + Num FREs: 14
> +#...
> diff --git a/ld/testsuite/ld-x86-64/sframe-gc-sections-2.s b/ld/testsuite/ld-x86-64/sframe-gc-sections-2.s
> new file mode 100644
> index 00000000000..9b5e7d9dbd7
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-gc-sections-2.s
> @@ -0,0 +1,35 @@
> +# --gc-sections will clean up .text.bar, and there should be no
> +# SFrame stack trace information for it.
> + .section .text.start,"ax",@progbits
> + .globl start
> + .type start, @function
> +start:
> + .cfi_startproc
> + jmp foo
> + .cfi_endproc
> + .size start, .-start
> +
> + .section .text.foo,"ax",@progbits
> + .globl foo
> + .type foo, @function
> +foo:
> + .cfi_startproc
> + pushq %rbp
> + .cfi_def_cfa_offset 16
> + .cfi_offset 6, -16
> + movq %rsp, %rbp
> + .cfi_def_cfa_register 6
> + leave
> + .cfi_def_cfa 7, 8
> + ret
> + .cfi_endproc
> + .size foo, .-foo
> +
> + .section .text.bar,"ax",@progbits
> + .globl bar
> + .type bar, @function
> +bar:
> + .cfi_startproc
> + ret
> + .cfi_endproc
> + .size bar, .-bar
> diff --git a/ld/testsuite/ld-x86-64/sframe-gc-sections-2a.d b/ld/testsuite/ld-x86-64/sframe-gc-sections-2a.d
> new file mode 100644
> index 00000000000..54bce29625e
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-gc-sections-2a.d
> @@ -0,0 +1,17 @@
> +#as: --gsframe
> +#source: sframe-gc-sections-2.s
> +#objdump: --sframe=.sframe
> +#ld: -r --gc-sections
> +#name: SFrame gc sections II
> +
> +.*: +file format .*
> +
> +Contents of the SFrame section .sframe:
> + Header :
> +
> + Version: SFRAME_VERSION_\d+
> +#...
> + CFA fixed RA offset: -8
> + Num FDEs: 2
> + Num FREs: 5
> +#...
Like you do in sframe-gc-sections-2b.d, I think we should explicitly
check for the two specific SFrame FDEs. The dump of the stack trace
information for _start and bar differ only in function size.
$
/scratch/ibhagat/BINUTILS-GDB/binutils-gdb/objdir/ld/../binutils/readelf
--sframe tmpdir/sframe-gc-sections-2.o
Contents of the SFrame section .sframe:
Header :
Version: SFRAME_VERSION_3
Flags: SFRAME_F_FDE_FUNC_START_PCREL
CFA fixed RA offset: -8
Num FDEs: 3
Num FREs: 6
Function Index :
func idx [0]: pc = 0x0, size = 5 bytes
STARTPC CFA FP RA
0000000000000000 sp+8 u f
func idx [1]: pc = 0x0, size = 6 bytes
STARTPC CFA FP RA
0000000000000000 sp+8 u f
0000000000000001 sp+16 c-16 f
0000000000000004 fp+16 c-16 f
0000000000000005 sp+8 c-16 f
func idx [2]: pc = 0x0, size = 1 bytes
STARTPC CFA FP RA
0000000000000000 sp+8 u f
So checking for the presence of first FDE *and* absence of third FDE
makes the test more tight. WDYT ?
> diff --git a/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.d b/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.d
> new file mode 100644
> index 00000000000..25640b3c94c
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.d
> @@ -0,0 +1,30 @@
> +#as: --gsframe
> +#source: sframe-gc-sections-2.s
> +#objdump: --sframe=.sframe
> +#ld: -T sframe-gc-sections-2b.t --gc-sections -e start
> +#name: SFrame gc sections with discard EH_Frame
> +
> +.*: +file format .*
> +
> +Contents of the SFrame section .sframe:
> + Header :
> +
> + Version: SFRAME_VERSION_\d+
> + Flags: SFRAME_F_FDE_SORTED,
> + SFRAME_F_FDE_FUNC_START_PCREL
> + CFA fixed RA offset: -8
> + Num FDEs: 2
> + Num FREs: 5
> +
> + Function Index :
> +
> + func idx \[0\]: pc = 0x[0-9a-f]+, size = 5 bytes
> + STARTPC +CFA +FP +RA +
> + [0-9a-f]+ +sp\+8 +u +f +
> +
> + func idx \[1\]: pc = 0x[0-9a-f]+, size = 6 bytes
> + STARTPC +CFA +FP +RA +
> + [0-9a-f]+ +sp\+8 +u +f +
> + [0-9a-f]+ +sp\+16 +c-16 +f +
> + [0-9a-f]+ +fp\+16 +c-16 +f +
> + [0-9a-f]+ +sp\+8 +c-16 +f +
> diff --git a/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.t b/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.t
> new file mode 100644
> index 00000000000..ae6b8cb46b9
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/sframe-gc-sections-2b.t
> @@ -0,0 +1,11 @@
> +ENTRY(_start)
> +SECTIONS
> +{
> + . = SIZEOF_HEADERS;
> + .text : { *(.text) }
> + .sframe : { KEEP (*(.sframe)) }
> + /* Sections to be discarded */
> + /DISCARD/ : {
> + *(.eh_frame)
> + }
> +}
> diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
> index aa5c90f8ca2..ac27a8394ae 100644
> --- a/ld/testsuite/ld-x86-64/x86-64.exp
> +++ b/ld/testsuite/ld-x86-64/x86-64.exp
> @@ -590,6 +590,9 @@ if { ![skip_sframe_tests] } {
> run_dump_test "sframe-link-1"
> run_dump_test "sframe-command-line-1"
> run_dump_test "sframe-reloc-1"
> + run_dump_test "sframe-gc-sections-1"
> + run_dump_test "sframe-gc-sections-2a"
> + run_dump_test "sframe-gc-sections-2b"
> run_dump_test "sframe-plt-1"
> run_dump_test "sframe-ibt-plt-1"
> run_dump_test "sframe-pltgot-1"
More information about the Binutils
mailing list