Skip to content

Commit 5f9843f

Browse files
committed
[rtsan] Support legacy pthread_cond variables
1 parent 1598062 commit 5f9843f

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,45 @@
4646

4747
using namespace __sanitizer;
4848

49+
50+
#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
51+
defined(__s390x__)
52+
#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
53+
#elif defined(__aarch64__) || SANITIZER_PPC64V2
54+
#define PTHREAD_ABI_BASE "GLIBC_2.17"
55+
#elif SANITIZER_LOONGARCH64
56+
#define PTHREAD_ABI_BASE "GLIBC_2.36"
57+
#elif SANITIZER_RISCV64
58+
# define PTHREAD_ABI_BASE "GLIBC_2.27"
59+
#endif
60+
61+
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, usize size)
62+
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
63+
4964
namespace {
5065
struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
5166
static bool UseImpl() { return !__rtsan_is_initialized(); }
5267
};
5368
} // namespace
5469

70+
// See note in tsan or ddsan as to why this is necessary
71+
static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {
72+
if (!common_flags()->legacy_pthread_cond)
73+
return c;
74+
75+
atomic_uintptr_t *p = (atomic_uintptr_t *)c;
76+
uptr cond = atomic_load(p, memory_order_acquire);
77+
if (!force && cond != 0)
78+
return (pthread_cond_t *)cond;
79+
void *newcond = WRAP(malloc)(sizeof(pthread_cond_t));
80+
internal_memset(newcond, 0, sizeof(pthread_cond_t));
81+
if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
82+
memory_order_acq_rel))
83+
return (pthread_cond_t *)newcond;
84+
WRAP(free)(newcond);
85+
return (pthread_cond_t *)cond;
86+
}
87+
5588
// Filesystem
5689

5790
INTERCEPTOR(int, open, const char *path, int oflag, ...) {
@@ -766,26 +799,49 @@ INTERCEPTOR(int, pthread_join, pthread_t thread, void **value_ptr) {
766799
return REAL(pthread_join)(thread, value_ptr);
767800
}
768801

802+
INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *cond,
803+
const pthread_condattr_t *a) {
804+
__rtsan_notify_intercepted_call("pthread_cond_init");
805+
pthread_cond_t *c = init_cond(cond, true);
806+
return REAL(pthread_cond_init)(c, a);
807+
}
808+
769809
INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) {
770810
__rtsan_notify_intercepted_call("pthread_cond_signal");
771-
return REAL(pthread_cond_signal)(cond);
811+
pthread_cond_t *c = init_cond(cond);
812+
return REAL(pthread_cond_signal)(c);
772813
}
773814

774815
INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *cond) {
775816
__rtsan_notify_intercepted_call("pthread_cond_broadcast");
776-
return REAL(pthread_cond_broadcast)(cond);
817+
pthread_cond_t *c = init_cond(cond);
818+
return REAL(pthread_cond_broadcast)(c);
777819
}
778820

779821
INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *cond,
780822
pthread_mutex_t *mutex) {
781823
__rtsan_notify_intercepted_call("pthread_cond_wait");
782-
return REAL(pthread_cond_wait)(cond, mutex);
824+
pthread_cond_t *c = init_cond(cond);
825+
return REAL(pthread_cond_wait)(c, mutex);
783826
}
784827

785828
INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,
786829
pthread_mutex_t *mutex, const timespec *ts) {
787830
__rtsan_notify_intercepted_call("pthread_cond_timedwait");
788-
return REAL(pthread_cond_timedwait)(cond, mutex, ts);
831+
pthread_cond_t *c = init_cond(cond);
832+
return REAL(pthread_cond_timedwait)(c, mutex, ts);
833+
}
834+
835+
INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
836+
__rtsan_notify_intercepted_call("pthread_cond_destroy");
837+
pthread_cond_t *c = init_cond(cond);
838+
int res = REAL(pthread_cond_destroy)(c);
839+
if (common_flags()->legacy_pthread_cond) {
840+
// Free our aux cond and zero the pointer to not leave dangling pointers.
841+
WRAP(free)(c);
842+
atomic_store((atomic_uintptr_t *)c, 0, memory_order_relaxed);
843+
}
844+
return res;
789845
}
790846

791847
INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) {
@@ -1641,10 +1697,14 @@ void __rtsan::InitializeInterceptors() {
16411697
INTERCEPT_FUNCTION(pthread_mutex_lock);
16421698
INTERCEPT_FUNCTION(pthread_mutex_unlock);
16431699
INTERCEPT_FUNCTION(pthread_join);
1644-
INTERCEPT_FUNCTION(pthread_cond_signal);
1645-
INTERCEPT_FUNCTION(pthread_cond_broadcast);
1646-
INTERCEPT_FUNCTION(pthread_cond_wait);
1647-
INTERCEPT_FUNCTION(pthread_cond_timedwait);
1700+
1701+
INTERCEPT_FUNCTION_VER(pthread_cond_init, PTHREAD_ABI_BASE);
1702+
INTERCEPT_FUNCTION_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
1703+
INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
1704+
INTERCEPT_FUNCTION_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
1705+
INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
1706+
INTERCEPT_FUNCTION_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
1707+
16481708
INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
16491709
INTERCEPT_FUNCTION(pthread_rwlock_unlock);
16501710
INTERCEPT_FUNCTION(pthread_rwlock_wrlock);

0 commit comments

Comments
 (0)