+euge...@google.com (our ARM expert) Christophe,
The change in sanitizer_common/sanitizer_stacktrace.cc changes the logic which is known to work well for us on Android/ARM. I'd like Evgeniy to comment on it. --kcc On Mon, May 6, 2013 at 10:52 PM, Christophe Lyon <christophe.l...@linaro.org> wrote: > Hi, > > Here is a 2nd attempt at enabling libsanitizer on ARM. > Compared with the previous version, this patch is more intrusive to > workaround some limitations with qemu: > > * qemu does not work well with threads, so I chose to disable > clone-test-1.c and rlimit-mmap-test-1.c when running on a simulator. > This is a bit overkill since the limitation is caused by qemu, not by > the fact of running on a simulator. Would it cause problems on other > targets? > > * due to different connexion mathod between runtest and the target > program in native mode and in simulated mode, causing isatty(2) to > give a different answer, I modified a few regexps to accept possible > decorations. This can be removed once ASAN_OPTIONS=color=0 is > implemented. > > Tested on x86 with no regression, on ARM cortex-a9 hardware and > a15-qemu with the expected new tests. > > OK? > > Christophe. > > 2013-05-06 Christophe Lyon <christophe.l...@linaro.org> > > gcc/ > * config/arm/arm.c (arm_asan_shadow_offset): New function. > (TARGET_ASAN_SHADOW_OFFSET): Define. > * config/arm/linux-eabi.h (ASAN_CC1_SPEC): Define. > (LINUX_OR_ANDROID_CC): Add ASAN_CC1_SPEC. > > libsanitizer/ > * configure.tgt: Add ARM pattern. > * sanitizer_common/sanitizer_stacktrace.cc: Return the computed > value. > > testsuite/ > * lib/target-supports.exp (check_effective_target_hw): New > function. > * c-c++-common/asan/clone-test-1.c: Call > check_effective_target_hw. > * c-c++-common/asan/rlimit-mmap-test-1.c: Likewise. > * c-c++-common/asan/heap-overflow-1.c: Update regexps to accept > possible decorations. > * c-c++-common/asan/null-deref-1.c: Likewise. > * c-c++-common/asan/stack-overflow-1.c: Likewise. > * c-c++-common/asan/strncpy-overflow-1.c: Likewise. > * c-c++-common/asan/use-after-free-1.c: Likewise. > * g++.dg/asan/deep-thread-stack-1.C: Likewise. > * g++.dg/asan/large-func-test-1.C: Likewise. > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index 0b97cf8..c036a21 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -281,6 +281,8 @@ static unsigned arm_add_stmt_cost (void *data, int count, > > static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1, > bool op0_preserve_value); > +static unsigned HOST_WIDE_INT arm_asan_shadow_offset (void); > + > > /* Table of machine attributes. */ > static const struct attribute_spec arm_attribute_table[] = > @@ -657,6 +659,9 @@ static const struct attribute_spec arm_attribute_table[] = > #define TARGET_CANONICALIZE_COMPARISON \ > arm_canonicalize_comparison > > +#undef TARGET_ASAN_SHADOW_OFFSET > +#define TARGET_ASAN_SHADOW_OFFSET arm_asan_shadow_offset > + > struct gcc_target targetm = TARGET_INITIALIZER; > > /* Obstack for minipool constant handling. */ > @@ -28062,4 +28067,12 @@ arm_validize_comparison (rtx *comparison, rtx > * op1, rtx * op2) > > } > > +/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ > + > +static unsigned HOST_WIDE_INT > +arm_asan_shadow_offset (void) > +{ > + return (unsigned HOST_WIDE_INT) 1 << 29; > +} > + > #include "gt-arm.h" > diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h > index 23671a7..cb0aad1 100644 > --- a/gcc/config/arm/linux-eabi.h > +++ b/gcc/config/arm/linux-eabi.h > @@ -84,10 +84,14 @@ > LINUX_OR_ANDROID_LD (LINUX_TARGET_LINK_SPEC, \ > LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC) > > +#undef ASAN_CC1_SPEC > +#define ASAN_CC1_SPEC "%{fsanitize=*:-funwind-tables}" > + > #undef CC1_SPEC > #define CC1_SPEC \ > - LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \ > - GNU_USER_TARGET_CC1_SPEC " " ANDROID_CC1_SPEC) > + LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC " " ASAN_CC1_SPEC, \ > + GNU_USER_TARGET_CC1_SPEC " " ASAN_CC1_SPEC " " \ > + ANDROID_CC1_SPEC) > > #define CC1PLUS_SPEC \ > LINUX_OR_ANDROID_CC ("", ANDROID_CC1PLUS_SPEC) > diff --git a/gcc/testsuite/c-c++-common/asan/clone-test-1.c > b/gcc/testsuite/c-c++-common/asan/clone-test-1.c > index d9acc0d..fd187aa 100644 > --- a/gcc/testsuite/c-c++-common/asan/clone-test-1.c > +++ b/gcc/testsuite/c-c++-common/asan/clone-test-1.c > @@ -3,6 +3,7 @@ > > /* { dg-do run { target { *-*-linux* } } } */ > /* { dg-require-effective-target clone } */ > +/* { dg-require-effective-target hw } */ > /* { dg-options "-D_GNU_SOURCE" } */ > > #include <stdio.h> > diff --git a/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c > b/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c > index 43d47a3..e0b9038 100644 > --- a/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c > +++ b/gcc/testsuite/c-c++-common/asan/heap-overflow-1.c > @@ -25,7 +25,7 @@ int main(int argc, char **argv) { > > /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ > -/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of > 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */ > -/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*0x\[0-9a-f\]+ is located 0 bytes to the right of > 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in > _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" > } */ > diff --git a/gcc/testsuite/c-c++-common/asan/null-deref-1.c > b/gcc/testsuite/c-c++-common/asan/null-deref-1.c > index 2eee986..95e5036 100644 > --- a/gcc/testsuite/c-c++-common/asan/null-deref-1.c > +++ b/gcc/testsuite/c-c++-common/asan/null-deref-1.c > @@ -18,6 +18,6 @@ int main() > > /* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown > address\[^\n\r]*" } */ > /* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc > 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ > -/* { dg-output "AddressSanitizer can not provide additional > info.*(\n|\r\n|\r)" } */ > +/* { dg-output ".*AddressSanitizer can not provide additional > info.*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*NullDeref\[^\n\r]* > (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" > } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" > } */ > diff --git a/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c > b/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c > index 0b3d2ae..9dbbc85 100644 > --- a/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c > +++ b/gcc/testsuite/c-c++-common/asan/rlimit-mmap-test-1.c > @@ -2,6 +2,7 @@ > > /* { dg-do run { target setrlimit } } */ > /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ > +/* { dg-require-effective-target hw } */ > /* { dg-shouldfail "asan" } */ > > #include <stdlib.h> > diff --git a/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c > b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c > index 790aa5e..5788b10 100644 > --- a/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c > +++ b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c > @@ -19,4 +19,4 @@ int main() { > > /* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } > */ > -/* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */ > +/* { dg-output ".*Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */ > diff --git a/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c > b/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c > index 10b3ad7..5e8ce40 100644 > --- a/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c > +++ b/gcc/testsuite/c-c++-common/asan/strncpy-overflow-1.c > @@ -15,7 +15,7 @@ int main(int argc, char **argv) { > /* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in > _*(interceptor_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } > */ > -/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of > 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */ > -/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*0x\[0-9a-f\]+ is located 0 bytes to the right of > 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in > _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" > } */ > diff --git a/gcc/testsuite/c-c++-common/asan/use-after-free-1.c > b/gcc/testsuite/c-c++-common/asan/use-after-free-1.c > index 939feeb..65318c8 100644 > --- a/gcc/testsuite/c-c++-common/asan/use-after-free-1.c > +++ b/gcc/testsuite/c-c++-common/asan/use-after-free-1.c > @@ -11,12 +11,12 @@ int main() { > > /* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on > address\[^\n\r]*" } */ > /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp > 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ > -/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*READ of size 1 at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ > -/* { dg-output "0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte > region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ > -/* { dg-output "freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte > region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in > _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ > -/* { dg-output "previously allocated by thread T0 > here:\[^\n\r]*(\n|\r\n|\r)" } */ > +/* { dg-output ".*previously allocated by thread T0 > here:\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #0 0x\[0-9a-f\]+ (in > _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ > /* { dg-output " #1 0x\[0-9a-f\]+ (in _*main > (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" > } */ > diff --git a/gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C > b/gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C > index 12d8a7a..d29fe31 100644 > --- a/gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C > +++ b/gcc/testsuite/g++.dg/asan/deep-thread-stack-1.C > @@ -45,9 +45,9 @@ int main(int argc, char *argv[]) { > } > > // { dg-output "ERROR: AddressSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } > -// { dg-output "WRITE of size 4 at 0x\[0-9a-f\]+ thread > T(\[0-9\]+).*(\n|\r\n|\r)" } > -// { dg-output "freed by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" } > -// { dg-output "previously allocated by thread T(\[0-9\]+) > here:.*(\n|\r\n|\r)" } > +// { dg-output ".*WRITE of size 4 at 0x\[0-9a-f\]+ thread > T(\[0-9\]+).*(\n|\r\n|\r)" } > +// { dg-output ".*freed by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" } > +// { dg-output ".*previously allocated by thread T(\[0-9\]+) > here:.*(\n|\r\n|\r)" } > // { dg-output "Thread T\\2 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } > // { dg-output "Thread T\\8 created by T0 here:.*(\n|\r\n|\r)" } > // { dg-output "Thread T\\4 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } > diff --git a/gcc/testsuite/g++.dg/asan/large-func-test-1.C > b/gcc/testsuite/g++.dg/asan/large-func-test-1.C > index 32808e7..0d5c383 100644 > --- a/gcc/testsuite/g++.dg/asan/large-func-test-1.C > +++ b/gcc/testsuite/g++.dg/asan/large-func-test-1.C > @@ -37,9 +37,9 @@ int main() { > > // { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on > address\[^\n\r]*" } > // { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp > 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } > -// { dg-output "READ of size 4 at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } > +// { dg-output ".*READ of size 4 at 0x\[0-9a-f\]+ thread > T0\[^\n\r]*(\n|\r\n|\r)" } > // { dg-output " #0 0x\[0-9a-f\]+ (in > \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" > } > -// { dg-output "0x\[0-9a-f\]+ is located 44 bytes to the right of > 400-byte region.*(\n|\r\n|\r)" } > -// { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } > +// { dg-output ".*0x\[0-9a-f\]+ is located 44 bytes to the right of > 400-byte region.*(\n|\r\n|\r)" } > +// { dg-output ".*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } > // { dg-output " #0( 0x\[0-9a-f\]+ (in > _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } > // { dg-output " #1|) 0x\[0-9a-f\]+ (in (operator > new|_*_Zn\[aw\]\[mj\])|\[(\])\[^\n\r]*(\n|\r\n|\r)" } > diff --git a/gcc/testsuite/lib/target-supports.exp > b/gcc/testsuite/lib/target-supports.exp > index 45c8b84..28b6b6d 100644 > --- a/gcc/testsuite/lib/target-supports.exp > +++ b/gcc/testsuite/lib/target-supports.exp > @@ -4668,6 +4668,33 @@ proc check_effective_target_simulator { } { > return 0 > } > > +# Return 1 if programs are intended to be run on hardware rather than > +# on a simulator > + > +proc check_effective_target_hw { } { > + > + # All "src/sim" simulators set this one. > + if [board_info target exists is_simulator] { > + if [board_info target is_simulator] { > + return 0 > + } else { > + return 1 > + } > + } > + > + # The "sid" simulators don't set that one, but at least they set > + # this one. > + if [board_info target exists slow_simulator] { > + if [board_info target slow_simulator] { > + return 0 > + } else { > + return 1 > + } > + } > + > + return 1 > +} > + > # Return 1 if the target is a VxWorks kernel. > > proc check_effective_target_vxworks_kernel { } { > diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt > index 265da01..bdfc22e 100644 > --- a/libsanitizer/configure.tgt > +++ b/libsanitizer/configure.tgt > @@ -29,6 +29,8 @@ case "${target}" in > ;; > sparc*-*-linux*) > ;; > + arm*-*-linux*) > + ;; > x86_64-*-darwin[1]* | i?86-*-darwin[1]*) > TSAN_SUPPORTED=no > ;; > diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc > b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc > index e14ea44..7b3e4ca 100644 > --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc > +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc > @@ -27,7 +27,7 @@ const char *StripPathPrefix(const char *filepath, > uptr StackTrace::GetPreviousInstructionPc(uptr pc) { > #ifdef __arm__ > // Cancel Thumb bit. > - pc = pc & (~1); > + return pc & (~1); > #endif > #if defined(__powerpc__) || defined(__powerpc64__) > // PCs are always 4 byte aligned.