Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 13 additions & 23 deletions compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,6 @@
#include "rtsan/rtsan.h"

#if SANITIZER_APPLE

#if TARGET_OS_MAC
// On MacOS OSSpinLockLock is deprecated and no longer present in the headers,
// but the symbol still exists on the system. Forward declare here so we
// don't get compilation errors.
#include <stdint.h>
extern "C" {
typedef int32_t OSSpinLock;
void OSSpinLockLock(volatile OSSpinLock *__lock);
// A pointer to this type is in the interface for `_os_nospin_lock_lock`, but
// it's an internal implementation detail of `os/lock.c` on Darwin, and
// therefore not available in any headers. As a workaround, we forward declare
// it here, which is enough to facilitate interception of _os_nospin_lock_lock.
struct _os_nospin_lock_s;
using _os_nospin_lock_t = _os_nospin_lock_s *;
}
#endif // TARGET_OS_MAC

#include <libkern/OSAtomic.h>
#include <os/lock.h>
#endif // SANITIZER_APPLE
Expand Down Expand Up @@ -706,26 +688,34 @@ INTERCEPTOR(mode_t, umask, mode_t cmask) {
#pragma clang diagnostic push
// OSSpinLockLock is deprecated, but still in use in libc++
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#undef OSSpinLockLock

INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
__rtsan_notify_intercepted_call("OSSpinLockLock");
return REAL(OSSpinLockLock)(lock);
}
#pragma clang diagnostic pop

#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK INTERCEPT_FUNCTION(OSSpinLockLock)
#else
#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK
#endif // SANITIZER_APPLE

#if SANITIZER_APPLE
INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
return REAL(os_unfair_lock_lock)(lock);
}
typedef volatile OSSpinLock *_os_nospin_lock_t;

INTERCEPTOR(void, _os_nospin_lock_lock, _os_nospin_lock_t lock) {
__rtsan_notify_intercepted_call("_os_nospin_lock_lock");
return REAL(_os_nospin_lock_lock)(lock);
}
#endif // SANITIZER_APPLE
#pragma clang diagnostic pop // "-Wdeprecated-declarations"

#if SANITIZER_APPLE
INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
__rtsan_notify_intercepted_call("os_unfair_lock_lock");
return REAL(os_unfair_lock_lock)(lock);
}

#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \
INTERCEPT_FUNCTION(os_unfair_lock_lock)
#else
Expand Down
38 changes: 17 additions & 21 deletions compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,14 @@ TEST(TestRtsanInterceptors, PthreadJoinDiesWhenRealtime) {
#pragma clang diagnostic push
// OSSpinLockLock is deprecated, but still in use in libc++
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#undef OSSpinLockLock
extern "C" {
typedef int32_t OSSpinLock;
void OSSpinLockLock(volatile OSSpinLock *__lock);
typedef volatile OSSpinLock *_os_nospin_lock_t;
void _os_nospin_lock_lock(_os_nospin_lock_t lock);
}

TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
auto Func = []() {
OSSpinLock spin_lock{};
Expand All @@ -1121,7 +1129,15 @@ TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
ExpectRealtimeDeath(Func, "OSSpinLockLock");
ExpectNonRealtimeSurvival(Func);
}
#pragma clang diagnostic pop

TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) {
OSSpinLock lock{};
auto Func = [&]() { _os_nospin_lock_lock(&lock); };
ExpectRealtimeDeath(Func, "_os_nospin_lock_lock");
ExpectNonRealtimeSurvival(Func);
}
#endif // SANITIZER_APPLE
#pragma clang diagnostic pop //"-Wdeprecated-declarations"

TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
auto Func = []() {
Expand All @@ -1132,26 +1148,6 @@ TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
ExpectNonRealtimeSurvival(Func);
}

// We intercept _os_nospin_lock_lock because it's the internal
// locking mechanism for MacOS's atomic implementation for data
// types that are larger than the hardware's maximum lock-free size.
// However, it's a private implementation detail and not visible in any headers,
// so we must duplicate the required type definitions to forward declaration
// what we need here.
extern "C" {
struct _os_nospin_lock_s {
unsigned int oul_value;
};
void _os_nospin_lock_lock(_os_nospin_lock_s *);
}
TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) {
_os_nospin_lock_s lock{};
auto Func = [&]() { _os_nospin_lock_lock(&lock); };
ExpectRealtimeDeath(Func, "_os_nospin_lock_lock");
ExpectNonRealtimeSurvival(Func);
}
#endif

#if SANITIZER_LINUX
TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) {
pthread_spinlock_t spin_lock;
Expand Down
Loading