]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/testsuite/lib/gdb.exp
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / gdb / testsuite / lib / gdb.exp
index c62f706bfb46ea61126e0d3da38c3bb87792159d..8b16b3827e96107741787ed70981001405bccd72 100644 (file)
@@ -1,5 +1,4 @@
-# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
 
 # 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
@@ -53,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"
+    set INTERNAL_GDBFLAGS "-nw -nx -data-directory $BUILD_DATA_DIRECTORY"
 }
 
 # The variable gdb_prompt is a regexp which matches the gdb prompt.
@@ -98,6 +100,8 @@ if ![info exists env(EXEEXT)] {
 
 set octal "\[0-7\]+"
 
+set inferior_exited_re "(\\\[Inferior \[0-9\]+ \\(.*\\) exited)"
+
 ### Only procedures should come after this point.
 
 #
@@ -124,6 +128,7 @@ proc gdb_version { } {
 
 #
 # gdb_unload -- unload a file if one is loaded
+# Return 0 on success, -1 on error.
 #
 
 proc gdb_unload {} {
@@ -134,9 +139,8 @@ proc gdb_unload {} {
     gdb_expect 60 {
        -re "No executable file now\[^\r\n\]*\[\r\n\]" { exp_continue }
        -re "No symbol file now\[^\r\n\]*\[\r\n\]" { exp_continue }
-       -re "A program is being debugged already..*Kill it.*y or n. $"\
-           { send_gdb "y\n"
-               verbose "\t\tKilling previous program being debugged"
+       -re "A program is being debugged already.*Are you sure you want to change the file.*y or n. $" {
+           send_gdb "y\n"
            exp_continue
        }
        -re "Discard symbol table from .*y or n.*$" {
@@ -145,10 +149,11 @@ proc gdb_unload {} {
        }
        -re "$gdb_prompt $" {}
        timeout {
-           perror "couldn't unload file in $GDB (timeout)."
+           perror "couldn't unload file in $GDB (timeout)."
            return -1
        }
     }
+    return 0
 }
 
 # Many of the tests depend on setting breakpoints at various places and
@@ -185,16 +190,17 @@ proc delete_breakpoints {} {
     }
 }
 
-
-#
 # Generic run command.
 #
 # The second pattern below matches up to the first newline *only*.
 # Using ``.*$'' could swallow up output that we attempt to match
 # elsewhere.
 #
+# N.B. This function does not wait for gdb to return to the prompt,
+# that is the caller's responsibility.
+
 proc gdb_run_cmd {args} {
-    global gdb_prompt
+    global gdb_prompt use_gdb_stub
 
     if [target_info exists gdb_init_command] {
        send_gdb "[target_info gdb_init_command]\n";
@@ -207,7 +213,7 @@ proc gdb_run_cmd {args} {
        }
     }
 
-    if [target_info exists use_gdb_stub] {
+    if $use_gdb_stub {
        if [target_info exists gdb,do_reload_on_run] {
            if { [gdb_reload] != 0 } {
                return;
@@ -265,13 +271,6 @@ proc gdb_run_cmd {args} {
                }
            }
        }
-       if [target_info exists gdb_stub] {
-           gdb_expect 60 {
-               -re "$gdb_prompt $" {
-                   send_gdb "continue\n"
-               }
-           }
-       }
        return
     }
 
@@ -290,14 +289,20 @@ proc gdb_run_cmd {args} {
            exp_continue
        }
        -notransfer -re "Starting program: \[^\r\n\]*" {}
+       -notransfer -re "$gdb_prompt $" {
+           # There is no more input expected.
+       }
     }
 }
 
 # Generic start command.  Return 0 if we could start the program, -1
 # if we could not.
+#
+# N.B. This function does not wait for gdb to return to the prompt,
+# that is the caller's responsibility.
 
 proc gdb_start_cmd {args} {
-    global gdb_prompt
+    global gdb_prompt use_gdb_stub
 
     if [target_info exists gdb_init_command] {
        send_gdb "[target_info gdb_init_command]\n";
@@ -305,12 +310,12 @@ proc gdb_start_cmd {args} {
            -re "$gdb_prompt $" { }
            default {
                perror "gdb_init_command for target failed";
-               return;
+               return -1;
            }
        }
     }
 
-    if [target_info exists use_gdb_stub] {
+    if $use_gdb_stub {
        return -1
     }
 
@@ -331,29 +336,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 {
@@ -362,8 +382,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
                }
@@ -372,19 +392,35 @@ proc gdb_breakpoint { function args } {
                send_gdb "$pending_response\n"
                exp_continue
        }
+       -re "A problem internal to GDB has been detected" {
+               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;
 }    
 
@@ -392,8 +428,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
@@ -401,7 +444,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;
     }
 
@@ -411,49 +475,64 @@ 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 $" {
+           if { $print_fail } {
+               unsupported "Non-stop mode not supported"
+           }
+           return 0
+       }
+       -re ".*A problem internal to GDB has been detected" {
+           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
        }
     }
+    if { $print_pass } {
+       pass $test_name
+    }
     return 1
 }
 
+# Ask gdb to run until we hit a breakpoint at main.
 #
-# runto_main -- 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.
-#
-proc runto_main { } {
-    global gdb_prompt
-    global decimal
-
-    if ![target_info exists gdb_stub] {
-       return [runto main]
-    }                  
+# N.B. This function deletes all existing breakpoints.
+# If you don't want that, use gdb_start_cmd.
 
-    delete_breakpoints
-
-    gdb_step_for_stub;
-
-    return 1
+proc runto_main { } {
+    return [runto main no-message]
 }
 
-
 ### Continue, and expect to hit a breakpoint.
 ### Report a pass or fail, depending on whether it seems to have
 ### worked.  Use NAME as part of the test name; each call to
@@ -465,7 +544,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 $" {
@@ -504,6 +583,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 {
@@ -559,13 +640,14 @@ proc gdb_internal_error_resync {} {
 #    }
 # }
 #
-# The standard patterns, such as "Program exited..." and "A problem
+# The standard patterns, such as "Inferior exited..." and "A problem
 # ...", all being implicitly appended to that list.
 #
 proc gdb_test_multiple { command message user_code } {
-    global verbose
+    global verbose use_gdb_stub
     global gdb_prompt
     global GDB
+    global inferior_exited_re
     upvar timeout timeout
     upvar expect_out expect_out
 
@@ -573,6 +655,20 @@ proc gdb_test_multiple { command message user_code } {
        set message $command
     }
 
+    if [string match "*\[\r\n\]" $command] {
+       error "Invalid trailing newline in \"$message\" test"
+    }
+
+    if [string match "*\[\r\n\]*" $message] {
+       error "Invalid newline in \"$message\" test"
+    }
+
+    if {$use_gdb_stub
+       && [regexp -nocase {^\s*(r|run|star|start|at|att|atta|attac|attach)\M} \
+           $command]} {
+       error "gdbserver does not support $command without extended-remote"
+    }
+
     # TCL/EXPECT WART ALERT
     # Expect does something very strange when it receives a single braced
     # argument.  It splits it along word separators and performs substitutions.
@@ -649,6 +745,7 @@ proc gdb_test_multiple { command message user_code } {
     set result -1
     set string "${command}\n";
     if { $command != "" } {
+       set multi_line_re "\[\r\n\] *>"
        while { "$string" != "" } {
            set foo [string first "\n" "$string"];
            set len [string length "$string"];
@@ -669,10 +766,11 @@ proc gdb_test_multiple { command message user_code } {
                # command output is not lost for pattern matching
                # - guo
                gdb_expect 2 {
-                   -notransfer -re "\[\r\n\]" { verbose "partial: match" 3 }
+                   -notransfer -re "$multi_line_re$" { verbose "partial: match" 3 }
                    timeout { verbose "partial: timeout" 3 }
                }
                set string [string range "$string" [expr $foo + 1] end];
+               set multi_line_re "$multi_line_re.*\[\r\n\] *>"
            } else {
                break;
            }
@@ -706,21 +804,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."
            }
@@ -728,17 +826,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 "Program exited 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 {
@@ -747,7 +845,7 @@ proc gdb_test_multiple { command message user_code } {
            fail "$errmsg"
            set result -1
        }
-        -re "EXIT code \[0-9\r\n\]+Program exited normally.*$gdb_prompt $" {
+       -re "$inferior_exited_re normally.*$gdb_prompt $" {
            if ![string match "" $message] then {
                set errmsg "$message (the program exited)"
            } else {
@@ -756,7 +854,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 {
@@ -765,16 +863,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)\\) " {
@@ -789,16 +887,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 {
@@ -814,11 +912,7 @@ proc gdb_test_multiple { command message user_code } {
     if {$code == 1} {
        global errorInfo errorCode;
        return -code error -errorinfo $errorInfo -errorcode $errorCode $string
-    } elseif {$code == 2} {
-       return -code return $string
-    } elseif {$code == 3} {
-       return
-    } elseif {$code > 4} {
+    } elseif {$code > 1} {
        return -code $code $string
     }
     return $result
@@ -877,6 +971,65 @@ proc gdb_test { args } {
        }
      }]
 }
+
+# gdb_test_no_output COMMAND MESSAGE
+# Send a command to GDB and verify that this command generated no output.
+#
+# See gdb_test_multiple for a description of the COMMAND and MESSAGE
+# parameters.  If MESSAGE is ommitted, then COMMAND will be used as
+# the message.  (If MESSAGE is the empty string, then sometimes we do not
+# call pass or fail at all; I don't understand this at all.)
+
+proc gdb_test_no_output { args } {
+    global gdb_prompt
+    set command [lindex $args 0]
+    if [llength $args]>1 then {
+       set message [lindex $args 1]
+    } else {
+       set message $command
+    }
+
+    set command_regex [string_to_regexp $command]
+    gdb_test_multiple $command $message {
+        -re "^$command_regex\r\n$gdb_prompt $" {
+           if ![string match "" $message] then {
+               pass "$message"
+            }
+        }
+    }
+}
+
+# Send a command and then wait for a sequence of outputs.
+# This is useful when the sequence is long and contains ".*", a single
+# regexp to match the entire output can get a timeout much easier.
+#
+# COMMAND is the command to send.
+# TEST_NAME is passed to pass/fail.  COMMAND is used if TEST_NAME is "".
+# EXPECTED_OUTPUT_LIST is a list of regexps of expected output, which are
+# processed in order, and all must be present in the output.
+#
+# It is unnecessary to specify ".*" at the beginning or end of any regexp,
+# there is an implicit ".*" between each element of EXPECTED_OUTPUT_LIST.
+# There is also an implicit ".*" between the last regexp and the gdb prompt.
+#
+# Like gdb_test and gdb_test_multiple, the output is expected to end with the
+# gdb prompt, which must not be specified in EXPECTED_OUTPUT_LIST.
+#
+# Returns:
+#    1 if the test failed,
+#    0 if the test passes,
+#   -1 if there was an internal error.
+
+proc gdb_test_sequence { command test_name expected_output_list } {
+    global gdb_prompt
+    if { $test_name == "" } {
+       set test_name $command
+    }
+    lappend expected_output_list ""; # implicit ".*" before gdb prompt
+    send_gdb "$command\n"
+    return [gdb_expect_list $test_name "$gdb_prompt $" $expected_output_list]
+}
+
 \f
 # Test that a command gives an error.  For pass or fail, return
 # a 1 to indicate that more tests can proceed.  However a timeout
@@ -997,6 +1150,59 @@ proc gdb_test_exact { args } {
 
     return [gdb_test $command $pattern $message]
 }
+
+# Wrapper around gdb_test_multiple that looks for a list of expected
+# output elements, but which can appear in any order.
+# CMD is the gdb command.
+# NAME is the name of the test.
+# ELM_FIND_REGEXP specifies how to partition the output into elements to
+# compare.
+# ELM_EXTRACT_REGEXP specifies the part of ELM_FIND_REGEXP to compare.
+# RESULT_MATCH_LIST is a list of exact matches for each expected element.
+# All elements of RESULT_MATCH_LIST must appear for the test to pass.
+#
+# A typical use of ELM_FIND_REGEXP/ELM_EXTRACT_REGEXP is to extract one line
+# of text per element and then strip trailing \r\n's.
+# Example:
+# gdb_test_list_exact "foo" "bar" \
+#    "\[^\r\n\]+\[\r\n\]+" \
+#    "\[^\r\n\]+" \
+#     { \
+#      {expected result 1} \
+#      {expected result 2} \
+#     }
+
+proc gdb_test_list_exact { cmd name elm_find_regexp elm_extract_regexp result_match_list } {
+    global gdb_prompt
+
+    set matches [lsort $result_match_list]
+    set seen {}
+    gdb_test_multiple $cmd $name {
+       "$cmd\[\r\n\]" { exp_continue }
+       -re $elm_find_regexp {
+           set str $expect_out(0,string)
+           verbose -log "seen: $str" 3
+           regexp -- $elm_extract_regexp $str elm_seen
+           verbose -log "extracted: $elm_seen" 3
+           lappend seen $elm_seen
+           exp_continue
+       }
+       -re "$gdb_prompt $" {
+           set failed ""
+           foreach got [lsort $seen] have $matches {
+               if {![string equal $got $have]} {
+                   set failed $have
+                   break
+               }
+           }
+           if {[string length $failed] != 0} {
+               fail "$name ($failed not found)"
+           } else {
+               pass $name
+           }
+       }
+    }
+}
 \f
 proc gdb_reinitialize_dir { subdir } {
     global gdb_prompt
@@ -1074,6 +1280,8 @@ proc default_gdb_exit {} {
 #
 #   debug    file was loaded successfully and has debug information
 #   nodebug  file was loaded successfully and has no debug information
+#   lzma     file was loaded, .gnu_debugdata found, but no LZMA support
+#            compiled in
 #   fail     file was not loaded
 #
 # I tried returning this information as part of the return value,
@@ -1089,6 +1297,7 @@ proc gdb_file_cmd { arg } {
     global GDB
     global last_loaded_file
 
+    # Save this for the benefit of gdbserver-support.exp.
     set last_loaded_file $arg
 
     # Set whether debug info was found.
@@ -1120,13 +1329,18 @@ proc gdb_file_cmd { arg } {
 
     send_gdb "file $arg\n"
     gdb_expect 120 {
+       -re "Reading symbols from.*LZMA support was disabled.*done.*$gdb_prompt $" {
+           verbose "\t\tLoaded $arg into $GDB; .gnu_debugdata found but no LZMA available"
+           set gdb_file_cmd_debug_info "lzma"
+           return 0
+       }
        -re "Reading symbols from.*no debugging symbols found.*done.*$gdb_prompt $" {
-           verbose "\t\tLoaded $arg into the $GDB with no debugging symbols"
+           verbose "\t\tLoaded $arg into $GDB with no debugging symbols"
            set gdb_file_cmd_debug_info "nodebug"
            return 0
        }
         -re "Reading symbols from.*done.*$gdb_prompt $" {
-            verbose "\t\tLoaded $arg into the $GDB"
+            verbose "\t\tLoaded $arg into $GDB"
            set gdb_file_cmd_debug_info "debug"
            return 0
         }
@@ -1139,28 +1353,37 @@ proc gdb_file_cmd { arg } {
                    return 0
                 }
                 timeout {
-                    perror "(timeout) Couldn't load $arg, other program already loaded."
+                    perror "Couldn't load $arg, other program already loaded (timeout)."
                    return -1
                 }
+               eof {
+                   perror "Couldn't load $arg, other program already loaded (eof)."
+                   return -1
+               }
             }
        }
         -re "No such file or directory.*$gdb_prompt $" {
             perror "($arg) No such file or directory"
            return -1
         }
+       -re "A problem internal to GDB has been detected" {
+           fail "($arg) (GDB internal error)"
+           gdb_internal_error_resync
+           return -1
+       }
         -re "$gdb_prompt $" {
-            perror "couldn't load $arg into $GDB."
+            perror "Couldn't load $arg into $GDB."
            return -1
             }
         timeout {
-            perror "couldn't load $arg into $GDB (timed out)."
+            perror "Couldn't load $arg into $GDB (timeout)."
            return -1
         }
         eof {
             # This is an attempt to detect a core dump, but seems not to
             # work.  Perhaps we need to match .* followed by eof, in which
             # gdb_expect does not seem to have a way to do that.
-            perror "couldn't load $arg into $GDB (end of file)."
+            perror "Couldn't load $arg into $GDB (eof)."
            return -1
         }
     }
@@ -1174,30 +1397,23 @@ proc gdb_file_cmd { arg } {
 # get really slow.  Give gdb at least 3 minutes to start up.
 #
 proc default_gdb_start { } {
-    global verbose
+    global verbose use_gdb_stub
     global GDB
     global INTERNAL_GDBFLAGS GDBFLAGS
     global gdb_prompt
     global timeout
     global gdb_spawn_id;
-    global env
 
     gdb_stop_suppressing_tests;
 
-    set env(LC_CTYPE) C
-
-    # Don't let a .inputrc file or an existing setting of INPUTRC mess up
-    # the test results.  Even if /dev/null doesn't exist on the particular
-    # platform, the readline library will use the default setting just by
-    # failing to open the file.  OTOH, opening /dev/null successfully will
-    # also result in the default settings being used since nothing will be
-    # read from this file.
-    set env(INPUTRC) "/dev/null"
-
-    # The gdb.base/readline.exp arrow key test relies on the standard VT100
-    # bindings, so make sure that an appropriate terminal is selected.
-    # The same bug doesn't show up if we use ^P / ^N instead.
-    set env(TERM) "vt100"
+    # Set the default value, it may be overriden later by specific testfile.
+    #
+    # Use `set_board_info use_gdb_stub' for the board file to flag the inferior
+    # is already started after connecting and run/attach are not supported.
+    # This is used for the "remote" protocol.  After GDB starts you should
+    # check global $use_gdb_stub instead of the board as the testfile may force
+    # a specific different target protocol itself.
+    set use_gdb_stub [target_info exists use_gdb_stub]
 
     verbose "Spawning $GDB $INTERNAL_GDBFLAGS $GDBFLAGS"
 
@@ -1318,6 +1534,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 {} {
@@ -1328,7 +1550,10 @@ proc skip_java_tests {} {
 
 proc skip_python_tests {} {
     global gdb_prompt
-    gdb_test_multiple "python print 'test'" "verify python support" {
+    global gdb_py_is_py3k
+    global gdb_py_is_py24
+
+    gdb_test_multiple "python print ('test')" "verify python support" {
        -re "not supported.*$gdb_prompt $"      {
            unsupported "Python support is disabled."
            return 1
@@ -1336,6 +1561,26 @@ proc skip_python_tests {} {
        -re "$gdb_prompt $"     {}
     }
 
+    set gdb_py_is_py24 0
+    gdb_test_multiple "python print (sys.version_info\[0\])" "check if python 3" {
+       -re "3.*$gdb_prompt $"  {
+            set gdb_py_is_py3k 1
+        }
+       -re ".*$gdb_prompt $"   {
+            set gdb_py_is_py3k 0
+        }
+    }
+    if { $gdb_py_is_py3k == 0 } {
+        gdb_test_multiple "python print (sys.version_info\[1\])" "check if python 2.4" {
+           -re "\[45\].*$gdb_prompt $" {
+                set gdb_py_is_py24 1
+            }
+           -re ".*$gdb_prompt $" {
+                set gdb_py_is_py24 0
+            }
+        }
+    }
+
     return 0
 }
 
@@ -1362,12 +1607,327 @@ 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 {} {
+    global support_complex_tests_saved
+
+    # Use the cached value, if it exists.
+    if [info exists support_complex_tests_saved] {
+        verbose "returning saved $support_complex_tests_saved" 2
+        return $support_complex_tests_saved
+    }
+
+    # Set up, compile, and execute a test program containing _Complex types.
+    # Include the current process ID in the file names to prevent conflicts
+    # with invocations for multiple testsuites.
+    set src complex[pid].c
+    set exe complex[pid].x
+
+    set f [open $src "w"]
+    puts $f "int main() {"
+    puts $f "_Complex float cf;"
+    puts $f "_Complex double cd;"
+    puts $f "_Complex long double cld;"
+    puts $f "  return 0; }"
+    close $f
+
+    verbose "compiling testfile $src" 2
+    set compile_flags {debug nowarnings quiet}
+    set lines [gdb_compile $src $exe executable $compile_flags]
+    file delete $src
+    file delete $exe
+
+    if ![string match "" $lines] then {
+        verbose "testfile compilation failed, returning 0" 2
+        set support_complex_tests_saved 0
+    } else {
+       set support_complex_tests_saved 1
+    }
+
+    return $support_complex_tests_saved
+}
+
+# Return 1 if target hardware or OS supports single stepping to signal
+# handler, otherwise, return 0.
+
+proc can_single_step_to_signal_handler {} {
+
+    # Targets don't have hardware single step.  On these targets, when
+    # a signal is delivered during software single step, gdb is unable
+    # to determine the next instruction addresses, because start of signal
+    # handler is one of them.
+    if { [istarget "arm*-*-*"] || [istarget "mips*-*-*"]
+        || [istarget "tic6x-*-*"] || [istarget "sparc*-*-linux*"] } {
+       return 0
+    }
+
+    return 1
+}
+
+# Return 1 if target supports process record, otherwise return 0.
+
+proc supports_process_record {} {
+
+    if [target_info exists gdb,use_precord] {
+       return [target_info gdb,use_precord]
+    }
+
+    if { [istarget "x86_64-*-linux*"] || [istarget "i\[34567\]86-*-linux*"] } {
+       return 1
+    }
+
+    return 0
+}
+
+# Return 1 if target supports reverse debugging, otherwise return 0.
+
+proc supports_reverse {} {
+
+    if [target_info exists gdb,can_reverse] {
+       return [target_info gdb,can_reverse]
+    }
+
+    if { [istarget "x86_64-*-linux*"] || [istarget "i\[34567\]86-*-linux*"] } {
+       return 1
+    }
+
+    return 0
+}
+
+# Return 1 if target is ILP32.
+# This cannot be decided simply from looking at the target string,
+# as it might depend on externally passed compiler options like -m64.
+proc is_ilp32_target {} {
+    global is_ilp32_target_saved
+
+    # Use the cached value, if it exists.  Cache value per "board" to handle
+    # runs with multiple options (e.g. unix/{-m32,-64}) correctly.
+    set me "is_ilp32_target"
+    set board [target_info name]
+    if [info exists is_ilp32_target_saved($board)] {
+        verbose "$me:  returning saved $is_ilp32_target_saved($board)" 2
+        return $is_ilp32_target_saved($board)
+    }
+
+
+    set src ilp32[pid].c
+    set obj ilp32[pid].o
+
+    set f [open $src "w"]
+    puts $f "int dummy\[sizeof (int) == 4"
+    puts $f "           && sizeof (void *) == 4"
+    puts $f "           && sizeof (long) == 4 ? 1 : -1\];"
+    close $f
+
+    verbose "$me:  compiling testfile $src" 2
+    set lines [gdb_compile $src $obj object {quiet}]
+    file delete $src
+    file delete $obj
+
+    if ![string match "" $lines] then {
+        verbose "$me:  testfile compilation failed, returning 0" 2
+        return [set is_ilp32_target_saved($board) 0]
+    }
+
+    verbose "$me:  returning 1" 2
+    return [set is_ilp32_target_saved($board) 1]
+}
+
+# Return 1 if target is LP64.
+# This cannot be decided simply from looking at the target string,
+# as it might depend on externally passed compiler options like -m64.
+proc is_lp64_target {} {
+    global is_lp64_target_saved
+
+    # Use the cached value, if it exists.  Cache value per "board" to handle
+    # runs with multiple options (e.g. unix/{-m32,-64}) correctly.
+    set me "is_lp64_target"
+    set board [target_info name]
+    if [info exists is_lp64_target_saved($board)] {
+        verbose "$me:  returning saved $is_lp64_target_saved($board)" 2
+        return $is_lp64_target_saved($board)
+    }
+
+    set src lp64[pid].c
+    set obj lp64[pid].o
+
+    set f [open $src "w"]
+    puts $f "int dummy\[sizeof (int) == 4"
+    puts $f "           && sizeof (void *) == 8"
+    puts $f "           && sizeof (long) == 8 ? 1 : -1\];"
+    close $f
+
+    verbose "$me:  compiling testfile $src" 2
+    set lines [gdb_compile $src $obj object {quiet}]
+    file delete $src
+    file delete $obj
+
+    if ![string match "" $lines] then {
+        verbose "$me:  testfile compilation failed, returning 0" 2
+        return [set is_lp64_target_saved($board) 0]
+    }
+
+    verbose "$me:  returning 1" 2
+    return [set is_lp64_target_saved($board) 1]
+}
+
+# Return 1 if target has x86_64 registers - either amd64 or x32.
+# x32 target identifies as x86_64-*-linux*, therefore it cannot be determined
+# just from the target string.
+proc is_amd64_regs_target {} {
+    global is_amd64_regs_target_saved
+
+    if {![istarget "x86_64-*-*"] && ![istarget "i?86-*"]} {
+       return 0
+    }
+
+    # Use the cached value, if it exists.  Cache value per "board" to handle
+    # runs with multiple options (e.g. unix/{-m32,-64}) correctly.
+    set me "is_amd64_regs_target"
+    set board [target_info name]
+    if [info exists is_amd64_regs_target_saved($board)] {
+        verbose "$me:  returning saved $is_amd64_regs_target_saved($board)" 2
+        return $is_amd64_regs_target_saved($board)
+    }
+
+    set src reg64[pid].s
+    set obj reg64[pid].o
+
+    set f [open $src "w"]
+    foreach reg \
+            {rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15} {
+       puts $f "\tincq %$reg"
+    }
+    close $f
+
+    verbose "$me:  compiling testfile $src" 2
+    set lines [gdb_compile $src $obj object {quiet}]
+    file delete $src
+    file delete $obj
+
+    if ![string match "" $lines] then {
+        verbose "$me:  testfile compilation failed, returning 0" 2
+        return [set is_amd64_regs_target_saved($board) 0]
+    }
+
+    verbose "$me:  returning 1" 2
+    return [set is_amd64_regs_target_saved($board) 1]
+}
+
+# Return 1 if this target is an x86 or x86-64 with -m32.
+proc is_x86_like_target {} {
+    if {![istarget "x86_64-*-*"] && ![istarget i?86-*]} {
+       return 0
+    }
+    return [expr [is_ilp32_target] && ![is_amd64_regs_target]]
+}
+
+# Return 1 if displaced stepping is supported on target, otherwise, return 0.
+proc support_displaced_stepping {} {
+
+    if { [istarget "x86_64-*-linux*"] || [istarget "i\[34567\]86-*-linux*"]
+        || [istarget "arm*-*-linux*"] || [istarget "powerpc-*-linux*"]
+        || [istarget "powerpc64-*-linux*"] || [istarget "s390*-*-*"] } {
+       return 1
+    }
+
+    return 0
+}
+
 # Run a test on the target to see if it supports vmx hardware.  Return 0 if so, 
 # 1 if it does not.  Based on 'check_vmx_hw_available' from the GCC testsuite.
 
 proc skip_altivec_tests {} {
     global skip_vmx_tests_saved
-    global srcdir subdir gdb_prompt
+    global srcdir subdir gdb_prompt inferior_exited_re
 
     # Use the cached value, if it exists.
     set me "skip_altivec_tests"
@@ -1384,7 +1944,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
     }
@@ -1434,7 +1994,7 @@ proc skip_altivec_tests {} {
             verbose -log "\n$me altivec hardware not detected" 
             set skip_vmx_tests_saved 1
         }
-        -re ".*Program exited normally.*${gdb_prompt} $" {
+        -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
             verbose -log "\n$me: altivec hardware detected" 
             set skip_vmx_tests_saved 0
         }
@@ -1455,7 +2015,7 @@ proc skip_altivec_tests {} {
 
 proc skip_vsx_tests {} {
     global skip_vsx_tests_saved
-    global srcdir subdir gdb_prompt
+    global srcdir subdir gdb_prompt inferior_exited_re
 
     # Use the cached value, if it exists.
     set me "skip_vsx_tests"
@@ -1473,14 +2033,14 @@ 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
     }
     if [test_compiler_info gcc*] {
         set compile_flags "$compile_flags additional_flags=-mvsx"
     } elseif [test_compiler_info xlc*] {
-        set compile_flags "$compile_flags additional_flags=-qvsx"
+        set compile_flags "$compile_flags additional_flags=-qasm=gcc"
     } else {
         verbose "Could not compile with vsx support, returning 1" 2
         return 1
@@ -1491,10 +2051,11 @@ proc skip_vsx_tests {} {
 
     set f [open $src "w"]
     puts $f "int main() {"
+    puts $f "  double a\[2\] = { 1.0, 2.0 };"
     puts $f "#ifdef __MACH__"
-    puts $f "  asm volatile (\"lxvd2x v0,v0,v0\");"
+    puts $f "  asm volatile (\"lxvd2x v0,v0,%\[addr\]\" : : \[addr\] \"r\" (a));"
     puts $f "#else"
-    puts $f "  asm volatile (\"lxvd2x 0,0,0\");"
+    puts $f "  asm volatile (\"lxvd2x 0,0,%\[addr\]\" : : \[addr\] \"r\" (a));"
     puts $f "#endif"
     puts $f "  return 0; }"
     close $f
@@ -1520,7 +2081,7 @@ proc skip_vsx_tests {} {
             verbose -log "\n$me VSX hardware not detected"
             set skip_vsx_tests_saved 1
         }
-        -re ".*Program exited normally.*${gdb_prompt} $" {
+        -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
             verbose -log "\n$me: VSX hardware detected"
             set skip_vsx_tests_saved 0
         }
@@ -1539,43 +2100,146 @@ proc skip_vsx_tests {} {
 # Skip all the tests in the file if you are not on an hppa running
 # hpux target.
 
-proc skip_hp_tests {} {
-    eval set skip_hp [ expr ![isnative] || ![istarget "hppa*-*-hpux*"] ]
-    verbose "Skip hp tests is $skip_hp"
-    return $skip_hp
+proc skip_hp_tests {} {
+    eval set skip_hp [ expr ![isnative] || ![istarget "hppa*-*-hpux*"] ]
+    verbose "Skip hp tests is $skip_hp"
+    return $skip_hp
+}
+
+# Return whether we should skip tests for showing inlined functions in
+# backtraces.  Requires get_compiler_info and get_debug_format.
+
+proc skip_inline_frame_tests {} {
+    # GDB only recognizes inlining information in DWARF 2 (DWARF 3).
+    if { ! [test_debug_format "DWARF 2"] } {
+       return 1
+    }
+
+    # GCC before 4.1 does not emit DW_AT_call_file / DW_AT_call_line.
+    if { ([test_compiler_info "gcc-2-*"]
+         || [test_compiler_info "gcc-3-*"]
+         || [test_compiler_info "gcc-4-0-*"]) } {
+       return 1
+    }
+
+    return 0
+}
+
+# Return whether we should skip tests for showing variables from
+# inlined functions.  Requires get_compiler_info and get_debug_format.
+
+proc skip_inline_var_tests {} {
+    # GDB only recognizes inlining information in DWARF 2 (DWARF 3).
+    if { ! [test_debug_format "DWARF 2"] } {
+       return 1
+    }
+
+    return 0
+}
+
+# Return a 1 if we should skip tests that require hardware breakpoints
+
+proc skip_hw_breakpoint_tests {} {
+    # Skip tests if requested by the board (note that no_hardware_watchpoints
+    # disables both watchpoints and breakpoints)
+    if { [target_info exists gdb,no_hardware_watchpoints]} {
+       return 1
+    }
+
+    # These targets support hardware breakpoints natively
+    if { [istarget "i?86-*-*"] 
+        || [istarget "x86_64-*-*"]
+        || [istarget "ia64-*-*"] 
+        || [istarget "arm*-*-*"]} {
+       return 0
+    }
+
+    return 1
+}
+
+# Return a 1 if we should skip tests that require hardware watchpoints
+
+proc skip_hw_watchpoint_tests {} {
+    # Skip tests if requested by the board
+    if { [target_info exists gdb,no_hardware_watchpoints]} {
+       return 1
+    }
+
+    # These targets support hardware watchpoints natively
+    if { [istarget "i?86-*-*"] 
+        || [istarget "x86_64-*-*"]
+        || [istarget "ia64-*-*"] 
+        || [istarget "arm*-*-*"]
+        || [istarget "powerpc*-*-linux*"]
+        || [istarget "s390*-*-*"] } {
+       return 0
+    }
+
+    return 1
 }
 
-# Return whether we should skip tests for showing inlined functions in
-# backtraces.  Requires get_compiler_info and get_debug_format.
+# Return a 1 if we should skip tests that require *multiple* hardware
+# watchpoints to be active at the same time
 
-proc skip_inline_frame_tests {} {
-    # GDB only recognizes inlining information in DWARF 2 (DWARF 3).
-    if { ! [test_debug_format "DWARF 2"] } {
+proc skip_hw_watchpoint_multi_tests {} {
+    if { [skip_hw_watchpoint_tests] } {
        return 1
     }
 
-    # GCC before 4.1 does not emit DW_AT_call_file / DW_AT_call_line.
-    if { ([test_compiler_info "gcc-2-*"]
-         || [test_compiler_info "gcc-3-*"]
-         || [test_compiler_info "gcc-4-0-*"]) } {
+    # These targets support just a single hardware watchpoint
+    if { [istarget "arm*-*-*"]
+        || [istarget "powerpc*-*-linux*"] } {
        return 1
     }
 
     return 0
 }
 
-# Return whether we should skip tests for showing variables from
-# inlined functions.  Requires get_compiler_info and get_debug_format.
+# Return a 1 if we should skip tests that require read/access watchpoints
 
-proc skip_inline_var_tests {} {
-    # GDB only recognizes inlining information in DWARF 2 (DWARF 3).
-    if { ! [test_debug_format "DWARF 2"] } {
+proc skip_hw_watchpoint_access_tests {} {
+    if { [skip_hw_watchpoint_tests] } {
+       return 1
+    }
+
+    # These targets support just write watchpoints
+    if { [istarget "s390*-*-*"] } {
        return 1
     }
 
     return 0
 }
 
+# Return 1 if we should skip tests that require the runtime unwinder
+# hook.  This must be invoked while gdb is running, after shared
+# libraries have been loaded.  This is needed because otherwise a
+# shared libgcc won't be visible.
+
+proc skip_unwinder_tests {} {
+    global gdb_prompt
+
+    set ok 0
+    gdb_test_multiple "print _Unwind_DebugHook" "check for unwinder hook" {
+       -re "= .*no debug info.*_Unwind_DebugHook.*\r\n$gdb_prompt $" {
+       }
+       -re "= .*_Unwind_DebugHook.*\r\n$gdb_prompt $" {
+           set ok 1
+       }
+       -re "No symbol .* in current context.\r\n$gdb_prompt $" {
+       }
+    }
+    if {!$ok} {
+       gdb_test_multiple "info probe" "check for stap probe in unwinder" {
+           -re ".*libgcc.*unwind.*\r\n$gdb_prompt $" {
+               set ok 1
+           }
+           -re "\r\n$gdb_prompt $" {
+           }
+       }
+    }
+    return $ok
+}
+
 set compiler_info              "unknown"
 set gcc_compiled               0
 set hp_cc_compiler             0
@@ -1583,10 +2247,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.
 #
@@ -1635,7 +2296,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
 
@@ -1653,7 +2314,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"
     }
 
@@ -1664,12 +2325,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" 
 
@@ -1829,14 +2490,14 @@ proc gdb_compile {source dest type options} {
     # dynamically load one by basename, we must specify rpath.  If we
     # are using a remote host, DejaGNU will link to the shared library
     # using a relative path, so again we must specify an rpath.
-    if { $shlib_load || ($shlib_found && [is_remote host]) } {
+    if { $shlib_load || ($shlib_found && [is_remote target]) } {
        if { ([istarget "*-*-mingw*"]
              || [istarget *-*-cygwin*]
              || [istarget *-*-pe*]
              || [istarget hppa*-*-hpux*])} {
            # Do not need anything.
-       } elseif { [istarget *-*-openbsd*] } {
-           lappend new_options "additional_flags=-Wl,-rpath,${outdir}"
+       } elseif { [istarget *-*-freebsd*] || [istarget *-*-openbsd*] } {
+           lappend new_options "ldflags=-Wl,-rpath,${outdir}"
        } elseif { [istarget arm*-*-symbianelf*] } {
            if { $shlib_load } {
                lappend new_options "libs=-ldl"
@@ -1845,19 +2506,13 @@ proc gdb_compile {source dest type options} {
            if { $shlib_load } {
                lappend new_options "libs=-ldl"
            }
-           lappend new_options "additional_flags=-Wl,-rpath,\\\$ORIGIN"
+           lappend new_options "ldflags=-Wl,-rpath,\\\$ORIGIN"
        }
     }
     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] {
@@ -2044,7 +2699,17 @@ proc gdb_compile_shlib {sources dest options} {
                 || [istarget *-*-cygwin*]
                 || [istarget *-*-pe*])} {
               lappend link_options "additional_flags=-Wl,--out-implib,${dest}.a"
-          }
+          } elseif [is_remote target] {
+            # By default, we do not set the soname.  This causes the linker
+            # on ELF systems to create a DT_NEEDED entry in the executable
+            # refering to the full path name of the library.  This is a
+            # problem in remote testing if the library is in a different
+            # directory there.  To fix this, we set a soname of just the
+            # base filename for the library, and add an appropriate -rpath
+            # to the main executable (in gdb_compile).
+             set destbase [file tail $dest]
+             lappend link_options "additional_flags=-Wl,-soname,$destbase"
+           }
        }
        if {[gdb_compile "${objects}" "${dest}" executable $link_options] != ""} {
            return -1
@@ -2052,6 +2717,41 @@ proc gdb_compile_shlib {sources dest options} {
     }
 }
 
+# This is just like gdb_compile_shlib, above, except that it tries compiling
+# against several different thread libraries, to see which one this
+# system has.
+proc gdb_compile_shlib_pthreads {sources dest options} {
+    set built_binfile 0
+    set why_msg "unrecognized error"
+    foreach lib {-lpthreads -lpthread -lthread ""} {
+        # This kind of wipes out whatever libs the caller may have
+        # set.  Or maybe theirs will override ours.  How infelicitous.
+        set options_with_lib [concat $options [list libs=$lib quiet]]
+        set ccout [gdb_compile_shlib $sources $dest $options_with_lib]
+        switch -regexp -- $ccout {
+            ".*no posix threads support.*" {
+                set why_msg "missing threads include file"
+                break
+            }
+            ".*cannot open -lpthread.*" {
+                set why_msg "missing runtime threads library"
+            }
+            ".*Can't find library for -lpthread.*" {
+                set why_msg "missing runtime threads library"
+            }
+            {^$} {
+                pass "successfully compiled posix threads test case"
+                set built_binfile 1
+                break
+            }
+        }
+    }
+    if {!$built_binfile} {
+        unsupported "Couldn't compile $sources: ${why_msg}"
+        return -1
+    }
+}
+
 # This is just like gdb_compile_pthreads, above, except that we always add the
 # objc library for compiling Objective-C programs
 proc gdb_compile_objc {source dest type options} {
@@ -2167,19 +2867,15 @@ proc gdb_expect { args } {
         global errorInfo errorCode;
 
        return -code error -errorinfo $errorInfo -errorcode $errorCode $string
-    } elseif {$code == 2} {
-       return -code return $string
-    } elseif {$code == 3} {
-       return
-    } elseif {$code > 4} {
+    } else {
        return -code $code $string
     }
 }
 
-# gdb_expect_list MESSAGE SENTINEL LIST -- expect a sequence of outputs
+# gdb_expect_list TEST SENTINEL LIST -- expect a sequence of outputs
 #
 # Check for long sequence of output by parts.
-# MESSAGE: is the test message to be printed with the test success/fail.
+# TEST: is the test message to be printed with the test success/fail.
 # SENTINEL: Is the terminal pattern indicating that output has finished.
 # LIST: is the sequence of outputs to match.
 # If the sentinel is recognized early, it is considered an error.
@@ -2188,7 +2884,7 @@ proc gdb_expect { args } {
 #    1 if the test failed,
 #    0 if the test passes,
 #   -1 if there was an internal error.
-#
+
 proc gdb_expect_list {test sentinel list} {
     global gdb_prompt
     global suppress_flag
@@ -2201,6 +2897,7 @@ proc gdb_expect_list {test sentinel list} {
     while { ${index} < [llength ${list}] } {
        set pattern [lindex ${list} ${index}]
         set index [expr ${index} + 1]
+       verbose -log "gdb_expect_list pattern: /$pattern/" 2
        if { ${index} == [llength ${list}] } {
            if { ${ok} } {
                gdb_expect {
@@ -2361,6 +3058,36 @@ proc gdb_load_cmd { args } {
     return -1
 }
 
+# Invoke "gcore".  CORE is the name of the core file to write.  TEST
+# is the name of the test case.  This will return 1 if the core file
+# was created, 0 otherwise.  If this fails to make a core file because
+# this configuration of gdb does not support making core files, it
+# will call "unsupported", not "fail".  However, if this fails to make
+# a core file for some other reason, then it will call "fail".
+
+proc gdb_gcore_cmd {core test} {
+    global gdb_prompt
+
+    set result 0
+    gdb_test_multiple "gcore $core" $test {
+       -re "Saved corefile .*\[\r\n\]+$gdb_prompt $" {
+           pass $test
+           set result 1
+       }
+
+       -re "Undefined command.*$gdb_prompt $" {
+           unsupported $test
+           verbose -log "'gcore' command undefined in gdb_gcore_cmd"
+       }
+
+       -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" {
+           unsupported $test
+       }
+    }
+
+    return $result
+}
+
 # Return the filename to download to the target and load on the target
 # for this shared library.  Normally just LIBNAME, unless shared libraries
 # for this target have separate link and load images.
@@ -2377,6 +3104,43 @@ proc shlib_symbol_file { libname } {
     return $libname
 }
 
+# Return the filename to download to the target and load for this
+# executable.  Normally just BINFILE unless it is renamed to something
+# else for this target.
+
+proc exec_target_file { binfile } {
+    return $binfile
+}
+
+# Return the filename GDB will load symbols from when debugging this
+# executable.  Normally just BINFILE unless executables for this target
+# have separate files for symbols.
+
+proc exec_symbol_file { binfile } {
+    return $binfile
+}
+
+# Rename the executable file.  Normally this is just BINFILE1 being renamed
+# to BINFILE2, but some targets require multiple binary files.
+proc gdb_rename_execfile { binfile1 binfile2 } {
+    file rename -force [exec_target_file ${binfile1}] \
+                      [exec_target_file ${binfile2}]
+    if { [exec_target_file ${binfile1}] != [exec_symbol_file ${binfile1}] } {
+       file rename -force [exec_symbol_file ${binfile1}] \
+                          [exec_symbol_file ${binfile2}]
+    }
+}
+
+# "Touch" the executable file to update the date.  Normally this is just
+# BINFILE, but some targets require multiple files.
+proc gdb_touch_execfile { binfile } {
+    set time [clock seconds]
+    file mtime [exec_target_file ${binfile}] $time
+    if { [exec_target_file ${binfile}] != [exec_symbol_file ${binfile}] } {
+       file mtime [exec_symbol_file ${binfile}] $time
+    }
+}
+
 # gdb_download
 #
 # Copy a file to the remote target and return its target filename.
@@ -2437,12 +3201,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] } {
@@ -2470,6 +3237,88 @@ proc default_gdb_init { args } {
     } else {
        set gdb_prompt "\\(gdb\\)"
     }
+    global use_gdb_stub
+    if [info exists use_gdb_stub] {
+       unset use_gdb_stub
+    }
+}
+
+# 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
@@ -2480,6 +3329,25 @@ if ![info exists gdb_test_timeout] {
     set gdb_test_timeout $timeout
 }
 
+# A list of global variables that GDB testcases should not use.
+# We try to prevent their use by monitoring write accesses and raising
+# 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 and procedures are already traced.
+set banned_traced 0
+
 proc gdb_init { args } {
     # Reset the timeout value to the default.  This way, any testcase
     # that changes the timeout value without resetting it cannot affect
@@ -2488,6 +3356,52 @@ proc gdb_init { args } {
     global timeout
     set timeout $gdb_test_timeout
 
+    # Block writes to all banned variables, and invocation of all
+    # banned procedures...
+    global banned_variables
+    global banned_procedures
+    global banned_traced
+    if (!$banned_traced) {
+       foreach banned_var $banned_variables {
+            global "$banned_var"
+            trace add variable "$banned_var" write error
+       }
+       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
+    # messages as expected.
+    setenv LC_ALL C
+    setenv LC_CTYPE C
+    setenv LANG C
+
+    # Don't let a .inputrc file or an existing setting of INPUTRC mess up
+    # the test results.  Even if /dev/null doesn't exist on the particular
+    # platform, the readline library will use the default setting just by
+    # failing to open the file.  OTOH, opening /dev/null successfully will
+    # also result in the default settings being used since nothing will be
+    # read from this file.
+    setenv INPUTRC "/dev/null"
+
+    # The gdb.base/readline.exp arrow key test relies on the standard VT100
+    # bindings, so make sure that an appropriate terminal is selected.
+    # The same bug doesn't show up if we use ^P / ^N instead.
+    setenv TERM "vt100"
+
+    # Some tests (for example gdb.base/maint.exp) shell out from gdb to use
+    # grep.  Clear GREP_OPTIONS to make the behavoiur predictable, 
+    # especially having color output turned on can cause tests to fail.
+    setenv GREP_OPTIONS ""
+
+    # Clear $gdbserver_reconnect_p.
+    global gdbserver_reconnect_p
+    set gdbserver_reconnect_p 1
+    unset gdbserver_reconnect_p
+
     return [eval default_gdb_init $args];
 }
 
@@ -2501,6 +3415,23 @@ proc gdb_finish { } {
        eval remote_file target delete $cleanfiles
        set cleanfiles {}
     }
+
+    # Unblock write access to the banned variables.  Dejagnu typically
+    # resets some of them between testcases.
+    global banned_variables
+    global banned_procedures
+    global banned_traced
+    if ($banned_traced) {
+       foreach banned_var $banned_variables {
+            global "$banned_var"
+            trace remove variable "$banned_var" write error
+       }
+       foreach banned_proc $banned_procedures {
+           global "$banned_proc"
+           trace remove execution "$banned_proc" enter error
+       }
+       set banned_traced 0
+    }
 }
 
 global debug_format
@@ -2532,7 +3463,7 @@ proc get_debug_format { } {
            return 1;
        }
        timeout {
-           warning "couldn't check debug format (timeout)."
+           warning "couldn't check debug format (timeout)."
            return 1;
        }
     }
@@ -2565,69 +3496,10 @@ proc setup_xfail_format { format } {
     return $ret;
 }
 
-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.
 #
@@ -2700,15 +3572,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
@@ -2720,8 +3590,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
@@ -2732,29 +3605,48 @@ proc gdb_get_line_number { text { file "" } } {
 #       stub is used, we set a breakpoint at exit because we cannot rely on
 #       exit() behavior of a remote target.
 # 
-# mssg is the error message that gets printed.
-
-proc gdb_continue_to_end {mssg} {
-  if [target_info exists use_gdb_stub] {
+# MSSG is the error message that gets printed.  If not given, a
+#      default is used.
+# COMMAND is the command to invoke.  If not given, "continue" is
+#      used.
+# ALLOW_EXTRA is a flag indicating whether the test should expect
+#      extra output between the "Continuing." line and the program
+#      exiting.  By default it is zero; if nonzero, any extra output
+#      is accepted.
+
+proc gdb_continue_to_end {{mssg ""} {command continue} {allow_extra 0}} {
+  global inferior_exited_re use_gdb_stub
+
+  if {$mssg == ""} {
+      set text "continue until exit"
+  } else {
+      set text "continue until exit at $mssg"
+  }
+  if {$allow_extra} {
+      set extra ".*"
+  } else {
+      set extra ""
+  }
+  if $use_gdb_stub {
     if {![gdb_breakpoint "exit"]} {
       return 0
     }
-    gdb_test "continue" "Continuing..*Breakpoint .*exit.*" \
-      "continue until exit at $mssg"
+    gdb_test $command "Continuing..*Breakpoint .*exit.*" \
+       $text
   } else {
     # Continue until we exit.  Should not stop again.
     # Don't bother to check the output of the program, that may be
     # extremely tough for some remote systems.
-    gdb_test "continue"\
-      "Continuing.\[\r\n0-9\]+(... EXIT code 0\[\r\n\]+|Program exited normally\\.).*"\
-      "continue until exit at $mssg"
+    gdb_test $command \
+      "Continuing.\[\r\n0-9\]+${extra}(... EXIT code 0\[\r\n\]+|$inferior_exited_re normally).*"\
+       $text
   }
 }
 
 proc rerun_to_main {} {
-  global gdb_prompt
+  global gdb_prompt use_gdb_stub
 
-  if [target_info exists use_gdb_stub] {
+  if $use_gdb_stub {
     gdb_run_cmd
     gdb_expect {
       -re ".*Breakpoint .*main .*$gdb_prompt $"\
@@ -2833,8 +3725,8 @@ proc gdb_skip_xml_test { } {
 # Note: the procedure gdb_gnu_strip_debug will produce an executable called
 # ${binfile}.dbglnk, which is just like the executable ($binfile) but without
 # the debuginfo. Instead $binfile has a .gnu_debuglink section which contains
-# the name of a debuginfo only file. This file will be stored in the 
-# gdb.base/.debug subdirectory.
+# the name of a debuginfo only file. This file will be stored in the same
+# subdirectory.
 
 # Functions for separate debug info testing
 
@@ -2843,27 +3735,9 @@ proc gdb_skip_xml_test { } {
 
 # at the end of the process we have:
 # foo.stripped --> foo w/o debug info
-# .debug/foo.debug --> foo's debug info
+# foo.debug --> foo's debug info
 # foo --> like foo, but with a new .gnu_debuglink section pointing to foo.debug.
 
-# Return the name of the file in which we should stor EXEC's separated
-# debug info. EXEC contains the full path.
-proc separate_debug_filename { exec } {
-
-    # In a .debug subdirectory off the same directory where the testcase
-    # executable is going to be. Something like:
-    # <your-path>/gdb/testsuite/gdb.base/.debug/blah.debug.
-    # This is the default location where gdb expects to findi
-    # the debug info file.
-
-    set exec_dir [file dirname $exec]
-    set exec_file [file tail $exec]
-    set debug_dir [file join $exec_dir ".debug"]
-    set debug_file [file join $debug_dir "${exec_file}.debug"]
-
-    return $debug_file
-}
-
 # Return the build-id hex string (usually 160 bits as 40 hex characters)
 # converted to the form: .build-id/ab/cdef1234...89.debug
 # Return "" if no build-id found.
@@ -2896,20 +3770,19 @@ proc build_id_debug_filename_get { exec } {
 # Create stripped files for DEST, replacing it.  If ARGS is passed, it is a
 # list of optional flags.  The only currently supported flag is no-main,
 # which removes the symbol entry for main from the separate debug file.
+#
+# Function returns zero on success.  Function will return non-zero failure code
+# on some targets not supporting separate debug info (such as i386-msdos).
 
 proc gdb_gnu_strip_debug { dest args } {
 
-    set debug_file [separate_debug_filename $dest]
+    # Use the first separate debug info file location searched by GDB so the
+    # run cannot be broken by some stale file searched with higher precedence.
+    set debug_file "${dest}.debug"
+
     set strip_to_file_program [transform strip]
     set objcopy_program [transform objcopy]
 
-    # Make sure the directory that will hold the separated debug
-    # info actually exists.
-    set debug_dir [file dirname $debug_file]
-    if {! [file isdirectory $debug_dir]} {
-       file mkdir $debug_dir
-    }
-
     set debug_link [file tail $debug_file]
     set stripped_file "${dest}.stripped"
 
@@ -2985,7 +3858,7 @@ proc help_test_raw { gdb_command expected_lines args } {
     gdb_test "${gdb_command}" "${expected_output}" $message
 }
 
-# Test the output of "help COMMNAD_CLASS". EXPECTED_INITIAL_LINES
+# Test the output of "help COMMAND_CLASS". EXPECTED_INITIAL_LINES
 # are regular expressions that should match the beginning of output,
 # before the list of commands in that class.  The presence of 
 # command list and standard epilogue will be tested automatically.
@@ -3030,29 +3903,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] != "" } {
@@ -3060,28 +3935,63 @@ proc build_executable { testname executable {sources ""} {options {debug}} } {
         return -1
     }
 
-    if [get_compiler_info ${binfile}] {
+    set info_options ""
+    if { [lsearch -exact $options "c++"] >= 0 } {
+       set info_options "c++"
+    }
+    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.
@@ -3151,6 +4061,33 @@ proc get_sizeof { type default } {
     return [get_integer_valueof "sizeof (${type})" $default]
 }
 
+# Get the current value for remotetimeout and return it.
+proc get_remotetimeout { } {
+    global gdb_prompt
+    global decimal
+
+    gdb_test_multiple "show remotetimeout" "" {
+       -re "Timeout limit to wait for target to respond is ($decimal).*$gdb_prompt $" {
+           return $expect_out(1,string);
+       }
+    }
+
+    # Pick the default that gdb uses
+    warning "Unable to read remotetimeout"
+    return 300
+}
+
+# Set the remotetimeout to the specified timeout.  Nothing is returned.
+proc set_remotetimeout { timeout } {
+    global gdb_prompt
+
+    gdb_test_multiple "set remotetimeout $timeout" "" {
+       -re "$gdb_prompt $" {
+           verbose "Set remotetimeout to $timeout\n"
+       }
+    }
+}
+
 # Log gdb command line and script if requested.
 if {[info exists TRANSCRIPT]} {
   rename send_gdb real_send_gdb
@@ -3218,7 +4155,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}"
@@ -3264,3 +4201,21 @@ proc core_find {binfile {deletefiles {}} {arg ""}} {
     }
     return $destcore
 }
+
+# gdb_target_symbol_prefix_flags returns a string that can be added
+# to gdb_compile options to define SYMBOL_PREFIX macro value
+# symbol_prefix_flags returns a string that can be added
+# for targets that use underscore as symbol prefix.
+# TODO: find out automatically if the target needs this.
+
+proc gdb_target_symbol_prefix_flags {} {
+    if { [istarget "*-*-cygwin*"] || [istarget "i?86-*-mingw*"]
+        || [istarget "*-*-msdosdjgpp*"] || [istarget "*-*-go32*"] } {
+       return "additional_flags=-DSYMBOL_PREFIX=\"_\""
+    } else {
+       return ""
+    }
+}
+
+# Always load compatibility stuff.
+load_lib future.exp