summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2018-07-24 16:19:06 +0000
committerKuba Mracek <mracek@apple.com>2018-07-24 16:19:06 +0000
commit3ac94fe6137e5d5123b064b03084ea7a0bd0f5ff (patch)
tree928d2f9702196b4131370ed35a57925ebdfdd23e /lib
parent37bd9aa510166186a9bba5cf13d717d6b097c95e (diff)
[tsan] Fix crash in objc_sync_enter/objc_sync_exit when using an Obj-C tagged pointer
Objective-C tagged pointers (either bottom-most or top-most bit is 1) are valid Obj-C objects but are not valid pointers. Make sure we don't crash on them when used in objc_sync_enter/objc_sync_exit. Instead, let's synchronize on a global object. Differential Revision: https://reviews.llvm.org/D49707 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@337837 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/tsan/rtl/tsan_interceptors_mac.cc28
1 files changed, 26 insertions, 2 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors_mac.cc b/lib/tsan/rtl/tsan_interceptors_mac.cc
index 1c4aa02a0..b58e6b707 100644
--- a/lib/tsan/rtl/tsan_interceptors_mac.cc
+++ b/lib/tsan/rtl/tsan_interceptors_mac.cc
@@ -294,16 +294,40 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) {
#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
+// Is the Obj-C object a tagged pointer (i.e. isn't really a valid pointer and
+// contains data in the pointers bits instead)?
+static bool IsTaggedObjCPointer(void *obj) {
+ const uptr kPossibleTaggedBits = 0x8000000000000001ull;
+ return ((uptr)obj & kPossibleTaggedBits) != 0;
+}
+
+// Return an address on which we can synchronize (Acquire and Release) for a
+// Obj-C tagged pointer (which is not a valid pointer). Ideally should be a
+// derived address from 'obj', but for now just return the same global address.
+// TODO(kubamracek): Return different address for different pointers.
+static uptr SyncAddressForTaggedPointer(void *obj) {
+ (void)obj;
+ static u64 addr;
+ return (uptr)&addr;
+}
+
+// Address on which we can synchronize for an Objective-C object. Supports
+// tagged pointers.
+static uptr SyncAddressForObjCObject(void *obj) {
+ if (IsTaggedObjCPointer(obj)) return SyncAddressForTaggedPointer(obj);
+ return (uptr)obj;
+}
+
TSAN_INTERCEPTOR(int, objc_sync_enter, void *obj) {
SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);
int result = REAL(objc_sync_enter)(obj);
- if (obj) Acquire(thr, pc, (uptr)obj);
+ if (obj) Acquire(thr, pc, SyncAddressForObjCObject(obj));
return result;
}
TSAN_INTERCEPTOR(int, objc_sync_exit, void *obj) {
SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);
- if (obj) Release(thr, pc, (uptr)obj);
+ if (obj) Release(thr, pc, SyncAddressForObjCObject(obj));
return REAL(objc_sync_exit)(obj);
}