[PATCH] ld: testsuite: Add sframe test for PR 33401

Indu Bhagat indu.bhagat@oracle.com
Thu Dec 11 08:23:41 GMT 2025
On 12/10/25 11:06 AM, claudiu.zissulescu-ianculescu@oracle.com wrote:
> From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
> 
> When linking for a relocable output file (-r), one or more R_*_NONE
> relocations may be generated for .sframe section. Two new tcl
> procedures are added to sframe.exp file. 'check-dump' is checking if
> an input bin file has the same relocation as specified in the second
> input argument. 'check_pr33401' is the main checking function for
> PR33401 which calls twice the ld tool to produce an relocable output
> file.
> 
> ld:
> 
> 	PR33401
> 	* testsuite/ld-sframe/StateClient.cpp:  New file.
> 	* testsuite/ld-sframe/StatePlaying.cpp: Likewise.
> 	* testsuite/ld-sframe/pr33401.rd: Likewise.
> 	* testsuite/ld-sframe/sframe.exp (check_dump): New procedure.
> 	(check_pr33401): Likewise.
> ---
>   ld/testsuite/ld-sframe/StateClient.cpp  |  26 ++++++
>   ld/testsuite/ld-sframe/StatePlaying.cpp |  41 ++++++++
>   ld/testsuite/ld-sframe/pr33401.rd       |   3 +
>   ld/testsuite/ld-sframe/sframe.exp       | 119 ++++++++++++++++++++++++
>   4 files changed, 189 insertions(+)
>   create mode 100644 ld/testsuite/ld-sframe/StateClient.cpp
>   create mode 100644 ld/testsuite/ld-sframe/StatePlaying.cpp
>   create mode 100644 ld/testsuite/ld-sframe/pr33401.rd
> 
> diff --git a/ld/testsuite/ld-sframe/StateClient.cpp b/ld/testsuite/ld-sframe/StateClient.cpp
> new file mode 100644
> index 00000000000..0154469ce6c
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/StateClient.cpp
> @@ -0,0 +1,26 @@
> +void a(void *);
> +class b {
> +  long ag;
> +  bool c();
> +  void m_fn2() {
> +    if (c())
> +      d(ag);
> +  }
> +  void d(long);
> +
> +public:
> +  ~b() { m_fn2(); }
> +};
> +class Player {
> +  int *an;
> +  b ao;
> +  char be;
> +
> +public:
> +  virtual ~Player() {
> +    a(&be);
> +    a(&be);
> +    a(&be);
> +    delete an;
> +  }
> +} e;
> diff --git a/ld/testsuite/ld-sframe/StatePlaying.cpp b/ld/testsuite/ld-sframe/StatePlaying.cpp
> new file mode 100644
> index 00000000000..f61c32d54c1
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/StatePlaying.cpp
> @@ -0,0 +1,41 @@
> +void b(void *);
> +class c {
> +public:
> +  long am;
> +  bool d();
> +  void e() {
> +    if (d())
> +      f(am);
> +  }
> +  void f(long);
> +  ~c() { e(); }
> +};
> +class g {
> +public:
> +  virtual ~g();
> +};
> +class Player {
> +  int *bh;
> +  c bi;
> +  char bj;
> +
> +public:
> +  virtual ~Player() {
> +    b(&bj);
> +    b(&bj);
> +    b(&bj);
> +    delete bh;
> +  }
> +};
> +class h {
> +public:
> +  ~h() {
> +    Player *a[0];
> +    delete a[0];
> +  }
> +};
> +class i : g {
> +  h bo;
> +  virtual int j();
> +};
> +int i::j() {}
> diff --git a/ld/testsuite/ld-sframe/pr33401.rd b/ld/testsuite/ld-sframe/pr33401.rd
> new file mode 100644
> index 00000000000..00142818b34
> --- /dev/null
> +++ b/ld/testsuite/ld-sframe/pr33401.rd
> @@ -0,0 +1,3 @@
> +#...
> +[0-9a-f]+ +0+ +R_.*_NONE +.*
> +#pass
> \ No newline at end of file
> diff --git a/ld/testsuite/ld-sframe/sframe.exp b/ld/testsuite/ld-sframe/sframe.exp
> index 61dc4dafa2e..d8ed73833b3 100644
> --- a/ld/testsuite/ld-sframe/sframe.exp
> +++ b/ld/testsuite/ld-sframe/sframe.exp
> @@ -18,6 +18,123 @@
>   # MA 02110-1301, USA.
>   #
>   
> +proc check_dump { binfile dumpfile } {
> +    global srcdir
> +    global READELF
> +    global subdir
> +    global env
> +    global runtests
> +
> +    set binary $READELF
> +    set progopts "-j .rela.sframe"
> +    set failed 0
> +
> +    # Ensure consistent sorting of symbols
> +    if {[info exists env(LC_ALL)]} {
> +	set old_lc_all $env(LC_ALL)
> +    }
> +    set env(LC_ALL) "C"
> +    set cmd "$binary $progopts $binfile > dump.out"
> +    send_log "$cmd\n"
> +    catch "exec $cmd" comp_output
> +    if {[info exists old_lc_all]} {
> +	set env(LC_ALL) $old_lc_all
> +    } else {
> +	unset env(LC_ALL)
> +    }
> +    set comp_output [prune_warnings $comp_output]
> +    if ![string match "" $comp_output] then {
> +	send_log "$comp_output\n"
> +	return 1
> +    }
> +
> +    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
> +	verbose -log "output is [file_contents "dump.out"]" 2
> +	return 1
> +    }
> +    return 0
> +}
> +
> +# Test infrastructure for bug 33401
> +# https://sourceware.org/bugzilla/show_bug.cgi?id=33401
> +# Sframe section contains R_*_NONE relocations intermingled with other
> +# relas in the output relocatable object.
> +#
> +# src_files filenames of assembler files
> +proc check_pr33401 { src_files } {
> +    global ld
> +    global CXX_FOR_TARGET
> +    global as
> +    global LDFLAGS
> +    global srcdir
> +    global subdir
> +    global env
> +    global runtests
> +
> +    set objfiles {}
> +    set testname "PR33401"
> +    set failed 0
> +    set linkfile "tmpdir/automa_module.o"
> +
> +    if ![runtest_file_p $runtests $testname] then {
> +	return 0
> +    }
> +
> +    # Check to see if C++ compiler work
> +    if { [which $CXX_FOR_TARGET] == 0 } {
> +	return 0
> +    }
> +
> +    # Assemble each file in the test.
> +    foreach src_file $src_files {
> +	set fileroot "[file rootname [file tail $src_file]]"
> +	set objfile "tmpdir/$fileroot.o"
> +
> +	if { [file extension $src_file] == ".cpp" } {
> +	    set as_file "tmpdir/$fileroot.s"
> +	    if ![ld_compile "$CXX_FOR_TARGET -S -O2 -w" $srcdir/$subdir/$src_file $as_file] {
> +		set failed 1
> +		break
> +	    }
> +	} else {
> +	    set as_file "$srcdir/$subdir/$src_file"
> +	}
> +	if { ![ld_assemble $as "--gsframe $as_file" $objfile] } {
> +	    set failed 1
> +	    break
> +	}
> +	lappend objfiles $objfile
> +    }
> +
> +    # Catch assembler errors.
> +    if { $failed } {
> +	verbose -log "Error during assembling one if the input files."
> +	unresolved $testname
> +	return 0
> +    }
> +
> +    # Do the first linking. If this fails, we cannot resolve the test.
> +    if { ![ld_link $ld $linkfile "-L$srcdir/$subdir -r $objfiles"] } {
> +	verbose -log "Error during linking assembled objects."
> +	unresolved $testname
> +	return 0
> +    }
> +
> +    # Check the output of the first ld invocation
> +    if { [check_dump $linkfile pr33401.rd] } {
> +	verbose -log "No R_*_NONE in .rela.sframe"
> +	unresolved $testname
> +	return 0
> +    }
> +
> +    # Check if the second ld -r invocation is ok
> +    if { ![ld_link $ld /dev/null "-L$srcdir/$subdir -r $linkfile"] } {
> +	fail $testname
> +    } else {
> +	pass $testname
> +    }
> +}
> +

Thanks Claudiu.

Following up on reusing the available proc's for this test.

Will the following work ?

(Excuse the formatting, Not fully tested etc. Also a new 
run_sframe_reloc_test is not strictly necessary, I was just testing 
something else..  But at least we do not need create a new check_dump 
and proc to build the files.)

# Procedure to run an SFrame relocation test.
#
# Arguments:
#   test_name   : Description of the test
#   src_files   : List of source files
#   ld_options  : Linker flags (e.g., "-r")
#   out_file    : Name of the output binary/object file
#   dump_prog   : Dumper program (e.g., "readelf")
#   dump_opts   : Dumper options (e.g., "-r -W")
#   dump_file   : Expected dump output file (.rd)
#
proc run_sframe_reloc_test { test_name src_files ld_options out_file 
dump_prog dump_opts dump_file } {
     # Default C flags for SFrame generation for pr33401, not for all 
sframe tests...
     set cflags "-g -O2 -w -Wa,--gsframe"

     # Construct the test definition list compatible with run_cc_link_tests.
     set test_list [list \
         [list \
             $test_name \
             $ld_options \
             $cflags \
             $src_files \
             [list [list $dump_prog $dump_opts $dump_file]] \
             $out_file \
             "c++"
         ] \
     ]

     # Run the test
     return [run_cc_link_tests $test_list]
}

#
# PR ld/33401: SFrame assertion failure when skipping R_*_NONE relocations
#
proc check_pr33401 { } {
     global CXX_FOR_TARGET
     global ld
     global LDFLAGS
     global srcdir
     global subdir

     # Check to see if C++ compiler work
     if { [which $CXX_FOR_TARGET] == 0 } {
         return 0
     }

     # 1. First step: Create a relocatable object (pr33401.o) from sources.
     #    Some R_*_NONE are expected for this input.
     set step1_status [run_sframe_reloc_test \
                         "PR ld/33401 (Step 1: Create relocatable object 
and check R_*_NONE)" \
                         { "StateClient.cpp" "StatePlaying.cpp" } \
                         "-r" \
                         "pr33401.o" \
                         "readelf" \
                         "-r -W" \
                         "pr33401.rd"]

     if { $step1_status == 0 } {
         return

     # 2. Final step: Run ld -r again on the output of step 1.
     #    The assertion failure in PR 33401 occurred when processing 
input BFDs
     #    containing R_*_NONE relocations in the .sframe section.
     set testname "PR ld/33401 (Step 2: Final link)"
     set final_out "pr33401-final.o"

     # Attempt to link the object created in step 1
     send_log "$ld -r -o tmpdir/$final_out tmpdir/pr33401.o\n"
     if { ![ld_link $ld tmpdir/$final_out "-L$srcdir/$subdir -r 
tmpdir/pr33401.o"] } {
         fail $testname
     } else {
         pass $testname
     }
}


check_pr33401


>   if [skip_sframe_tests] {
>       unsupported "no SFrame format support in the assembler, or SFrame disabled"
>       return 0
> @@ -40,6 +157,8 @@ foreach sframe_test $sframe_test_list {
>       run_dump_test [file rootname $sframe_test]
>   }
>   
> +check_pr33401 {StateClient.cpp  StatePlaying.cpp}
> +
>   if {[info exists old_lc_all]} {
>       set env(LC_ALL) $old_lc_all
>   } else {



More information about the Binutils mailing list