From 19b84a02247cc805bd720b2b3f0cc9162438998e Mon Sep 17 00:00:00 2001 From: Sagar Thakur Date: Tue, 16 Aug 2016 05:06:56 +0000 Subject: [PATCH] [TSan][MIPS] Implements setjmp assembly for MIPS64 Reviewed by dvyukov Differential: https://reviews.llvm.org/D23494 llvm-svn: 278775 --- compiler-rt/lib/tsan/CMakeLists.txt | 5 + compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 2 + compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S | 214 ++++++++++++++++++++++++++ compiler-rt/test/tsan/ignore_lib4.cc | 2 - compiler-rt/test/tsan/longjmp.cc | 3 - compiler-rt/test/tsan/longjmp2.cc | 3 - compiler-rt/test/tsan/longjmp3.cc | 3 - compiler-rt/test/tsan/longjmp4.cc | 3 - compiler-rt/test/tsan/signal_longjmp.cc | 2 - 9 files changed, 221 insertions(+), 16 deletions(-) create mode 100644 compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt index 7c84e0a..1ce5821 100644 --- a/compiler-rt/lib/tsan/CMakeLists.txt +++ b/compiler-rt/lib/tsan/CMakeLists.txt @@ -160,6 +160,11 @@ else() # Pass ASM file directly to the C++ compiler. set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES LANGUAGE C) + elseif(arch MATCHES "mips64|mips64le") + set(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.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/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 90b1264..a3a50e1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -483,6 +483,8 @@ static void LongJmp(ThreadState *thr, uptr *env) { #elif defined(SANITIZER_LINUX) # ifdef __aarch64__ uptr mangled_sp = env[13]; +# elif defined(__mips64) + uptr mangled_sp = env[1]; # else uptr mangled_sp = env[6]; # endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S new file mode 100644 index 0000000..d0f7a3f --- /dev/null +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mips64.S @@ -0,0 +1,214 @@ +.section .text +.set noreorder + +.hidden __tsan_setjmp +.comm _ZN14__interception11real_setjmpE,8,8 +.globl setjmp +.type setjmp, @function +setjmp: + + // save env parameters + daddiu $sp,$sp,-40 + sd $s0,32($sp) + sd $ra,24($sp) + sd $fp,16($sp) + sd $gp,8($sp) + + // calculate and save pointer to GOT + lui $gp,%hi(%neg(%gp_rel(setjmp))) + daddu $gp,$gp,$t9 + daddiu $gp,$gp,%lo(%neg(%gp_rel(setjmp))) + move $s0,$gp + + // save jmp_buf + sd $a0,0($sp) + + // obtain $sp + dadd $a0,$zero,$sp + + // call tsan interceptor + jal __tsan_setjmp + daddiu $a1,$a0,40 + + // restore jmp_buf + ld $a0,0($sp) + + // restore gp + move $gp,$s0 + + // load pointer of libc setjmp to t9 + dla $t9,(_ZN14__interception11real_setjmpE) + + // restore env parameters + ld $gp,8($sp) + ld $fp,16($sp) + ld $ra,24($sp) + ld $s0,32($sp) + daddiu $sp,$sp,40 + + // tail jump to libc setjmp + ld $t9,0($t9) + jr $t9 + nop + +.size setjmp, .-setjmp + +.hidden __tsan_setjmp +.globl _setjmp +.comm _ZN14__interception12real__setjmpE,8,8 +.type _setjmp, @function +_setjmp: + + // Save env parameters + daddiu $sp,$sp,-40 + sd $s0,32($sp) + sd $ra,24($sp) + sd $fp,16($sp) + sd $gp,8($sp) + + // calculate and save pointer to GOT + lui $gp,%hi(%neg(%gp_rel(_setjmp))) + daddu $gp,$gp,$t9 + daddiu $gp,$gp,%lo(%neg(%gp_rel(_setjmp))) + move $s0,$gp + + // save jmp_buf + sd $a0,0($sp) + + // obtain $sp + dadd $a0,$zero,$sp + + // call tsan interceptor + jal __tsan_setjmp + daddiu $a1,$a0,40 + + // restore jmp_buf + ld $a0,0($sp) + + // restore gp + move $gp,$s0 + + // load pointer of libc _setjmp to t9 + dla $t9,(_ZN14__interception12real__setjmpE) + + // restore env parameters + ld $gp,8($sp) + ld $fp,16($sp) + ld $ra,24($sp) + ld $s0,32($sp) + daddiu $sp,$sp,40 + + // tail jump to libc _setjmp + ld $t9,0($t9) + jr $t9 + nop + +.size _setjmp, .-_setjmp + +.hidden __tsan_setjmp +.globl sigsetjmp +.comm _ZN14__interception14real_sigsetjmpE,8,8 +.type sigsetjmp, @function +sigsetjmp: + + // Save env parameters + daddiu $sp,$sp,-48 + sd $s0,40($sp) + sd $ra,32($sp) + sd $fp,24($sp) + sd $gp,16($sp) + + // calculate and save pointer to GOT + lui $gp,%hi(%neg(%gp_rel(sigsetjmp))) + daddu $gp,$gp,$t9 + daddiu $gp,$gp,%lo(%neg(%gp_rel(sigsetjmp))) + move $s0,$gp + + // save jmp_buf and savesig + sd $a0,0($sp) + sd $a1,8($sp) + + // obtain $sp + dadd $a0,$zero,$sp + + // call tsan interceptor + jal __tsan_setjmp + daddiu $a1,$a0,48 + + // restore jmp_buf and savesig + ld $a0,0($sp) + ld $a1,8($sp) + + // restore gp + move $gp,$s0 + + // load pointer of libc sigsetjmp to t9 + dla $t9,(_ZN14__interception14real_sigsetjmpE) + + // restore env parameters + ld $gp,16($sp) + ld $fp,24($sp) + ld $ra,32($sp) + ld $s0,40($sp) + daddiu $sp,$sp,48 + + // tail jump to libc sigsetjmp + ld $t9,0($t9) + jr $t9 + nop + +.size sigsetjmp, .-sigsetjmp + +.hidden __tsan_setjmp +.comm _ZN14__interception16real___sigsetjmpE,8,8 +.globl __sigsetjmp +.type __sigsetjmp, @function +__sigsetjmp: + + // Save env parameters + daddiu $sp,$sp,-48 + sd $s0,40($sp) + sd $ra,32($sp) + sd $fp,24($sp) + sd $gp,16($sp) + + // calculate and save pointer to GOT + lui $gp,%hi(%neg(%gp_rel(__sigsetjmp))) + daddu $gp,$gp,$t9 + daddiu $gp,$gp,%lo(%neg(%gp_rel(__sigsetjmp))) + move $s0,$gp + + // save jmp_buf and savesig + sd $a0,0($sp) + sd $a1,8($sp) + + // obtain $sp + dadd $a0,$zero,$sp + + // call tsan interceptor + jal __tsan_setjmp + daddiu $a1,$a0,48 + + // restore jmp_buf and savesig + ld $a0,0($sp) + ld $a1,8($sp) + + // restore gp + move $gp,$s0 + + // load pointer to libc __sigsetjmp in t9 + dla $t9,(_ZN14__interception16real___sigsetjmpE) + + // restore env parameters + ld $gp,16($sp) + ld $fp,24($sp) + ld $ra,32($sp) + ld $s0,40($sp) + daddiu $sp,$sp,48 + + // tail jump to libc __sigsetjmp + ld $t9,0($t9) + jr $t9 + nop + +.size __sigsetjmp, .-__sigsetjmp diff --git a/compiler-rt/test/tsan/ignore_lib4.cc b/compiler-rt/test/tsan/ignore_lib4.cc index 1c94a51..84d8b27 100644 --- a/compiler-rt/test/tsan/ignore_lib4.cc +++ b/compiler-rt/test/tsan/ignore_lib4.cc @@ -3,8 +3,6 @@ // RUN: echo "called_from_lib:libignore_lib4.so" > %t.supp // RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 // powerpc64 big endian bots failed with "FileCheck error: '-' is empty" due // to a segmentation fault. // UNSUPPORTED: powerpc64-unknown-linux-gnu diff --git a/compiler-rt/test/tsan/longjmp.cc b/compiler-rt/test/tsan/longjmp.cc index 73e4e4d..a8abca6 100644 --- a/compiler-rt/test/tsan/longjmp.cc +++ b/compiler-rt/test/tsan/longjmp.cc @@ -1,8 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 - #include #include #include diff --git a/compiler-rt/test/tsan/longjmp2.cc b/compiler-rt/test/tsan/longjmp2.cc index 971f69c..d396f3f 100644 --- a/compiler-rt/test/tsan/longjmp2.cc +++ b/compiler-rt/test/tsan/longjmp2.cc @@ -1,8 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 - #include #include #include diff --git a/compiler-rt/test/tsan/longjmp3.cc b/compiler-rt/test/tsan/longjmp3.cc index ac3f3ef..842cf26 100644 --- a/compiler-rt/test/tsan/longjmp3.cc +++ b/compiler-rt/test/tsan/longjmp3.cc @@ -1,8 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 - #include #include #include diff --git a/compiler-rt/test/tsan/longjmp4.cc b/compiler-rt/test/tsan/longjmp4.cc index cdf4069..4c2fbf0 100644 --- a/compiler-rt/test/tsan/longjmp4.cc +++ b/compiler-rt/test/tsan/longjmp4.cc @@ -1,8 +1,5 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 - #include #include #include diff --git a/compiler-rt/test/tsan/signal_longjmp.cc b/compiler-rt/test/tsan/signal_longjmp.cc index 290056b..f9fa4f5 100644 --- a/compiler-rt/test/tsan/signal_longjmp.cc +++ b/compiler-rt/test/tsan/signal_longjmp.cc @@ -3,8 +3,6 @@ // Test case for longjumping out of signal handler: // https://github.com/google/sanitizers/issues/482 -// Longjmp assembly has not been implemented for mips64 yet -// XFAIL: target-is-mips64 // This test fails on powerpc64 BE (VMA=44), a segmentation fault // error happens at the second assignment // "((volatile int *volatile)mem)[1] = 1". -- 2.7.4