diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -528,10 +528,13 @@ uptr mangled_sp = env[6]; # endif #endif + uptr sp = UnmangleLongJmpSp(mangled_sp); // Find the saved buf by mangled_sp. for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) { JmpBuf *buf = &thr->jmp_bufs[i]; if (buf->mangled_sp == mangled_sp) { + CHECK_EQ(buf->sp, sp); + // TODO(yln): Lookup via sp, remove mangled_sp from struct. CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos); // Unwind the stack. while (thr->shadow_stack_pos > buf->shadow_stack_pos) diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -1011,6 +1011,7 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); int ExtractResolvFDs(void *state, int *fds, int nfd); int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); +uptr UnmangleLongJmpSp(uptr mangled_sp); void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size); int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -69,6 +69,7 @@ #if SANITIZER_LINUX && defined(__aarch64__) void InitializeGuardPtr() __attribute__((visibility("hidden"))); +extern "C" uptr _tsan_pointer_chk_guard; #endif namespace __tsan { @@ -334,6 +335,38 @@ return res; } +// Reverse operation of libc stack pointer mangling +uptr UnmangleLongJmpSp(uptr mangled_sp) { +#if defined(__x86_64__) +#if SANITIZER_FREEBSD || SANITIZER_NETBSD + return mangled_sp; +#else // Linux + // Reverse of: + // xor %fs:0x30, %rsi + // rol $0x11, %rsi + uptr sp; + asm("ror $0x11, %0 \n" + "xor %%fs:0x30, %0 \n" + : "=r" (sp) + : "0" (mangled_sp)); + return sp; +#endif +#elif defined(__aarch64__) + return mangled_sp ^ _tsan_pointer_chk_guard; +#elif defined(__powerpc64__) + // Reverse of: + // ld r4, -28696(r13) + // xor r4, r3, r4 + uptr xor_guard; + asm("ld %0, -28696(%%r13) \n" : "=r" (xor_guard)); + return mangled_sp ^ xor_guard; +#elif defined(__mips__) + return mangled_sp; +#else + #error "Unknown platform" +#endif +} + void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { // Check that the thr object is in tls; const uptr thr_beg = (uptr)thr; diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc --- a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc @@ -260,6 +260,10 @@ } } +uptr UnmangleLongJmpSp(uptr mangled_sp) { + return mangled_sp ^ __tsan_darwin_setjmp_xor_key; +} + #if !SANITIZER_GO void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { // The pointer to the ThreadState object is stored in the shadow memory