Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/dd/dd_interceptors.cpp
35269 views
//===-- dd_interceptors.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <pthread.h>910#include "dd_rtl.h"11#include "interception/interception.h"12#include "sanitizer_common/sanitizer_allocator_internal.h"13#include "sanitizer_common/sanitizer_procmaps.h"1415using namespace __dsan;1617__attribute__((tls_model("initial-exec")))18static __thread Thread *thr;19__attribute__((tls_model("initial-exec")))20static __thread volatile int initing;21static bool inited;22static uptr g_data_start;23static uptr g_data_end;2425static bool InitThread() {26if (initing)27return false;28if (thr != 0)29return true;30initing = true;31if (!inited) {32inited = true;33Initialize();34}35thr = (Thread*)InternalAlloc(sizeof(*thr));36internal_memset(thr, 0, sizeof(*thr));37ThreadInit(thr);38initing = false;39return true;40}4142INTERCEPTOR(int, pthread_mutex_destroy, pthread_mutex_t *m) {43InitThread();44MutexDestroy(thr, (uptr)m);45return REAL(pthread_mutex_destroy)(m);46}4748INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *m) {49InitThread();50MutexBeforeLock(thr, (uptr)m, true);51int res = REAL(pthread_mutex_lock)(m);52MutexAfterLock(thr, (uptr)m, true, false);53return res;54}5556INTERCEPTOR(int, pthread_mutex_trylock, pthread_mutex_t *m) {57InitThread();58int res = REAL(pthread_mutex_trylock)(m);59if (res == 0)60MutexAfterLock(thr, (uptr)m, true, true);61return res;62}6364INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *m) {65InitThread();66MutexBeforeUnlock(thr, (uptr)m, true);67return REAL(pthread_mutex_unlock)(m);68}6970INTERCEPTOR(int, pthread_spin_destroy, pthread_spinlock_t *m) {71InitThread();72int res = REAL(pthread_spin_destroy)(m);73MutexDestroy(thr, (uptr)m);74return res;75}7677INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *m) {78InitThread();79MutexBeforeLock(thr, (uptr)m, true);80int res = REAL(pthread_spin_lock)(m);81MutexAfterLock(thr, (uptr)m, true, false);82return res;83}8485INTERCEPTOR(int, pthread_spin_trylock, pthread_spinlock_t *m) {86InitThread();87int res = REAL(pthread_spin_trylock)(m);88if (res == 0)89MutexAfterLock(thr, (uptr)m, true, true);90return res;91}9293INTERCEPTOR(int, pthread_spin_unlock, pthread_spinlock_t *m) {94InitThread();95MutexBeforeUnlock(thr, (uptr)m, true);96return REAL(pthread_spin_unlock)(m);97}9899INTERCEPTOR(int, pthread_rwlock_destroy, pthread_rwlock_t *m) {100InitThread();101MutexDestroy(thr, (uptr)m);102return REAL(pthread_rwlock_destroy)(m);103}104105INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *m) {106InitThread();107MutexBeforeLock(thr, (uptr)m, false);108int res = REAL(pthread_rwlock_rdlock)(m);109MutexAfterLock(thr, (uptr)m, false, false);110return res;111}112113INTERCEPTOR(int, pthread_rwlock_tryrdlock, pthread_rwlock_t *m) {114InitThread();115int res = REAL(pthread_rwlock_tryrdlock)(m);116if (res == 0)117MutexAfterLock(thr, (uptr)m, false, true);118return res;119}120121INTERCEPTOR(int, pthread_rwlock_timedrdlock, pthread_rwlock_t *m,122const timespec *abstime) {123InitThread();124int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);125if (res == 0)126MutexAfterLock(thr, (uptr)m, false, true);127return res;128}129130INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *m) {131InitThread();132MutexBeforeLock(thr, (uptr)m, true);133int res = REAL(pthread_rwlock_wrlock)(m);134MutexAfterLock(thr, (uptr)m, true, false);135return res;136}137138INTERCEPTOR(int, pthread_rwlock_trywrlock, pthread_rwlock_t *m) {139InitThread();140int res = REAL(pthread_rwlock_trywrlock)(m);141if (res == 0)142MutexAfterLock(thr, (uptr)m, true, true);143return res;144}145146INTERCEPTOR(int, pthread_rwlock_timedwrlock, pthread_rwlock_t *m,147const timespec *abstime) {148InitThread();149int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);150if (res == 0)151MutexAfterLock(thr, (uptr)m, true, true);152return res;153}154155INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *m) {156InitThread();157MutexBeforeUnlock(thr, (uptr)m, true); // note: not necessary write unlock158return REAL(pthread_rwlock_unlock)(m);159}160161static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {162atomic_uintptr_t *p = (atomic_uintptr_t*)c;163uptr cond = atomic_load(p, memory_order_acquire);164if (!force && cond != 0)165return (pthread_cond_t*)cond;166void *newcond = InternalAlloc(sizeof(pthread_cond_t));167internal_memset(newcond, 0, sizeof(pthread_cond_t));168if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,169memory_order_acq_rel))170return (pthread_cond_t*)newcond;171InternalFree(newcond);172return (pthread_cond_t*)cond;173}174175INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *c,176const pthread_condattr_t *a) {177InitThread();178pthread_cond_t *cond = init_cond(c, true);179return REAL(pthread_cond_init)(cond, a);180}181182INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *c, pthread_mutex_t *m) {183InitThread();184pthread_cond_t *cond = init_cond(c);185MutexBeforeUnlock(thr, (uptr)m, true);186MutexBeforeLock(thr, (uptr)m, true);187int res = REAL(pthread_cond_wait)(cond, m);188MutexAfterLock(thr, (uptr)m, true, false);189return res;190}191192INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *c, pthread_mutex_t *m,193const timespec *abstime) {194InitThread();195pthread_cond_t *cond = init_cond(c);196MutexBeforeUnlock(thr, (uptr)m, true);197MutexBeforeLock(thr, (uptr)m, true);198int res = REAL(pthread_cond_timedwait)(cond, m, abstime);199MutexAfterLock(thr, (uptr)m, true, false);200return res;201}202203INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *c) {204InitThread();205pthread_cond_t *cond = init_cond(c);206return REAL(pthread_cond_signal)(cond);207}208209INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *c) {210InitThread();211pthread_cond_t *cond = init_cond(c);212return REAL(pthread_cond_broadcast)(cond);213}214215INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *c) {216InitThread();217pthread_cond_t *cond = init_cond(c);218int res = REAL(pthread_cond_destroy)(cond);219InternalFree(cond);220atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);221return res;222}223224// for symbolizer225INTERCEPTOR(char*, realpath, const char *path, char *resolved_path) {226InitThread();227return REAL(realpath)(path, resolved_path);228}229230INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {231InitThread();232return REAL(read)(fd, ptr, count);233}234235INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {236InitThread();237return REAL(pread)(fd, ptr, count, offset);238}239240extern "C" {241void __dsan_before_mutex_lock(uptr m, int writelock) {242if (!InitThread())243return;244MutexBeforeLock(thr, m, writelock);245}246247void __dsan_after_mutex_lock(uptr m, int writelock, int trylock) {248if (!InitThread())249return;250MutexAfterLock(thr, m, writelock, trylock);251}252253void __dsan_before_mutex_unlock(uptr m, int writelock) {254if (!InitThread())255return;256MutexBeforeUnlock(thr, m, writelock);257}258259void __dsan_mutex_destroy(uptr m) {260if (!InitThread())261return;262// if (m >= g_data_start && m < g_data_end)263// return;264MutexDestroy(thr, m);265}266} // extern "C"267268namespace __dsan {269270static void InitDataSeg() {271MemoryMappingLayout proc_maps(true);272char name[128];273MemoryMappedSegment segment(name, ARRAY_SIZE(name));274bool prev_is_data = false;275while (proc_maps.Next(&segment)) {276bool is_data = segment.offset != 0 && segment.filename[0] != 0;277// BSS may get merged with [heap] in /proc/self/maps. This is not very278// reliable.279bool is_bss = segment.offset == 0 &&280(segment.filename[0] == 0 ||281internal_strcmp(segment.filename, "[heap]") == 0) &&282prev_is_data;283if (g_data_start == 0 && is_data) g_data_start = segment.start;284if (is_bss) g_data_end = segment.end;285prev_is_data = is_data;286}287VPrintf(1, "guessed data_start=0x%zx data_end=0x%zx\n", g_data_start,288g_data_end);289CHECK_LT(g_data_start, g_data_end);290CHECK_GE((uptr)&g_data_start, g_data_start);291CHECK_LT((uptr)&g_data_start, g_data_end);292}293294void InitializeInterceptors() {295INTERCEPT_FUNCTION(pthread_mutex_destroy);296INTERCEPT_FUNCTION(pthread_mutex_lock);297INTERCEPT_FUNCTION(pthread_mutex_trylock);298INTERCEPT_FUNCTION(pthread_mutex_unlock);299300INTERCEPT_FUNCTION(pthread_spin_destroy);301INTERCEPT_FUNCTION(pthread_spin_lock);302INTERCEPT_FUNCTION(pthread_spin_trylock);303INTERCEPT_FUNCTION(pthread_spin_unlock);304305INTERCEPT_FUNCTION(pthread_rwlock_destroy);306INTERCEPT_FUNCTION(pthread_rwlock_rdlock);307INTERCEPT_FUNCTION(pthread_rwlock_tryrdlock);308INTERCEPT_FUNCTION(pthread_rwlock_timedrdlock);309INTERCEPT_FUNCTION(pthread_rwlock_wrlock);310INTERCEPT_FUNCTION(pthread_rwlock_trywrlock);311INTERCEPT_FUNCTION(pthread_rwlock_timedwrlock);312INTERCEPT_FUNCTION(pthread_rwlock_unlock);313314INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");315INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");316INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");317INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");318INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");319INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");320321// for symbolizer322INTERCEPT_FUNCTION(realpath);323INTERCEPT_FUNCTION(read);324INTERCEPT_FUNCTION(pread);325326InitDataSeg();327}328329} // namespace __dsan330331332