diff options
author | Martin Liska <mliska@suse.cz> | 2023-04-26 09:42:29 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2023-04-26 15:51:56 +0200 |
commit | d53b3d94aaf211ffb2159614f5aaaf03ceb861cc (patch) | |
tree | 4202fe134ccc618029a07e7d1913c608bd7fb77f /libsanitizer/tsan | |
parent | a8e1551bdb372aa3cfe754429b5efd6229ae5fdb (diff) | |
download | gcc-d53b3d94aaf211ffb2159614f5aaaf03ceb861cc.zip gcc-d53b3d94aaf211ffb2159614f5aaaf03ceb861cc.tar.gz gcc-d53b3d94aaf211ffb2159614f5aaaf03ceb861cc.tar.bz2 |
libsanitizer: merge from upstream (3185e47b5a8444e9fd).
Diffstat (limited to 'libsanitizer/tsan')
-rw-r--r-- | libsanitizer/tsan/tsan_external.cpp | 31 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_flags.cpp | 10 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors_mac.cpp | 1 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interceptors_posix.cpp | 176 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_interface.h | 5 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_mman.cpp | 19 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform.h | 170 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform_linux.cpp | 25 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_platform_posix.cpp | 2 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl.cpp | 3 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl.h | 11 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_aarch64.S | 37 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_loongarch64.S | 196 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_ppc64.S | 1 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_report.cpp | 10 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_spinlock_defs_mac.h | 45 | ||||
-rw-r--r-- | libsanitizer/tsan/tsan_suppressions.cpp | 5 |
17 files changed, 587 insertions, 160 deletions
diff --git a/libsanitizer/tsan/tsan_external.cpp b/libsanitizer/tsan/tsan_external.cpp index 19ae174..98abff5 100644 --- a/libsanitizer/tsan/tsan_external.cpp +++ b/libsanitizer/tsan/tsan_external.cpp @@ -46,10 +46,6 @@ const char *GetReportHeaderFromTag(uptr tag) { return tag_data ? tag_data->header : nullptr; } -void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) { - FuncEntry(thr, (uptr)®istered_tags[tag]); -} - uptr TagFromShadowStackFrame(uptr pc) { uptr tag_count = atomic_load(&used_tags, memory_order_relaxed); void *pc_ptr = (void *)pc; @@ -60,15 +56,26 @@ uptr TagFromShadowStackFrame(uptr pc) { #if !SANITIZER_GO -void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessType typ) { +// We need to track tags for individual memory accesses, but there is no space +// in the shadow cells for them. Instead we push/pop them onto the thread +// traces and ignore the extra tag frames when printing reports. +static void PushTag(ThreadState *thr, uptr tag) { + FuncEntry(thr, (uptr)®istered_tags[tag]); +} +static void PopTag(ThreadState *thr) { FuncExit(thr); } + +static void ExternalAccess(void *addr, uptr caller_pc, uptr tsan_caller_pc, + void *tag, AccessType typ) { CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed)); + bool in_ignored_lib; + if (caller_pc && libignore()->IsIgnored(caller_pc, &in_ignored_lib)) + return; + ThreadState *thr = cur_thread(); if (caller_pc) FuncEntry(thr, caller_pc); - InsertShadowStackFrameForTag(thr, (uptr)tag); - bool in_ignored_lib; - if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib)) - MemoryAccess(thr, CALLERPC, (uptr)addr, 1, typ); - FuncExit(thr); + PushTag(thr, (uptr)tag); + MemoryAccess(thr, tsan_caller_pc, (uptr)addr, 1, typ); + PopTag(thr); if (caller_pc) FuncExit(thr); } @@ -112,12 +119,12 @@ void __tsan_external_assign_tag(void *addr, void *tag) { SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_read(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessRead); + ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessRead); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_external_write(void *addr, void *caller_pc, void *tag) { - ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessWrite); + ExternalAccess(addr, STRIP_PAC_PC(caller_pc), CALLERPC, tag, kAccessWrite); } } // extern "C" diff --git a/libsanitizer/tsan/tsan_flags.cpp b/libsanitizer/tsan/tsan_flags.cpp index ee78f25..3fd58f4 100644 --- a/libsanitizer/tsan/tsan_flags.cpp +++ b/libsanitizer/tsan/tsan_flags.cpp @@ -10,19 +10,21 @@ // //===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_flags.h" +#include "tsan_flags.h" + #include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" -#include "tsan_flags.h" -#include "tsan_rtl.h" +#include "tsan_interface.h" #include "tsan_mman.h" +#include "tsan_rtl.h" #include "ubsan/ubsan_flags.h" namespace __tsan { // Can be overriden in frontend. #ifdef TSAN_EXTERNAL_HOOKS -extern "C" const char* __tsan_default_options(); +extern "C" const char *__tsan_default_options(); #else SANITIZER_WEAK_DEFAULT_IMPL const char *__tsan_default_options() { diff --git a/libsanitizer/tsan/tsan_interceptors_mac.cpp b/libsanitizer/tsan/tsan_interceptors_mac.cpp index 1ee47bc..e4f9e29 100644 --- a/libsanitizer/tsan/tsan_interceptors_mac.cpp +++ b/libsanitizer/tsan/tsan_interceptors_mac.cpp @@ -18,6 +18,7 @@ #include "tsan_interceptors.h" #include "tsan_interface.h" #include "tsan_interface_ann.h" +#include "tsan_spinlock_defs_mac.h" #include "sanitizer_common/sanitizer_addrhashmap.h" #include <errno.h> diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp index c557d5d..6ac6ac6 100644 --- a/libsanitizer/tsan/tsan_interceptors_posix.cpp +++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp @@ -76,6 +76,8 @@ struct ucontext_t { #define PTHREAD_ABI_BASE "GLIBC_2.3.2" #elif defined(__aarch64__) || SANITIZER_PPC64V2 #define PTHREAD_ABI_BASE "GLIBC_2.17" +#elif SANITIZER_LOONGARCH64 +#define PTHREAD_ABI_BASE "GLIBC_2.36" #endif extern "C" int pthread_attr_init(void *attr); @@ -126,6 +128,7 @@ const int SIGSYS = 12; const int SIGBUS = 7; const int SIGSYS = 31; #endif +const int SI_TIMER = -2; void *const MAP_FAILED = (void*)-1; #if SANITIZER_NETBSD const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567; @@ -247,13 +250,21 @@ SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {} } // namespace __tsan static ThreadSignalContext *SigCtx(ThreadState *thr) { - ThreadSignalContext *ctx = (ThreadSignalContext*)thr->signal_ctx; + // This function may be called reentrantly if it is interrupted by a signal + // handler. Use CAS to handle the race. + uptr ctx = atomic_load(&thr->signal_ctx, memory_order_relaxed); if (ctx == 0 && !thr->is_dead) { - ctx = (ThreadSignalContext*)MmapOrDie(sizeof(*ctx), "ThreadSignalContext"); - MemoryResetRange(thr, (uptr)&SigCtx, (uptr)ctx, sizeof(*ctx)); - thr->signal_ctx = ctx; + uptr pctx = + (uptr)MmapOrDie(sizeof(ThreadSignalContext), "ThreadSignalContext"); + MemoryResetRange(thr, (uptr)&SigCtx, pctx, sizeof(ThreadSignalContext)); + if (atomic_compare_exchange_strong(&thr->signal_ctx, &ctx, pctx, + memory_order_relaxed)) { + ctx = pctx; + } else { + UnmapOrDie((ThreadSignalContext *)pctx, sizeof(ThreadSignalContext)); + } } - return ctx; + return (ThreadSignalContext *)ctx; } ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, @@ -968,9 +979,10 @@ void DestroyThreadState() { } void PlatformCleanUpThreadState(ThreadState *thr) { - ThreadSignalContext *sctx = thr->signal_ctx; + ThreadSignalContext *sctx = (ThreadSignalContext *)atomic_load( + &thr->signal_ctx, memory_order_relaxed); if (sctx) { - thr->signal_ctx = 0; + atomic_store(&thr->signal_ctx, 0, memory_order_relaxed); UnmapOrDie(sctx, sizeof(*sctx)); } } @@ -1351,6 +1363,19 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) { return res; } +TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m); + MutexPreLock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_lock)(m); + if (res == errno_EOWNERDEAD) + MutexRepair(thr, pc, (uptr)m); + if (res == 0 || res == errno_EOWNERDEAD) + MutexPostLock(thr, pc, (uptr)m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m); int res = REAL(pthread_mutex_trylock)(m); @@ -1372,6 +1397,43 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } #endif +TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m); + MutexUnlock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_unlock)(m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + +#if SANITIZER_GLIBC +# if !__GLIBC_PREREQ(2, 34) +// glibc 2.34 applies a non-default version for the two functions. They are no +// longer expected to be intercepted by programs. +TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) { + SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m); + MutexPreLock(thr, pc, (uptr)m); + int res = REAL(__pthread_mutex_lock)(m); + if (res == errno_EOWNERDEAD) + MutexRepair(thr, pc, (uptr)m); + if (res == 0 || res == errno_EOWNERDEAD) + MutexPostLock(thr, pc, (uptr)m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + +TSAN_INTERCEPTOR(int, __pthread_mutex_unlock, void *m) { + SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_unlock, m); + MutexUnlock(thr, pc, (uptr)m); + int res = REAL(__pthread_mutex_unlock)(m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} +# endif +#endif + #if !SANITIZER_APPLE TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); @@ -1943,12 +2005,34 @@ TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout, return res; } -#define TSAN_MAYBE_INTERCEPT_EPOLL \ - TSAN_INTERCEPT(epoll_create); \ - TSAN_INTERCEPT(epoll_create1); \ - TSAN_INTERCEPT(epoll_ctl); \ - TSAN_INTERCEPT(epoll_wait); \ - TSAN_INTERCEPT(epoll_pwait) +TSAN_INTERCEPTOR(int, epoll_pwait2, int epfd, void *ev, int cnt, void *timeout, + void *sigmask) { + SCOPED_INTERCEPTOR_RAW(epoll_pwait2, epfd, ev, cnt, timeout, sigmask); + // This function is new and may not be present in libc and/or kernel. + // Since we effectively add it to libc (as will be probed by the program + // using dlsym or a weak function pointer) we need to handle the case + // when it's not present in the actual libc. + if (!REAL(epoll_pwait2)) { + errno = errno_ENOSYS; + return -1; + } + if (MustIgnoreInterceptor(thr)) + REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask); + if (epfd >= 0) + FdAccess(thr, pc, epfd); + int res = BLOCK_REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask); + if (res > 0 && epfd >= 0) + FdAcquire(thr, pc, epfd); + return res; +} + +# define TSAN_MAYBE_INTERCEPT_EPOLL \ + TSAN_INTERCEPT(epoll_create); \ + TSAN_INTERCEPT(epoll_create1); \ + TSAN_INTERCEPT(epoll_ctl); \ + TSAN_INTERCEPT(epoll_wait); \ + TSAN_INTERCEPT(epoll_pwait); \ + TSAN_INTERCEPT(epoll_pwait2) #else #define TSAN_MAYBE_INTERCEPT_EPOLL #endif @@ -2082,11 +2166,19 @@ void ProcessPendingSignalsImpl(ThreadState *thr) { } // namespace __tsan -static bool is_sync_signal(ThreadSignalContext *sctx, int sig) { +static bool is_sync_signal(ThreadSignalContext *sctx, int sig, + __sanitizer_siginfo *info) { + // If we are sending signal to ourselves, we must process it now. + if (sctx && sig == sctx->int_signal_send) + return true; +#if SANITIZER_HAS_SIGINFO + // POSIX timers can be configured to send any kind of signal; however, it + // doesn't make any sense to consider a timer signal as synchronous! + if (info->si_code == SI_TIMER) + return false; +#endif return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP || - sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS || - // If we are sending signal to ourselves, we must process it now. - (sctx && sig == sctx->int_signal_send); + sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS; } void sighandler(int sig, __sanitizer_siginfo *info, void *ctx) { @@ -2097,7 +2189,7 @@ void sighandler(int sig, __sanitizer_siginfo *info, void *ctx) { return; } // Don't mess with synchronous signals. - const bool sync = is_sync_signal(sctx, sig); + const bool sync = is_sync_signal(sctx, sig, info); if (sync || // If we are in blocking function, we can safely process it now // (but check if we are in a recursive interceptor, @@ -2405,11 +2497,21 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, res; \ }) +// Ignore interceptors in OnLibraryLoaded()/Unloaded(). These hooks use code +// (ListOfModules::init, MemoryMappingLayout::DumpListOfModules) that make +// intercepted calls, which can cause deadlockes with ReportRace() which also +// uses this code. #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ - libignore()->OnLibraryLoaded(filename) + ({ \ + ScopedIgnoreInterceptors ignore_interceptors; \ + libignore()->OnLibraryLoaded(filename); \ + }) -#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \ - libignore()->OnLibraryUnloaded() +#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \ + ({ \ + ScopedIgnoreInterceptors ignore_interceptors; \ + libignore()->OnLibraryUnloaded(); \ + }) #define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \ Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u) @@ -2446,26 +2548,6 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, #define COMMON_INTERCEPTOR_ON_EXIT(ctx) \ OnExit(((TsanInterceptorContext *) ctx)->thr) -#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \ - MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \ - MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \ - MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \ - MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \ - MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \ off) \ do { \ @@ -2762,7 +2844,9 @@ TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m) +TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_lock, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m) +TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_unlock, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m) @@ -2864,8 +2948,16 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_mutex_init); TSAN_INTERCEPT(pthread_mutex_destroy); + TSAN_INTERCEPT(pthread_mutex_lock); TSAN_INTERCEPT(pthread_mutex_trylock); TSAN_INTERCEPT(pthread_mutex_timedlock); + TSAN_INTERCEPT(pthread_mutex_unlock); +#if SANITIZER_GLIBC +# if !__GLIBC_PREREQ(2, 34) + TSAN_INTERCEPT(__pthread_mutex_lock); + TSAN_INTERCEPT(__pthread_mutex_unlock); +# endif +#endif TSAN_INTERCEPT(pthread_spin_init); TSAN_INTERCEPT(pthread_spin_destroy); @@ -3010,7 +3102,9 @@ void InitializeInterceptors() { TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy); + TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_lock); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock); + TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_unlock); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock); diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h index 5b9d664..d53c1e3 100644 --- a/libsanitizer/tsan/tsan_interface.h +++ b/libsanitizer/tsan/tsan_interface.h @@ -32,6 +32,9 @@ extern "C" { // before any instrumented code is executed and before any call to malloc. SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init(); +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char * +__tsan_default_options(); + SANITIZER_INTERFACE_ATTRIBUTE void __tsan_flush_memory(); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr); @@ -85,6 +88,8 @@ SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit(); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_begin(); SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_end(); +SANITIZER_INTERFACE_ATTRIBUTE void __tsan_on_thread_idle(); + SANITIZER_INTERFACE_ATTRIBUTE void *__tsan_external_register_tag(const char *object_type); SANITIZER_INTERFACE_ATTRIBUTE diff --git a/libsanitizer/tsan/tsan_mman.cpp b/libsanitizer/tsan/tsan_mman.cpp index 0937e52..e5271cf 100644 --- a/libsanitizer/tsan/tsan_mman.cpp +++ b/libsanitizer/tsan/tsan_mman.cpp @@ -15,6 +15,7 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_errno.h" #include "sanitizer_common/sanitizer_placement_new.h" +#include "tsan_interface.h" #include "tsan_mman.h" #include "tsan_rtl.h" #include "tsan_report.h" @@ -351,6 +352,20 @@ void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) { return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize)); } +static const void *user_alloc_begin(const void *p) { + if (p == nullptr || !IsAppMem((uptr)p)) + return nullptr; + void *beg = allocator()->GetBlockBegin(p); + if (!beg) + return nullptr; + + MBlock *b = ctx->metamap.GetBlock((uptr)beg); + if (!b) + return nullptr; // Not a valid pointer. + + return (const void *)beg; +} + uptr user_alloc_usable_size(const void *p) { if (p == 0 || !IsAppMem((uptr)p)) return 0; @@ -429,6 +444,10 @@ int __sanitizer_get_ownership(const void *p) { return allocator()->GetBlockBegin(p) != 0; } +const void *__sanitizer_get_allocated_begin(const void *p) { + return user_alloc_begin(p); +} + uptr __sanitizer_get_allocated_size(const void *p) { return user_alloc_usable_size(p); } diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h index 7c13c73..f0cdaf4 100644 --- a/libsanitizer/tsan/tsan_platform.h +++ b/libsanitizer/tsan/tsan_platform.h @@ -34,6 +34,14 @@ enum { // This is bad and can lead to unpredictable memory corruptions, etc // because range access functions assume linearity. kBrokenLinearity = 1 << 2, + // Meta for an app region overlaps with the meta of another app region. + // This is determined by recomputing the individual meta regions for + // each app region. + // + // N.B. There is no "kBrokenReverseMetaMapping" constant because there + // is no MetaToMem function. However, note that (!kBrokenLinearity + // && !kBrokenAliasedMetas) implies that MemToMeta is invertible. + kBrokenAliasedMetas = 1 << 3, }; /* @@ -42,8 +50,8 @@ C/C++ on linux/x86_64 and freebsd/x86_64 0040 0000 0000 - 0100 0000 0000: - 0100 0000 0000 - 1000 0000 0000: shadow 1000 0000 0000 - 3000 0000 0000: - -3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects) -4000 0000 0000 - 5500 0000 0000: - +3000 0000 0000 - 3400 0000 0000: metainfo (memory blocks and sync objects) +3400 0000 0000 - 5500 0000 0000: - 5500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels 5680 0000 0000 - 7d00 0000 0000: - 7b00 0000 0000 - 7c00 0000 0000: heap @@ -147,88 +155,133 @@ struct MappingAppleAarch64 { /* C/C++ on linux/aarch64 (39-bit VMA) -0000 0010 00 - 0100 0000 00: main binary -0100 0000 00 - 0400 0000 00: - -0400 0000 00 - 1000 0000 00: shadow memory -2000 0000 00 - 3100 0000 00: - -3100 0000 00 - 3400 0000 00: metainfo -3400 0000 00 - 5500 0000 00: - -5500 0000 00 - 5600 0000 00: main binary (PIE) +0000 0010 00 - 0500 0000 00: main binary (20 GB) +0100 0000 00 - 2000 0000 00: - +2000 0000 00 - 4000 0000 00: shadow memory (128 GB) +4000 0000 00 - 4800 0000 00: metainfo (32 GB) +4800 0000 00 - 5500 0000 00: - +5500 0000 00 - 5a00 0000 00: main binary (PIE) (20 GB) 5600 0000 00 - 7c00 0000 00: - -7c00 0000 00 - 7d00 0000 00: heap -7d00 0000 00 - 7fff ffff ff: modules and main thread stack +7a00 0000 00 - 7d00 0000 00: heap (12 GB) +7d00 0000 00 - 7fff ffff ff: modules and main thread stack (12 GB) */ struct MappingAarch64_39 { static const uptr kLoAppMemBeg = 0x0000001000ull; - static const uptr kLoAppMemEnd = 0x0100000000ull; - static const uptr kShadowBeg = 0x0400000000ull; - static const uptr kShadowEnd = 0x1000000000ull; - static const uptr kMetaShadowBeg = 0x3100000000ull; - static const uptr kMetaShadowEnd = 0x3400000000ull; + static const uptr kLoAppMemEnd = 0x0500000000ull; + static const uptr kShadowBeg = 0x2000000000ull; + static const uptr kShadowEnd = 0x4000000000ull; + static const uptr kMetaShadowBeg = 0x4000000000ull; + static const uptr kMetaShadowEnd = 0x4800000000ull; static const uptr kMidAppMemBeg = 0x5500000000ull; - static const uptr kMidAppMemEnd = 0x5600000000ull; - static const uptr kHeapMemBeg = 0x7c00000000ull; + static const uptr kMidAppMemEnd = 0x5a00000000ull; + static const uptr kHeapMemBeg = 0x7a00000000ull; static const uptr kHeapMemEnd = 0x7d00000000ull; - static const uptr kHiAppMemBeg = 0x7e00000000ull; + static const uptr kHiAppMemBeg = 0x7d00000000ull; static const uptr kHiAppMemEnd = 0x7fffffffffull; - static const uptr kShadowMsk = 0x7800000000ull; - static const uptr kShadowXor = 0x0200000000ull; - static const uptr kShadowAdd = 0x0000000000ull; + static const uptr kShadowMsk = 0x7000000000ull; + static const uptr kShadowXor = 0x1000000000ull; + static const uptr kShadowAdd = 0x0000000000ull; static const uptr kVdsoBeg = 0x7f00000000ull; }; /* C/C++ on linux/aarch64 (42-bit VMA) -00000 0010 00 - 01000 0000 00: main binary -01000 0000 00 - 08000 0000 00: - -08000 0000 00 - 10000 0000 00: shadow memory -10000 0000 00 - 26000 0000 00: - -26000 0000 00 - 28000 0000 00: metainfo -28000 0000 00 - 2aa00 0000 00: - -2aa00 0000 00 - 2ab00 0000 00: main binary (PIE) -2ab00 0000 00 - 3e000 0000 00: - -3e000 0000 00 - 3f000 0000 00: heap -3f000 0000 00 - 3ffff ffff ff: modules and main thread stack +00000 0010 00 - 02000 0000 00: main binary (128 GB) +02000 0000 00 - 08000 0000 00: - +10000 0000 00 - 20000 0000 00: shadow memory (1024 GB) +20000 0000 00 - 24000 0000 00: metainfo (256 GB) +24000 0000 00 - 2aa00 0000 00: - +2aa00 0000 00 - 2c000 0000 00: main binary (PIE) (88 GB) +2c000 0000 00 - 3c000 0000 00: - +3c000 0000 00 - 3f000 0000 00: heap (192 GB) +3f000 0000 00 - 3ffff ffff ff: modules and main thread stack (64 GB) */ struct MappingAarch64_42 { - static const uptr kBroken = kBrokenReverseMapping; static const uptr kLoAppMemBeg = 0x00000001000ull; - static const uptr kLoAppMemEnd = 0x01000000000ull; - static const uptr kShadowBeg = 0x08000000000ull; - static const uptr kShadowEnd = 0x10000000000ull; - static const uptr kMetaShadowBeg = 0x26000000000ull; - static const uptr kMetaShadowEnd = 0x28000000000ull; + static const uptr kLoAppMemEnd = 0x02000000000ull; + static const uptr kShadowBeg = 0x10000000000ull; + static const uptr kShadowEnd = 0x20000000000ull; + static const uptr kMetaShadowBeg = 0x20000000000ull; + static const uptr kMetaShadowEnd = 0x24000000000ull; static const uptr kMidAppMemBeg = 0x2aa00000000ull; - static const uptr kMidAppMemEnd = 0x2ab00000000ull; - static const uptr kHeapMemBeg = 0x3e000000000ull; + static const uptr kMidAppMemEnd = 0x2c000000000ull; + static const uptr kHeapMemBeg = 0x3c000000000ull; static const uptr kHeapMemEnd = 0x3f000000000ull; static const uptr kHiAppMemBeg = 0x3f000000000ull; static const uptr kHiAppMemEnd = 0x3ffffffffffull; - static const uptr kShadowMsk = 0x3c000000000ull; - static const uptr kShadowXor = 0x04000000000ull; - static const uptr kShadowAdd = 0x00000000000ull; + static const uptr kShadowMsk = 0x38000000000ull; + static const uptr kShadowXor = 0x08000000000ull; + static const uptr kShadowAdd = 0x00000000000ull; static const uptr kVdsoBeg = 0x37f00000000ull; }; +/* +C/C++ on linux/aarch64 (48-bit VMA) +0000 0000 1000 - 0a00 0000 0000: main binary (10240 GB) +0a00 0000 1000 - 1554 0000 0000: - +1554 0000 1000 - 5400 0000 0000: shadow memory (64176 GB) +5400 0000 1000 - 8000 0000 0000: - +8000 0000 1000 - 0a00 0000 0000: metainfo (32768 GB) +a000 0000 1000 - aaaa 0000 0000: - +aaaa 0000 1000 - ac00 0000 0000: main binary (PIE) (1368 GB) +ac00 0000 1000 - fc00 0000 0000: - +fc00 0000 1000 - ffff ffff ffff: modules and main thread stack (4096 GB) + +N.B. the shadow memory region has a strange start address, because it +contains the shadows for the mid, high and low app regions (in this +unusual order). +*/ struct MappingAarch64_48 { static const uptr kLoAppMemBeg = 0x0000000001000ull; - static const uptr kLoAppMemEnd = 0x0000200000000ull; - static const uptr kShadowBeg = 0x0001000000000ull; - static const uptr kShadowEnd = 0x0002000000000ull; - static const uptr kMetaShadowBeg = 0x0005000000000ull; - static const uptr kMetaShadowEnd = 0x0006000000000ull; + static const uptr kLoAppMemEnd = 0x00a0000000000ull; + static const uptr kShadowBeg = 0x0155400000000ull; + static const uptr kShadowEnd = 0x0540000000000ull; + static const uptr kMetaShadowBeg = 0x0800000000000ull; + static const uptr kMetaShadowEnd = 0x0a00000000000ull; static const uptr kMidAppMemBeg = 0x0aaaa00000000ull; - static const uptr kMidAppMemEnd = 0x0aaaf00000000ull; - static const uptr kHeapMemBeg = 0x0ffff00000000ull; - static const uptr kHeapMemEnd = 0x0ffff00000000ull; - static const uptr kHiAppMemBeg = 0x0ffff00000000ull; + static const uptr kMidAppMemEnd = 0x0ac0000000000ull; + static const uptr kHiAppMemBeg = 0x0fc0000000000ull; static const uptr kHiAppMemEnd = 0x1000000000000ull; - static const uptr kShadowMsk = 0x0fff800000000ull; - static const uptr kShadowXor = 0x0000800000000ull; - static const uptr kShadowAdd = 0x0000000000000ull; + static const uptr kHeapMemBeg = 0x0fc0000000000ull; + static const uptr kHeapMemEnd = 0x0fc0000000000ull; + static const uptr kShadowMsk = 0x0c00000000000ull; + static const uptr kShadowXor = 0x0200000000000ull; + static const uptr kShadowAdd = 0x0000000000000ull; static const uptr kVdsoBeg = 0xffff000000000ull; }; +/* C/C++ on linux/loongarch64 (47-bit VMA) +0000 0000 4000 - 0080 0000 0000: main binary +0080 0000 0000 - 0100 0000 0000: - +0100 0000 0000 - 1000 0000 0000: shadow memory +1000 0000 0000 - 3000 0000 0000: - +3000 0000 0000 - 3400 0000 0000: metainfo +3400 0000 0000 - 5555 0000 0000: - +5555 0000 0000 - 5556 0000 0000: main binary (PIE) +5556 0000 0000 - 7ffe 0000 0000: - +7ffe 0000 0000 - 7fff 0000 0000: heap +7fff 0000 0000 - 7fff 8000 0000: - +7fff 8000 0000 - 8000 0000 0000: modules and main thread stack +*/ +struct MappingLoongArch64_47 { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x340000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x7ffe00000000ull; + static const uptr kHeapMemEnd = 0x7fff00000000ull; + static const uptr kLoAppMemBeg = 0x000000004000ull; + static const uptr kLoAppMemEnd = 0x008000000000ull; + static const uptr kMidAppMemBeg = 0x555500000000ull; + static const uptr kMidAppMemEnd = 0x555600000000ull; + static const uptr kHiAppMemBeg = 0x7fff80000000ull; + static const uptr kHiAppMemEnd = 0x800000000000ull; + static const uptr kShadowMsk = 0x780000000000ull; + static const uptr kShadowXor = 0x040000000000ull; + static const uptr kShadowAdd = 0x000000000000ull; + static const uptr kVdsoBeg = 0x7fffffffc000ull; +}; + /* C/C++ on linux/powerpc64 (44-bit VMA) 0000 0000 0100 - 0001 0000 0000: main binary @@ -242,8 +295,8 @@ C/C++ on linux/powerpc64 (44-bit VMA) 0f60 0000 0000 - 1000 0000 0000: modules and main thread stack */ struct MappingPPC64_44 { - static const uptr kBroken = - kBrokenMapping | kBrokenReverseMapping | kBrokenLinearity; + static const uptr kBroken = kBrokenMapping | kBrokenReverseMapping | + kBrokenLinearity | kBrokenAliasedMetas; static const uptr kMetaShadowBeg = 0x0b0000000000ull; static const uptr kMetaShadowEnd = 0x0d0000000000ull; static const uptr kShadowBeg = 0x000100000000ull; @@ -599,6 +652,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) { case 48: return Func::template Apply<MappingAarch64_48>(arg); } +# elif SANITIZER_LOONGARCH64 + return Func::template Apply<MappingLoongArch64_47>(arg); # elif defined(__powerpc64__) switch (vmaSize) { case 44: @@ -627,6 +682,7 @@ void ForEachMapping() { Func::template Apply<MappingAarch64_39>(); Func::template Apply<MappingAarch64_42>(); Func::template Apply<MappingAarch64_48>(); + Func::template Apply<MappingLoongArch64_47>(); Func::template Apply<MappingPPC64_44>(); Func::template Apply<MappingPPC64_46>(); Func::template Apply<MappingPPC64_47>(); diff --git a/libsanitizer/tsan/tsan_platform_linux.cpp b/libsanitizer/tsan/tsan_platform_linux.cpp index 807f6be..384a443 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cpp +++ b/libsanitizer/tsan/tsan_platform_linux.cpp @@ -66,7 +66,8 @@ extern "C" void *__libc_stack_end; void *__libc_stack_end = 0; #endif -#if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO +#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64)) && \ + !SANITIZER_GO # define INIT_LONGJMP_XOR_KEY 1 #else # define INIT_LONGJMP_XOR_KEY 0 @@ -230,6 +231,14 @@ void InitializePlatformEarly() { Die(); } #endif +#elif SANITIZER_LOONGARCH64 +# if !SANITIZER_GO + if (vmaSize != 47) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %zd - Supported 47\n", vmaSize); + Die(); + } +# endif #elif defined(__powerpc64__) # if !SANITIZER_GO if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) { @@ -290,11 +299,12 @@ void InitializePlatform() { SetAddressSpaceUnlimited(); reexec = true; } -#if SANITIZER_LINUX && defined(__aarch64__) +#if SANITIZER_ANDROID && (defined(__aarch64__) || defined(__x86_64__)) // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in // linux kernel, the random gap between stack and mapped area is increased // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover // this big range, we should disable randomized virtual space on aarch64. + // ASLR personality check. int old_personality = personality(0xffffffff); if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) { VReport(1, "WARNING: Program is run with randomized virtual address " @@ -303,6 +313,9 @@ void InitializePlatform() { CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); reexec = true; } + +#endif +#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64)) // Initialize the xor key used in {sig}{set,long}jump. InitializeLongjmpXorKey(); #endif @@ -375,6 +388,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # else return mangled_sp; # endif +#elif defined(__loongarch_lp64) + return mangled_sp ^ longjmp_xor_key; #elif defined(__powerpc64__) // Reverse of: // ld r4, -28696(r13) @@ -410,6 +425,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { #elif SANITIZER_LINUX # ifdef __aarch64__ # define LONG_JMP_SP_ENV_SLOT 13 +# elif defined(__loongarch__) +# define LONG_JMP_SP_ENV_SLOT 1 # elif defined(__mips64) # define LONG_JMP_SP_ENV_SLOT 1 # elif defined(__s390x__) @@ -436,7 +453,11 @@ static void InitializeLongjmpXorKey() { // 2. Retrieve vanilla/mangled SP. uptr sp; +#ifdef __loongarch__ + asm("move %0, $sp" : "=r" (sp)); +#else asm("mov %0, sp" : "=r" (sp)); +#endif uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT]; // 3. xor SPs to obtain key. diff --git a/libsanitizer/tsan/tsan_platform_posix.cpp b/libsanitizer/tsan/tsan_platform_posix.cpp index 71874aa..e7dcd66 100644 --- a/libsanitizer/tsan/tsan_platform_posix.cpp +++ b/libsanitizer/tsan/tsan_platform_posix.cpp @@ -32,7 +32,7 @@ static const char kShadowMemoryMappingHint[] = "TSAN_OPTIONS=%s=0\n"; # if !SANITIZER_GO -static void DontDumpShadow(uptr addr, uptr size) { +void DontDumpShadow(uptr addr, uptr size) { if (common_flags()->use_madv_dontdump) if (!DontDumpShadowMemory(addr, size)) { Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size, diff --git a/libsanitizer/tsan/tsan_rtl.cpp b/libsanitizer/tsan/tsan_rtl.cpp index db3d945..6b1ec1d 100644 --- a/libsanitizer/tsan/tsan_rtl.cpp +++ b/libsanitizer/tsan/tsan_rtl.cpp @@ -213,6 +213,9 @@ static void DoResetImpl(uptr epoch) { #else auto resetFailed = !MmapFixedSuperNoReserve(shadow_begin, shadow_end-shadow_begin, "shadow"); +# if !SANITIZER_GO + DontDumpShadow(shadow_begin, shadow_end - shadow_begin); +# endif #endif if (resetFailed) { Printf("failed to reset shadow memory\n"); diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index f0918d8..a5606db 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -56,7 +56,8 @@ namespace __tsan { #if !SANITIZER_GO struct MapUnmapCallback; -#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) +#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \ + defined(__powerpc__) struct AP32 { static const uptr kSpaceBeg = 0; @@ -219,7 +220,7 @@ struct ThreadState { #endif atomic_uintptr_t in_signal_handler; - ThreadSignalContext *signal_ctx; + atomic_uintptr_t signal_ctx; #if !SANITIZER_GO StackID last_sleep_stack_id; @@ -483,6 +484,7 @@ void MapThreadTrace(uptr addr, uptr size, const char *name); void DontNeedShadowFor(uptr addr, uptr size); void UnmapShadow(ThreadState *thr, uptr addr, uptr size); void InitializeShadowMemory(); +void DontDumpShadow(uptr addr, uptr size); void InitializeInterceptors(); void InitializeLibIgnore(); void InitializeDynamicAnnotations(); @@ -678,8 +680,9 @@ ALWAYS_INLINE void LazyInitialize(ThreadState *thr) { // If we can use .preinit_array, assume that __tsan_init // called from .preinit_array initializes runtime before - // any instrumented code except ANDROID. -#if (!SANITIZER_CAN_USE_PREINIT_ARRAY || defined(__ANDROID__)) + // any instrumented code except when tsan is used as a + // shared library. +#if (!SANITIZER_CAN_USE_PREINIT_ARRAY || defined(SANITIZER_SHARED)) if (UNLIKELY(!is_initialized)) Initialize(thr); #endif diff --git a/libsanitizer/tsan/tsan_rtl_aarch64.S b/libsanitizer/tsan/tsan_rtl_aarch64.S index e0b4c71..c616265 100644 --- a/libsanitizer/tsan/tsan_rtl_aarch64.S +++ b/libsanitizer/tsan/tsan_rtl_aarch64.S @@ -3,28 +3,6 @@ #include "sanitizer_common/sanitizer_asm.h" -#if defined(__APPLE__) -.align 2 - -.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers -.long _setjmp$non_lazy_ptr -_setjmp$non_lazy_ptr: -.indirect_symbol _setjmp -.long 0 - -.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers -.long __setjmp$non_lazy_ptr -__setjmp$non_lazy_ptr: -.indirect_symbol __setjmp -.long 0 - -.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers -.long _sigsetjmp$non_lazy_ptr -_sigsetjmp$non_lazy_ptr: -.indirect_symbol _sigsetjmp -.long 0 -#endif - #if !defined(__APPLE__) .section .text #else @@ -75,9 +53,8 @@ ASM_SYMBOL_INTERCEPTOR(setjmp): ldr x1, [x1, #:got_lo12:_ZN14__interception11real_setjmpE] ldr x1, [x1] #else - adrp x1, _setjmp$non_lazy_ptr@page - add x1, x1, _setjmp$non_lazy_ptr@pageoff - ldr x1, [x1] + adrp x1, _setjmp@GOTPAGE + ldr x1, [x1, _setjmp@GOTPAGEOFF] #endif br x1 @@ -126,9 +103,8 @@ ASM_SYMBOL_INTERCEPTOR(_setjmp): ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE] ldr x1, [x1] #else - adrp x1, __setjmp$non_lazy_ptr@page - add x1, x1, __setjmp$non_lazy_ptr@pageoff - ldr x1, [x1] + adrp x1, __setjmp@GOTPAGE + ldr x1, [x1, __setjmp@GOTPAGEOFF] #endif br x1 @@ -179,9 +155,8 @@ ASM_SYMBOL_INTERCEPTOR(sigsetjmp): ldr x2, [x2, #:got_lo12:_ZN14__interception14real_sigsetjmpE] ldr x2, [x2] #else - adrp x2, _sigsetjmp$non_lazy_ptr@page - add x2, x2, _sigsetjmp$non_lazy_ptr@pageoff - ldr x2, [x2] + adrp x2, _sigsetjmp@GOTPAGE + ldr x2, [x2, _sigsetjmp@GOTPAGEOFF] #endif br x2 CFI_ENDPROC diff --git a/libsanitizer/tsan/tsan_rtl_loongarch64.S b/libsanitizer/tsan/tsan_rtl_loongarch64.S new file mode 100644 index 0000000..12856bd --- /dev/null +++ b/libsanitizer/tsan/tsan_rtl_loongarch64.S @@ -0,0 +1,196 @@ +#include "sanitizer_common/sanitizer_asm.h" + +.section .text + +ASM_HIDDEN(__tsan_setjmp) +.comm _ZN14__interception11real_setjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(setjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp)) +ASM_SYMBOL_INTERCEPTOR(setjmp): + CFI_STARTPROC + + // Save frame pointer and return address register + addi.d $sp, $sp, -32 + st.d $ra, $sp, 24 + st.d $fp, $sp, 16 + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (1, -8) + CFI_OFFSET (22, -16) + + // Adjust the SP for previous frame + addi.d $fp, $sp, 32 + CFI_DEF_CFA_REGISTER (22) + + // Save env parameter + st.d $a0, $sp, 8 + CFI_OFFSET (4, -24) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + addi.d $a0, $fp, 0 + + // call tsan interceptor + bl ASM_SYMBOL(__tsan_setjmp) + + // Restore env parameter + ld.d $a0, $sp, 8 + CFI_RESTORE (4) + + // Restore frame/link register + ld.d $fp, $sp, 16 + ld.d $ra, $sp, 24 + addi.d $sp, $sp, 32 + CFI_RESTORE (22) + CFI_RESTORE (1) + CFI_DEF_CFA (3, 0) + + // tail jump to libc setjmp + la.local $a1, _ZN14__interception11real_setjmpE + ld.d $a1, $a1, 0 + jr $a1 + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp)) + +.comm _ZN14__interception12real__setjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(_setjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp)) +ASM_SYMBOL_INTERCEPTOR(_setjmp): + CFI_STARTPROC + + // Save frame pointer and return address register + addi.d $sp, $sp, -32 + st.d $ra, $sp, 24 + st.d $fp, $sp, 16 + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (1, -8) + CFI_OFFSET (22, -16) + + // Adjust the SP for previous frame + addi.d $fp, $sp, 32 + CFI_DEF_CFA_REGISTER (22) + + // Save env parameter + st.d $a0, $sp, 8 + CFI_OFFSET (4, -24) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + addi.d $a0, $fp, 0 + + // call tsan interceptor + bl ASM_SYMBOL(__tsan_setjmp) + + // Restore env parameter + ld.d $a0, $sp, 8 + CFI_RESTORE (4) + + // Restore frame/link register + ld.d $fp, $sp, 16 + ld.d $ra, $sp, 24 + addi.d $sp, $sp, 32 + CFI_RESTORE (22) + CFI_RESTORE (1) + CFI_DEF_CFA (3, 0) + + // tail jump to libc setjmp + la.local $a1, _ZN14__interception12real__setjmpE + ld.d $a1, $a1, 0 + jr $a1 + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp)) + +.comm _ZN14__interception14real_sigsetjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp)) +ASM_SYMBOL_INTERCEPTOR(sigsetjmp): + CFI_STARTPROC + + // Save frame pointer and return address register + addi.d $sp, $sp, -32 + st.d $ra, $sp, 24 + st.d $fp, $sp, 16 + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (1, -8) + CFI_OFFSET (22, -16) + + // Adjust the SP for previous frame + addi.d $fp, $sp, 32 + CFI_DEF_CFA_REGISTER (22) + + // Save env parameter + st.d $a0, $sp, 8 + CFI_OFFSET (4, -24) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + addi.d $a0, $fp, 0 + + // call tsan interceptor + bl ASM_SYMBOL(__tsan_setjmp) + + // Restore env parameter + ld.d $a0, $sp, 8 + CFI_RESTORE (4) + + // Restore frame/link register + ld.d $fp, $sp, 16 + ld.d $ra, $sp, 24 + addi.d $sp, $sp, 32 + CFI_RESTORE (22) + CFI_RESTORE (1) + CFI_DEF_CFA (3, 0) + + // tail jump to libc setjmp + la.local $a1, _ZN14__interception14real_sigsetjmpE + ld.d $a1, $a1, 0 + jr $a1 + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp)) + +.comm _ZN14__interception16real___sigsetjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) +ASM_SYMBOL_INTERCEPTOR(__sigsetjmp): + CFI_STARTPROC + + // Save frame pointer and return address register + addi.d $sp, $sp, -32 + st.d $ra, $sp, 24 + st.d $fp, $sp, 16 + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (1, -8) + CFI_OFFSET (22, -16) + + // Adjust the SP for previous frame + addi.d $fp, $sp, 32 + CFI_DEF_CFA_REGISTER (22) + + // Save env parameter + st.d $a0, $sp, 8 + CFI_OFFSET (4, -24) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + addi.d $a0, $fp, 0 + + // call tsan interceptor + bl ASM_SYMBOL(__tsan_setjmp) + + // Restore env parameter + ld.d $a0, $sp, 8 + CFI_RESTORE (4) + + // Restore frame/link register + ld.d $fp, $sp, 16 + ld.d $ra, $sp, 24 + addi.d $sp, $sp, 32 + CFI_RESTORE (22) + CFI_RESTORE (1) + CFI_DEF_CFA (3, 0) + + // tail jump to libc setjmp + la.local $a1, _ZN14__interception16real___sigsetjmpE + ld.d $a1, $a1, 0 + jr $a1 + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) diff --git a/libsanitizer/tsan/tsan_rtl_ppc64.S b/libsanitizer/tsan/tsan_rtl_ppc64.S index 9e533a7..8285e21 100644 --- a/libsanitizer/tsan/tsan_rtl_ppc64.S +++ b/libsanitizer/tsan/tsan_rtl_ppc64.S @@ -1,6 +1,5 @@ #include "tsan_ppc_regs.h" - .machine altivec .section .text .hidden __tsan_setjmp .globl _setjmp diff --git a/libsanitizer/tsan/tsan_rtl_report.cpp b/libsanitizer/tsan/tsan_rtl_report.cpp index c2cff60..0311df5 100644 --- a/libsanitizer/tsan/tsan_rtl_report.cpp +++ b/libsanitizer/tsan/tsan_rtl_report.cpp @@ -10,20 +10,20 @@ // //===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" -#include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_stacktrace.h" +#include "tsan_fd.h" +#include "tsan_flags.h" +#include "tsan_mman.h" #include "tsan_platform.h" +#include "tsan_report.h" #include "tsan_rtl.h" #include "tsan_suppressions.h" #include "tsan_symbolize.h" -#include "tsan_report.h" #include "tsan_sync.h" -#include "tsan_mman.h" -#include "tsan_flags.h" -#include "tsan_fd.h" namespace __tsan { diff --git a/libsanitizer/tsan/tsan_spinlock_defs_mac.h b/libsanitizer/tsan/tsan_spinlock_defs_mac.h new file mode 100644 index 0000000..1a99a81 --- /dev/null +++ b/libsanitizer/tsan/tsan_spinlock_defs_mac.h @@ -0,0 +1,45 @@ +//===-- tsan_spinlock_defs_mac.h -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific forward-declared function defintions that may be +// deprecated in later versions of the OS. +// These are needed for interceptors. +// +//===----------------------------------------------------------------------===// + +#if SANITIZER_APPLE + +#ifndef TSAN_SPINLOCK_DEFS_MAC_H +#define TSAN_SPINLOCK_DEFS_MAC_H + +#include <stdint.h> + +extern "C" { + +/* +Provides forward declarations related to OSSpinLocks on Darwin. These functions are +deprecated on macOS version 10.12 and later, +and are no longer included in the system headers. + +However, the symbols are still available on the system, so we provide these forward +declarations to prevent compilation errors in tsan_interceptors_mac.cpp, which +references these functions when defining TSAN interceptor functions. +*/ + +typedef int32_t OSSpinLock; + +void OSSpinLockLock(volatile OSSpinLock *__lock); +void OSSpinLockUnlock(volatile OSSpinLock *__lock); +bool OSSpinLockTry(volatile OSSpinLock *__lock); + +} + +#endif //TSAN_SPINLOCK_DEFS_MAC_H +#endif // SANITIZER_APPLE diff --git a/libsanitizer/tsan/tsan_suppressions.cpp b/libsanitizer/tsan/tsan_suppressions.cpp index a1c1bf8..9cdfa32 100644 --- a/libsanitizer/tsan/tsan_suppressions.cpp +++ b/libsanitizer/tsan/tsan_suppressions.cpp @@ -10,15 +10,16 @@ // //===----------------------------------------------------------------------===// +#include "tsan_suppressions.h" + #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_suppressions.h" -#include "tsan_suppressions.h" -#include "tsan_rtl.h" #include "tsan_flags.h" #include "tsan_mman.h" #include "tsan_platform.h" +#include "tsan_rtl.h" #if !SANITIZER_GO // Suppressions for true/false positives in standard libraries. |