[compiler-rt] 686fe29 - [TSan][libdispatch] Ensure TSan dylib works on old systems

Julian Lettner via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 18:35:31 PDT 2020


Author: Julian Lettner
Date: 2020-08-18T18:34:14-07:00
New Revision: 686fe293e6c5fd51fa0a3c86a43c2d9a652d53b1

URL: https://github.com/llvm/llvm-project/commit/686fe293e6c5fd51fa0a3c86a43c2d9a652d53b1
DIFF: https://github.com/llvm/llvm-project/commit/686fe293e6c5fd51fa0a3c86a43c2d9a652d53b1.diff

LOG: [TSan][libdispatch] Ensure TSan dylib works on old systems

`dispatch_async_and_wait()` was introduced in macOS 10.14, which is
greater than our minimal deployment target.  We need to forward declare
it as a "weak import" to ensure we generate a weak reference so the TSan
dylib continues to work on older systems.  We cannot simply `#include
<dispatch.h>` or use the Darwin availability macros since this file is
multi-platform.

In addition, we want to prevent building these interceptors at all when
building with older SDKs because linking always fails.

Before:
```
➤ dyldinfo -bind ./lib/clang/12.0.0/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib | grep dispatch_async_and_wait
__DATA  __interpose      0x000F5E68    pointer      0 libSystem        _dispatch_async_and_wait_f
```

After:
```
➤ dyldinfo -bind ./lib/clang/12.0.0/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib | grep dispatch_async_and_wait
__DATA  __got            0x000EC0A8    pointer      0 libSystem        _dispatch_async_and_wait (weak import)
__DATA  __interpose      0x000F5E78    pointer      0 libSystem        _dispatch_async_and_wait (weak import)
```

This is a follow-up to D85854 and should fix:
https://reviews.llvm.org/D85854#2221529

Reviewed By: kubamracek

Differential Revision: https://reviews.llvm.org/D86103

Added: 
    

Modified: 
    compiler-rt/lib/tsan/rtl/tsan_dispatch_defs.h
    compiler-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/tsan/rtl/tsan_dispatch_defs.h b/compiler-rt/lib/tsan/rtl/tsan_dispatch_defs.h
index 298297af31eb..94e0b50fed36 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_dispatch_defs.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_dispatch_defs.h
@@ -51,11 +51,18 @@ extern const dispatch_block_t _dispatch_data_destructor_munmap;
 #define DISPATCH_DATA_DESTRUCTOR_MUNMAP  _dispatch_data_destructor_munmap
 
 #if __has_attribute(noescape)
-  #define DISPATCH_NOESCAPE __attribute__((__noescape__))
+# define DISPATCH_NOESCAPE __attribute__((__noescape__))
 #else
-  #define DISPATCH_NOESCAPE
+# define DISPATCH_NOESCAPE
 #endif
 
+#if SANITIZER_MAC
+# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak_import))
+#else
+# define SANITIZER_WEAK_IMPORT extern "C" __attribute((weak))
+#endif
+
+
 // Data types used in dispatch APIs
 typedef unsigned long size_t;
 typedef unsigned long uintptr_t;

diff  --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp
index 292ea5fbb239..99ec27501100 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp
@@ -19,6 +19,10 @@
 #include "BlocksRuntime/Block.h"
 #include "tsan_dispatch_defs.h"
 
+#if SANITIZER_MAC
+# include <Availability.h>
+#endif
+
 namespace __tsan {
   typedef u16 uint16_t;
 
@@ -219,8 +223,23 @@ static void invoke_and_release_block(void *param) {
 DISPATCH_INTERCEPT(dispatch, false)
 DISPATCH_INTERCEPT(dispatch_barrier, true)
 
-DISPATCH_INTERCEPT_SYNC_F(dispatch_async_and_wait_f, false)
+// dispatch_async_and_wait() and friends were introduced in macOS 10.14.
+// Linking of these interceptors fails when using an older SDK.
+#if !SANITIZER_MAC || defined(__MAC_10_14)
+// macOS 10.14 is greater than our minimal deployment target.  To ensure we
+// generate a weak reference so the TSan dylib continues to work on older
+// systems, we need to forward declare the intercepted functions as "weak
+// imports".   Note that this file is multi-platform, so we cannot include the
+// actual header file (#include <dispatch/dispatch.h>).
+SANITIZER_WEAK_IMPORT void dispatch_async_and_wait(
+    dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
+SANITIZER_WEAK_IMPORT void dispatch_async_and_wait_f(
+    dispatch_queue_t queue, void *context, dispatch_function_t work);
+
 DISPATCH_INTERCEPT_SYNC_B(dispatch_async_and_wait, false)
+DISPATCH_INTERCEPT_SYNC_F(dispatch_async_and_wait_f, false)
+#endif
+
 
 DECLARE_REAL(void, dispatch_after_f, dispatch_time_t when,
              dispatch_queue_t queue, void *context, dispatch_function_t work)


        


More information about the llvm-commits mailing list