testsuite: Introduce dejagnu_version
[deliverable/binutils-gdb.git] / gdb / testsuite / lib / gdb.exp
index 441107ba457fcf645d236d70f2239061adcbcc0b..c773d41baee49f099526310180fddb1c9d2e9e3a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1992-2016 Free Software Foundation, Inc.
+# Copyright 1992-2017 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
@@ -28,6 +28,7 @@ if {$tool == ""} {
 load_lib libgloss.exp
 load_lib cache.exp
 load_lib gdb-utils.exp
+load_lib memory.exp
 
 global GDB
 
@@ -117,6 +118,10 @@ set octal "\[0-7\]+"
 
 set inferior_exited_re "(\\\[Inferior \[0-9\]+ \\(.*\\) exited)"
 
+# A regular expression that matches a value history number.
+# E.g., $1, $2, etc.
+set valnum_re "\\\$$decimal"
+
 ### Only procedures should come after this point.
 
 #
@@ -519,7 +524,7 @@ proc runto { function args } {
        }
        -re "The target does not support running in non-stop mode.\r\n$gdb_prompt $" {
            if { $print_fail } {
-               unsupported "Non-stop mode not supported"
+               unsupported "non-stop mode not supported"
            }
            return 0
        }
@@ -1359,7 +1364,7 @@ proc default_gdb_exit {} {
     global GDB
     global INTERNAL_GDBFLAGS GDBFLAGS
     global verbose
-    global gdb_spawn_id
+    global gdb_spawn_id inferior_spawn_id
     global inotify_log_file
 
     gdb_stop_suppressing_tests
@@ -1400,6 +1405,7 @@ proc default_gdb_exit {} {
        remote_close host
     }
     unset gdb_spawn_id
+    unset inferior_spawn_id
 }
 
 # Load a file into the debugger.
@@ -1721,18 +1727,17 @@ proc skip_go_tests {} {
     return 0
 }
 
-# Return a 1 if I don't even want to try to test java.
-
-proc skip_java_tests {} {
-    return 0
-}
-
 # Return a 1 if I don't even want to try to test D.
 
 proc skip_d_tests {} {
     return 0
 }
 
+# Return 1 to skip Rust tests, 0 to try them.
+proc skip_rust_tests {} {
+    return [expr {![isnative]}]
+}
+
 # Return a 1 for configurations that do not support Python scripting.
 # PROMPT_REGEXP is the expected prompt.
 
@@ -1918,6 +1923,14 @@ proc foreach_with_prefix {var list body} {
     }
 }
 
+# Like TCL's native proc, but defines a procedure that wraps its body
+# within 'with_test_prefix "$proc_name" { ... }'.
+proc proc_with_prefix {name arguments body} {
+    # Define the advertised proc.
+    proc $name $arguments [list with_test_prefix $name $body]
+}
+
+
 # Run BODY in the context of the caller.  After BODY is run, the variables
 # listed in VARS will be reset to the values they had before BODY was run.
 #
@@ -2069,6 +2082,56 @@ proc with_target_charset { target_charset body } {
     }
 }
 
+# Switch the default spawn id to SPAWN_ID, so that gdb_test,
+# mi_gdb_test etc. default to using it.
+
+proc switch_gdb_spawn_id {spawn_id} {
+    global gdb_spawn_id
+    global board board_info
+
+    set gdb_spawn_id $spawn_id
+    set board [host_info name]
+    set board_info($board,fileid) $spawn_id
+}
+
+# Clear the default spawn id.
+
+proc clear_gdb_spawn_id {} {
+    global gdb_spawn_id
+    global board board_info
+
+    unset -nocomplain gdb_spawn_id
+    set board [host_info name]
+    unset -nocomplain board_info($board,fileid)
+}
+
+# Run BODY with SPAWN_ID as current spawn id.
+
+proc with_spawn_id { spawn_id body } {
+    global gdb_spawn_id
+
+    if [info exists gdb_spawn_id] {
+       set saved_spawn_id $gdb_spawn_id
+    }
+
+    switch_gdb_spawn_id $spawn_id
+
+    set code [catch {uplevel 1 $body} result]
+
+    if [info exists saved_spawn_id] {
+       switch_gdb_spawn_id $saved_spawn_id
+    } else {
+       clear_gdb_spawn_id
+    }
+
+    if {$code == 1} {
+       global errorInfo errorCode
+       return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+    } else {
+       return -code $code $result
+    }
+}
+
 # Select the largest timeout from all the timeouts:
 # - the local "timeout" variable of the scope two levels above,
 # - the global "timeout" variable,
@@ -2120,6 +2183,13 @@ proc with_timeout_factor { factor body } {
 # Return 1 if _Complex types are supported, otherwise, return 0.
 
 gdb_caching_proc support_complex_tests {
+
+    if { [gdb_skip_float_test] } {
+       # If floating point is not supported, _Complex is not
+       # supported.
+       return 0
+    }
+
     # 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.
@@ -2897,7 +2967,8 @@ proc skip_hw_breakpoint_tests {} {
         || [istarget "x86_64-*-*"]
         || [istarget "ia64-*-*"] 
         || [istarget "arm*-*-*"]
-        || [istarget "aarch64*-*-*"]} {
+        || [istarget "aarch64*-*-*"]
+        || [istarget "s390*-*-*"] } {
        return 0
     }
 
@@ -3053,6 +3124,26 @@ proc gdb_is_target_remote {} {
     return [gdb_is_target_remote_prompt "$gdb_prompt $"]
 }
 
+# Return the effective value of use_gdb_stub.
+#
+# If the use_gdb_stub global has been set (it is set when the gdb process is
+# spawned), return that.  Otherwise, return the value of the use_gdb_stub
+# property from the board file.
+#
+# This is the preferred way of checking use_gdb_stub, since it allows to check
+# the value before the gdb has been spawned and it will return the correct value
+# even when it was overriden by the test.
+
+proc use_gdb_stub {} {
+  global use_gdb_stub
+
+  if [info exists use_gdb_stub] {
+     return $use_gdb_stub
+  }
+
+  return [target_info exists use_gdb_stub]
+}
+
 # Return 1 if the current remote target is an instance of our GDBserver, 0
 # otherwise.  Return -1 if there was an error and we can't tell.
 
@@ -3060,7 +3151,7 @@ gdb_caching_proc target_is_gdbserver {
     global gdb_prompt
 
     set is_gdbserver -1
-    set test "Probing for GDBserver"
+    set test "probing for GDBserver"
 
     gdb_test_multiple "monitor help" $test {
        -re "The following monitor commands are supported.*Quit GDBserver.*$gdb_prompt $" {
@@ -3212,12 +3303,8 @@ proc get_compiler_info {{arg ""}} {
     }
 
     # Set the legacy symbols.
-    set gcc_compiled     0
-    if { [regexp "^gcc-1-" "$compiler_info" ] } { set gcc_compiled 1 }
-    if { [regexp "^gcc-2-" "$compiler_info" ] } { set gcc_compiled 2 }
-    if { [regexp "^gcc-3-" "$compiler_info" ] } { set gcc_compiled 3 }
-    if { [regexp "^gcc-4-" "$compiler_info" ] } { set gcc_compiled 4 }
-    if { [regexp "^gcc-5-" "$compiler_info" ] } { set gcc_compiled 5 }
+    set gcc_compiled 0
+    regexp "^gcc-(\[0-9\]+)-" "$compiler_info" matchall gcc_compiled
 
     # Log what happened.
     verbose -log "get_compiler_info: $compiler_info"
@@ -3516,7 +3603,7 @@ proc gdb_compile_pthreads {source dest type options} {
         }
     }
     if {!$built_binfile} {
-       unsupported "Couldn't compile [file tail $source]: ${why_msg}"
+       unsupported "couldn't compile [file tail $source]: ${why_msg}"
         return -1
     }
 }
@@ -3645,7 +3732,7 @@ proc gdb_compile_shlib_pthreads {sources dest options} {
         }
     }
     if {!$built_binfile} {
-        unsupported "Couldn't compile $sources: ${why_msg}"
+        unsupported "couldn't compile $sources: ${why_msg}"
         return -1
     }
 }
@@ -3685,7 +3772,7 @@ proc gdb_compile_objc {source dest type options} {
         }
     }
     if {!$built_binfile} {
-        unsupported "Couldn't compile [file tail $source]: ${why_msg}"
+        unsupported "couldn't compile [file tail $source]: ${why_msg}"
         return -1
     }
 }
@@ -4229,11 +4316,11 @@ proc gdb_remote_download {dest fromfile {tofile {}}} {
     }
 }
 
-# gdb_load_shlibs LIB...
+# gdb_load_shlib LIB...
 #
 # Copy the listed library to the target.
 
-proc gdb_load_shlibs { file } {
+proc gdb_load_shlib { file } {
     set dest [gdb_remote_download target [shlib_target_file $file]]
 
     if {[is_remote target]} {
@@ -4824,14 +4911,102 @@ proc rerun_to_main {} {
   }
 }
 
-# Print a message and return true if a test should be skipped
-# due to lack of floating point suport.
+# Return true if a test should be skipped due to lack of floating
+# point support or GDB can't fetch the contents from floating point
+# registers.
 
-proc gdb_skip_float_test { msg } {
+gdb_caching_proc gdb_skip_float_test {
     if [target_info exists gdb,skip_float_tests] {
-       verbose "Skipping test '$msg': no float tests."
        return 1
     }
+
+    # There is an ARM kernel ptrace bug that hardware VFP registers
+    # are not updated after GDB ptrace set VFP registers.  The bug
+    # was introduced by kernel commit 8130b9d7b9d858aa04ce67805e8951e3cb6e9b2f
+    # in 2012 and is fixed in e2dfb4b880146bfd4b6aa8e138c0205407cebbaf
+    # in May 2016.  In other words, kernels older than 4.6.3, 4.4.14,
+    # 4.1.27, 3.18.36, and 3.14.73 have this bug.
+    # This kernel bug is detected by check how does GDB change the
+    # program result by changing one VFP register.
+    if { [istarget "arm*-*-linux*"] } {
+
+       set compile_flags {debug nowarnings }
+
+       # Set up, compile, and execute a test program having VFP
+       # operations.
+       set src [standard_temp_file arm_vfp[pid].c]
+       set exe [standard_temp_file arm_vfp[pid].x]
+
+       gdb_produce_source $src {
+           int main() {
+               double d = 4.0;
+               int ret;
+
+               asm ("vldr d0, [%0]" : : "r" (&d));
+               asm ("vldr d1, [%0]" : : "r" (&d));
+               asm (".global break_here\n"
+                    "break_here:");
+               asm ("vcmp.f64 d0, d1\n"
+                    "vmrs APSR_nzcv, fpscr\n"
+                    "bne L_value_different\n"
+                    "movs %0, #0\n"
+                    "b L_end\n"
+                    "L_value_different:\n"
+                    "movs %0, #1\n"
+                    "L_end:\n" : "=r" (ret) :);
+
+               /* Return $d0 != $d1.  */
+               return ret;
+           }
+       }
+
+       verbose "compiling testfile $src" 2
+       set lines [gdb_compile $src $exe executable $compile_flags]
+       file delete $src
+
+       if ![string match "" $lines] then {
+           verbose "testfile compilation failed, returning 1" 2
+           return 0
+       }
+
+       # No error message, compilation succeeded so now run it via gdb.
+       # Run the test up to 5 times to detect whether ptrace can
+       # correctly update VFP registers or not.
+       set skip_vfp_test 0
+       for {set i 0} {$i < 5} {incr i} {
+           global gdb_prompt srcdir subdir
+
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_load "$exe"
+
+           runto_main
+           gdb_test "break *break_here"
+           gdb_continue_to_breakpoint "break_here"
+
+           # Modify $d0 to a different value, so the exit code should
+           # be 1.
+           gdb_test "set \$d0 = 5.0"
+
+           set test "continue to exit"
+           gdb_test_multiple "continue" "$test" {
+               -re "exited with code 01.*$gdb_prompt $" {
+               }
+               -re "exited normally.*$gdb_prompt $" {
+                   # However, the exit code is 0.  That means something
+                   # wrong in setting VFP registers.
+                   set skip_vfp_test 1
+                   break
+               }
+           }
+       }
+
+       gdb_exit
+       remote_file build delete $exe
+
+       return $skip_vfp_test
+    }
     return 0
 }
 
@@ -4855,9 +5030,14 @@ proc gdb_skip_bogus_test { msg } {
 # NOTE: This must be called while gdb is *not* running.
 
 gdb_caching_proc gdb_skip_xml_test {
+    global gdb_spawn_id
     global gdb_prompt
     global srcdir
 
+    if { [info exists gdb_spawn_id] } {
+        error "GDB must not be running in gdb_skip_xml_tests."
+    }
+
     set xml_file [gdb_remote_download host "${srcdir}/gdb.xml/trivial.xml"]
 
     gdb_start
@@ -5238,6 +5418,16 @@ proc build_executable_from_specs {testname executable options args} {
            }
        }
        set ret [$func $sources_path "${binfile}" $options]
+    } elseif {[lsearch -exact $options rust] != -1} {
+       set sources_path {}
+       foreach {s local_options} $args {
+           if { [regexp "^/" "$s"] } then {
+               lappend sources_path "$s"
+           } else {
+               lappend sources_path "$srcdir/$subdir/$s"
+           }
+       }
+       set ret [gdb_compile_rust $sources_path "${binfile}" $options]
     } else {
        set objects {}
        set i 0
@@ -5367,19 +5557,24 @@ proc get_integer_valueof { exp default } {
     return ${val}
 }
 
-proc get_hexadecimal_valueof { exp default } {
+# Retrieve the value of EXP in the inferior, as an hexadecimal value
+# (using "print /x").  DEFAULT is used as fallback if print fails.
+# TEST is the test message to use.  If can be ommitted, in which case
+# a test message is built from EXP.
+
+proc get_hexadecimal_valueof { exp default {test ""} } {
     global gdb_prompt
-    send_gdb "print /x ${exp}\n"
-    set test "get hexadecimal valueof \"${exp}\""
-    gdb_expect {
+
+    if {$test == ""} {
+       set test "get hexadecimal valueof \"${exp}\""
+    }
+
+    set val ${default}
+    gdb_test_multiple "print /x ${exp}" $test {
        -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}
 }
@@ -5405,6 +5600,30 @@ proc get_target_charset { } {
     return "UTF-8"
 }
 
+# Get the address of VAR.
+
+proc get_var_address { var } {
+    global gdb_prompt hex
+
+    # Match output like:
+    # $1 = (int *) 0x0
+    # $5 = (int (*)()) 0
+    # $6 = (int (*)()) 0x24 <function_bar>
+
+    gdb_test_multiple "print &${var}" "get address of ${var}" {
+       -re "\\\$\[0-9\]+ = \\(.*\\) (0|$hex)( <${var}>)?\[\r\n\]+${gdb_prompt} $"
+       {
+           pass "get address of ${var}"
+           if { $expect_out(1,string) == "0" } {
+               return "0x0"
+           } else {
+               return $expect_out(1,string)
+           }
+       }
+    }
+    return ""
+}
+
 # Get the current value for remotetimeout and return it.
 proc get_remotetimeout { } {
     global gdb_prompt
@@ -5796,5 +6015,40 @@ proc multi_line { args } {
     return [join $args "\r\n"]
 }
 
+# Similar to the above, but while multi_line is meant to be used to
+# match GDB output, this one is meant to be used to build strings to
+# send as GDB input.
+
+proc multi_line_input { args } {
+    return [join $args "\n"]
+}
+
+# Return the version of the DejaGnu framework.
+#
+# The return value is a list containing the major, minor and patch version
+# numbers.  If the version does not contain a minor or patch number, they will
+# be set to 0.  For example:
+#
+#   1.6   -> {1 6 0}
+#   1.6.1 -> {1 6 1}
+#   2     -> {2 0 0}
+
+proc dejagnu_version { } {
+    # The frame_version variable is defined by DejaGnu, in runtest.exp.
+    global frame_version
+
+    verbose -log "DejaGnu version: $frame_version"
+    verbose -log "Expect version: [exp_version]"
+    verbose -log "Tcl version: [info tclversion]"
+
+    set dg_ver [split $frame_version .]
+
+    while { [llength $dg_ver] < 3 } {
+       lappend dg_ver 0
+    }
+
+    return $dg_ver
+}
+
 # Always load compatibility stuff.
 load_lib future.exp
This page took 0.034208 seconds and 4 git commands to generate.