| Index: gdb/testsuite/lib/gdb.exp
|
| diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
| index b06e723fc6df86899a1c824e28179bbb10f0223e..df2d81839e2ef092f272c03b13ea8efc220c8de8 100644
|
| --- a/gdb/testsuite/lib/gdb.exp
|
| +++ b/gdb/testsuite/lib/gdb.exp
|
| @@ -52,10 +52,13 @@ if ![info exists GDBFLAGS] {
|
| }
|
| verbose "using GDBFLAGS = $GDBFLAGS" 2
|
|
|
| +# Make the build data directory available to tests.
|
| +set BUILD_DATA_DIRECTORY "[pwd]/../data-directory"
|
| +
|
| # INTERNAL_GDBFLAGS contains flags that the testsuite requires.
|
| global INTERNAL_GDBFLAGS
|
| if ![info exists INTERNAL_GDBFLAGS] {
|
| - set INTERNAL_GDBFLAGS "-nw -nx -data-directory [pwd]/../data-directory"
|
| + set INTERNAL_GDBFLAGS "-nw -nx -data-directory $BUILD_DATA_DIRECTORY"
|
| }
|
|
|
| # The variable gdb_prompt is a regexp which matches the gdb prompt.
|
| @@ -266,13 +269,6 @@ proc gdb_run_cmd {args} {
|
| }
|
| }
|
| }
|
| - if [target_info exists gdb_stub] {
|
| - gdb_expect 60 {
|
| - -re "$gdb_prompt $" {
|
| - send_gdb "continue\n"
|
| - }
|
| - }
|
| - }
|
| return
|
| }
|
|
|
| @@ -312,7 +308,7 @@ proc gdb_start_cmd {args} {
|
| -re "$gdb_prompt $" { }
|
| default {
|
| perror "gdb_init_command for target failed";
|
| - return;
|
| + return -1;
|
| }
|
| }
|
| }
|
| @@ -338,29 +334,44 @@ proc gdb_start_cmd {args} {
|
|
|
| # Set a breakpoint at FUNCTION. If there is an additional argument it is
|
| # a list of options; the supported options are allow-pending, temporary,
|
| -# and no-message.
|
| +# message, no-message, and passfail.
|
| +# The result is 1 for success, 0 for failure.
|
| +#
|
| +# Note: The handling of message vs no-message is messed up, but it's based
|
| +# on historical usage. By default this function does not print passes,
|
| +# only fails.
|
| +# no-message: turns off printing of fails (and passes, but they're already off)
|
| +# message: turns on printing of passes (and fails, but they're already on)
|
|
|
| proc gdb_breakpoint { function args } {
|
| global gdb_prompt
|
| global decimal
|
|
|
| set pending_response n
|
| - if {[lsearch -exact [lindex $args 0] allow-pending] != -1} {
|
| + if {[lsearch -exact $args allow-pending] != -1} {
|
| set pending_response y
|
| }
|
|
|
| set break_command "break"
|
| set break_message "Breakpoint"
|
| - if {[lsearch -exact [lindex $args 0] temporary] != -1} {
|
| + if {[lsearch -exact $args temporary] != -1} {
|
| set break_command "tbreak"
|
| set break_message "Temporary breakpoint"
|
| }
|
|
|
| - set no_message 0
|
| - if {[lsearch -exact [lindex $args 0] no-message] != -1} {
|
| - set no_message 1
|
| + set print_pass 0
|
| + set print_fail 1
|
| + set no_message_loc [lsearch -exact $args no-message]
|
| + set message_loc [lsearch -exact $args message]
|
| + # The last one to appear in args wins.
|
| + if { $no_message_loc > $message_loc } {
|
| + set print_fail 0
|
| + } elseif { $message_loc > $no_message_loc } {
|
| + set print_pass 1
|
| }
|
|
|
| + set test_name "setting breakpoint at $function"
|
| +
|
| send_gdb "$break_command $function\n"
|
| # The first two regexps are what we get with -g, the third is without -g.
|
| gdb_expect 30 {
|
| @@ -369,8 +380,8 @@ proc gdb_breakpoint { function args } {
|
| -re "$break_message \[0-9\]* at .*$gdb_prompt $" {}
|
| -re "$break_message \[0-9\]* \\(.*\\) pending.*$gdb_prompt $" {
|
| if {$pending_response == "n"} {
|
| - if { $no_message == 0 } {
|
| - fail "setting breakpoint at $function"
|
| + if { $print_fail } {
|
| + fail $test_name
|
| }
|
| return 0
|
| }
|
| @@ -380,23 +391,34 @@ proc gdb_breakpoint { function args } {
|
| exp_continue
|
| }
|
| -re "A problem internal to GDB has been detected" {
|
| - fail "setting breakpoint at $function in runto (GDB internal error)"
|
| + if { $print_fail } {
|
| + fail "$test_name (GDB internal error)"
|
| + }
|
| gdb_internal_error_resync
|
| return 0
|
| }
|
| -re "$gdb_prompt $" {
|
| - if { $no_message == 0 } {
|
| - fail "setting breakpoint at $function"
|
| + if { $print_fail } {
|
| + fail $test_name
|
| + }
|
| + return 0
|
| + }
|
| + eof {
|
| + if { $print_fail } {
|
| + fail "$test_name (eof)"
|
| }
|
| return 0
|
| }
|
| timeout {
|
| - if { $no_message == 0 } {
|
| - fail "setting breakpoint at $function (timeout)"
|
| + if { $print_fail } {
|
| + fail "$test_name (timeout)"
|
| }
|
| return 0
|
| }
|
| }
|
| + if { $print_pass } {
|
| + pass $test_name
|
| + }
|
| return 1;
|
| }
|
|
|
| @@ -404,8 +426,15 @@ proc gdb_breakpoint { function args } {
|
| # Since this is the only breakpoint that will be set, if it stops
|
| # at a breakpoint, we will assume it is the one we want. We can't
|
| # just compare to "function" because it might be a fully qualified,
|
| -# single quoted C++ function specifier. If there's an additional argument,
|
| -# pass it to gdb_breakpoint.
|
| +# single quoted C++ function specifier.
|
| +#
|
| +# If there are additional arguments, pass them to gdb_breakpoint.
|
| +# We recognize no-message/message ourselves.
|
| +# The default is no-message.
|
| +# no-message is messed up here, like gdb_breakpoint: to preserve
|
| +# historical usage fails are always printed by default.
|
| +# no-message: turns off printing of fails (and passes, but they're already off)
|
| +# message: turns on printing of passes (and fails, but they're already on)
|
|
|
| proc runto { function args } {
|
| global gdb_prompt
|
| @@ -413,7 +442,28 @@ proc runto { function args } {
|
|
|
| delete_breakpoints
|
|
|
| - if ![gdb_breakpoint $function [lindex $args 0]] {
|
| + # Default to "no-message".
|
| + set args "no-message $args"
|
| +
|
| + set print_pass 0
|
| + set print_fail 1
|
| + set no_message_loc [lsearch -exact $args no-message]
|
| + set message_loc [lsearch -exact $args message]
|
| + # The last one to appear in args wins.
|
| + if { $no_message_loc > $message_loc } {
|
| + set print_fail 0
|
| + } elseif { $message_loc > $no_message_loc } {
|
| + set print_pass 1
|
| + }
|
| +
|
| + set test_name "running to $function in runto"
|
| +
|
| + # We need to use eval here to pass our varargs args to gdb_breakpoint
|
| + # which is also a varargs function.
|
| + # But we also have to be careful because $function may have multiple
|
| + # elements, and we don't want Tcl to move the remaining elements after
|
| + # the first to $args. That is why $function is wrapped in {}.
|
| + if ![eval gdb_breakpoint {$function} $args] {
|
| return 0;
|
| }
|
|
|
| @@ -423,30 +473,46 @@ proc runto { function args } {
|
| # the "in func" output we get without -g.
|
| gdb_expect 30 {
|
| -re "Break.* at .*:$decimal.*$gdb_prompt $" {
|
| + if { $print_pass } {
|
| + pass $test_name
|
| + }
|
| return 1
|
| }
|
| -re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in .*$gdb_prompt $" {
|
| + if { $print_pass } {
|
| + pass $test_name
|
| + }
|
| return 1
|
| }
|
| -re "The target does not support running in non-stop mode.\r\n$gdb_prompt $" {
|
| - unsupported "Non-stop mode not supported"
|
| + if { $print_fail } {
|
| + unsupported "Non-stop mode not supported"
|
| + }
|
| return 0
|
| }
|
| -re ".*A problem internal to GDB has been detected" {
|
| - fail "running to $function in runto (GDB internal error)"
|
| + if { $print_fail } {
|
| + fail "$test_name (GDB internal error)"
|
| + }
|
| gdb_internal_error_resync
|
| return 0
|
| }
|
| -re "$gdb_prompt $" {
|
| - fail "running to $function in runto"
|
| + if { $print_fail } {
|
| + fail $test_name
|
| + }
|
| return 0
|
| }
|
| eof {
|
| - fail "running to $function in runto (end of file)"
|
| + if { $print_fail } {
|
| + fail "$test_name (eof)"
|
| + }
|
| return 0
|
| }
|
| timeout {
|
| - fail "running to $function in runto (timeout)"
|
| + if { $print_fail } {
|
| + fail "$test_name (timeout)"
|
| + }
|
| return 0
|
| }
|
| }
|
| @@ -454,26 +520,12 @@ proc runto { function args } {
|
| }
|
|
|
| # Ask gdb to run until we hit a breakpoint at main.
|
| -# The case where the target uses stubs has to be handled
|
| -# specially--if it uses stubs, assuming we hit
|
| -# breakpoint() and just step out of the function.
|
| #
|
| # N.B. This function deletes all existing breakpoints.
|
| # If you don't want that, use gdb_start_cmd.
|
|
|
| proc runto_main { } {
|
| - global gdb_prompt
|
| - global decimal
|
| -
|
| - if ![target_info exists gdb_stub] {
|
| - return [runto main]
|
| - }
|
| -
|
| - delete_breakpoints
|
| -
|
| - gdb_step_for_stub;
|
| -
|
| - return 1
|
| + return [runto main no-message]
|
| }
|
|
|
| ### Continue, and expect to hit a breakpoint.
|
| @@ -487,7 +539,7 @@ proc gdb_continue_to_breakpoint {name {location_pattern .*}} {
|
|
|
| send_gdb "continue\n"
|
| gdb_expect {
|
| - -re "Breakpoint .* (at|in) $location_pattern\r\n$gdb_prompt $" {
|
| + -re "(?:Breakpoint|Temporary breakpoint) .* (at|in) $location_pattern\r\n$gdb_prompt $" {
|
| pass $full_name
|
| }
|
| -re ".*$gdb_prompt $" {
|
| @@ -526,6 +578,8 @@ proc gdb_continue_to_breakpoint {name {location_pattern .*}} {
|
| proc gdb_internal_error_resync {} {
|
| global gdb_prompt
|
|
|
| + verbose -log "Resyncing due to internal error."
|
| +
|
| set count 0
|
| while {$count < 10} {
|
| gdb_expect {
|
| @@ -605,7 +659,7 @@ proc gdb_test_multiple { command message user_code } {
|
| }
|
|
|
| if {$use_gdb_stub
|
| - && [regexp -nocase {^\s*(r|run|star|start|at|att|atta|attac|attach)\M} \
|
| + && [regexp -nocase {^\s*(r|run|star|start|at|att|atta|attac|attach)\M} \
|
| $command]} {
|
| error "gdbserver does not support $command without extended-remote"
|
| }
|
| @@ -745,21 +799,21 @@ proc gdb_test_multiple { command message user_code } {
|
| }
|
|
|
| set code {
|
| - -re ".*A problem internal to GDB has been detected" {
|
| - fail "$message (GDB internal error)"
|
| - gdb_internal_error_resync
|
| - }
|
| - -re "\\*\\*\\* DOSEXIT code.*" {
|
| - if { $message != "" } {
|
| - fail "$message";
|
| - }
|
| - gdb_suppress_entire_file "GDB died";
|
| - set result -1;
|
| - }
|
| + -re ".*A problem internal to GDB has been detected" {
|
| + fail "$message (GDB internal error)"
|
| + gdb_internal_error_resync
|
| + }
|
| + -re "\\*\\*\\* DOSEXIT code.*" {
|
| + if { $message != "" } {
|
| + fail "$message";
|
| + }
|
| + gdb_suppress_entire_file "GDB died";
|
| + set result -1;
|
| + }
|
| }
|
| append code $processed_code
|
| append code {
|
| - -re "Ending remote debugging.*$gdb_prompt $" {
|
| + -re "Ending remote debugging.*$gdb_prompt $" {
|
| if ![isnative] then {
|
| warning "Can`t communicate to remote target."
|
| }
|
| @@ -767,17 +821,17 @@ proc gdb_test_multiple { command message user_code } {
|
| gdb_start
|
| set result -1
|
| }
|
| - -re "Undefined\[a-z\]* command:.*$gdb_prompt $" {
|
| + -re "Undefined\[a-z\]* command:.*$gdb_prompt $" {
|
| perror "Undefined command \"$command\"."
|
| - fail "$message"
|
| + fail "$message"
|
| set result 1
|
| }
|
| - -re "Ambiguous command.*$gdb_prompt $" {
|
| + -re "Ambiguous command.*$gdb_prompt $" {
|
| perror "\"$command\" is not a unique command name."
|
| - fail "$message"
|
| + fail "$message"
|
| set result 1
|
| }
|
| - -re "$inferior_exited_re with code \[0-9\]+.*$gdb_prompt $" {
|
| + -re "$inferior_exited_re with code \[0-9\]+.*$gdb_prompt $" {
|
| if ![string match "" $message] then {
|
| set errmsg "$message (the program exited)"
|
| } else {
|
| @@ -786,7 +840,7 @@ proc gdb_test_multiple { command message user_code } {
|
| fail "$errmsg"
|
| set result -1
|
| }
|
| - -re "$inferior_exited_re normally.*$gdb_prompt $" {
|
| + -re "$inferior_exited_re normally.*$gdb_prompt $" {
|
| if ![string match "" $message] then {
|
| set errmsg "$message (the program exited)"
|
| } else {
|
| @@ -795,7 +849,7 @@ proc gdb_test_multiple { command message user_code } {
|
| fail "$errmsg"
|
| set result -1
|
| }
|
| - -re "The program is not being run.*$gdb_prompt $" {
|
| + -re "The program is not being run.*$gdb_prompt $" {
|
| if ![string match "" $message] then {
|
| set errmsg "$message (the program is no longer running)"
|
| } else {
|
| @@ -804,16 +858,16 @@ proc gdb_test_multiple { command message user_code } {
|
| fail "$errmsg"
|
| set result -1
|
| }
|
| - -re "\r\n$gdb_prompt $" {
|
| + -re "\r\n$gdb_prompt $" {
|
| if ![string match "" $message] then {
|
| fail "$message"
|
| }
|
| set result 1
|
| }
|
| - "<return>" {
|
| + "<return>" {
|
| send_gdb "\n"
|
| perror "Window too small."
|
| - fail "$message"
|
| + fail "$message"
|
| set result -1
|
| }
|
| -re "\\((y or n|y or \\\[n\\\]|\\\[y\\\] or n)\\) " {
|
| @@ -828,16 +882,16 @@ proc gdb_test_multiple { command message user_code } {
|
| fail "$message (got breakpoint menu)"
|
| set result -1
|
| }
|
| - eof {
|
| - perror "Process no longer exists"
|
| - if { $message != "" } {
|
| - fail "$message"
|
| - }
|
| - return -1
|
| + eof {
|
| + perror "Process no longer exists"
|
| + if { $message != "" } {
|
| + fail "$message"
|
| + }
|
| + return -1
|
| }
|
| - full_buffer {
|
| + full_buffer {
|
| perror "internal buffer is full."
|
| - fail "$message"
|
| + fail "$message"
|
| set result -1
|
| }
|
| timeout {
|
| @@ -1458,6 +1512,12 @@ proc skip_ada_tests {} {
|
| return 0
|
| }
|
|
|
| +# Return a 1 if I don't even want to try to test GO.
|
| +
|
| +proc skip_go_tests {} {
|
| + return 0
|
| +}
|
| +
|
| # Return a 1 if I don't even want to try to test java.
|
|
|
| proc skip_java_tests {} {
|
| @@ -1502,6 +1562,93 @@ proc skip_shlib_tests {} {
|
| return 1
|
| }
|
|
|
| +# Test files shall make sure all the test result lines in gdb.sum are
|
| +# unique in a test run, so that comparing the gdb.sum files of two
|
| +# test runs gives correct results. Test files that exercise
|
| +# variations of the same tests more than once, shall prefix the
|
| +# different test invocations with different identifying strings in
|
| +# order to make them unique.
|
| +#
|
| +# About test prefixes:
|
| +#
|
| +# $pf_prefix is the string that dejagnu prints after the result (FAIL,
|
| +# PASS, etc.), and before the test message/name in gdb.sum. E.g., the
|
| +# underlined substring in
|
| +#
|
| +# PASS: gdb.base/mytest.exp: some test
|
| +# ^^^^^^^^^^^^^^^^^^^^
|
| +#
|
| +# is $pf_prefix.
|
| +#
|
| +# The easiest way to adjust the test prefix is to append a test
|
| +# variation prefix to the $pf_prefix, using the with_test_prefix
|
| +# procedure. E.g.,
|
| +#
|
| +# proc do_tests {} {
|
| +# gdb_test ... ... "test foo"
|
| +# gdb_test ... ... "test bar"
|
| +#
|
| +# with_test_prefix "subvariation a" {
|
| +# gdb_test ... ... "test x"
|
| +# }
|
| +#
|
| +# with_test_prefix "subvariation b" {
|
| +# gdb_test ... ... "test x"
|
| +# }
|
| +# }
|
| +#
|
| +# with_test_prefix "variation1" {
|
| +# ...do setup for variation 1...
|
| +# do_tests
|
| +# }
|
| +#
|
| +# with_test_prefix "variation2" {
|
| +# ...do setup for variation 2...
|
| +# do_tests
|
| +# }
|
| +#
|
| +# Results in:
|
| +#
|
| +# PASS: gdb.base/mytest.exp: variation1: test foo
|
| +# PASS: gdb.base/mytest.exp: variation1: test bar
|
| +# PASS: gdb.base/mytest.exp: variation1: subvariation a: test x
|
| +# PASS: gdb.base/mytest.exp: variation1: subvariation b: test x
|
| +# PASS: gdb.base/mytest.exp: variation2: test foo
|
| +# PASS: gdb.base/mytest.exp: variation2: test bar
|
| +# PASS: gdb.base/mytest.exp: variation2: subvariation a: test x
|
| +# PASS: gdb.base/mytest.exp: variation2: subvariation b: test x
|
| +#
|
| +# If for some reason more flexibility is necessary, one can also
|
| +# manipulate the pf_prefix global directly, treating it as a string.
|
| +# E.g.,
|
| +#
|
| +# global pf_prefix
|
| +# set saved_pf_prefix
|
| +# append pf_prefix "${foo}: bar"
|
| +# ... actual tests ...
|
| +# set pf_prefix $saved_pf_prefix
|
| +#
|
| +
|
| +# Run BODY in the context of the caller, with the current test prefix
|
| +# (pf_prefix) appended with one space, then PREFIX, and then a colon.
|
| +# Returns the result of BODY.
|
| +#
|
| +proc with_test_prefix { prefix body } {
|
| + global pf_prefix
|
| +
|
| + set saved $pf_prefix
|
| + append pf_prefix " " $prefix ":"
|
| + set code [catch {uplevel 1 $body} result]
|
| + set pf_prefix $saved
|
| +
|
| + if {$code == 1} {
|
| + global errorInfo errorCode
|
| + return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
|
| + } else {
|
| + return -code $code $result
|
| + }
|
| +}
|
| +
|
| # Return 1 if _Complex types are supported, otherwise, return 0.
|
|
|
| proc support_complex_tests {} {
|
| @@ -1752,7 +1899,7 @@ proc skip_altivec_tests {} {
|
|
|
| # Make sure we have a compiler that understands altivec.
|
| set compile_flags {debug nowarnings}
|
| - if [get_compiler_info not-used] {
|
| + if [get_compiler_info] {
|
| warning "Could not get compiler info"
|
| return 1
|
| }
|
| @@ -1841,7 +1988,7 @@ proc skip_vsx_tests {} {
|
|
|
| # Make sure we have a compiler that understands altivec.
|
| set compile_flags {debug nowarnings quiet}
|
| - if [get_compiler_info not-used] {
|
| + if [get_compiler_info] {
|
| warning "Could not get compiler info"
|
| return 1
|
| }
|
| @@ -2025,10 +2172,7 @@ set hp_aCC_compiler 0
|
|
|
| # Figure out what compiler I am using.
|
| #
|
| -# BINFILE is a "compiler information" output file. This implementation
|
| -# does not use BINFILE.
|
| -#
|
| -# ARGS can be empty or "C++". If empty, "C" is assumed.
|
| +# ARG can be empty or "C++". If empty, "C" is assumed.
|
| #
|
| # There are several ways to do this, with various problems.
|
| #
|
| @@ -2077,7 +2221,7 @@ set hp_aCC_compiler 0
|
| #
|
| # -- chastain 2004-01-06
|
|
|
| -proc get_compiler_info {binfile args} {
|
| +proc get_compiler_info {{arg ""}} {
|
| # For compiler.c and compiler.cc
|
| global srcdir
|
|
|
| @@ -2095,7 +2239,7 @@ proc get_compiler_info {binfile args} {
|
|
|
| # Choose which file to preprocess.
|
| set ifile "${srcdir}/lib/compiler.c"
|
| - if { [llength $args] > 0 && [lindex $args 0] == "c++" } {
|
| + if { $arg == "c++" } {
|
| set ifile "${srcdir}/lib/compiler.cc"
|
| }
|
|
|
| @@ -2106,12 +2250,12 @@ proc get_compiler_info {binfile args} {
|
| # We have to use -E and -o together, despite the comments
|
| # above, because of how DejaGnu handles remote host testing.
|
| set ppout "$outdir/compiler.i"
|
| - gdb_compile "${ifile}" "$ppout" preprocess [list "$args" quiet]
|
| + gdb_compile "${ifile}" "$ppout" preprocess [list "$arg" quiet]
|
| set file [open $ppout r]
|
| set cppout [read $file]
|
| close $file
|
| } else {
|
| - set cppout [ gdb_compile "${ifile}" "" preprocess [list "$args" quiet] ]
|
| + set cppout [ gdb_compile "${ifile}" "" preprocess [list "$arg" quiet] ]
|
| }
|
| log_file -a "$outdir/$tool.log"
|
|
|
| @@ -2292,14 +2436,8 @@ proc gdb_compile {source dest type options} {
|
| }
|
| set options $new_options
|
|
|
| - if [target_info exists gdb_stub] {
|
| - set options2 { "additional_flags=-Dusestubs" }
|
| - lappend options "libs=[target_info gdb_stub]";
|
| - set options [concat $options2 $options]
|
| - }
|
| if [target_info exists is_vxworks] {
|
| set options2 { "additional_flags=-Dvxworks" }
|
| - lappend options "libs=[target_info gdb_stub]";
|
| set options [concat $options2 $options]
|
| }
|
| if [info exists GDB_TESTCASE_OPTIONS] {
|
| @@ -2958,12 +3096,15 @@ proc gdb_continue { function } {
|
| proc default_gdb_init { args } {
|
| global gdb_wrapper_initialized
|
| global gdb_wrapper_target
|
| + global gdb_test_file_name
|
| global cleanfiles
|
|
|
| set cleanfiles {}
|
|
|
| gdb_clear_suppressed;
|
|
|
| + set gdb_test_file_name [file rootname [file tail [lindex $args 0]]]
|
| +
|
| # Make sure that the wrapper is rebuilt
|
| # with the appropriate multilib option.
|
| if { $gdb_wrapper_target != [current_target_name] } {
|
| @@ -2997,6 +3138,84 @@ proc default_gdb_init { args } {
|
| }
|
| }
|
|
|
| +# Turn BASENAME into a full file name in the standard output
|
| +# directory. It is ok if BASENAME is the empty string; in this case
|
| +# the directory is returned.
|
| +
|
| +proc standard_output_file {basename} {
|
| + global objdir subdir
|
| +
|
| + return [file join $objdir $subdir $basename]
|
| +}
|
| +
|
| +# Set 'testfile', 'srcfile', and 'binfile'.
|
| +#
|
| +# ARGS is a list of source file specifications.
|
| +# Without any arguments, the .exp file's base name is used to
|
| +# compute the source file name. The ".c" extension is added in this case.
|
| +# If ARGS is not empty, each entry is a source file specification.
|
| +# If the specification starts with a ".", it is treated as a suffix
|
| +# to append to the .exp file's base name.
|
| +# If the specification is the empty string, it is treated as if it
|
| +# were ".c".
|
| +# Otherwise it is a file name.
|
| +# The first file in the list is used to set the 'srcfile' global.
|
| +# Each subsequent name is used to set 'srcfile2', 'srcfile3', etc.
|
| +#
|
| +# Most tests should call this without arguments.
|
| +#
|
| +# If a completely different binary file name is needed, then it
|
| +# should be handled in the .exp file with a suitable comment.
|
| +
|
| +proc standard_testfile {args} {
|
| + global gdb_test_file_name
|
| + global subdir
|
| + global gdb_test_file_last_vars
|
| +
|
| + # Outputs.
|
| + global testfile binfile
|
| +
|
| + set testfile $gdb_test_file_name
|
| + set binfile [standard_output_file ${testfile}]
|
| +
|
| + if {[llength $args] == 0} {
|
| + set args .c
|
| + }
|
| +
|
| + # Unset our previous output variables.
|
| + # This can help catch hidden bugs.
|
| + if {[info exists gdb_test_file_last_vars]} {
|
| + foreach varname $gdb_test_file_last_vars {
|
| + global $varname
|
| + catch {unset $varname}
|
| + }
|
| + }
|
| + # 'executable' is often set by tests.
|
| + set gdb_test_file_last_vars {executable}
|
| +
|
| + set suffix ""
|
| + foreach arg $args {
|
| + set varname srcfile$suffix
|
| + global $varname
|
| +
|
| + # Handle an extension.
|
| + if {$arg == ""} {
|
| + set arg $testfile.c
|
| + } elseif {[string range $arg 0 0] == "."} {
|
| + set arg $testfile$arg
|
| + }
|
| +
|
| + set $varname $arg
|
| + lappend gdb_test_file_last_vars $varname
|
| +
|
| + if {$suffix == ""} {
|
| + set suffix 2
|
| + } else {
|
| + incr suffix
|
| + }
|
| + }
|
| +}
|
| +
|
| # The default timeout used when testing GDB commands. We want to use
|
| # the same timeout as the default dejagnu timeout, unless the user has
|
| # already provided a specific value (probably through a site.exp file).
|
| @@ -3010,14 +3229,19 @@ if ![info exists gdb_test_timeout] {
|
| # an error when that happens.
|
| set banned_variables { bug_id prms_id }
|
|
|
| +# A list of procedures that GDB testcases should not use.
|
| +# We try to prevent their use by monitoring invocations and raising
|
| +# an error when that happens.
|
| +set banned_procedures { strace }
|
| +
|
| # gdb_init is called by runtest at start, but also by several
|
| # tests directly; gdb_finish is only called from within runtest after
|
| # each test source execution.
|
| # Placing several traces by repetitive calls to gdb_init leads
|
| # to problems, as only one trace is removed in gdb_finish.
|
| # To overcome this possible problem, we add a variable that records
|
| -# if the banned variables are traced.
|
| -set banned_variables_traced 0
|
| +# if the banned variables and procedures are already traced.
|
| +set banned_traced 0
|
|
|
| proc gdb_init { args } {
|
| # Reset the timeout value to the default. This way, any testcase
|
| @@ -3027,15 +3251,21 @@ proc gdb_init { args } {
|
| global timeout
|
| set timeout $gdb_test_timeout
|
|
|
| - # Block writes to all banned variables...
|
| + # Block writes to all banned variables, and invocation of all
|
| + # banned procedures...
|
| global banned_variables
|
| - global banned_variables_traced
|
| - if (!$banned_variables_traced) {
|
| + global banned_procedures
|
| + global banned_traced
|
| + if (!$banned_traced) {
|
| foreach banned_var $banned_variables {
|
| global "$banned_var"
|
| trace add variable "$banned_var" write error
|
| }
|
| - set banned_variables_traced 1
|
| + foreach banned_proc $banned_procedures {
|
| + global "$banned_proc"
|
| + trace add execution "$banned_proc" enter error
|
| + }
|
| + set banned_traced 1
|
| }
|
|
|
| # We set LC_ALL, LC_CTYPE, and LANG to C so that we get the same
|
| @@ -3084,13 +3314,18 @@ proc gdb_finish { } {
|
| # Unblock write access to the banned variables. Dejagnu typically
|
| # resets some of them between testcases.
|
| global banned_variables
|
| - global banned_variables_traced
|
| - if ($banned_variables_traced) {
|
| + global banned_procedures
|
| + global banned_traced
|
| + if ($banned_traced) {
|
| foreach banned_var $banned_variables {
|
| global "$banned_var"
|
| trace remove variable "$banned_var" write error
|
| }
|
| - set banned_variables_traced 0
|
| + foreach banned_proc $banned_procedures {
|
| + global "$banned_proc"
|
| + trace remove execution "$banned_proc" enter error
|
| + }
|
| + set banned_traced 0
|
| }
|
| }
|
|
|
| @@ -3164,95 +3399,10 @@ proc setup_kfail_for_target { PR target } {
|
| }
|
| }
|
|
|
| -# Test programs for embedded (often "bare board") systems sometimes use a
|
| -# "stub" either embedded in the test program itself or in the boot rom.
|
| -# The job of the stub is to implement the remote protocol to communicate
|
| -# with gdb and control the inferior. To initiate the remote protocol
|
| -# session with gdb the stub needs to be given control by the inferior.
|
| -# They do this by calling a function that typically triggers a trap
|
| -# from main that transfers control to the stub.
|
| -# The purpose of this function, gdb_step_for_stub, is to step out of
|
| -# that function ("breakpoint" in the example below) and back into main.
|
| -#
|
| -# Example:
|
| -#
|
| -# int
|
| -# main ()
|
| -# {
|
| -# #ifdef usestubs
|
| -# set_debug_traps (); /* install trap handlers for stub */
|
| -# breakpoint (); /* trigger a trap to give the stub control */
|
| -# #endif
|
| -# /* test program begins here */
|
| -# }
|
| -#
|
| -# Note that one consequence of this design is that a breakpoint on "main"
|
| -# does not Just Work (because if the target could stop there you still have
|
| -# to step past the calls to set_debug_traps,breakpoint).
|
| -
|
| -proc gdb_step_for_stub { } {
|
| - global gdb_prompt;
|
| -
|
| - if ![target_info exists gdb,use_breakpoint_for_stub] {
|
| - if [target_info exists gdb_stub_step_command] {
|
| - set command [target_info gdb_stub_step_command];
|
| - } else {
|
| - set command "step";
|
| - }
|
| - send_gdb "${command}\n";
|
| - set tries 0;
|
| - gdb_expect 60 {
|
| - -re "(main.* at |.*in .*start).*$gdb_prompt" {
|
| - return;
|
| - }
|
| - -re ".*$gdb_prompt" {
|
| - incr tries;
|
| - if { $tries == 5 } {
|
| - fail "stepping out of breakpoint function";
|
| - return;
|
| - }
|
| - send_gdb "${command}\n";
|
| - exp_continue;
|
| - }
|
| - default {
|
| - fail "stepping out of breakpoint function";
|
| - return;
|
| - }
|
| - }
|
| - }
|
| - send_gdb "where\n";
|
| - gdb_expect {
|
| - -re "main\[^\r\n\]*at \(\[^:]+\):\(\[0-9\]+\)" {
|
| - set file $expect_out(1,string);
|
| - set linenum [expr $expect_out(2,string) + 1];
|
| - set breakplace "${file}:${linenum}";
|
| - }
|
| - default {}
|
| - }
|
| - send_gdb "break ${breakplace}\n";
|
| - gdb_expect 60 {
|
| - -re "Breakpoint (\[0-9\]+) at.*$gdb_prompt" {
|
| - set breakpoint $expect_out(1,string);
|
| - }
|
| - -re "Breakpoint (\[0-9\]+): file.*$gdb_prompt" {
|
| - set breakpoint $expect_out(1,string);
|
| - }
|
| - default {}
|
| - }
|
| - send_gdb "continue\n";
|
| - gdb_expect 60 {
|
| - -re "Breakpoint ${breakpoint},.*$gdb_prompt" {
|
| - gdb_test "delete $breakpoint" ".*" "";
|
| - return;
|
| - }
|
| - default {}
|
| - }
|
| -}
|
| -
|
| # gdb_get_line_number TEXT [FILE]
|
| #
|
| # Search the source file FILE, and return the line number of the
|
| -# first line containing TEXT. If no match is found, return -1.
|
| +# first line containing TEXT. If no match is found, an error is thrown.
|
| #
|
| # TEXT is a string literal, not a regular expression.
|
| #
|
| @@ -3325,15 +3475,13 @@ proc gdb_get_line_number { text { file "" } } {
|
| }
|
|
|
| if { [ catch { set fd [open "$file"] } message ] } then {
|
| - perror "$message"
|
| - return -1
|
| + error "$message"
|
| }
|
|
|
| set found -1
|
| for { set line 1 } { 1 } { incr line } {
|
| if { [ catch { set nchar [gets "$fd" body] } message ] } then {
|
| - perror "$message"
|
| - return -1
|
| + error "$message"
|
| }
|
| if { $nchar < 0 } then {
|
| break
|
| @@ -3345,8 +3493,11 @@ proc gdb_get_line_number { text { file "" } } {
|
| }
|
|
|
| if { [ catch { close "$fd" } message ] } then {
|
| - perror "$message"
|
| - return -1
|
| + error "$message"
|
| + }
|
| +
|
| + if {$found == -1} {
|
| + error "undefined tag \"$text\""
|
| }
|
|
|
| return $found
|
| @@ -3655,29 +3806,31 @@ proc test_prefix_command_help { command_list expected_initial_lines args } {
|
| }
|
| }
|
|
|
| -# Build executable named EXECUTABLE, from SOURCES. If SOURCES are not
|
| -# provided, uses $EXECUTABLE.c. The TESTNAME paramer is the name of test
|
| -# to pass to untested, if something is wrong. OPTIONS are passed
|
| -# to gdb_compile directly.
|
| -proc build_executable { testname executable {sources ""} {options {debug}} } {
|
| -
|
| - global objdir
|
| +# Build executable named EXECUTABLE from specifications that allow
|
| +# different options to be passed to different sub-compilations.
|
| +# TESTNAME is the name of the test; this is passed to 'untested' if
|
| +# something fails.
|
| +# OPTIONS is passed to the final link, using gdb_compile.
|
| +# ARGS is a flat list of source specifications, of the form:
|
| +# { SOURCE1 OPTIONS1 [ SOURCE2 OPTIONS2 ]... }
|
| +# Each SOURCE is compiled to an object file using its OPTIONS,
|
| +# using gdb_compile.
|
| +# Returns 0 on success, -1 on failure.
|
| +proc build_executable_from_specs {testname executable options args} {
|
| global subdir
|
| global srcdir
|
| - if {[llength $sources]==0} {
|
| - set sources ${executable}.c
|
| - }
|
|
|
| - set binfile ${objdir}/${subdir}/${executable}
|
| + set binfile [standard_output_file $executable]
|
|
|
| set objects {}
|
| - for {set i 0} "\$i<[llength $sources]" {incr i} {
|
| - set s [lindex $sources $i]
|
| - if { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $options] != "" } {
|
| + set i 0
|
| + foreach {s local_options} $args {
|
| + if { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $local_options] != "" } {
|
| untested $testname
|
| return -1
|
| }
|
| lappend objects "${binfile}${i}.o"
|
| + incr i
|
| }
|
|
|
| if { [gdb_compile $objects "${binfile}" executable $options] != "" } {
|
| @@ -3689,28 +3842,59 @@ proc build_executable { testname executable {sources ""} {options {debug}} } {
|
| if { [lsearch -exact $options "c++"] >= 0 } {
|
| set info_options "c++"
|
| }
|
| - if [get_compiler_info ${binfile} ${info_options}] {
|
| + if [get_compiler_info ${info_options}] {
|
| return -1
|
| }
|
| return 0
|
| }
|
|
|
| +# Build executable named EXECUTABLE, from SOURCES. If SOURCES are not
|
| +# provided, uses $EXECUTABLE.c. The TESTNAME paramer is the name of test
|
| +# to pass to untested, if something is wrong. OPTIONS are passed
|
| +# to gdb_compile directly.
|
| +proc build_executable { testname executable {sources ""} {options {debug}} } {
|
| + if {[llength $sources]==0} {
|
| + set sources ${executable}.c
|
| + }
|
| +
|
| + set arglist [list $testname $executable $options]
|
| + foreach source $sources {
|
| + lappend arglist $source $options
|
| + }
|
| +
|
| + return [eval build_executable_from_specs $arglist]
|
| +}
|
| +
|
| # Starts fresh GDB binary and loads EXECUTABLE into GDB. EXECUTABLE is
|
| -# the name of binary in ${objdir}/${subdir}.
|
| +# the basename of the binary.
|
| proc clean_restart { executable } {
|
| global srcdir
|
| - global objdir
|
| global subdir
|
| - set binfile ${objdir}/${subdir}/${executable}
|
| + set binfile [standard_output_file ${executable}]
|
|
|
| gdb_exit
|
| gdb_start
|
| gdb_reinitialize_dir $srcdir/$subdir
|
| gdb_load ${binfile}
|
| +}
|
|
|
| - if [target_info exists gdb_stub] {
|
| - gdb_step_for_stub;
|
| - }
|
| +# Prepares for testing by calling build_executable_full, then
|
| +# clean_restart.
|
| +# TESTNAME is the name of the test.
|
| +# Each element in ARGS is a list of the form
|
| +# { EXECUTABLE OPTIONS SOURCE_SPEC... }
|
| +# These are passed to build_executable_from_specs, which see.
|
| +# The last EXECUTABLE is passed to clean_restart.
|
| +# Returns 0 on success, non-zero on failure.
|
| +proc prepare_for_testing_full {testname args} {
|
| + foreach spec $args {
|
| + if {[eval build_executable_from_specs [list $testname] $spec] == -1} {
|
| + return -1
|
| + }
|
| + set executable [lindex $spec 0]
|
| + }
|
| + clean_restart $executable
|
| + return 0
|
| }
|
|
|
| # Prepares for testing, by calling build_executable, and then clean_restart.
|
| @@ -3874,7 +4058,7 @@ proc core_find {binfile {deletefiles {}} {arg ""}} {
|
| # could have many core files lying around, and it may be difficult to
|
| # tell which one is ours, so let's run the program in a subdirectory.
|
| set found 0
|
| - set coredir "${objdir}/${subdir}/coredir.[getpid]"
|
| + set coredir [standard_output_file coredir.[getpid]]
|
| file mkdir $coredir
|
| catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\""
|
| # remote_exec host "${binfile}"
|
|
|