diff options
author | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
commit | 1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch) | |
tree | c607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/gcc/testsuite/lib/asan-dg.exp | |
parent | 283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff) | |
download | toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2 toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip |
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/gcc/testsuite/lib/asan-dg.exp')
-rw-r--r-- | gcc-4.9/gcc/testsuite/lib/asan-dg.exp | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/testsuite/lib/asan-dg.exp b/gcc-4.9/gcc/testsuite/lib/asan-dg.exp new file mode 100644 index 000000000..9ba39db15 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/lib/asan-dg.exp @@ -0,0 +1,310 @@ +# Copyright (C) 2012-2014 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 +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Return 1 if compilation with -fsanitize=address is error-free for trivial +# code, 0 otherwise. + +proc check_effective_target_faddress_sanitizer {} { + return [check_no_compiler_messages faddress_sanitizer object { + void foo (void) { } + } "-fsanitize=address"] +} + +# +# asan_link_flags -- compute library path and flags to find libasan. +# (originally from g++.exp) +# + +proc asan_link_flags { paths } { + global srcdir + global ld_library_path + global shlib_ext + + set gccpath ${paths} + set flags "" + + set shlib_ext [get_shlib_extension] + + if { $gccpath != "" } { + if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"] + || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } { + append flags " -B${gccpath}/libsanitizer/ " + append flags " -B${gccpath}/libsanitizer/asan/ " + append flags " -L${gccpath}/libsanitizer/asan/.libs " + append ld_library_path ":${gccpath}/libsanitizer/asan/.libs" + } + } else { + global tool_root_dir + + set libasan [lookfor_file ${tool_root_dir} libasan] + if { $libasan != "" } { + append flags "-L${libasan} " + append ld_library_path ":${libasan}" + } + } + + set_ld_library_path_env_vars + + return "$flags" +} + +# +# asan_init -- called at the start of each subdir of tests +# + +proc asan_init { args } { + global TEST_ALWAYS_FLAGS + global ALWAYS_CXXFLAGS + global TOOL_OPTIONS + global asan_saved_TEST_ALWAYS_FLAGS + + set link_flags "" + if ![is_remote host] { + if [info exists TOOL_OPTIONS] { + set link_flags "[asan_link_flags [get_multilibs ${TOOL_OPTIONS}]]" + } else { + set link_flags "[asan_link_flags [get_multilibs]]" + } + } + + if [info exists TEST_ALWAYS_FLAGS] { + set asan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS + } + if [info exists ALWAYS_CXXFLAGS] { + set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS] + set ALWAYS_CXXFLAGS [concat "{additional_flags=-fsanitize=address -g}" $ALWAYS_CXXFLAGS] + } else { + if [info exists TEST_ALWAYS_FLAGS] { + set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g $TEST_ALWAYS_FLAGS" + } else { + set TEST_ALWAYS_FLAGS "$link_flags -fsanitize=address -g" + } + } + if { $link_flags != "" } { + return 1 + } + return 0 +} + +# +# asan_finish -- called at the start of each subdir of tests +# + +proc asan_finish { args } { + global TEST_ALWAYS_FLAGS + global asan_saved_TEST_ALWAYS_FLAGS + + if [info exists asan_saved_TEST_ALWAYS_FLAGS] { + set TEST_ALWAYS_FLAGS $asan_saved_TEST_ALWAYS_FLAGS + } else { + unset TEST_ALWAYS_FLAGS + } +} + +# Symbolize lines like +# #2 0xdeadbeef (/some/path/libsanitizer.so.0.0.0+0xbeef) +# in $output using addr2line to +# #2 0xdeadbeef in foobar file:123 +proc asan_symbolize { output } { + set addresses [regexp -inline -all -line "^ *#\[0-9\]+ 0x\[0-9a-f\]+ \[(\](\[^)\]+)\[+\](0x\[0-9a-f\]+)\[)\]$" "$output"] + if { [llength $addresses] > 0 } { + set addr2line_name [find_binutils_prog addr2line] + set idx 1 + while { $idx < [llength $addresses] } { + set key [regsub -all "\[\]\[\]" [lindex $addresses $idx] "\\\\&"] + set val [lindex $addresses [expr $idx + 1]] + lappend arr($key) $val + set idx [expr $idx + 3] + } + foreach key [array names arr] { + set args "-f -e $key $arr($key)" + set status [remote_exec host "$addr2line_name" "$args"] + if { [lindex $status 0] > 0 } continue + regsub -all "\r\n" [lindex $status 1] "\n" addr2line_output + regsub -all "\[\n\r\]BFD: \[^\n\r\]*" $addr2line_output "" addr2line_output + regsub -all "^BFD: \[^\n\r\]*\[\n\r\]" $addr2line_output "" addr2line_output + set addr2line_output [regexp -inline -all -line "^\[^\n\r]*" $addr2line_output] + set idx 0 + foreach val $arr($key) { + if { [expr $idx + 1] < [llength $addr2line_output] } { + set fnname [lindex $addr2line_output $idx] + set fileline [lindex $addr2line_output [expr $idx + 1]] + if { "$fnname" != "??" } { + set newkey "$key+$val" + set repl($newkey) "$fnname $fileline" + } + set idx [expr $idx + 2] + } + } + } + set idx 0 + set new_output "" + while {[regexp -start $idx -indices " #\[0-9\]+ 0x\[0-9a-f\]+ \[(\](\[^)\]+\[+\]0x\[0-9a-f\]+)\[)\]" "$output" -> addr] > 0} { + set low [lindex $addr 0] + set high [lindex $addr 1] + set val [string range "$output" $low $high] + append new_output [string range "$output" $idx [expr $low - 2]] + if [info exists repl($val)] { + append new_output "in $repl($val)" + } else { + append new_output "($val)" + } + set idx [expr $high + 2] + } + append new_output [string range "$output" $idx [string length "$output"]] + return "$new_output" + } + return "$output" +} + +# Return a list of gtest tests, printed in the form +# DEJAGNU_GTEST_TEST AddressSanitizer_SimpleDeathTest +# DEJAGNU_GTEST_TEST AddressSanitizer_VariousMallocsTest +proc asan_get_gtest_test_list { output } { + set idx 0 + set ret "" + while {[regexp -start $idx -indices "DEJAGNU_GTEST_TEST (\[^\n\r\]*)(\r\n|\n|\r)" "$output" -> testname] > 0} { + set low [lindex $testname 0] + set high [lindex $testname 1] + set val [string range "$output" $low $high] + lappend ret $val + set idx [expr $high + 1] + } + return $ret +} + +# Return a list of gtest EXPECT_DEATH tests, printed in the form +# DEJAGNU_GTEST_EXPECT_DEATH1 statement DEJAGNU_GTEST_EXPECT_DEATH1 regexp DEJAGNU_GTEST_EXPECT_DEATH1 +# DEJAGNU_GTEST_EXPECT_DEATH2 other statement DEJAGNU_GTEST_EXPECT_DEATH2 other regexp DEJAGNU_GTEST_EXPECT_DEATH2 +proc asan_get_gtest_expect_death_list { output } { + set idx 0 + set ret "" + while {[regexp -start $idx -indices "DEJAGNU_GTEST_EXPECT_DEATH(\[0-9\]*)" "$output" -> id ] > 0} { + set low [lindex $id 0] + set high [lindex $id 1] + set val_id [string range "$output" $low $high] + if {[regexp -start $low -indices "$val_id (.*) DEJAGNU_GTEST_EXPECT_DEATH$val_id (.*) DEJAGNU_GTEST_EXPECT_DEATH$val_id\[\n\r\]" "$output" whole statement regexpr ] == 0} { break } + set low [lindex $statement 0] + set high [lindex $statement 1] + set val_statement [string range "$output" $low $high] + set low [lindex $regexpr 0] + set high [lindex $regexpr 1] + set val_regexpr [string range "$output" $low $high] + lappend ret [list "$val_id" "$val_statement" "$val_regexpr"] + set idx [lindex $whole 1] + } + return $ret +} + +# Replace ${tool}_load with a wrapper so that we can symbolize the output. +if { [info procs ${tool}_load] != [list] \ + && [info procs saved_asan_${tool}_load] == [list] } { + rename ${tool}_load saved_asan_${tool}_load + + proc ${tool}_load { program args } { + global tool + global asan_last_gtest_test_list + global asan_last_gtest_expect_death_list + set result [eval [list saved_asan_${tool}_load $program] $args] + set output [lindex $result 1] + set symbolized_output [asan_symbolize "$output"] + set asan_last_gtest_test_list [asan_get_gtest_test_list "$output"] + set asan_last_gtest_expect_death_list [asan_get_gtest_expect_death_list "$output"] + set result [list [lindex $result 0] $symbolized_output] + return $result + } +} + +# Utility for running gtest asan emulation under dejagnu, invoked via dg-final. +# Call pass if variable has the desired value, otherwise fail. +# +# Argument 0 handles expected failures and the like +proc asan-gtest { args } { + global tool + global asan_last_gtest_test_list + global asan_last_gtest_expect_death_list + + if { ![info exists asan_last_gtest_test_list] } { return } + if { [llength $asan_last_gtest_test_list] == 0 } { return } + if { ![isnative] || [is_remote target] } { return } + + set gtest_test_list $asan_last_gtest_test_list + unset asan_last_gtest_test_list + + if { [llength $args] >= 1 } { + switch [dg-process-target [lindex $args 0]] { + "S" { } + "N" { return } + "F" { setup_xfail "*-*-*" } + "P" { } + } + } + + # This assumes that we are three frames down from dg-test, and that + # it still stores the filename of the testcase in a local variable "name". + # A cleaner solution would require a new DejaGnu release. + upvar 2 name testcase + upvar 2 prog prog + + set output_file "[file rootname [file tail $prog]].exe" + + foreach gtest $gtest_test_list { + set testname "$testcase $gtest" + set status -1 + + setenv DEJAGNU_GTEST_ARG "$gtest" + set result [${tool}_load ./$output_file $gtest] + unsetenv DEJAGNU_GTEST_ARG + set status [lindex $result 0] + set output [lindex $result 1] + if { "$status" == "pass" } { + pass "$testname execution test" + if { [info exists asan_last_gtest_expect_death_list] } { + set gtest_expect_death_list $asan_last_gtest_expect_death_list + foreach gtest_death $gtest_expect_death_list { + set id [lindex $gtest_death 0] + set testname "$testcase $gtest [lindex $gtest_death 1]" + set regexpr [lindex $gtest_death 2] + set status -1 + + setenv DEJAGNU_GTEST_ARG "$gtest:$id" + set result [${tool}_load ./$output_file "$gtest:$id"] + unsetenv DEJAGNU_GTEST_ARG + set status [lindex $result 0] + set output [lindex $result 1] + if { "$status" == "fail" } { + pass "$testname execution test" + if { ![regexp $regexpr ${output}] } { + fail "$testname output pattern test" + send_log "Output should match: $regexpr\n" + } else { + pass "$testname output pattern test" + } + } elseif { "$status" == "pass" } { + fail "$testname execution test" + } else { + $status "$testname execution test" + } + } + } + } else { + $status "$testname execution test" + } + unset asan_last_gtest_expect_death_list + } + + return +} |