1212#import " BSG_KSDynamicLinker.h"
1313#import " BSG_KSMachHeaders.h"
1414
15+ // MARK: - Locking
16+
17+ // Pragma's hide unavoidable (and expected) deprecation/unavailable warnings
18+ _Pragma (" clang diagnostic push" )
19+ _Pragma (" clang diagnostic ignored \" -Wunguarded-availability\" " )
20+ static os_unfair_lock bsg_mach_binary_images_access_lock_unfair = OS_UNFAIR_LOCK_INIT;
21+ _Pragma (" clang diagnostic pop" )
22+
23+ _Pragma (" clang diagnostic push" )
24+ _Pragma (" clang diagnostic ignored \" -Wdeprecated-declarations\" " )
25+ static OSSpinLock bsg_mach_binary_images_access_lock_spin = OS_SPINLOCK_INIT;
26+ _Pragma (" clang diagnostic pop" )
27+
28+ static BOOL bsg_unfair_lock_supported;
29+
30+ // Lock helpers. These use bulky Pragmas to hide warnings so are in their own functions for clarity.
31+
32+ void bsg_spin_lock () {
33+ _Pragma (" clang diagnostic push" )
34+ _Pragma (" clang diagnostic ignored \" -Wdeprecated-declarations\" " )
35+ OSSpinLockLock (&bsg_mach_binary_images_access_lock_spin);
36+ _Pragma (" clang diagnostic pop" )
37+ }
38+
39+ void bsg_spin_unlock () {
40+ _Pragma (" clang diagnostic push" )
41+ _Pragma (" clang diagnostic ignored \" -Wdeprecated-declarations\" " )
42+ OSSpinLockUnlock (&bsg_mach_binary_images_access_lock_spin);
43+ _Pragma (" clang diagnostic pop" )
44+ }
45+
46+ void bsg_unfair_lock () {
47+ _Pragma (" clang diagnostic push" )
48+ _Pragma (" clang diagnostic ignored \" -Wunguarded-availability\" " )
49+ os_unfair_lock_lock (&bsg_mach_binary_images_access_lock_unfair);
50+ _Pragma (" clang diagnostic pop" )
51+ }
52+
53+ void bsg_unfair_unlock () {
54+ _Pragma (" clang diagnostic push" )
55+ _Pragma (" clang diagnostic ignored \" -Wunguarded-availability\" " )
56+ os_unfair_lock_unlock (&bsg_mach_binary_images_access_lock_unfair);
57+ _Pragma (" clang diagnostic pop" )
58+ }
59+
60+ // Lock and unlock sections of code
61+
62+ void bsg_dyld_cache_lock () {
63+ if (bsg_unfair_lock_supported) {
64+ bsg_unfair_lock ();
65+ } else {
66+ bsg_spin_lock ();
67+ }
68+ }
69+
70+ void bsg_dyld_cache_unlock () {
71+ if (bsg_unfair_lock_supported) {
72+ bsg_unfair_unlock ();
73+ } else {
74+ bsg_spin_unlock ();
75+ }
76+ }
77+
78+ BOOL BSGIsUnfairLockSupported (NSProcessInfo *processInfo) {
79+ NSOperatingSystemVersion minSdk = {0 ,0 ,0 };
80+ #if TARGET_OS_IOS
81+ minSdk.majorVersion = 10 ;
82+ #elif TARGET_OS_OSX
83+ minSdk.majorVersion = 10 ;
84+ minSdk.minorVersion = 12 ;
85+ #elif TARGET_OS_TV
86+ minSdk.majorVersion = 10 ;
87+ #elif TARGET_OS_WATCH
88+ minSdk.majorVersion = 3 ;
89+ #endif
90+ return [processInfo isOperatingSystemAtLeastVersion: minSdk];
91+ }
92+
93+ void bsg_check_unfair_lock_support () {
94+ bsg_unfair_lock_supported = BSGIsUnfairLockSupported ([NSProcessInfo processInfo ]);
95+ }
96+
1597// MARK: - Replicate the DYLD API
1698
1799uint32_t bsg_dyld_image_count (void ) {
@@ -53,7 +135,7 @@ intptr_t bsg_dyld_get_image_vmaddr_slide(uint32_t imageIndex) {
53135 */
54136void bsg_add_mach_binary_image (BSG_Mach_Binary_Image_Info element) {
55137
56- BSG_DYLD_CACHE_LOCK
138+ bsg_dyld_cache_lock ();
57139
58140 // Expand array if necessary. We're slightly paranoid here. An OOM is likely to be indicative of bigger problems
59141 // but we should still do *our* best not to crash the app.
@@ -69,15 +151,15 @@ void bsg_add_mach_binary_image(BSG_Mach_Binary_Image_Info element) {
69151 }
70152 else {
71153 // Exit early, don't expand the array, don't store the header info and unlock
72- BSG_DYLD_CACHE_UNLOCK
154+ bsg_dyld_cache_unlock ();
73155 return ;
74156 }
75157 }
76158
77159 // Store the value, increment the number of used elements
78160 bsg_mach_binary_images.contents [bsg_mach_binary_images.used++] = element;
79161
80- BSG_DYLD_CACHE_UNLOCK
162+ bsg_dyld_cache_unlock ();
81163}
82164
83165/* *
@@ -87,7 +169,7 @@ void bsg_add_mach_binary_image(BSG_Mach_Binary_Image_Info element) {
87169 */
88170void bsg_remove_mach_binary_image (uint64_t imageVmAddr) {
89171
90- BSG_DYLD_CACHE_LOCK
172+ bsg_dyld_cache_lock ();
91173
92174 for (uint32_t i=0 ; i<bsg_mach_binary_images.used ; i++) {
93175 BSG_Mach_Binary_Image_Info item = bsg_mach_binary_images.contents [i];
@@ -104,9 +186,16 @@ void bsg_remove_mach_binary_image(uint64_t imageVmAddr) {
104186 }
105187 }
106188
107- BSG_DYLD_CACHE_UNLOCK
189+ bsg_dyld_cache_unlock ();
108190}
109191
192+ /* *
193+ * Create an empty array with initial capacity to hold Mach header info.
194+ *
195+ * @param initialSize The initial array capacity
196+ *
197+ * @returns A struct for holding Mach binary image info
198+ */
110199BSG_Mach_Binary_Images *bsg_initialise_mach_binary_headers (uint32_t initialSize) {
111200 bsg_mach_binary_images.contents = (BSG_Mach_Binary_Image_Info *)malloc (initialSize * sizeof (BSG_Mach_Binary_Image_Info));
112201 bsg_mach_binary_images.used = 0 ;
0 commit comments