[gdb/testsuite] Catch condition evaluation errors in gdb_assert
[deliverable/binutils-gdb.git] / gdb / testsuite / lib / gdb.exp
index 2d230b791ee54882fc9bed3e6721e67cab56a44d..59439f8e37975acffb006e07e738ab73ec2183e1 100644 (file)
@@ -25,10 +25,65 @@ if {$tool == ""} {
     exit 2
 }
 
+# List of procs to run in gdb_finish.
+set gdb_finish_hooks [list]
+
+# Variable in which we keep track of globals that are allowed to be live
+# across test-cases.
+array set gdb_persistent_globals {}
+
+# Mark variable names in ARG as a persistent global, and declare them as
+# global in the calling context.  Can be used to rewrite "global var_a var_b"
+# into "gdb_persistent_global var_a var_b".
+proc gdb_persistent_global { args } {
+    global gdb_persistent_globals
+    foreach varname $args {
+       uplevel 1 global $varname
+       set gdb_persistent_globals($varname) 1
+    }
+}
+
+# Mark variable names in ARG as a persistent global.
+proc gdb_persistent_global_no_decl { args } {
+    global gdb_persistent_globals
+    foreach varname $args {
+       set gdb_persistent_globals($varname) 1
+    }
+}
+
+# Override proc load_lib.
+rename load_lib saved_load_lib
+# Run the runtest version of load_lib, and mark all variables that were
+# created by this call as persistent.
+proc load_lib { file } {
+    array set known_global {}
+    foreach varname [info globals] {
+       set known_globals($varname) 1
+    }
+
+    set code [catch "saved_load_lib $file" result]
+
+    foreach varname [info globals] {
+       if { ![info exists known_globals($varname)] } {
+           gdb_persistent_global_no_decl $varname
+       }
+    }
+
+    if {$code == 1} {
+       global errorInfo errorCode
+       return -code error -errorinfo $errorInfo -errorcode $errorCode $result
+    } elseif {$code > 1} {
+       return -code $code $result
+    }
+
+    return $result
+}
+
 load_lib libgloss.exp
 load_lib cache.exp
 load_lib gdb-utils.exp
 load_lib memory.exp
+load_lib check-test-names.exp
 
 global GDB
 
@@ -117,7 +172,7 @@ if ![info exists env(EXEEXT)] {
 
 set octal "\[0-7\]+"
 
-set inferior_exited_re "(\\\[Inferior \[0-9\]+ \\(.*\\) exited)"
+set inferior_exited_re "(?:\\\[Inferior \[0-9\]+ \\(\[^\n\r\]*\\) exited)"
 
 # A regular expression that matches a value history number.
 # E.g., $1, $2, etc.
@@ -159,7 +214,6 @@ proc gdb_version { } {
 #
 
 proc gdb_unload {} {
-    global verbose
     global GDB
     global gdb_prompt
     send_gdb "file\n"
@@ -242,14 +296,19 @@ proc target_can_use_run_cmd {} {
 
 # Generic run command.
 #
+# Return 0 if we could start the program, -1 if we could not.
+#
 # The second pattern below matches up to the first newline *only*.
 # Using ``.*$'' could swallow up output that we attempt to match
 # elsewhere.
 #
+# INFERIOR_ARGS is passed as arguments to the start command, so may contain
+# inferior arguments.
+#
 # 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} {
+proc gdb_run_cmd { {inferior_args {}} } {
     global gdb_prompt use_gdb_stub
 
     foreach command [gdb_init_commands] {
@@ -265,15 +324,15 @@ proc gdb_run_cmd {args} {
 
     if $use_gdb_stub {
        if [target_info exists gdb,do_reload_on_run] {
-           if { [gdb_reload] != 0 } {
-               return
+           if { [gdb_reload $inferior_args] != 0 } {
+               return -1
            }
            send_gdb "continue\n"
            gdb_expect 60 {
                -re "Continu\[^\r\n\]*\[\r\n\]" {}
                default {}
            }
-           return
+           return 0
        }
 
        if [target_info exists gdb,start_symbol] {
@@ -289,7 +348,7 @@ proc gdb_run_cmd {args} {
            # clever and not send a command when it has failed.
            if [expr $start_attempt > 3] {
                perror "Jump to start() failed (retry count exceeded)"
-               return
+               return -1
            }
            set start_attempt [expr $start_attempt + 1]
            gdb_expect 30 {
@@ -298,7 +357,7 @@ proc gdb_run_cmd {args} {
                }
                -re "No symbol \"_start\" in current.*$gdb_prompt $" {
                    perror "Can't find start symbol to run in gdb_run"
-                   return
+                   return -1
                }
                -re "No symbol \"start\" in current.*$gdb_prompt $" {
                    send_gdb "jump *_start\n"
@@ -310,26 +369,27 @@ proc gdb_run_cmd {args} {
                    send_gdb "y\n" answer
                }
                -re "The program is not being run.*$gdb_prompt $" {
-                   if { [gdb_reload] != 0 } {
-                       return
+                   if { [gdb_reload $inferior_args] != 0 } {
+                       return -1
                    }
                    send_gdb "jump *$start\n"
                }
                timeout {
                    perror "Jump to start() failed (timeout)"
-                   return
+                   return -1
                }
            }
        }
-       return
+
+       return 0
     }
 
     if [target_info exists gdb,do_reload_on_run] {
-       if { [gdb_reload] != 0 } {
-           return
+       if { [gdb_reload $inferior_args] != 0 } {
+           return -1
        }
     }
-    send_gdb "run $args\n"
+    send_gdb "run $inferior_args\n"
 # This doesn't work quite right yet.
 # Use -notransfer here so that test cases (like chng-sym.exp)
 # may test for additional start-up messages.
@@ -343,15 +403,20 @@ proc gdb_run_cmd {args} {
            # There is no more input expected.
        }
     }
+
+    return 0
 }
 
 # Generic start command.  Return 0 if we could start the program, -1
 # if we could not.
 #
+# INFERIOR_ARGS is passed as arguments to the start command, so may contain
+# inferior arguments.
+#
 # 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} {
+proc gdb_start_cmd { {inferior_args {}} } {
     global gdb_prompt use_gdb_stub
 
     foreach command [gdb_init_commands] {
@@ -369,7 +434,7 @@ proc gdb_start_cmd {args} {
        return -1
     }
 
-    send_gdb "start $args\n"
+    send_gdb "start $inferior_args\n"
     # Use -notransfer here so that test cases (like chng-sym.exp)
     # may test for additional start-up messages.
     gdb_expect 60 {
@@ -387,10 +452,13 @@ proc gdb_start_cmd {args} {
 # Generic starti command.  Return 0 if we could start the program, -1
 # if we could not.
 #
+# INFERIOR_ARGS is passed as arguments to the starti command, so may contain
+# inferior arguments.
+#
 # N.B. This function does not wait for gdb to return to the prompt,
 # that is the caller's responsibility.
 
-proc gdb_starti_cmd {args} {
+proc gdb_starti_cmd { {inferior_args {}} } {
     global gdb_prompt use_gdb_stub
 
     foreach command [gdb_init_commands] {
@@ -408,7 +476,7 @@ proc gdb_starti_cmd {args} {
        return -1
     }
 
-    send_gdb "starti $args\n"
+    send_gdb "starti $inferior_args\n"
     gdb_expect 60 {
        -re "The program .* has been started already.*y or n. $" {
            send_gdb "y\n" answer
@@ -584,9 +652,9 @@ proc runto { function args } {
            return 0
        }
        -re ".*A problem internal to GDB has been detected" {
-           if { $print_fail } {
-               fail "$test_name (GDB internal error)"
-           }
+           # Always emit a FAIL if we encounter an internal error: internal
+           # errors are never expected.
+           fail "$test_name (GDB internal error)"
            gdb_internal_error_resync
            return 0
        }
@@ -699,20 +767,22 @@ proc gdb_internal_error_resync {} {
 }
 
 
-# gdb_test_multiple COMMAND MESSAGE EXPECT_ARGUMENTS PROMPT_REGEXP
+# gdb_test_multiple COMMAND MESSAGE [ -promp PROMPT_REGEXP] [ -lbl ]
+#                   EXPECT_ARGUMENTS
 # Send a command to gdb; test the result.
 #
 # COMMAND is the command to execute, send to GDB with send_gdb.  If
 #   this is the null string no command is sent.
 # MESSAGE is a message to be printed with the built-in failure patterns
 #   if one of them matches.  If MESSAGE is empty COMMAND will be used.
+# -prompt PROMPT_REGEXP specifies a regexp matching the expected prompt
+#   after the command output.  If empty, defaults to "$gdb_prompt $".
+# -lbl specifies that line-by-line matching will be used.
 # EXPECT_ARGUMENTS will be fed to expect in addition to the standard
 #   patterns.  Pattern elements will be evaluated in the caller's
 #   context; action elements will be executed in the caller's context.
 #   Unlike patterns for gdb_test, these patterns should generally include
 #   the final newline and prompt.
-# PROMPT_REGEXP is a regexp matching the expected prompt after the command
-#   output.  If empty, defaults to "$gdb_prompt $"
 #
 # Returns:
 #    1 if the test failed, according to a built-in failure pattern
@@ -792,7 +862,7 @@ proc gdb_internal_error_resync {} {
 #      }
 #    }
 #
-proc gdb_test_multiple { command message user_code { prompt_regexp "" } } {
+proc gdb_test_multiple { command message args } {
     global verbose use_gdb_stub
     global gdb_prompt pagination_prompt
     global GDB
@@ -802,6 +872,26 @@ proc gdb_test_multiple { command message user_code { prompt_regexp "" } } {
     upvar expect_out expect_out
     global any_spawn_id
 
+    set line_by_line 0
+    set prompt_regexp ""
+    for {set i 0} {$i < [llength $args]} {incr i} {
+       set arg [lindex $args $i]
+       if { $arg  == "-prompt" } {
+           incr i
+           set prompt_regexp [lindex $args $i]
+       } elseif { $arg == "-lbl" } {
+           set line_by_line 1
+       } else {
+           set user_code $arg
+           break
+       }
+    }
+    if { [expr $i + 1] < [llength $args] } {
+       error "Too many arguments to gdb_test_multiple"
+    } elseif { ![info exists user_code] } {
+       error "Too few arguments to gdb_test_multiple"
+    }
+
     if { "$prompt_regexp" == "" } {
        set prompt_regexp "$gdb_prompt $"
     }
@@ -1070,6 +1160,14 @@ proc gdb_test_multiple { command message user_code { prompt_regexp "" } } {
        }
     }
 
+    if {$line_by_line} {
+       append code {
+           -re "\r\n\[^\r\n\]*(?=\r\n)" {
+               exp_continue
+           }
+       }
+    }
+
     # Now patterns that apply to any spawn id specified.
     append code {
        -i $any_spawn_id
@@ -1138,6 +1236,28 @@ proc gdb_test_multiple { command message user_code { prompt_regexp "" } } {
     return $result
 }
 
+# Usage: gdb_test_multiline NAME INPUT RESULT {INPUT RESULT} ...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+
+proc gdb_test_multiline { name args } {
+    global gdb_prompt
+    set inputnr 0
+    foreach {input result} $args {
+       incr inputnr
+       if {[gdb_test_multiple $input "$name: input $inputnr: $input" {
+           -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+               pass $gdb_test_name
+           }
+       }]} {
+           return 1
+       }
+    }
+    return 0
+}
+
+
 # gdb_test COMMAND PATTERN MESSAGE QUESTION RESPONSE
 # Send a command to gdb; test the result.
 #
@@ -1569,8 +1689,8 @@ proc gdb_assert { condition {message ""} } {
        set message $condition
     }
 
-    set res [uplevel 1 expr $condition]
-    if {!$res} {
+    set code [catch {uplevel 1 expr $condition} res]
+    if {$code != 0 || !$res} {
        fail $message
     } else {
        pass $message
@@ -1617,7 +1737,6 @@ proc gdb_reinitialize_dir { subdir } {
 proc default_gdb_exit {} {
     global GDB
     global INTERNAL_GDBFLAGS GDBFLAGS
-    global verbose
     global gdb_spawn_id inferior_spawn_id
     global inotify_log_file
 
@@ -1683,7 +1802,6 @@ proc default_gdb_exit {} {
 
 proc gdb_file_cmd { arg } {
     global gdb_prompt
-    global verbose
     global GDB
     global last_loaded_file
 
@@ -1719,6 +1837,8 @@ proc gdb_file_cmd { arg } {
     }
 
     send_gdb "file $arg\n"
+    set new_symbol_table 0
+    set basename [file tail $arg]
     gdb_expect 120 {
        -re "Reading symbols from.*LZMA support was disabled.*$gdb_prompt $" {
            verbose "\t\tLoaded $arg into $GDB; .gnu_debugdata found but no LZMA available"
@@ -1736,45 +1856,40 @@ proc gdb_file_cmd { arg } {
            return 0
         }
         -re "Load new symbol table from \".*\".*y or n. $" {
+           if { $new_symbol_table > 0 } {
+               perror [join [list "Couldn't load $basename,"
+                             "interactive prompt loop detected."]]
+               return -1
+           }
             send_gdb "y\n" answer
-            gdb_expect 120 {
-                -re "Reading symbols from.*$gdb_prompt $" {
-                    verbose "\t\tLoaded $arg with new symbol table into $GDB"
-                   set gdb_file_cmd_debug_info "debug"
-                   return 0
-                }
-                timeout {
-                    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
-               }
-            }
+           incr new_symbol_table
+           set suffix "-- with new symbol table"
+           set arg "$arg $suffix"
+           set basename "$basename $suffix"
+           exp_continue
        }
         -re "No such file or directory.*$gdb_prompt $" {
-            perror "($arg) No such file or directory"
+            perror "($basename) No such file or directory"
            return -1
         }
        -re "A problem internal to GDB has been detected" {
-           fail "($arg) (GDB internal error)"
+           perror "Couldn't load $basename into GDB (GDB internal error)."
            gdb_internal_error_resync
            return -1
        }
         -re "$gdb_prompt $" {
-            perror "Couldn't load $arg into $GDB."
+            perror "Couldn't load $basename into GDB."
            return -1
             }
         timeout {
-            perror "Couldn't load $arg into $GDB (timeout)."
+            perror "Couldn't load $basename 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 (eof)."
+            perror "Couldn't load $basename into GDB (eof)."
            return -1
         }
     }
@@ -1867,6 +1982,11 @@ proc default_gdb_start { } {
            unset gdb_spawn_id
            return -1
        }
+       eof {
+           perror "(eof) GDB never initialized."
+           unset gdb_spawn_id
+           return -1
+       }
     }
 
     # force the height to "unlimited", so no pagers get used
@@ -1999,22 +2119,24 @@ proc skip_rust_tests {} {
 proc skip_python_tests_prompt { prompt_regexp } {
     global gdb_py_is_py3k
 
-    gdb_test_multiple "python print ('test')" "verify python support" {
-       -re "not supported.*$prompt_regexp" {
-           unsupported "Python support is disabled."
-           return 1
+    gdb_test_multiple "python print ('test')" "verify python support" \
+       -prompt "$prompt_regexp" {
+           -re "not supported.*$prompt_regexp" {
+               unsupported "Python support is disabled."
+               return 1
+           }
+           -re "$prompt_regexp" {}
        }
-       -re "$prompt_regexp" {}
-    } "$prompt_regexp"
 
-    gdb_test_multiple "python print (sys.version_info\[0\])" "check if python 3" {
-       -re "3.*$prompt_regexp" {
-            set gdb_py_is_py3k 1
-        }
-       -re ".*$prompt_regexp" {
-            set gdb_py_is_py3k 0
-        }
-    } "$prompt_regexp"
+    gdb_test_multiple "python print (sys.version_info\[0\])" "check if python 3" \
+       -prompt "$prompt_regexp" {
+           -re "3.*$prompt_regexp" {
+               set gdb_py_is_py3k 1
+           }
+           -re ".*$prompt_regexp" {
+               set gdb_py_is_py3k 0
+           }
+       }
 
     return 0
 }
@@ -2490,6 +2612,18 @@ gdb_caching_proc support_complex_tests {
     } executable]
 }
 
+# Return 1 if compiling go is supported.
+gdb_caching_proc support_go_compile {
+
+    return [gdb_can_simple_compile go-hello {
+       package main
+       import "fmt"
+       func main() {
+           fmt.Println("hello world")
+       }
+    } executable go]
+}
+
 # Return 1 if GDB can get a type for siginfo from the target, otherwise
 # return 0.
 
@@ -2927,6 +3061,57 @@ gdb_caching_proc skip_tsx_tests {
     return $skip_tsx_tests
 }
 
+# Run a test on the target to see if it supports avx512bf16.  Return 0 if so,
+# 1 if it does not.  Based on 'check_vmx_hw_available' from the GCC testsuite.
+
+gdb_caching_proc skip_avx512bf16_tests {
+    global srcdir subdir gdb_prompt inferior_exited_re
+
+    set me "skip_avx512bf16_tests"
+    if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+        verbose "$me:  target does not support avx512bf16, returning 1" 2
+        return 1
+    }
+
+    # Compile a test program.
+    set src {
+        int main() {
+            asm volatile ("vcvtne2ps2bf16 %xmm0, %xmm1, %xmm0");
+            return 0;
+        }
+    }
+    if {![gdb_simple_compile $me $src executable]} {
+        return 1
+    }
+
+    # No error message, compilation succeeded so now run it via gdb.
+
+    gdb_exit
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_load "$obj"
+    gdb_run_cmd
+    gdb_expect {
+        -re ".*Illegal instruction.*${gdb_prompt} $" {
+            verbose -log "$me:  avx512bf16 hardware not detected."
+            set skip_avx512bf16_tests 1
+        }
+        -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+            verbose -log "$me:  avx512bf16 hardware detected."
+            set skip_avx512bf16_tests 0
+        }
+        default {
+            warning "\n$me:  default case taken."
+            set skip_avx512bf16_tests 1
+        }
+    }
+    gdb_exit
+    remote_file build delete $obj
+
+    verbose "$me:  returning $skip_avx512bf16_tests" 2
+    return $skip_avx512bf16_tests
+}
+
 # Run a test on the target to see if it supports btrace hardware.  Return 0 if so,
 # 1 if it does not.  Based on 'check_vmx_hw_available' from the GCC testsuite.
 
@@ -3256,13 +3441,14 @@ proc skip_unwinder_tests {} {
 
 proc skip_libstdcxx_probe_tests_prompt { prompt_regexp } {
     set supported 0
-    gdb_test_multiple "info probe" "check for stap probe in libstdc++" {
-       -re ".*libstdcxx.*catch.*\r\n$prompt_regexp" {
-           set supported 1
-       }
-       -re "\r\n$prompt_regexp" {
+    gdb_test_multiple "info probe" "check for stap probe in libstdc++" \
+       -prompt "$prompt_regexp" {
+           -re ".*libstdcxx.*catch.*\r\n$prompt_regexp" {
+               set supported 1
+           }
+           -re "\r\n$prompt_regexp" {
+           }
        }
-    } "$prompt_regexp"
     set skip [expr !$supported]
     return $skip
 }
@@ -3302,15 +3488,16 @@ proc skip_compile_feature_tests {} {
 
 proc gdb_is_target_1 { target_name target_stack_regexp prompt_regexp } {
     set test "probe for target ${target_name}"
-    gdb_test_multiple "maint print target-stack" $test {
-       -re "${target_stack_regexp}${prompt_regexp}" {
-           pass $test
-           return 1
-       }
-       -re "$prompt_regexp" {
-           pass $test
+    gdb_test_multiple "maint print target-stack" $test \
+       -prompt "$prompt_regexp" {
+           -re "${target_stack_regexp}${prompt_regexp}" {
+               pass $test
+               return 1
+           }
+           -re "$prompt_regexp" {
+               pass $test
+           }
        }
-    } "$prompt_regexp"
     return 0
 }
 
@@ -3558,6 +3745,8 @@ proc current_target_name { } {
 
 set gdb_wrapper_initialized 0
 set gdb_wrapper_target ""
+set gdb_wrapper_file ""
+set gdb_wrapper_flags ""
 
 proc gdb_wrapper_init { args } {
     global gdb_wrapper_initialized
@@ -3572,11 +3761,18 @@ proc gdb_wrapper_init { args } {
        set result [build_wrapper "testglue.o"]
        if { $result != "" } {
            set gdb_wrapper_file [lindex $result 0]
+           if ![is_remote host] {
+               set gdb_wrapper_file [file join [pwd] $gdb_wrapper_file]
+           }
            set gdb_wrapper_flags [lindex $result 1]
        } else {
            warning "Status wrapper failed to build."
        }
+    } else {
+       set gdb_wrapper_file ""
+       set gdb_wrapper_flags ""
     }
+    verbose "set gdb_wrapper_file = $gdb_wrapper_file"
     set gdb_wrapper_initialized 1
     set gdb_wrapper_target [current_target_name]
 }
@@ -3631,7 +3827,14 @@ proc gdb_simple_compile {name code {type object} {compile_flags {}} {object obj}
             set postfix "s"
         }
     }
-    set src [standard_temp_file $name-[pid].c]
+    set ext "c"
+    foreach flag $compile_flags {
+       if { "$flag" == "go" } {
+           set ext "go"
+           break
+       }
+    }
+    set src [standard_temp_file $name-[pid].$ext]
     set obj [standard_temp_file $name-[pid].$postfix]
     set compile_flags [concat $compile_flags {debug nowarnings quiet}]
 
@@ -3696,7 +3899,8 @@ set gdb_saved_set_unbuffered_mode_obj ""
 #   - ldflags=flag: Add FLAG to the linker flags.
 #   - incdir=path: Add PATH to the searched include directories.
 #   - libdir=path: Add PATH to the linker searched directories.
-#   - ada, c++, f77: Compile the file as Ada, C++ or Fortran.
+#   - ada, c++, f77, f90, go, rust: Compile the file as Ada, C++,
+#     Fortran 77, Fortran 90, Go or Rust.
 #   - debug: Build with debug information.
 #   - optimize: Build with optimization.
 
@@ -3704,7 +3908,6 @@ proc gdb_compile {source dest type options} {
     global GDB_TESTCASE_OPTIONS
     global gdb_wrapper_file
     global gdb_wrapper_flags
-    global gdb_wrapper_initialized
     global srcdir
     global objdir
     global gdb_saved_set_unbuffered_mode_obj
@@ -3720,6 +3923,31 @@ proc gdb_compile {source dest type options} {
        set new_options [universal_compile_options]
     }
 
+    # Some C/C++ testcases unconditionally pass -Wno-foo as additional
+    # options to disable some warning.  That is OK with GCC, because
+    # by design, GCC accepts any -Wno-foo option, even if it doesn't
+    # support -Wfoo.  Clang however warns about unknown -Wno-foo by
+    # default, unless you pass -Wno-unknown-warning-option as well.
+    # We do that here, so that individual testcases don't have to
+    # worry about it.
+    if {[lsearch -exact $options getting_compiler_info] == -1
+       && [lsearch -exact $options rust] == -1
+       && [lsearch -exact $options ada] == -1
+       && [lsearch -exact $options f77] == -1
+       && [lsearch -exact $options f90] == -1
+       && [lsearch -exact $options go] == -1
+       && [test_compiler_info "clang-*"]} {
+       lappend new_options "additional_flags=-Wno-unknown-warning-option"
+    }
+
+    # Treating .c input files as C++ is deprecated in Clang, so
+    # explicitly force C++ language.
+    if { [lsearch -exact $options getting_compiler_info] == -1
+        && [lsearch -exact $options c++] != -1
+        && [test_compiler_info "clang-*"]} {
+       lappend new_options additional_flags=-x\ c++
+    }
+
     # Place (and look for) Fortran `.mod` files in the output
     # directory for this specific test.
     if {[lsearch -exact $options f77] != -1 \
@@ -3812,11 +4040,11 @@ proc gdb_compile {source dest type options} {
     verbose "options are $options"
     verbose "source is $source $dest $type $options"
 
-    if { $gdb_wrapper_initialized == 0 } { gdb_wrapper_init }
+    gdb_wrapper_init
 
     if {[target_info exists needs_status_wrapper] && \
            [target_info needs_status_wrapper] != "0" && \
-           [info exists gdb_wrapper_file]} {
+           $gdb_wrapper_file != "" } {
        lappend options "libs=${gdb_wrapper_file}"
        lappend options "ldflags=${gdb_wrapper_flags}"
     }
@@ -4589,7 +4817,7 @@ proc gdb_core_cmd { core test } {
            fail "$test (bad file format)"
            return -1
        }
-       -re ": No such file or directory.*\r\n$gdb_prompt $" {
+       -re -wrap "[string_to_regexp $core]: No such file or directory.*" {
            fail "$test (file not found)"
            return -1
        }
@@ -4753,8 +4981,13 @@ proc gdb_load { arg } {
 # either the first time or after already starting the program once,
 # for remote targets.  Most files that override gdb_load should now
 # override this instead.
+#
+# INFERIOR_ARGS contains the arguments to pass to the inferiors, as a
+# single string to get interpreted by a shell.  If the target board
+# overriding gdb_reload is a "stub", then it should arrange things such
+# these arguments make their way to the inferior process.
 
-proc gdb_reload { } {
+proc gdb_reload { {inferior_args {}} } {
     # For the benefit of existing configurations, default to gdb_load.
     # Specifying no file defaults to the executable currently being
     # debugged.
@@ -4767,6 +5000,7 @@ proc gdb_continue { function } {
     return [gdb_test "continue" ".*Breakpoint $decimal, $function .*" "continue to $function"]
 }
 
+# Default implementation of gdb_init.
 proc default_gdb_init { test_file_name } {
     global gdb_wrapper_initialized
     global gdb_wrapper_target
@@ -4774,6 +5008,107 @@ proc default_gdb_init { test_file_name } {
     global cleanfiles
     global pf_prefix
     
+    # Reset the timeout value to the default.  This way, any testcase
+    # that changes the timeout value without resetting it cannot affect
+    # the timeout used in subsequent testcases.
+    global gdb_test_timeout
+    global timeout
+    set timeout $gdb_test_timeout
+
+    if { [regexp ".*gdb\.reverse\/.*" $test_file_name]
+        && [target_info exists gdb_reverse_timeout] } {
+       set timeout [target_info gdb_reverse_timeout]
+    }
+
+    # If GDB_INOTIFY is given, check for writes to '.'.  This is a
+    # debugging tool to help confirm that the test suite is
+    # parallel-safe.  You need "inotifywait" from the
+    # inotify-tools package to use this.
+    global GDB_INOTIFY inotify_pid
+    if {[info exists GDB_INOTIFY] && ![info exists inotify_pid]} {
+       global outdir tool inotify_log_file
+
+       set exclusions {outputs temp gdb[.](log|sum) cache}
+       set exclusion_re ([join $exclusions |])
+
+       set inotify_log_file [standard_temp_file inotify.out]
+       set inotify_pid [exec inotifywait -r -m -e move,create,delete . \
+                            --exclude $exclusion_re \
+                            |& tee -a $outdir/$tool.log $inotify_log_file &]
+
+       # Wait for the watches; hopefully this is long enough.
+       sleep 2
+
+       # Clear the log so that we don't emit a warning the first time
+       # we check it.
+       set fd [open $inotify_log_file w]
+       close $fd
+    }
+
+    # 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"
+
+    # This disables style output, which would interfere with many
+    # tests.
+    setenv TERM "dumb"
+
+    # Ensure that GDBHISTFILE and GDBHISTSIZE are removed from the
+    # environment, we don't want these modifications to the history
+    # settings.
+    unset -nocomplain ::env(GDBHISTFILE)
+    unset -nocomplain ::env(GDBHISTSIZE)
+
+    # Initialize GDB's pty with a fixed size, to make sure we avoid pagination
+    # during startup.  See "man expect" for details about stty_init.
+    global stty_init
+    set stty_init "rows 25 cols 80"
+
+    # Some tests (for example gdb.base/maint.exp) shell out from gdb to use
+    # grep.  Clear GREP_OPTIONS to make the behavior 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
+
+    # Clear $last_loaded_file
+    global last_loaded_file
+    unset -nocomplain last_loaded_file
+
+    # Reset GDB number of instances
+    global gdb_instances
+    set gdb_instances 0
+
     set cleanfiles {}
 
     gdb_clear_suppressed
@@ -4807,6 +5142,22 @@ proc default_gdb_init { test_file_name } {
     if [info exists use_gdb_stub] {
        unset use_gdb_stub
     }
+
+    gdb_setup_known_globals
+
+    if { [info procs ::gdb_tcl_unknown] != "" } {
+       # Dejagnu overrides proc unknown.  The dejagnu version may trigger in a
+       # test-case but abort the entire test run.  To fix this, we install a
+       # local version here, which reverts dejagnu's override, and restore
+       # dejagnu's version in gdb_finish.
+       rename ::unknown ::dejagnu_unknown
+       proc unknown { args } {
+           # Use tcl's unknown.
+           set cmd [lindex $args 0]
+           unresolved "testcase aborted due to invalid command name: $cmd"
+           return [uplevel 1 ::gdb_tcl_unknown $args]
+       }
+    }
 }
 
 # Return a path using GDB_PARALLEL.
@@ -4840,7 +5191,7 @@ proc standard_output_file {basename} {
     file mkdir $dir
     # If running on MinGW, replace /c/foo with c:/foo
     if { [ishost *-*-mingw*] } {
-        set dir [regsub {^/([a-z])/} $dir {\1:/}]
+        set dir [exec sh -c "cd ${dir} && pwd -W"]
     }
     return [file join $dir $basename]
 }
@@ -4870,6 +5221,51 @@ proc standard_temp_file {basename} {
     return [file join $dir $basename]
 }
 
+# Rename file A to file B, if B does not already exists.  Otherwise, leave B
+# as is and delete A.  Return 1 if rename happened.
+
+proc tentative_rename { a b } {
+    global errorInfo errorCode
+    set code [catch {file rename -- $a $b} result]
+    if { $code == 1 && [lindex $errorCode 0] == "POSIX" \
+            && [lindex $errorCode 1] == "EEXIST" } {
+       file delete $a
+       return 0
+    }
+    if {$code == 1} {
+       return -code error -errorinfo $errorInfo -errorcode $errorCode $result
+    } elseif {$code > 1} {
+       return -code $code $result
+    }
+    return 1
+}
+
+# Create a file with name FILENAME and contents TXT in the cache directory.
+# If EXECUTABLE, mark the new file for execution.
+
+proc cached_file { filename txt {executable 0}} {
+    set filename [make_gdb_parallel_path cache $filename]
+
+    if { [file exists $filename] } {
+       return $filename
+    }
+
+    set dir [file dirname $filename]
+    file mkdir $dir
+
+    set tmp_filename $filename.[pid]
+    set fd [open $tmp_filename w]
+    puts $fd $txt
+    close $fd
+
+    if { $executable } {
+       exec chmod +x $tmp_filename
+    }
+    tentative_rename $tmp_filename $filename
+
+    return $filename
+}
+
 # Set 'testfile', 'srcfile', and 'binfile'.
 #
 # ARGS is a list of source file specifications.
@@ -4965,105 +5361,73 @@ set banned_procedures { strace }
 # if the banned variables and procedures are already traced.
 set banned_traced 0
 
-proc gdb_init { test_file_name } {
-    # Reset the timeout value to the default.  This way, any testcase
-    # that changes the timeout value without resetting it cannot affect
-    # the timeout used in subsequent testcases.
-    global gdb_test_timeout
-    global timeout
-    set timeout $gdb_test_timeout
-
-    if { [regexp ".*gdb\.reverse\/.*" $test_file_name]
-        && [target_info exists gdb_reverse_timeout] } {
-       set timeout [target_info gdb_reverse_timeout]
-    }
-
-    # If GDB_INOTIFY is given, check for writes to '.'.  This is a
-    # debugging tool to help confirm that the test suite is
-    # parallel-safe.  You need "inotifywait" from the
-    # inotify-tools package to use this.
-    global GDB_INOTIFY inotify_pid
-    if {[info exists GDB_INOTIFY] && ![info exists inotify_pid]} {
-       global outdir tool inotify_log_file
-
-       set exclusions {outputs temp gdb[.](log|sum) cache}
-       set exclusion_re ([join $exclusions |])
-
-       set inotify_log_file [standard_temp_file inotify.out]
-       set inotify_pid [exec inotifywait -r -m -e move,create,delete . \
-                            --exclude $exclusion_re \
-                            |& tee -a $outdir/$tool.log $inotify_log_file &]
+# Global array that holds the name of all global variables at the time
+# a test script is started.  After the test script has completed any
+# global not in this list is deleted.
+array set gdb_known_globals {}
 
-       # Wait for the watches; hopefully this is long enough.
-       sleep 2
+# Setup the GDB_KNOWN_GLOBALS array with the names of all current
+# global variables.
+proc gdb_setup_known_globals {} {
+    global gdb_known_globals
 
-       # Clear the log so that we don't emit a warning the first time
-       # we check it.
-       set fd [open $inotify_log_file w]
-       close $fd
+    array set gdb_known_globals {}
+    foreach varname [info globals] {
+       set gdb_known_globals($varname) 1
     }
+}
 
-    # 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
+# Cleanup the global namespace.  Any global not in the
+# GDB_KNOWN_GLOBALS array is unset, this ensures we don't "leak"
+# globals from one test script to another.
+proc gdb_cleanup_globals {} {
+    global gdb_known_globals gdb_persistent_globals
+
+    foreach varname [info globals] {
+       if {![info exists gdb_known_globals($varname)]} {
+           if { [info exists gdb_persistent_globals($varname)] } {
+               continue
+           }
+           uplevel #0 unset $varname
        }
-       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"
-
-    # This disables style output, which would interfere with many
-    # tests.
-    setenv TERM "dumb"
-
-    # Initialize GDB's pty with a fixed size, to make sure we avoid pagination
-    # during startup.  See "man expect" for details about stty_init.
-    global stty_init
-    set stty_init "rows 25 cols 80"
-
-    # Some tests (for example gdb.base/maint.exp) shell out from gdb to use
-    # grep.  Clear GREP_OPTIONS to make the behavior 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
-
-    # Reset GDB number of instances
-    global gdb_instances
-    set gdb_instances 0
+# Create gdb_tcl_unknown, a copy tcl's ::unknown, provided it's present as a
+# proc.
+set temp [interp create]
+if { [interp eval $temp "info procs ::unknown"] != "" } {
+    set old_args [interp eval $temp "info args ::unknown"]
+    set old_body [interp eval $temp "info body ::unknown"]
+    eval proc gdb_tcl_unknown {$old_args} {$old_body}
+}
+interp delete $temp
+unset temp
 
-    return [default_gdb_init $test_file_name]
+# GDB implementation of ${tool}_init.  Called right before executing the
+# test-case.
+# Overridable function -- you can override this function in your
+# baseboard file.
+proc gdb_init { args } {
+    # A baseboard file overriding this proc and calling the default version
+    # should behave the same as this proc.  So, don't add code here, but to
+    # the default version instead.
+    return [default_gdb_init {*}$args]
 }
 
+# GDB implementation of ${tool}_finish.  Called right after executing the
+# test-case.
 proc gdb_finish { } {
     global gdbserver_reconnect_p
     global gdb_prompt
     global cleanfiles
+    global known_globals
+
+    if { [info procs ::gdb_tcl_unknown] != "" } {
+       # Restore dejagnu's version of proc unknown.
+       rename ::unknown ""
+       rename ::dejagnu_unknown ::unknown
+    }
 
     # Exit first, so that the files are no longer in use.
     gdb_exit
@@ -5089,6 +5453,14 @@ proc gdb_finish { } {
        }
        set banned_traced 0
     }
+
+    global gdb_finish_hooks
+    foreach gdb_finish_hook $gdb_finish_hooks {
+       $gdb_finish_hook
+    }
+    set gdb_finish_hooks [list]
+
+    gdb_cleanup_globals
 }
 
 global debug_format
@@ -5099,7 +5471,6 @@ set debug_format "unknown"
 
 proc get_debug_format { } {
     global gdb_prompt
-    global verbose
     global expect_out
     global debug_format
 
@@ -5390,11 +5761,15 @@ proc exec_is_pie { executable } {
        return -1
     }
     set readelf_program [gdb_find_readelf]
-    set res [catch {exec $readelf_program -d $executable} output]
+    # We're not testing readelf -d | grep "FLAGS_1.*Flags:.*PIE"
+    # because the PIE flag is not set by all versions of gold, see PR
+    # binutils/26039.
+    set res [catch {exec $readelf_program -h $executable} output]
     if { $res != 0 } {
        return -1
     }
-    set res [regexp -line {\(FLAGS_1\).*Flags:.* PIE($| )} $output]
+    set res [regexp -line {^[ \t]*Type:[ \t]*DYN \(Shared object file\)$} \
+                $output]
     if { $res == 1 } {
        return 1
     }
@@ -5984,24 +6359,44 @@ proc build_executable { testname executable {sources ""} {options {debug}} } {
 # Starts fresh GDB binary and loads an optional executable into GDB.
 # Usage: clean_restart [executable]
 # EXECUTABLE is the basename of the binary.
+# Return -1 if starting gdb or loading the executable failed.
 
 proc clean_restart { args } {
     global srcdir
     global subdir
+    global errcnt
+    global warncnt
 
     if { [llength $args] > 1 } {
        error "bad number of args: [llength $args]"
     }
 
     gdb_exit
+
+    # This is a clean restart, so reset error and warning count.
+    set errcnt 0
+    set warncnt 0
+
+    # We'd like to do:
+    #   if { [gdb_start] == -1 } {
+    #     return -1
+    #   }
+    # but gdb_start is a ${tool}_start proc, which doesn't have a defined
+    # return value.  So instead, we test for errcnt.
     gdb_start
+    if { $errcnt > 0 } {
+       return -1
+    }
+
     gdb_reinitialize_dir $srcdir/$subdir
 
     if { [llength $args] >= 1 } {
        set executable [lindex $args 0]
        set binfile [standard_output_file ${executable}]
-       gdb_load ${binfile}
+       return [gdb_load ${binfile}]
     }
+
+    return 0
 }
 
 # Prepares for testing by calling build_executable_full, then
@@ -6060,6 +6455,30 @@ proc get_valueof { fmt exp default {test ""} } {
     return ${val}
 }
 
+# Retrieve the value of local var EXP in the inferior.  DEFAULT is used as
+# fallback if print fails.  TEST is the test message to use.  It can be
+# omitted, in which case a test message is built from EXP.
+
+proc get_local_valueof { exp default {test ""} } {
+    global gdb_prompt
+
+    if {$test == "" } {
+       set test "get local valueof \"${exp}\""
+    }
+
+    set val ${default}
+    gdb_test_multiple "info locals ${exp}" "$test" {
+       -re "$exp = (\[^\r\n\]*)\[\r\n\]*$gdb_prompt $" {
+           set val $expect_out(1,string)
+           pass "$test"
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
+    }
+    return ${val}
+}
+
 # Retrieve the value of EXP in the inferior, as a signed decimal value
 # (using "print /d").  DEFAULT is used as fallback if print fails.
 # TEST is the test message to use.  It can be omitted, in which case
@@ -6749,7 +7168,7 @@ proc gdbserver_debug_enabled { } {
 # Open the file for logging gdb input
 
 proc gdb_stdin_log_init { } {
-    global in_file
+    gdb_persistent_global in_file
 
     if {[info exists in_file]} {
       # Close existing file.
@@ -6824,9 +7243,16 @@ proc cmp_file_string { file str msg } {
 }
 
 # Does the compiler support CTF debug output using '-gt' compiler
-# flag?  If not then we should skip these tests.
+# flag?  If not then we should skip these tests.  We should also
+# skip them if libctf was explicitly disabled.
 
 gdb_caching_proc skip_ctf_tests {
+    global enable_libctf
+
+    if {$enable_libctf eq "no"} {
+       return 1
+    }
+
     return ![gdb_can_simple_compile ctfdebug {
        int main () {
            return 0;
@@ -6834,5 +7260,259 @@ gdb_caching_proc skip_ctf_tests {
     } executable "additional_flags=-gt"]
 }
 
+# Return 1 if compiler supports -gstatement-frontiers.  Otherwise,
+# return 0.
+
+gdb_caching_proc supports_statement_frontiers {
+    return [gdb_can_simple_compile supports_statement_frontiers {
+       int main () {
+           return 0;
+       }
+    } executable "additional_flags=-gstatement-frontiers"]
+}
+
+# Return 1 if compiler supports -mmpx -fcheck-pointer-bounds.  Otherwise,
+# return 0.
+
+gdb_caching_proc supports_mpx_check_pointer_bounds {
+    set flags "additional_flags=-mmpx additional_flags=-fcheck-pointer-bounds"
+    return [gdb_can_simple_compile supports_mpx_check_pointer_bounds {
+       int main () {
+           return 0;
+       }
+    } executable $flags]
+}
+
+# Return 1 if compiler supports -fcf-protection=.  Otherwise,
+# return 0.
+
+gdb_caching_proc supports_fcf_protection {
+    return [gdb_can_simple_compile supports_fcf_protection {
+       int main () {
+           return 0;
+       }
+  } executable "additional_flags=-fcf-protection=full"]
+}
+
+# Return 1 if symbols were read in using -readnow.  Otherwise, return 0.
+
+proc readnow { } {
+    set cmd "maint print objfiles"
+    gdb_test_multiple $cmd "" {
+       -re -wrap "\r\n.gdb_index: faked for \"readnow\"\r\n.*" {
+           return 1
+       }
+       -re -wrap "" {
+           return 0
+       }
+    }
+
+    return 0
+}
+
+# Return 1 if partial symbols are available.  Otherwise, return 0.
+
+proc psymtabs_p {  } {
+    global gdb_prompt
+
+    set cmd "maint info psymtab"
+    gdb_test_multiple $cmd "" {
+       -re "$cmd\r\n$gdb_prompt $" {
+           return 0
+       }
+       -re -wrap "" {
+           return 1
+       }
+    }
+
+    return 0
+}
+
+# Verify that partial symtab expansion for $filename has state $readin.
+
+proc verify_psymtab_expanded { filename readin } {
+    global gdb_prompt
+
+    set cmd "maint info psymtab"
+    set test "$cmd: $filename: $readin"
+    set re [multi_line \
+               "  \{ psymtab \[^\r\n\]*$filename\[^\r\n\]*" \
+               "    readin $readin" \
+               ".*"]
+
+    gdb_test_multiple $cmd $test {
+       -re "$cmd\r\n$gdb_prompt $" {
+           unsupported $gdb_test_name
+       }
+       -re -wrap $re {
+           pass $gdb_test_name
+       }
+    }
+}
+
+# Add a .gdb_index section to PROGRAM.
+# PROGRAM is assumed to be the output of standard_output_file.
+# Returns the 0 if there is a failure, otherwise 1.
+
+proc add_gdb_index { program } {
+    global srcdir GDB env BUILD_DATA_DIRECTORY
+    set contrib_dir "$srcdir/../contrib"
+    set env(GDB) "$GDB --data-directory=$BUILD_DATA_DIRECTORY"
+    set result [catch "exec $contrib_dir/gdb-add-index.sh $program" output]
+    if { $result != 0 } {
+       verbose -log "result is $result"
+       verbose -log "output is $output"
+       return 0
+    }
+
+    return 1
+}
+
+# Add a .gdb_index section to PROGRAM, unless it alread has an index
+# (.gdb_index/.debug_names).  Gdb doesn't support building an index from a
+# program already using one.  Return 1 if a .gdb_index was added, return 0
+# if it already contained an index, and -1 if an error occurred.
+
+proc ensure_gdb_index { binfile } {
+    set testfile [file tail $binfile]
+    set test "check if index present"
+    gdb_test_multiple "mt print objfiles ${testfile}" $test {
+       -re -wrap "gdb_index.*" {
+           return 0
+       }
+       -re -wrap "debug_names.*" {
+           return 0
+       }
+       -re -wrap "Psymtabs.*" {
+           if { [add_gdb_index $binfile] != "1" } {
+               return -1
+           }
+           return 1
+       }
+    }
+    return -1
+}
+
+# Return 1 if executable contains .debug_types section.  Otherwise, return 0.
+
+proc debug_types { } {
+    global hex
+
+    set cmd "maint info sections"
+    gdb_test_multiple $cmd "" {
+       -re -wrap "at $hex: .debug_types.*" {
+           return 1
+       }
+       -re -wrap "" {
+           return 0
+       }
+    }
+
+    return 0
+}
+
+# Return the addresses in the line table for FILE for which is_stmt is true.
+
+proc is_stmt_addresses { file } {
+    global decimal
+    global hex
+
+    set is_stmt [list]
+
+    gdb_test_multiple "maint info line-table $file" "" {
+       -re "\r\n$decimal\[ \t\]+$decimal\[ \t\]+($hex)\[ \t\]+Y\[^\r\n\]*" {
+           lappend is_stmt $expect_out(1,string)
+           exp_continue
+       }
+       -re -wrap "" {
+       }
+    }
+
+    return $is_stmt
+}
+
+# Return 1 if hex number VAL is an element of HEXLIST.
+
+proc hex_in_list { val hexlist } {
+    # Normalize val by removing 0x prefix, and leading zeros.
+    set val [regsub ^0x $val ""]
+    set val [regsub ^0+ $val "0"]
+
+    set re 0x0*$val
+    set index [lsearch -regexp $hexlist $re]
+    return [expr $index != -1]
+}
+
+# Override proc NAME to proc OVERRIDE for the duration of the execution of
+# BODY.
+
+proc with_override { name override body } {
+    # Implementation note: It's possible to implement the override using
+    # rename, like this:
+    #   rename $name save_$name
+    #   rename $override $name
+    #   set code [catch {uplevel 1 $body} result]
+    #   rename $name $override
+    #   rename save_$name $name
+    # but there are two issues here:
+    # - the save_$name might clash with an existing proc
+    # - the override is no longer available under its original name during
+    #   the override
+    # So, we use this more elaborate but cleaner mechanism.
+
+    # Save the old proc.
+    set old_args [info args $name]
+    set old_body [info body $name]
+
+    # Install the override.
+    set new_args [info args $override]
+    set new_body [info body $override]
+    eval proc $name {$new_args} {$new_body}
+
+    # Execute body.
+    set code [catch {uplevel 1 $body} result]
+
+    # Restore old proc.
+    eval proc $name {$old_args} {$old_body}
+
+    # Return as appropriate.
+    if { $code == 1 } {
+        global errorInfo errorCode
+        return -code error -errorinfo $errorInfo -errorcode $errorCode $result
+    } elseif { $code > 1 } {
+        return -code $code $result
+    }
+
+    return $result
+}
+
+# Setup tuiterm.exp environment.  To be used in test-cases instead of
+# "load_lib tuiterm.exp".  Calls initialization function and schedules
+# finalization function.
+proc tuiterm_env { } {
+    load_lib tuiterm.exp
+
+    # Do initialization.
+    tuiterm_env_init
+
+    # Schedule finalization.
+    global gdb_finish_hooks
+    lappend gdb_finish_hooks tuiterm_env_finish
+}
+
+# Dejagnu has a version of note, but usage is not allowed outside of dejagnu.
+# Define a local version.
+proc gdb_note { message } {
+    verbose -- "NOTE: $message" 0
+}
+
+# Return 1 if compiler supports -fuse-ld=gold, otherwise return 0.
+gdb_caching_proc have_fuse_ld_gold {
+    set me "have_fuse_ld_gold"
+    set flags "additional_flags=-fuse-ld=gold"
+    set src { int main() { return 0; } }
+    return [gdb_simple_compile $me $src executable $flags]
+}
+
 # Always load compatibility stuff.
 load_lib future.exp
This page took 0.042604 seconds and 4 git commands to generate.