Patchwork [ARM,v2] Enable libsanitizer

login
register
mail settings
Submitter Christophe Lyon
Date May 6, 2013, 6:52 p.m.
Message ID <CAKdteOY1Qoe1dXTSGSgABp3RPi+4+ge-XreNr9URK4kLjbfRQQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/241756/
State New
Headers show

Comments

Christophe Lyon - May 6, 2013, 6:52 p.m.
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.lyon@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.
Konstantin Serebryany - May 7, 2013, 7:33 a.m.
+eugenis@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.lyon@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.lyon@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.
Evgeniy Stepanov - May 7, 2013, 7:44 a.m.
On Tue, May 7, 2013 at 9:33 AM, Konstantin Serebryany
<konstantin.s.serebryany@gmail.com> wrote:
> +eugenis@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.lyon@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.lyon@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);

Here you are cancelling "pc - 1" operation, why? It is needed for the
function to return the address of the _previous_ instruction. It
matters when the call instruction is the last one in a function
(because the callee is no-return), and return address is actually
outside the function.

>>  #endif
>>  #if defined(__powerpc__) || defined(__powerpc64__)
>>    // PCs are always 4 byte aligned.
Christophe Lyon - May 7, 2013, 8:12 a.m.
Oops, you are correct, I read the code too quickly and didn't notice
the #endif right after the Thumb bit cancellation (I thought the
function didn't return any value when on ARM).

A white line before #if defined(__powerpc__) would help readability :-)

Forget that part.

Thanks,

Christophe.




On 7 May 2013 09:44, Evgeniy Stepanov <eugenis@google.com> wrote:
> On Tue, May 7, 2013 at 9:33 AM, Konstantin Serebryany
> <konstantin.s.serebryany@gmail.com> wrote:
>> +eugenis@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.lyon@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.lyon@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);
>
> Here you are cancelling "pc - 1" operation, why? It is needed for the
> function to return the address of the _previous_ instruction. It
> matters when the call instruction is the last one in a function
> (because the callee is no-return), and return address is actually
> outside the function.
>
>>>  #endif
>>>  #if defined(__powerpc__) || defined(__powerpc64__)
>>>    // PCs are always 4 byte aligned.
Konstantin Serebryany - May 7, 2013, 8:38 a.m.
The rest of the patch is gcc-specific. Jakub?

On Tue, May 7, 2013 at 12:12 PM, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
> Oops, you are correct, I read the code too quickly and didn't notice
> the #endif right after the Thumb bit cancellation (I thought the
> function didn't return any value when on ARM).
>
> A white line before #if defined(__powerpc__) would help readability :-)
>
> Forget that part.
>
> Thanks,
>
> Christophe.
>
>
>
>
> On 7 May 2013 09:44, Evgeniy Stepanov <eugenis@google.com> wrote:
>> On Tue, May 7, 2013 at 9:33 AM, Konstantin Serebryany
>> <konstantin.s.serebryany@gmail.com> wrote:
>>> +eugenis@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.lyon@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.lyon@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);
>>
>> Here you are cancelling "pc - 1" operation, why? It is needed for the
>> function to return the address of the _previous_ instruction. It
>> matters when the call instruction is the last one in a function
>> (because the callee is no-return), and return address is actually
>> outside the function.
>>
>>>>  #endif
>>>>  #if defined(__powerpc__) || defined(__powerpc64__)
>>>>    // PCs are always 4 byte aligned.
Jakub Jelinek - May 7, 2013, 8:44 a.m.
On Mon, May 06, 2013 at 08:52:21PM +0200, Christophe Lyon wrote:
> --- 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);
> +

Unnecessary extra line?

> --- 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)" } */

Please avoid .* whenever possible, in dejagnu that includes newlines.
So, use \[^\n\r]* instead unless it prints extra lines.
Repeated many times through the patch.

> --- 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.

And this change needs to be merged from upstream libsanitizer.

	Jakub

Patch

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.