binutils-gdb/gdb/testsuite/gdb.base/all-architectures.exp.in

342 lines
10 KiB
Plaintext
Raw Normal View History

# Copyright (C) 2016-2017 Free Software Foundation, Inc.
Add test that exercises all bfd architecture, osabi, endian, etc. combinations This adds a test that exposes several problems fixed by earlier patches: #1 - Buffer overrun when host/target formats match, but sizes don't. https://sourceware.org/ml/gdb-patches/2016-03/msg00125.html #2 - Missing handling for FR-V FR300. https://sourceware.org/ml/gdb-patches/2016-03/msg00117.html #3 - BFD architectures with spaces in their names (v850). https://sourceware.org/ml/binutils/2016-03/msg00108.html #4 - The OS ABI names with spaces issue. https://sourceware.org/ml/gdb-patches/2016-03/msg00116.html #5 - Bogus HP/PA long double format. https://sourceware.org/ml/gdb-patches/2016-03/msg00122.html #6 - Cris big endian internal error. https://sourceware.org/ml/gdb-patches/2016-03/msg00126.html #7 - Several PowerPC bfd archs/machines not handled by gdb. https://sourceware.org/bugzilla/show_bug.cgi?id=19797 And hopefully helps catch others in the future. This started out as a test that simply did, gdb -ex "print 1.0L" to exercise #1 above. Then to cover both 32-bit target / 64-bit host and the converse, I thought of having the testcase print the floats twice, once with the architecture set to "i386" and then to "i386:x86-64". This way it wouldn't matter whether gdb was built as 32-bit or a 64-bit program. Then I thought that other archs might have similar host/target floatformat conversion issues as well. Instead of hardcoding some architectures in the test file, I thought we could just iterate over all bfd architectures and OS ABIs supported by the gdb build being tested. This is what then exposed all the other problems listed above... With an --enable-targets=all, this exercises over 14 thousand combinations. If left in a single test file, it all consistenly runs in under a minute on my machine (An Intel i7-4810MQ @ 2.8 MHZ running Fedora 23). Split in 8 chunks, as in this commit, it runs in around 25 seconds, with make -j8. To avoid flooding the gdb.sum file, it avoids calling "pass" on each tested combination/iteration. I'm explicitly not implementing that by passing an empty message to gdb_test / gdb_test_multiple, because I still want a FAIL to be logged in gdb.sum. So instead this puts the internal passes in the gdb.log file, only, prefixed "IPASS:", for internal pass. TBC, if some iteration fails, it'll still show up as FAIL in gdb.sum. If this is an approach that takes on, I can see us extending the common bits to support it for all testcases. gdb/testsuite/ChangeLog: 2016-12-09 Pedro Alves <palves@redhat.com> * gdb.base/all-architectures-0.exp: New file. * gdb.base/all-architectures-1.exp: New file. * gdb.base/all-architectures-2.exp: New file. * gdb.base/all-architectures-3.exp: New file. * gdb.base/all-architectures-4.exp: New file. * gdb.base/all-architectures-5.exp: New file. * gdb.base/all-architectures-6.exp: New file. * gdb.base/all-architectures-7.exp: New file. * gdb.base/all-architectures.exp.in: New file.
2016-12-09 15:59:09 +01:00
# 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, see <http://www.gnu.org/licenses/>.
# This file is part of the gdb testsuite.
# Test manually setting _all_ combinations of all supported bfd
# architectures and OS ABIs. This ensures that gdbarch initialization
# routines handle unusual combinations gracefully, at least without
# crashing.
# While at it, because the number of possible combinations is quite
# large, embed other checks that might be useful to do with all
# supported archs.
# One such test is ensuring that printing float, double and long
# double types works in cross/bi-arch scenarios. Some of GDB's float
# format conversion routines used to fail to consider that even if
# host and target floating formats match, their sizes may still
# differ. E.g., on x86, long double is 80-bit extended precision on
# both 32-bit vs 64-bit, but it's stored as 96 bit on 32-bit, and 128
# bit on 64-bit. This resulted in GDB accessing memory out of bounds.
# This test catches the issue when run against gdb linked with
# libmcheck, or run under Valgrind.
# Note: this test is actually split in several driver .exp files, in
# order to be able to parallelize the work. Each driver .exp file
# exercises a different slice of the supported architectures. See
# all-architectures-*.exp and the TEST_SLICE variable.
clean_restart
# By default, preparation steps don't output a PASS message. This is
# because the testcase has several thousand such steps.
set want_tests_messages 0
# Call this when an "internal" preparation-like step test passed.
# Logs the pass in gdb.log, but not in gdb.sum.
proc internal_pass {message} {
global want_tests_messages
if {$want_tests_messages} {
pass $message
} else {
# Skip the sum file, but still log an internal pass in the log
# file.
global pf_prefix
verbose -log "IPASS: $pf_prefix $message"
}
}
# The number of times gdb_test_internal was called, and the number of
# time that resulted in an internal pass. If these don't match, then
# some test failed.
set test_count 0
set internal_pass_count 0
# Like gdb_test, but calls internal_pass instead of pass, on success.
proc gdb_test_internal {cmd pattern {message ""}} {
global test_count internal_pass_count
global gdb_prompt
incr test_count
if {$message == ""} {
set message $cmd
}
gdb_test_multiple $cmd $message {
-re "$pattern\r\n$gdb_prompt $" {
internal_pass $message
incr internal_pass_count
}
}
}
gdb_test_internal "set max-completions unlimited" \
"^set max-completions unlimited"
# Return a list of all the accepted values of "set WHAT".
proc get_set_option_choices {what} {
global gdb_prompt
set values {}
set test "complete set $what"
gdb_test_multiple "complete set $what " "$test" {
-re "set $what (\[^\r\n\]+)\r\n" {
lappend values $expect_out(1,string)
exp_continue
}
-re "$gdb_prompt " {
internal_pass $test
}
}
return $values
}
set supported_archs [get_set_option_choices "architecture"]
# There should be at least one more than "auto".
gdb_assert {[llength $supported_archs] > 1} "at least one architecture"
set supported_osabis [get_set_option_choices "osabi"]
# There should be at least one more than "auto" and "default".
gdb_assert {[llength $supported_osabis] > 2} "at least one osabi"
if {[lsearch $supported_archs "mips"] >= 0} {
set supported_mipsfpu [get_set_option_choices "mipsfpu"]
set supported_mips_abi [get_set_option_choices "mips abi"]
gdb_assert {[llength $supported_mipsfpu] != 0} "at least one mipsfpu"
gdb_assert {[llength $supported_mips_abi] != 0} "at least one mips abi"
}
if {[lsearch $supported_archs "arm"] >= 0} {
set supported_arm_fpu [get_set_option_choices "arm fpu"]
set supported_arm_abi [get_set_option_choices "arm abi"]
gdb_assert {[llength $supported_arm_fpu] != 0} "at least one arm fpu"
gdb_assert {[llength $supported_arm_abi] != 0} "at least one arm abi"
}
# Exercise printing float, double and long double.
proc print_floats {} {
gdb_test_internal "ptype 1.0L" "type = long double" "ptype, long double"
gdb_test_internal "print 1.0L" " = 1" "print, long double"
gdb_test_internal "ptype 1.0" "type = double" "ptype, double"
gdb_test_internal "print 1.0" " = 1" "print, double"
gdb_test_internal "ptype 1.0f" "type = float" "ptype, float"
gdb_test_internal "print 1.0f" " = 1" "print, float"
}
# Run tests on the current architecture.
proc do_arch_tests {} {
print_floats
Don't throw exception in dis_asm_memory_error Hi, GDB calls some APIs from opcodes to do disassembly and provide some call backs. This model makes troubles on C++ exception unwinding, because GDB is a C++ program, and opcodes is still compiled as C. As we can see, frame #10 and #12 are C++, while #frame 11 is C, #10 0x0000000000544228 in memory_error (err=TARGET_XFER_E_IO, memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:237 #11 0x00000000006b0a54 in print_insn_aarch64 (pc=0, info=0xffffffffeeb0) at ../../binutils-gdb/opcodes/aarch64-dis.c:3185 #12 0x0000000000553590 in gdb_pretty_print_insn (gdbarch=gdbarch@entry=0xbbceb0, uiout=uiout@entry=0xbc73d0, di=di@entry=0xffffffffeeb0, insn=0xffffffffed40, insn@entry=0xffffffffed90, flags=flags@entry=0, C++ exception unwinder can't go across frame #11 unless it has unwind table. However, C program on many architectures doesn't have it in default. As a result, GDB aborts, which is described in PR 20939. This is not the first time we see this kind of problem. We've had a commit 89525768cd086a0798a504c81fdf7ebcd4c904e1 "Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH". We can fix the disassembly bug in a similar way, this is the option one. Since opcodes is built with gdb, we fix this problem in a different way as we did for the same issue with readline. Instead of throwing exception in dis_asm_memory_error, we record the failed memory address, and throw exception when GDB returns from opcodes disassemblers. gdb: 2017-01-26 Yao Qi <yao.qi@linaro.org> Pedro Alves <palves@redhat.com> PR gdb/20939 * disasm.c (gdb_disassembler::dis_asm_memory_error): Don't call memory_error, save memaddr instead. (gdb_disassembler::print_insn): If gdbarch_print_insn returns negative, cal memory_error. * disasm.h (gdb_disassembler) <m_err_memaddr>: New field. gdb/testsuite: 2017-01-26 Yao Qi <yao.qi@linaro.org> * gdb.base/all-architectures.exp.in (do_arch_tests): Test disassemble on address 0.
2017-01-26 15:29:20 +01:00
# GDB can't access memory because there is no loaded executable
# nor live inferior.
gdb_test_internal "disassemble 0x0,+4" \
"Cannot access memory at address 0x0"
Add test that exercises all bfd architecture, osabi, endian, etc. combinations This adds a test that exposes several problems fixed by earlier patches: #1 - Buffer overrun when host/target formats match, but sizes don't. https://sourceware.org/ml/gdb-patches/2016-03/msg00125.html #2 - Missing handling for FR-V FR300. https://sourceware.org/ml/gdb-patches/2016-03/msg00117.html #3 - BFD architectures with spaces in their names (v850). https://sourceware.org/ml/binutils/2016-03/msg00108.html #4 - The OS ABI names with spaces issue. https://sourceware.org/ml/gdb-patches/2016-03/msg00116.html #5 - Bogus HP/PA long double format. https://sourceware.org/ml/gdb-patches/2016-03/msg00122.html #6 - Cris big endian internal error. https://sourceware.org/ml/gdb-patches/2016-03/msg00126.html #7 - Several PowerPC bfd archs/machines not handled by gdb. https://sourceware.org/bugzilla/show_bug.cgi?id=19797 And hopefully helps catch others in the future. This started out as a test that simply did, gdb -ex "print 1.0L" to exercise #1 above. Then to cover both 32-bit target / 64-bit host and the converse, I thought of having the testcase print the floats twice, once with the architecture set to "i386" and then to "i386:x86-64". This way it wouldn't matter whether gdb was built as 32-bit or a 64-bit program. Then I thought that other archs might have similar host/target floatformat conversion issues as well. Instead of hardcoding some architectures in the test file, I thought we could just iterate over all bfd architectures and OS ABIs supported by the gdb build being tested. This is what then exposed all the other problems listed above... With an --enable-targets=all, this exercises over 14 thousand combinations. If left in a single test file, it all consistenly runs in under a minute on my machine (An Intel i7-4810MQ @ 2.8 MHZ running Fedora 23). Split in 8 chunks, as in this commit, it runs in around 25 seconds, with make -j8. To avoid flooding the gdb.sum file, it avoids calling "pass" on each tested combination/iteration. I'm explicitly not implementing that by passing an empty message to gdb_test / gdb_test_multiple, because I still want a FAIL to be logged in gdb.sum. So instead this puts the internal passes in the gdb.log file, only, prefixed "IPASS:", for internal pass. TBC, if some iteration fails, it'll still show up as FAIL in gdb.sum. If this is an approach that takes on, I can see us extending the common bits to support it for all testcases. gdb/testsuite/ChangeLog: 2016-12-09 Pedro Alves <palves@redhat.com> * gdb.base/all-architectures-0.exp: New file. * gdb.base/all-architectures-1.exp: New file. * gdb.base/all-architectures-2.exp: New file. * gdb.base/all-architectures-3.exp: New file. * gdb.base/all-architectures-4.exp: New file. * gdb.base/all-architectures-5.exp: New file. * gdb.base/all-architectures-6.exp: New file. * gdb.base/all-architectures-7.exp: New file. * gdb.base/all-architectures.exp.in: New file.
2016-12-09 15:59:09 +01:00
}
# Given we can't change arch, osabi, endianness, etc. atomically, we
# need to silently ignore the case of the current OS ABI (not the one
# we'll switch to) not having a handler for the arch.
set osabi_warning \
[multi_line \
"warning: A handler for the OS ABI .* is not built into this configuration" \
"of GDB. Attempting to continue with the default .* settings." \
"" \
"" \
]
set endian_warning "(Little|Big) endian target not supported by GDB\r\n"
# Like gdb_test_no_output, but use internal_pass instead of pass, and
# ignore "no handler for OS ABI" warnings.
proc gdb_test_no_output_osabi {cmd test} {
global osabi_warning
global gdb_prompt
gdb_test_multiple "$cmd" $test {
-re "^${cmd}\r\n(${osabi_warning})?$gdb_prompt $" {
internal_pass $test
}
}
}
# It'd be nicer/safer to restart GDB on each iteration, but, that
# increases the testcase's run time several times fold. At the time
# of writting, it'd jump from 20s to 4min on x86-64 GNU/Linux with
# --enable-targets=all.
set num_slices 8
set num_archs [llength $supported_archs]
set archs_per_slice [expr (($num_archs + $num_slices - 1) / $num_slices)]
with_test_prefix "tests" {
foreach_with_prefix osabi $supported_osabis {
gdb_test_no_output_osabi "set osabi $osabi" \
"set osabi"
set arch_count 0
foreach_with_prefix arch $supported_archs {
incr arch_count
# Skip architectures outside our slice.
if {$arch_count < [expr $test_slice * $archs_per_slice]} {
continue
}
if {$arch_count >= [expr ($test_slice + 1) * $archs_per_slice]} {
continue
}
if {$arch == "auto"} {
continue
}
set default_endian ""
foreach_with_prefix endian {"auto" "big" "little"} {
set test "set endian"
if {$endian == $default_endian} {
continue
} elseif {$endian == "auto"} {
gdb_test_multiple "set endian $endian" $test {
-re "^set endian $endian\r\n(${osabi_warning})?The target endianness is set automatically \\(currently .* endian\\)\r\n$gdb_prompt $" {
internal_pass $test
}
}
} else {
gdb_test_multiple "set endian $endian" $test {
-re "^set endian $endian\r\n${endian_warning}.*\r\n$gdb_prompt $" {
internal_pass $test
continue
}
-re "^set endian $endian\r\n(${osabi_warning})?The target is assumed to be $endian endian\r\n$gdb_prompt $" {
internal_pass $test
}
}
}
# Skip setting the same architecture again.
if {$endian == "auto"} {
set arch_re [string_to_regexp $arch]
set test "set architecture $arch"
gdb_test_multiple $test $test {
-re "^set architecture $arch_re\r\n(${osabi_warning})?The target architecture is assumed to be $arch_re\r\n$gdb_prompt $" {
internal_pass $test
}
-re "Architecture .* not recognized.*$gdb_prompt $" {
# GDB is missing support for a few
# machines that bfd supports.
if {$arch == "powerpc:EC603e"
|| $arch == "powerpc:e500mc"
|| $arch == "powerpc:e500mc64"
|| $arch == "powerpc:vle"
|| $arch == "powerpc:titan"
|| $arch == "powerpc:e5500"
|| $arch == "powerpc:e6500"} {
if {$want_tests_messages} {
kfail $test "gdb/19797"
}
} else {
fail "$test (arch not recognized)"
}
continue
}
}
# Record what is the default endianess. As an
# optimization, we'll skip testing the manual "set
# endian DEFAULT" case.
set test "show endian"
gdb_test_multiple "show endian" $test {
-re "currently little endian.*$gdb_prompt $" {
set default_endian "little"
internal_pass $test
}
-re "currently big endian.*$gdb_prompt $" {
set default_endian "big"
internal_pass $test
}
}
}
# Some architectures have extra settings that affect
# the ABI. Specify the extra testing axes in a
# declarative form.
#
# A list of {COMMAND, VAR, OPTIONS-LIST} elements.
set all_axes {}
if {$arch == "mips"} {
lappend all_axes [list "set mips abi" mips_abi $supported_mips_abi]
lappend all_axes [list "set mipsfpu" mipsfpu $supported_mipsfpu]
} elseif {$arch == "arm"} {
lappend all_axes [list "set arm abi" arm_abi $supported_arm_abi]
lappend all_axes [list "set arm fpu" arm_fpu $supported_arm_fpu]
}
# Run testing axis CUR_AXIS. This is a recursive
# procedure that tries all combinations of options of
# all the testing axes.
proc run_axis {all_axes cur_axis} {
if {$cur_axis == [llength $all_axes]} {
do_arch_tests
return
}
# Unpack the axis.
set axis [lindex $all_axes $cur_axis]
set cmd [lindex $axis 0]
set var [lindex $axis 1]
set options [lindex $axis 2]
foreach v $options {
with_test_prefix "$var=$v" {
gdb_test_no_output_osabi "$cmd $v" "$cmd"
run_axis $all_axes [expr $cur_axis + 1]
}
}
}
run_axis $all_axes 0
}
}
}
}
# A test that:
#
# - ensures there's a PASS if all internal tests actually passed
#
# - ensures there's at least one test that is interpreted as a
# regression (a matching PASS->FAIL) if some of the internal tests
# failed, instead of looking like it could be a new FAIL that could
# be ignored.
#
gdb_assert {$internal_pass_count == $test_count} "all passed"