diff options
Diffstat (limited to 'ld/testsuite/ld-plugin')
-rw-r--r-- | ld/testsuite/ld-plugin/lto-binutils.exp | 530 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/plugin.exp | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr25618a.h | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr25618b.h | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr33246.c | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1a-fat.c | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1a-fat.rd | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1a-s-all.nd | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1a.c | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1b-fat.c | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1b-fat.rd | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/strip-1b.c | 3 |
13 files changed, 575 insertions, 13 deletions
diff --git a/ld/testsuite/ld-plugin/lto-binutils.exp b/ld/testsuite/ld-plugin/lto-binutils.exp new file mode 100644 index 0000000..1e156e4 --- /dev/null +++ b/ld/testsuite/ld-plugin/lto-binutils.exp @@ -0,0 +1,530 @@ +# Expect script for binutils tests with LTO +# Copyright (C) 2025 Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. +# + +# Make sure that binutils can correctly handle LTO IR in ELF. + +if { !([istarget *-*-linux*] + || [istarget arm*-*-uclinuxfdpiceabi] + || [istarget *-*-gnu*]) || [istarget *ecoff] } then { + return +} + +# Check to see if the C and C++ compilers work +if { ![check_compiler_available] || [which $CXX_FOR_TARGET] == 0 } { + return +} + +# These tests require plugin and LTO. +if { ![check_plugin_api_available] + || ![check_lto_available] } { + return +} + +set lto_fat "" +set lto_no_fat "" +if { [check_lto_fat_available] } { + set lto_fat "-ffat-lto-objects" + set lto_no_fat "-fno-fat-lto-objects" + set no_lto "-fno-lto" +} + +# List contains test-items: +# 0:program name +# 1:program options +# 2:input file +# 3:output file +# 4:action list (optional) +# +proc run_lto_binutils_test { lto_tests } { + global srcdir + global subdir + global nm + global objcopy + global objdump + global READELF + global strip + global plug_opt + + foreach testitem $lto_tests { + set prog_name [lindex $testitem 0] + set prog_options [lindex $testitem 1] + set input tmpdir/[lindex $testitem 2] + set output tmpdir/[lindex $testitem 3] + set actions [lindex $testitem 4] + set objfiles {} + set is_unresolved 0 + set failed 0 + +# eval set prog \$$prog_name + switch -- $prog_name { + objcopy + { + set prog $objcopy + set prog_output "$output" + } + strip + { + set prog $strip + set prog_output "-o $output" + } + default + { + perror "Unrecognized action $action" + set is_unresolved 1 + break + } + } + + # Don't leave previous output around + if { $output ne "tmpdir/" } { + remote_file host delete $output + } + + append prog_options " $plug_opt" + + set cmd_options "$prog_options $prog_output $input" + set test_name "$prog_name $cmd_options" + + set cmd "$prog $cmd_options" + send_log "$cmd\n" + set got [remote_exec host "$cmd"] + if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + fail "$test_name" + continue + } + + if { $failed == 0 } { + foreach actionlist $actions { + set action [lindex $actionlist 0] + set progopts [lindex $actionlist 1] + + # There are actions where we run regexp_diff on the + # output, and there are other actions (presumably). + # Handling of the former look the same. + set dump_prog "" + switch -- $action { + objdump + { set dump_prog $objdump } + nm + { set dump_prog "$nm $plug_opt" } + readelf + { set dump_prog $READELF } + default + { + perror "Unrecognized action $action" + set is_unresolved 1 + break + } + } + + if { $dump_prog != "" } { + set dumpfile [lindex $actionlist 2] + set binary $dump_prog + + # 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 $output > tmpdir/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" + set failed 1 + break + } + + if { [regexp_diff "tmpdir/dump.out" "$srcdir/$subdir/$dumpfile"] } then { + verbose -log "output is [file_contents "tmpdir/dump.out"]" 2 + set failed 1 + break + } + } + } + } + + if { $failed } { + fail $test_name + } elseif { $is_unresolved } { + unresolved $test_name + } else { + pass $test_name + } + } +} + +run_cc_link_tests [list \ + [list \ + "Build strip-1a.o" \ + "" \ + "-O2 -flto $lto_no_fat" \ + { strip-1a.c } \ + ] \ + [list \ + "Build libstrip-1a.a" \ + "$plug_opt" \ + "-O2 -flto $lto_no_fat" \ + { strip-1a.c } \ + {} \ + "libstrip-1a.a" \ + ] \ + [list \ + "Build strip-1a-fat.o" \ + "" \ + "-O2 -flto $lto_fat" \ + { strip-1a-fat.c } \ + ] \ + [list \ + "Build libstrip-1a-fat.a" \ + "$plug_opt" \ + "-O2 -flto $lto_fat" \ + { strip-1a-fat.c } \ + {} \ + "libstrip-1a-fat.a" \ + ] \ +] + +run_lto_binutils_test [list \ + [list \ + "strip" \ + "--strip-unneeded" \ + "libstrip-1a.a" \ + "libstrip-1a-s.a" \ + ] \ + [list \ + "strip" \ + "--strip-unneeded" \ + "strip-1a.o" \ + "strip-1a-s.o" \ + ] \ + [list \ + "strip" \ + "--strip-unneeded -R .gnu.*lto_* -N __gnu_lto_v1" \ + "libstrip-1a-fat.a" \ + "libstrip-1a-fat-s.a" \ + {{readelf -SW strip-1a-fat.rd}} \ + ] \ + [list \ + "strip" \ + "--strip-unneeded -R .gnu.*lto_* -N __gnu_lto_v1" \ + "strip-1a-fat.o" \ + "strip-1a-fat-s.o" \ + {{readelf -SW strip-1a-fat.rd}} \ + ] \ + [list \ + "strip" \ + "--strip-unneeded -R .gnu.debuglto_*" \ + "libstrip-1a-fat.a" \ + "libstrip-1b-fat-s.a" \ + {{readelf -SW strip-1b-fat.rd}} \ + ] \ + [list \ + "strip" \ + "--strip-unneeded -R .gnu.debuglto_*" \ + "strip-1a-fat.o" \ + "strip-1b-fat-s.o" \ + {{readelf -SW strip-1b-fat.rd}} \ + ] \ +] + +run_lto_binutils_test [list \ + [list \ + "strip" \ + "-R .gnu.*lto_* -N __gnu_lto_v1" \ + "strip-1a.o" \ + "strip-1a-s-all.o" \ + {{nm -n strip-1a-s-all.nd}} \ + ] \ + [list \ + "strip" \ + "-R .gnu.*lto_* -N __gnu_lto_v1" \ + "libstrip-1a.a" \ + "libstrip-1a-s-all.a" \ + {{nm -n strip-1a-s-all.nd}} \ + ] \ +] + +run_cc_link_tests [list \ + [list \ + "Build strip-1a (strip-1a.o)" \ + "" \ + "-O2 -flto $lto_no_fat" \ + { strip-1b.c } \ + {} \ + "libstrip-1a" \ + "C" \ + "tmpdir/strip-1a.o" \ + ] \ + [list \ + "Build strip-1b (strip-1a-s.o)" \ + "" \ + "-O2 -flto $lto_no_fat" \ + { strip-1b.c } \ + {} \ + "libstrip-1b" \ + "C" \ + "tmpdir/strip-1a-s.o" \ + ] \ + [list \ + "Build strip-1c (libstrip-1a.a)" \ + "" \ + "-O2 -flto $lto_no_fat" \ + { strip-1b.c } \ + {} \ + "libstrip-1c" \ + "C" \ + "tmpdir/libstrip-1a.a" \ + ] \ + [list \ + "Build strip-1d (libstrip-1a-s.a)" \ + "" \ + "-O2 -flto $lto_no_fat" \ + { strip-1b.c } \ + {} \ + "libstrip-1d" \ + "C" \ + "tmpdir/libstrip-1a-s.a" \ + ] \ + [list \ + "Build strip-1e (strip-1a-fat-s.o)" \ + "" \ + "-O2 -flto $lto_fat" \ + { strip-1b-fat.c } \ + {} \ + "libstrip-1e" \ + "C" \ + "tmpdir/strip-1a-fat-s.o" \ + ] \ + [list \ + "Build strip-1f (libstrip-1a-fat-s.a)" \ + "" \ + "-O2 -flto $lto_fat" \ + { strip-1b-fat.c } \ + {} \ + "libstrip-1f" \ + "C" \ + "tmpdir/libstrip-1a-fat-s.a" \ + ] \ + [list \ + "Build strip-1g (strip-1b-fat-s.o)" \ + "" \ + "-O2 -flto $lto_fat" \ + { strip-1b-fat.c } \ + {} \ + "libstrip-1g" \ + "C" \ + "tmpdir/strip-1b-fat-s.o" \ + ] \ + [list \ + "Build strip-1h (libstrip-1b-fat-s.a)" \ + "" \ + "-O2 -flto $lto_fat" \ + { strip-1b-fat.c } \ + {} \ + "libstrip-1h" \ + "C" \ + "tmpdir/libstrip-1b-fat-s.a" \ + ] \ +] + +proc run_pr33246_test { llvm fat } { + global srcdir + global subdir + global plug_opt + global llvm_plug_opt + global ar + global CLANG_FOR_TARGET + global CC_FOR_TARGET + global NM + global READELF + global strip + + set strip_flags "--strip-debug --enable-deterministic-archives" + + set test pr33246 + set testname "${test}${llvm}${fat} with $strip_flags" + + if { "$llvm" == "-llvm" } { + # Skip native x32 and i?86 targets since system LLVMgold.so may + # not be compatible with native x32 and i?86 targets binutils. + if { [istarget "x86_64-*-linux*-gnux32"] + || [istarget "i?86-*-*"] + || ![info exists CLANG_FOR_TARGET] + || [string match "" $llvm_plug_opt] } then { + untested $testname + return + } + set CC $CLANG_FOR_TARGET + set binutils_plug_opt "$llvm_plug_opt" + } else { + if { ![info exists CC_FOR_TARGET] + || [string match "" $plug_opt] } then { + untested $testname + return + } + set CC $CC_FOR_TARGET + set binutils_plug_opt "$plug_opt" + } + + append strip_flags " $binutils_plug_opt" + + set src $srcdir/$subdir/${test}.c + set obj tmpdir/${test}${llvm}${fat}.o + set archive tmpdir/${test}${llvm}${fat}.a + set CFLAGS "-c -g -O2 -flto" + if { "$fat" == "-fat" } { + append CFLAGS " -ffat-lto-objects" + } else { + append CFLAGS " -fno-fat-lto-objects" + } + + set cmd "$CC $CFLAGS -o $obj $src" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname ($obj)" + return + } + + set cmd "$strip $strip_flags $obj -o ${obj}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $obj)" + return + } + + set cmd "$NM $binutils_plug_opt ${obj}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![regexp "0+ T foo" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $obj)" + return + } + + if { "$fat" == "-fat" } { + set cmd "$READELF -SW ${obj}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if [regexp " \.debug_" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $obj)" + return + } + } else { + set cmd "cmp $obj ${obj}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $obj)" + return + } + } + + pass "$testname (strip $obj)" + + set cmd "$ar $binutils_plug_opt -D -s -r -c $archive $obj" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname ($archive)" + return + } + + set cmd "$strip $strip_flags $archive -o ${archive}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $archive)" + return + } + + set cmd "$NM $binutils_plug_opt ${archive}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![regexp "0+ T foo" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $archive)" + return + } + + if { "$fat" == "-fat" } { + set cmd "$READELF -SW ${archive}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if [regexp " \.debug_" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $archive)" + return + } + } else { + set cmd "cmp $archive ${archive}.strip" + send_log "$cmd\n" + verbose "$cmd" 1 + catch "exec $cmd" got + if ![string match "" $got] then { + send_log "$got\n" + verbose "$got" 1 + fail "$testname (strip $archive)" + return + } + } + + pass "$testname (strip $archive)" +} + +run_pr33246_test "" "" +run_pr33246_test "" "-fat" +run_pr33246_test "-llvm" "" +run_pr33246_test "-llvm" "-fat" diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index 3a56fb5..9ac3cf6 100644 --- a/ld/testsuite/ld-plugin/lto.exp +++ b/ld/testsuite/ld-plugin/lto.exp @@ -51,6 +51,11 @@ if { [check_lto_fat_available] } { set no_lto "-fno-lto" } +set as_gsframe "" +if { [gas_sframe_check] } { + set as_gsframe "-Wa,--gsframe" +} + # Simple LTO tests and generate input files for complex LTO tests. set lto_link_tests [list \ [list "LTO 1" \ @@ -76,10 +81,10 @@ set lto_link_tests [list \ "" "-flto $lto_fat" \ {lto-4a.c} {} ""] \ [list "Compile 4b" \ - "" "-O2" \ + "" "-O2 $as_gsframe" \ {lto-4b.c} {} ""] \ [list "Compile 4c" \ - "" "-O2" \ + "" "-O2 $as_gsframe" \ {lto-4c.c} {} ""] \ [list "Compile 5a" \ "" "-flto $lto_fat" \ @@ -1004,7 +1009,7 @@ run_cc_link_tests [list \ set board_flags [get_board_flags] set exec_output [run_host_cmd "sh" \ - "-c \"ulimit -n 20; \ + "-c \"ulimit -n 25; \ $CC_FOR_TARGET $gcc_B_opt $CFLAGS_FOR_TARGET \ $board_flags $ld_L_opt -o tmpdir/pr28138 \ tmpdir/pr28138.o tmpdir/pr28138.a\""] @@ -1158,9 +1163,8 @@ remote_exec host "mv" "tmpdir/dump tmpdir/lto-5.o" run_dump_test "lto-10r" remote_exec host "mv" "tmpdir/dump tmpdir/lto-10.o" set testname "nm mixed object" -set lto_plugin [string trim [run_host_cmd "$CC_FOR_TARGET" "-print-prog-name=liblto_plugin.so"]] -if { [ regexp "liblto_plugin.so" $lto_plugin ] } { - set exec_output [run_host_cmd "$NM" "--plugin $lto_plugin tmpdir/lto-10.o"] +if { $plug_opt != "" } { + set exec_output [run_host_cmd "$NM" "$plug_opt tmpdir/lto-10.o"] if { [ regexp "(D|T) main" $exec_output ] } { pass $testname } else { diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp index 38a4036..2e148e4 100644 --- a/ld/testsuite/ld-plugin/plugin.exp +++ b/ld/testsuite/ld-plugin/plugin.exp @@ -87,11 +87,11 @@ set regcln "-plugin-opt registercleanup" set failed_compile 0 set _ "" set plugin_nm_output "" -set old_CFLAGS "$CFLAGS_FOR_TARGET" -append CFLAGS_FOR_TARGET " $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" +set old_CFLAGS "$CFLAGS_FOR_TARGET_TEST" +append CFLAGS_FOR_TARGET_TEST " $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" if { [istarget m681*-*-*] || [istarget m68hc1*-*-*] || [istarget m9s12x*-*-*] } { # otherwise get FAILS due to _.frame - append CFLAGS_FOR_TARGET " -fomit-frame-pointer" + append CFLAGS_FOR_TARGET_TEST " -fomit-frame-pointer" } if { $can_compile && \ @@ -291,7 +291,7 @@ if { !$can_compile || $failed_compile } { unsupported [lindex $testitem 0] } } - set CFLAGS_FOR_TARGET "$old_CFLAGS" + set CFLAGS_FOR_TARGET_TEST "$old_CFLAGS" return } @@ -394,4 +394,4 @@ if [ar_simple_create $ar "--plugin $plugin4_path" "tmpdir/libpr20070.a" \ unsupported "PR ld/20070" } -set CFLAGS_FOR_TARGET "$old_CFLAGS" +set CFLAGS_FOR_TARGET_TEST "$old_CFLAGS" diff --git a/ld/testsuite/ld-plugin/pr25618a.h b/ld/testsuite/ld-plugin/pr25618a.h index 9bf857c..04be194 100644 --- a/ld/testsuite/ld-plugin/pr25618a.h +++ b/ld/testsuite/ld-plugin/pr25618a.h @@ -1,2 +1 @@ -#pragma once __attribute__((visibility("default"))) int bar(); diff --git a/ld/testsuite/ld-plugin/pr25618b.h b/ld/testsuite/ld-plugin/pr25618b.h index cd80074..65e72a0 100644 --- a/ld/testsuite/ld-plugin/pr25618b.h +++ b/ld/testsuite/ld-plugin/pr25618b.h @@ -1,2 +1 @@ -#pragma once __attribute__((visibility("default"))) int foo(); diff --git a/ld/testsuite/ld-plugin/pr33246.c b/ld/testsuite/ld-plugin/pr33246.c new file mode 100644 index 0000000..cd0130c --- /dev/null +++ b/ld/testsuite/ld-plugin/pr33246.c @@ -0,0 +1,4 @@ +void +foo (void) +{ +} diff --git a/ld/testsuite/ld-plugin/strip-1a-fat.c b/ld/testsuite/ld-plugin/strip-1a-fat.c new file mode 100644 index 0000000..03b2a5c --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1a-fat.c @@ -0,0 +1 @@ +#include "strip-1a.c" diff --git a/ld/testsuite/ld-plugin/strip-1a-fat.rd b/ld/testsuite/ld-plugin/strip-1a-fat.rd new file mode 100644 index 0000000..aefe1c5 --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1a-fat.rd @@ -0,0 +1,6 @@ +#failif +#... +Section Headers: +#... + \[[ 0-9]+\] \.gnu.lto_.* +#... diff --git a/ld/testsuite/ld-plugin/strip-1a-s-all.nd b/ld/testsuite/ld-plugin/strip-1a-s-all.nd new file mode 100644 index 0000000..52265c2 --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1a-s-all.nd @@ -0,0 +1,6 @@ +#... + + U foo2 + + U foo3 +0+ T foo1 +0+ T main +#pass diff --git a/ld/testsuite/ld-plugin/strip-1a.c b/ld/testsuite/ld-plugin/strip-1a.c new file mode 100644 index 0000000..d84af20 --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1a.c @@ -0,0 +1,4 @@ +extern void foo2(void); +extern void foo3(void); +void foo1(void) { foo3(); } +int main(void) { foo2(); } diff --git a/ld/testsuite/ld-plugin/strip-1b-fat.c b/ld/testsuite/ld-plugin/strip-1b-fat.c new file mode 100644 index 0000000..1a2e4d2 --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1b-fat.c @@ -0,0 +1 @@ +#include "strip-1b.c" diff --git a/ld/testsuite/ld-plugin/strip-1b-fat.rd b/ld/testsuite/ld-plugin/strip-1b-fat.rd new file mode 100644 index 0000000..e3a266f --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1b-fat.rd @@ -0,0 +1,5 @@ +#... +Section Headers: +#... + \[[ 0-9]+\] \.gnu.lto_.* +#pass diff --git a/ld/testsuite/ld-plugin/strip-1b.c b/ld/testsuite/ld-plugin/strip-1b.c new file mode 100644 index 0000000..967872a --- /dev/null +++ b/ld/testsuite/ld-plugin/strip-1b.c @@ -0,0 +1,3 @@ +extern void foo1(void); +void foo2(void) { foo1(); } +void foo3(void) {} |