forked from Imagelibrary/binutils-gdb
Pass $plug_opt to nm when setting dump_prog to nm to load plugin. PR binutils/21479 * testsuite/ld-plugin/lto-binutils.exp (run_lto_binutils_test): Pass $plug_opt to nm. Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
533 lines
11 KiB
Plaintext
533 lines
11 KiB
Plaintext
# 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}} \
|
|
] \
|
|
]
|
|
|
|
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" \
|
|
] \
|
|
]
|
|
|
|
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"
|