On Thu, Nov 15, 2012 at 5:01 PM, Andrew Pinski <pins...@gmail.com> wrote: > On Wed, Nov 14, 2012 at 2:59 PM, Jakub Jelinek <ja...@redhat.com> wrote: >> On Wed, Nov 14, 2012 at 11:12:05AM -0800, Mike Stump wrote: >>> On Nov 14, 2012, at 8:22 AM, Jakub Jelinek <ja...@redhat.com> wrote: >>> > On Wed, Nov 14, 2012 at 12:11:13PM +0100, Jakub Jelinek wrote: >>> >> Anyway, once asan_symbolize actually symbolizes the output, we could use >>> >> something like: >>> >> /* { dg-output "ERROR: AddressSanitizer stack-buffer-overflow.*" } */ >>> >> /* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp >>> >> |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ >>> >> /* { dg-output " #1 0x\[0-9a-f\]+ (in >>> >> _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ >>> >> (this way it will check function names if symbolizer was actually >>> >> successful, and just accept #0 0xdeadbeef (foobarbaz.so+0xbeef) style >>> >> if it wasn't), but will not accept other function names in the backtrace. >>> > >>> > Here it is even with symbolizer, written in (poor) tcl. It will pass even >>> > if e.g. addr2line is replaced by a script that always fails, but if it >>> > succeeds, will fail if the dg-output regexps contain different function >>> > name >>> > than what is actually emitted. >>> > >>> > Ok for trunk? >>> >>> Ok. If others would like to improve this… :-) feel free to step forward. >> >> Thanks, here is what I've committed, had to add a TEST_ALWAYS_FLAG restore >> in asan_finish, otherwise C tests after asan.exp would run with >> -faddress-sanitizer -g in the flags. > > All of these tests failure for me because my addr2line is too old and > does not support dwarf4. Can we move over to using libbacktrace in > libsanitzer instead of depending on addr2line here?
That would be lovely. We moved away from addr2line to llvm-symbolizer for the same set of reasons. --kcc > > ==21154== ERROR: AddressSanitizer stack-buffer-overflow on address > 0x7fff572cddd4 at pc 0x2b7549a5c550 bp 0x7fff572cdd80 sp > 0x7fff572cdd48 > READ of size 1 at 0x7fff572cddd4 thread T0 > #0 0x2b7549a5c54f in BFD: Dwarf Error: found dwarf version '4', > this reader only handles version 2 and 3 information. memcmp > #1 0x400a59 in BFD: Dwarf Error: found dwarf version '4', this > reader only handles version 2 and 3 information. main > #2 0x2b754c697c4c in __libc_start_main > /home/aurel32/eglibc/eglibc-2.11.2/csu/libc-start.c:228 > > > Thanks, > Andrew > >> >> 2012-11-14 Jakub Jelinek <ja...@redhat.com> >> >> * lib/asan-dg.exp: New file. >> * gcc.dg/asan/asan.exp: New file. >> * g++.dg/dg.exp: Prune also asan tests. >> * g++.dg/asan/asan.exp: New file. >> * c-c++-common/asan/memcmp-1.c: New test. >> >> --- gcc/testsuite/lib/asan-dg.exp.jj 2012-11-14 21:04:53.520943144 +0100 >> +++ gcc/testsuite/lib/asan-dg.exp 2012-11-14 21:21:03.215801626 +0100 >> @@ -0,0 +1,176 @@ >> +# Copyright (C) 2012 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 -faddress-sanitizer 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) { } >> + } "-faddress-sanitizer"] >> +} >> + >> +# >> +# 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 " -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=-faddress-sanitizer >> -g}" $ALWAYS_CXXFLAGS] >> + } else { >> + if [info exists TEST_ALWAYS_FLAGS] { >> + set TEST_ALWAYS_FLAGS "$link_flags -faddress-sanitizer -g >> $TEST_ALWAYS_FLAGS" >> + } else { >> + set TEST_ALWAYS_FLAGS "$link_flags -faddress-sanitizer -g" >> + } >> + } >> +} >> + >> +# >> +# 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 [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 >> + set addr2line_output [regexp -inline -all -line "^\[^\n\r]*" >> [lindex $status 1]] >> + 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 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" >> +} >> + >> +# 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 >> + set result [eval [list saved_asan_${tool}_load $program] $args] >> + set output [lindex $result 1] >> + set symbolized_output [asan_symbolize "$output"] >> + set result [list [lindex $result 0] $symbolized_output] >> + return $result >> + } >> +} >> --- gcc/testsuite/gcc.dg/asan/asan.exp.jj 2012-11-14 >> 21:04:53.520943144 +0100 >> +++ gcc/testsuite/gcc.dg/asan/asan.exp 2012-11-14 21:07:25.213157962 +0100 >> @@ -0,0 +1,38 @@ >> +# Copyright (C) 2012 Free Software Foundation, Inc. >> +# >> +# This file is part of GCC. >> +# >> +# GCC 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, or (at your option) >> +# any later version. >> +# >> +# GCC 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/>. >> + >> +# GCC testsuite that uses the `dg.exp' driver. >> + >> +# Load support procs. >> +load_lib gcc-dg.exp >> +load_lib asan-dg.exp >> + >> +if ![check_effective_target_faddress_sanitizer] { >> + return >> +} >> + >> +# Initialize `dg'. >> +dg-init >> +asan_init >> + >> +# Main loop. >> +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c >> $srcdir/c-c++-common/asan/*.c]] "" >> + >> +# All done. >> +asan_finish >> +dg-finish >> --- gcc/testsuite/g++.dg/dg.exp.jj 2012-11-14 20:26:35.460378708 +0100 >> +++ gcc/testsuite/g++.dg/dg.exp 2012-11-14 21:04:53.520943144 +0100 >> @@ -1,4 +1,5 @@ >> -# Copyright (C) 2000, 2007, 2009, 2010 Free Software Foundation, Inc. >> +# Copyright (C) 2000, 2007, 2009, 2010, 2011, 2012 >> +# 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 >> @@ -50,6 +51,7 @@ set tests [prune $tests $srcdir/$subdir/ >> set tests [prune $tests $srcdir/$subdir/tm/*] >> set tests [prune $tests $srcdir/$subdir/guality/*] >> set tests [prune $tests $srcdir/$subdir/simulate-thread/*] >> +set tests [prune $tests $srcdir/$subdir/asan/*] >> >> # Main loop. >> g++-dg-runtest $tests $DEFAULT_CXXFLAGS >> --- gcc/testsuite/g++.dg/asan/asan.exp.jj 2012-11-14 >> 21:04:53.520943144 +0100 >> +++ gcc/testsuite/g++.dg/asan/asan.exp 2012-11-14 21:07:35.967092385 +0100 >> @@ -0,0 +1,36 @@ >> +# Copyright (C) 2012 Free Software Foundation, Inc. >> +# >> +# This file is part of GCC. >> +# >> +# GCC 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, or (at your option) >> +# any later version. >> +# >> +# GCC 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/>. >> + >> +# Load support procs. >> +load_lib g++-dg.exp >> +load_lib asan-dg.exp >> + >> +if ![check_effective_target_faddress_sanitizer] { >> + return >> +} >> + >> +# Initialize `dg'. >> +dg-init >> +asan_init >> + >> +# Main loop. >> +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C >> $srcdir/c-c++-common/asan/*.c]] "" >> + >> +# All done. >> +asan_finish >> +dg-finish >> --- gcc/testsuite/c-c++-common/asan/memcmp-1.c.jj 2012-11-14 >> 21:04:53.521943120 +0100 >> +++ gcc/testsuite/c-c++-common/asan/memcmp-1.c 2012-11-14 >> 21:04:53.521943120 +0100 >> @@ -0,0 +1,18 @@ >> +/* { dg-do run } */ >> +/* { dg-options "-fno-builtin-memcmp" } */ >> +/* { dg-shouldfail "asan" } */ >> + >> +#include <string.h> >> + >> +int >> +main (int argc, char **argv) >> +{ >> + char a1[] = {argc, 2, 3, 4}; >> + char a2[] = {1, 2*argc, 3, 4}; >> + int res = memcmp (a1, a2, 5 + argc); >> + return res; >> +} >> + >> +/* { dg-output "ERROR: AddressSanitizer >> stack-buffer-overflow.*(\n|\r\n|\r)" } */ >> +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)memcmp >> |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ >> +/* { dg-output " #1 0x\[0-9a-f\]+ (in >> _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ >> >> >> Jakub