diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2015-11-16 13:55:19 +0000 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2015-11-16 13:55:19 +0000 |
commit | d992eb6a41d3f14df04f482c528826727573cce6 (patch) | |
tree | c0acf2b17702750488e1da15f684bd29bf753145 | |
parent | 3cd0a5a8def018a7065fbe999da3b160b5b9eaae (diff) |
[compiler-rt] [tsan] Enable intercept setjmp/longjmp for AArch64
This patch adds assembly routines to enable setjmp/longjmp for aarch64
on linux. It fixes:
* test/tsan/longjmp2.cc
* test/tsan/longjmp3.cc
* test/tsan/longjmp4.cc
* test/tsan/signal_longjmp.cc
I also checked with perlbench from specpu2006 (it fails to run
with missing setjmp/longjmp intrumentation).
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@253205 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/sanitizer_common/sanitizer_asm.h | 6 | ||||
-rw-r--r-- | lib/tsan/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_aarch64.S | 206 | ||||
-rw-r--r-- | test/tsan/longjmp.cc | 3 | ||||
-rw-r--r-- | test/tsan/longjmp2.cc | 3 | ||||
-rw-r--r-- | test/tsan/longjmp3.cc | 3 | ||||
-rw-r--r-- | test/tsan/longjmp4.cc | 3 | ||||
-rw-r--r-- | test/tsan/signal_longjmp.cc | 3 |
9 files changed, 227 insertions, 11 deletions
diff --git a/lib/sanitizer_common/sanitizer_asm.h b/lib/sanitizer_common/sanitizer_asm.h index 906012a96..731f1a539 100644 --- a/lib/sanitizer_common/sanitizer_asm.h +++ b/lib/sanitizer_common/sanitizer_asm.h @@ -23,8 +23,11 @@ # define CFI_STARTPROC .cfi_startproc # define CFI_ENDPROC .cfi_endproc # define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n +# define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n # define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n +# define CFI_OFFSET(reg, n) .cfi_offset reg, n # define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg +# define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n # define CFI_RESTORE(reg) .cfi_restore reg #else // No CFI @@ -32,8 +35,11 @@ # define CFI_STARTPROC # define CFI_ENDPROC # define CFI_ADJUST_CFA_OFFSET(n) +# define CFI_DEF_CFA_OFFSET(n) # define CFI_REL_OFFSET(reg, n) +# define CFI_OFFSET(reg, n) # define CFI_DEF_CFA_REGISTER(reg) +# define CFI_DEF_CFA(reg, n) # define CFI_RESTORE(reg) #endif diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index bfad73fe7..de0fb439e 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -121,6 +121,11 @@ else() WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go COMMENT "Checking TSan Go runtime..." VERBATIM) + elseif(arch STREQUAL "aarch64") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_aarch64.S) + # Pass ASM file directly to the C++ compiler. + set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES + LANGUAGE C) else() set(TSAN_ASM_SOURCES) endif() diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 800c7bd98..7aaa4c304 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -451,8 +451,12 @@ static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) { static void LongJmp(ThreadState *thr, uptr *env) { #if SANITIZER_FREEBSD uptr mangled_sp = env[2]; -#else +#elif defined(SANITIZER_LINUX) +# ifdef __aarch64__ + uptr mangled_sp = env[13]; +# else uptr mangled_sp = env[6]; +# endif #endif // SANITIZER_FREEBSD // Find the saved buf by mangled_sp. for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) { diff --git a/lib/tsan/rtl/tsan_rtl_aarch64.S b/lib/tsan/rtl/tsan_rtl_aarch64.S new file mode 100644 index 000000000..9cea3cf02 --- /dev/null +++ b/lib/tsan/rtl/tsan_rtl_aarch64.S @@ -0,0 +1,206 @@ +#include "sanitizer_common/sanitizer_asm.h" +.section .text + +.hidden __tsan_setjmp +.comm _ZN14__interception11real_setjmpE,8,8 +.type setjmp, @function +setjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf + str x19, [sp, 16] + CFI_OFFSET (19, -16) + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // restore env parameter + mov x0, x19 + ldr x19, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (19) + CFI_DEF_CFA (31, 0) + + // tail jump to libc setjmp + adrp x1, :got:_ZN14__interception11real_setjmpE + ldr x1, [x1, #:got_lo12:_ZN14__interception11real_setjmpE] + ldr x1, [x1] + br x1 + + CFI_ENDPROC +.size setjmp, .-setjmp + +.comm _ZN14__interception12real__setjmpE,8,8 +.globl _setjmp +.type _setjmp, @function +_setjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf + str x19, [sp, 16] + CFI_OFFSET (19, -16) + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // Restore jmp_buf parameter + mov x0, x19 + ldr x19, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (19) + CFI_DEF_CFA (31, 0) + + // tail jump to libc setjmp + adrp x1, :got:_ZN14__interception12real__setjmpE + ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE] + ldr x1, [x1] + br x1 + + CFI_ENDPROC +.size _setjmp, .-_setjmp + +.comm _ZN14__interception14real_sigsetjmpE,8,8 +.globl sigsetjmp +.type sigsetjmp, @function +sigsetjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf and savesigs + stp x19, x20, [sp, 16] + CFI_OFFSET (19, -16) + CFI_OFFSET (20, -8) + mov w20, w1 + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + // restore env parameter + mov w1, w20 + mov x0, x19 + ldp x19, x20, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (29) + CFI_RESTORE (19) + CFI_RESTORE (20) + CFI_DEF_CFA (31, 0) + + // tail jump to libc sigsetjmp + adrp x2, :got:_ZN14__interception14real_sigsetjmpE + ldr x2, [x2, #:got_lo12:_ZN14__interception14real_sigsetjmpE] + ldr x2, [x2] + br x2 + CFI_ENDPROC +.size sigsetjmp, .-sigsetjmp + +.comm _ZN14__interception16real___sigsetjmpE,8,8 +.globl __sigsetjmp +.type __sigsetjmp, @function +__sigsetjmp: + CFI_STARTPROC + + // save env parameters for function call + stp x29, x30, [sp, -32]! + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (29, -32) + CFI_OFFSET (30, -24) + + // Adjust the SP for previous frame + add x29, sp, 0 + CFI_DEF_CFA_REGISTER (29) + + // Save jmp_buf and savesigs + stp x19, x20, [sp, 16] + CFI_OFFSET (19, -16) + CFI_OFFSET (20, -8) + mov w20, w1 + mov x19, x0 + + // SP pointer mangling (see glibc setjmp) + adrp x2, :got:__pointer_chk_guard + ldr x2, [x2, #:got_lo12:__pointer_chk_guard] + add x0, x29, 32 + ldr x2, [x2] + eor x1, x2, x0 + + // call tsan interceptor + bl __tsan_setjmp + + mov w1, w20 + mov x0, x19 + ldp x19, x20, [sp, 16] + ldp x29, x30, [sp], 32 + CFI_RESTORE (30) + CFI_RESTORE (29) + CFI_RESTORE (19) + CFI_RESTORE (20) + CFI_DEF_CFA (31, 0) + + // tail jump to libc __sigsetjmp + adrp x2, :got:_ZN14__interception16real___sigsetjmpE + ldr x2, [x2, #:got_lo12:_ZN14__interception16real___sigsetjmpE] + ldr x2, [x2] + br x2 + CFI_ENDPROC +.size __sigsetjmp, .-__sigsetjmp + +#if defined(__linux__) +/* We do not need executable stack. */ +.section .note.GNU-stack,"",@progbits +#endif diff --git a/test/tsan/longjmp.cc b/test/tsan/longjmp.cc index 9ac6b99c2..d64206739 100644 --- a/test/tsan/longjmp.cc +++ b/test/tsan/longjmp.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/longjmp2.cc b/test/tsan/longjmp2.cc index dfbd84b49..eee423dc5 100644 --- a/test/tsan/longjmp2.cc +++ b/test/tsan/longjmp2.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include <stdio.h> #include <stdlib.h> diff --git a/test/tsan/longjmp3.cc b/test/tsan/longjmp3.cc index df426fac2..79965c419 100644 --- a/test/tsan/longjmp3.cc +++ b/test/tsan/longjmp3.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include <pthread.h> #include <stdio.h> diff --git a/test/tsan/longjmp4.cc b/test/tsan/longjmp4.cc index 9f5d6d1a8..c85839973 100644 --- a/test/tsan/longjmp4.cc +++ b/test/tsan/longjmp4.cc @@ -1,8 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include <pthread.h> #include <stdio.h> diff --git a/test/tsan/signal_longjmp.cc b/test/tsan/signal_longjmp.cc index c02917f49..2525c8988 100644 --- a/test/tsan/signal_longjmp.cc +++ b/test/tsan/signal_longjmp.cc @@ -3,9 +3,8 @@ // Test case for longjumping out of signal handler: // https://code.google.com/p/thread-sanitizer/issues/detail?id=75 -// Longjmp assembly has not been implemented for mips64 or aarch64 yet +// Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 -// XFAIL: aarch64 #include <setjmp.h> #include <signal.h> |