+proc gdb_skip_stdio_test { msg } {
+ if [target_info exists gdb,noinferiorio] {
+ verbose "Skipping test '$msg': no inferior i/o.";
+ return 1;
+ }
+ return 0;
+}
+
+proc gdb_skip_bogus_test { msg } {
+ return 0;
+}
+
+# Return true if a test should be skipped due to lack of XML support
+# in the host GDB.
+# NOTE: This must be called while gdb is *not* running.
+
+proc gdb_skip_xml_test { } {
+ global gdb_prompt
+ global srcdir
+ global xml_missing_cached
+
+ if {[info exists xml_missing_cached]} {
+ return $xml_missing_cached
+ }
+
+ gdb_start
+ set xml_missing_cached 0
+ gdb_test_multiple "set tdesc filename ${srcdir}/gdb.xml/trivial.xml" "" {
+ -re ".*XML support was disabled at compile time.*$gdb_prompt $" {
+ set xml_missing_cached 1
+ }
+ -re ".*$gdb_prompt $" { }
+ }
+ gdb_exit
+ return $xml_missing_cached
+}
+
+# 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.
+
+# Functions for separate debug info testing
+
+# starting with an executable:
+# foo --> original executable
+
+# at the end of the process we have:
+# foo.stripped --> foo w/o debug info
+# .debug/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.
+proc build_id_debug_filename_get { exec } {
+ set tmp "${exec}-tmp"
+ set objcopy_program [transform objcopy]
+
+ set result [catch "exec $objcopy_program -j .note.gnu.build-id -O binary $exec $tmp" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return ""
+ }
+ set fi [open $tmp]
+ fconfigure $fi -translation binary
+ # Skip the NOTE header.
+ read $fi 16
+ set data [read $fi]
+ close $fi
+ file delete $tmp
+ if ![string compare $data ""] then {
+ return ""
+ }
+ # Convert it to hex.
+ binary scan $data H* data
+ set data [regsub {^..} $data {\0/}]
+ return ".build-id/${data}.debug";
+}
+
+# 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.
+
+proc gdb_gnu_strip_debug { dest args } {
+
+ set debug_file [separate_debug_filename $dest]
+ 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"
+
+ # Get rid of the debug info, and store result in stripped_file
+ # something like gdb/testsuite/gdb.base/blah.stripped.
+ set result [catch "exec $strip_to_file_program --strip-debug ${dest} -o ${stripped_file}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ # Workaround PR binutils/10802:
+ # Preserve the 'x' bit also for PIEs (Position Independent Executables).
+ set perm [file attributes ${dest} -permissions]
+ file attributes ${stripped_file} -permissions $perm
+
+ # Get rid of everything but the debug info, and store result in debug_file
+ # This will be in the .debug subdirectory, see above.
+ set result [catch "exec $strip_to_file_program --only-keep-debug ${dest} -o ${debug_file}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ # If no-main is passed, strip the symbol for main from the separate
+ # file. This is to simulate the behavior of elfutils's eu-strip, which
+ # leaves the symtab in the original file only. There's no way to get
+ # objcopy or strip to remove the symbol table without also removing the
+ # debugging sections, so this is as close as we can get.
+ if { [llength $args] == 1 && [lindex $args 0] == "no-main" } {
+ set result [catch "exec $objcopy_program -N main ${debug_file} ${debug_file}-tmp" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+ file delete "${debug_file}"
+ file rename "${debug_file}-tmp" "${debug_file}"
+ }
+
+ # Link the two previous output files together, adding the .gnu_debuglink
+ # section to the stripped_file, containing a pointer to the debug_file,
+ # save the new file in dest.
+ # This will be the regular executable filename, in the usual location.
+ set result [catch "exec $objcopy_program --add-gnu-debuglink=${debug_file} ${stripped_file} ${dest}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ # Workaround PR binutils/10802:
+ # Preserve the 'x' bit also for PIEs (Position Independent Executables).
+ set perm [file attributes ${stripped_file} -permissions]
+ file attributes ${dest} -permissions $perm
+
+ return 0
+}
+
+# Test the output of GDB_COMMAND matches the pattern obtained
+# by concatenating all elements of EXPECTED_LINES. This makes
+# it possible to split otherwise very long string into pieces.
+# If third argument is not empty, it's used as the name of the
+# test to be printed on pass/fail.
+proc help_test_raw { gdb_command expected_lines args } {
+ set message $gdb_command
+ if [llength $args]>0 then {
+ set message [lindex $args 0]
+ }
+ set expected_output [join $expected_lines ""]
+ gdb_test "${gdb_command}" "${expected_output}" $message
+}
+
+# Test the output of "help COMMNAD_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.
+proc test_class_help { command_class expected_initial_lines args } {
+ set l_stock_body {
+ "List of commands\:.*\[\r\n\]+"
+ "Type \"help\" followed by command name for full documentation\.\[\r\n\]+"
+ "Type \"apropos word\" to search for commands related to \"word\"\.[\r\n\]+"
+ "Command name abbreviations are allowed if unambiguous\."
+ }
+ set l_entire_body [concat $expected_initial_lines $l_stock_body]
+
+ eval [list help_test_raw "help ${command_class}" $l_entire_body] $args
+}
+
+# COMMAND_LIST should have either one element -- command to test, or
+# two elements -- abbreviated command to test, and full command the first
+# element is abbreviation of.
+# The command must be a prefix command. EXPECTED_INITIAL_LINES
+# are regular expressions that should match the beginning of output,
+# before the list of subcommands. The presence of
+# subcommand list and standard epilogue will be tested automatically.
+proc test_prefix_command_help { command_list expected_initial_lines args } {
+ set command [lindex $command_list 0]
+ if {[llength $command_list]>1} {
+ set full_command [lindex $command_list 1]
+ } else {
+ set full_command $command
+ }
+ # Use 'list' and not just {} because we want variables to
+ # be expanded in this list.
+ set l_stock_body [list\
+ "List of $full_command subcommands\:.*\[\r\n\]+"\
+ "Type \"help $full_command\" followed by $full_command subcommand name for full documentation\.\[\r\n\]+"\
+ "Type \"apropos word\" to search for commands related to \"word\"\.\[\r\n\]+"\
+ "Command name abbreviations are allowed if unambiguous\."]
+ set l_entire_body [concat $expected_initial_lines $l_stock_body]
+ if {[llength $args]>0} {
+ help_test_raw "help ${command}" $l_entire_body [lindex $args 0]
+ } else {
+ help_test_raw "help ${command}" $l_entire_body
+ }
+}
+
+# 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
+ global subdir
+ global srcdir
+ if {[llength $sources]==0} {
+ set sources ${executable}.c
+ }
+
+ set binfile ${objdir}/${subdir}/${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] != "" } {
+ untested $testname
+ return -1
+ }
+ lappend objects "${binfile}${i}.o"
+ }
+
+ if { [gdb_compile $objects "${binfile}" executable $options] != "" } {
+ untested $testname
+ return -1
+ }
+
+ if [get_compiler_info ${binfile}] {
+ return -1
+ }
+ return 0
+}
+
+# Starts fresh GDB binary and loads EXECUTABLE into GDB. EXECUTABLE is
+# the name of binary in ${objdir}/${subdir}.
+proc clean_restart { executable } {
+ global srcdir
+ global objdir
+ global subdir
+ set binfile ${objdir}/${subdir}/${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, and then clean_restart.
+# Please refer to build_executable for parameter description.
+proc prepare_for_testing { testname executable {sources ""} {options {debug}}} {
+
+ if {[build_executable $testname $executable $sources $options] == -1} {
+ return -1
+ }
+ clean_restart $executable
+
+ return 0
+}
+
+proc get_valueof { fmt exp default } {
+ global gdb_prompt
+
+ set test "get valueof \"${exp}\""
+ set val ${default}
+ gdb_test_multiple "print${fmt} ${exp}" "$test" {
+ -re "\\$\[0-9\]* = (.*)\[\r\n\]*$gdb_prompt $" {
+ set val $expect_out(1,string)
+ pass "$test ($val)"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+ return ${val}
+}
+
+proc get_integer_valueof { exp default } {
+ global gdb_prompt
+
+ set test "get integer valueof \"${exp}\""
+ set val ${default}
+ gdb_test_multiple "print /d ${exp}" "$test" {
+ -re "\\$\[0-9\]* = (\[-\]*\[0-9\]*).*$gdb_prompt $" {
+ set val $expect_out(1,string)
+ pass "$test ($val)"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+ return ${val}
+}
+
+proc get_hexadecimal_valueof { exp default } {
+ global gdb_prompt
+ send_gdb "print /x ${exp}\n"
+ set test "get hexadecimal valueof \"${exp}\""
+ gdb_expect {
+ -re "\\$\[0-9\]* = (0x\[0-9a-zA-Z\]+).*$gdb_prompt $" {
+ set val $expect_out(1,string)
+ pass "$test"
+ }
+ timeout {
+ set val ${default}
+ fail "$test (timeout)"
+ }
+ }
+ return ${val}
+}
+
+proc get_sizeof { type default } {
+ return [get_integer_valueof "sizeof (${type})" $default]
+}
+
+# Log gdb command line and script if requested.
+if {[info exists TRANSCRIPT]} {
+ rename send_gdb real_send_gdb
+ rename remote_spawn real_remote_spawn
+ rename remote_close real_remote_close
+
+ global gdb_transcript
+ set gdb_transcript ""
+
+ global gdb_trans_count
+ set gdb_trans_count 1
+
+ proc remote_spawn {args} {
+ global gdb_transcript gdb_trans_count outdir
+
+ if {$gdb_transcript != ""} {
+ close $gdb_transcript
+ }
+ set gdb_transcript [open [file join $outdir transcript.$gdb_trans_count] w]
+ puts $gdb_transcript [lindex $args 1]
+ incr gdb_trans_count
+
+ return [uplevel real_remote_spawn $args]