[TSan] Intercept __tls_get_addr_internal and __tls_get_offset on SystemZ

Reuse the assembly glue code from sanitizer_common_interceptors.inc and
the handling logic from the __tls_get_addr interceptor.

Reviewed By: dvyukov

Differential Revision: https://reviews.llvm.org/D105629
This commit is contained in:
Ilya Leoshkevich 2021-07-02 16:59:32 +02:00
parent b17673816d
commit bd77f742d6
2 changed files with 44 additions and 16 deletions

View File

@ -5303,6 +5303,12 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
#define INIT_TIMES
#endif
#if SANITIZER_S390 && \
(SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
#endif
#if SANITIZER_INTERCEPT_TLS_GET_ADDR
#if !SANITIZER_S390
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
@ -5342,11 +5348,7 @@ void *__tls_get_addr_opt(void *arg);
// descriptor offset as an argument instead of a pointer. GOT address
// is passed in r12, so it's necessary to write it in assembly. This is
// the function used by the compiler.
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
@ -5362,6 +5364,15 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
}
return res;
}
#endif // SANITIZER_S390
#else
#define INIT_TLS_GET_ADDR
#endif
#if SANITIZER_S390 && \
(SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
extern "C" uptr __tls_get_offset(void *arg);
extern "C" uptr __interceptor___tls_get_offset(void *arg);
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
@ -5400,9 +5411,6 @@ asm(
"br %r3\n"
".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
#endif // SANITIZER_S390
#else
#define INIT_TLS_GET_ADDR
#endif
#if SANITIZER_INTERCEPT_LISTXATTR

View File

@ -2271,6 +2271,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
#define NEED_TLS_GET_ADDR
#endif
#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1
#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
@ -2586,6 +2587,20 @@ static void syscall_post_fork(uptr pc, int pid) {
#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
#ifdef NEED_TLS_GET_ADDR
static void handle_tls_addr(void *arg, void *res) {
ThreadState *thr = cur_thread();
if (!thr)
return;
DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
thr->tls_addr + thr->tls_size);
if (!dtv)
return;
// New DTLS block has been allocated.
MemoryResetRange(thr, 0, dtv->beg, dtv->size);
}
#if !SANITIZER_S390
// Define own interceptor instead of sanitizer_common's for three reasons:
// 1. It must not process pending signals.
// Signal handlers may contain MOVDQA instruction (see below).
@ -2598,17 +2613,17 @@ static void syscall_post_fork(uptr pc, int pid) {
// execute MOVDQA with stack addresses.
TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
void *res = REAL(__tls_get_addr)(arg);
ThreadState *thr = cur_thread();
if (!thr)
return res;
DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
thr->tls_addr + thr->tls_size);
if (!dtv)
return res;
// New DTLS block has been allocated.
MemoryResetRange(thr, 0, dtv->beg, dtv->size);
handle_tls_addr(arg, res);
return res;
}
#else // SANITIZER_S390
TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
char *tp = static_cast<char *>(__builtin_thread_pointer());
handle_tls_addr(arg, res + tp);
return res;
}
#endif
#endif
#if SANITIZER_NETBSD
@ -2831,7 +2846,12 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(_exit);
#ifdef NEED_TLS_GET_ADDR
#if !SANITIZER_S390
TSAN_INTERCEPT(__tls_get_addr);
#else
TSAN_INTERCEPT(__tls_get_addr_internal);
TSAN_INTERCEPT(__tls_get_offset);
#endif
#endif
TSAN_MAYBE_INTERCEPT__LWP_EXIT;