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

Reply via email to