blob: 5b4e0a10991810b3fdec770b0015c6f3203c4acc [file] [log] [blame]
# 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 *-*-nacl*]
|| [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 }
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}} \
] \
]
if { [check_lto_fat_available] } {
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" \
] \
]