]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
2fd3f4e8 | 3 | * Copyright (c) 2004-2012 Apple Inc. All rights reserved. |
0959b6d4 A |
4 | * |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | #include <stddef.h> | |
26 | #include <string.h> | |
39a8cd10 | 27 | #include <malloc/malloc.h> |
2fd3f4e8 | 28 | #include <sys/mman.h> |
39a8cd10 | 29 | |
0959b6d4 | 30 | #include <crt_externs.h> |
39a8cd10 | 31 | #include <Availability.h> |
2fd3f4e8 | 32 | #include <vproc_priv.h> |
0959b6d4 A |
33 | |
34 | #include "mach-o/dyld.h" | |
35 | #include "mach-o/dyld_priv.h" | |
36 | ||
19894a12 | 37 | #include "ImageLoader.h" |
0959b6d4 | 38 | #include "dyldLock.h" |
2fd3f4e8 | 39 | #include "start_glue.h" |
0959b6d4 | 40 | |
412ebb8e A |
41 | extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso); |
42 | extern "C" void __cxa_finalize(const void *dso); | |
19894a12 | 43 | extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges[], int count); |
bac542e6 | 44 | |
832b6fce A |
45 | |
46 | #ifndef LC_VERSION_MIN_MACOSX | |
47 | #define LC_VERSION_MIN_MACOSX 0x24 | |
48 | struct version_min_command { | |
49 | uint32_t cmd; /* LC_VERSION_MIN_MACOSX or | |
50 | LC_VERSION_MIN_IPHONEOS */ | |
51 | uint32_t cmdsize; /* sizeof(struct min_version_command) */ | |
52 | uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ | |
53 | uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ | |
54 | }; | |
55 | #endif | |
56 | ||
57 | #ifndef LC_VERSION_MIN_IPHONEOS | |
58 | #define LC_VERSION_MIN_IPHONEOS 0x25 | |
59 | #endif | |
60 | ||
df9d6cf7 A |
61 | #ifndef LC_VERSION_MIN_TVOS |
62 | #define LC_VERSION_MIN_TVOS 0x2F | |
63 | #endif | |
64 | ||
65 | #ifndef LC_VERSION_MIN_WATCHOS | |
66 | #define LC_VERSION_MIN_WATCHOS 0x30 | |
67 | #endif | |
68 | ||
832b6fce | 69 | |
412ebb8e A |
70 | #ifndef LC_LOAD_UPWARD_DYLIB |
71 | #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ | |
72 | #endif | |
73 | ||
39a8cd10 A |
74 | |
75 | // deprecated APIs are still availble on Mac OS X, but not on iPhone OS | |
76 | #if __IPHONE_OS_VERSION_MIN_REQUIRED | |
77 | #define DEPRECATED_APIS_SUPPORTED 0 | |
78 | #else | |
79 | #define DEPRECATED_APIS_SUPPORTED 1 | |
80 | #endif | |
bac542e6 | 81 | |
0959b6d4 A |
82 | /* |
83 | * names_match() takes an install_name from an LC_LOAD_DYLIB command and a | |
84 | * libraryName (which is -lx or -framework Foo argument passed to the static | |
85 | * link editor for the same library) and determines if they match. This depends | |
86 | * on conventional use of names including major versioning. | |
87 | */ | |
88 | static | |
89 | bool | |
90 | names_match( | |
19894a12 | 91 | const char *install_name, |
0959b6d4 A |
92 | const char* libraryName) |
93 | { | |
19894a12 | 94 | const char *basename; |
0959b6d4 A |
95 | unsigned long n; |
96 | ||
97 | /* | |
98 | * Conventional install names have these forms: | |
99 | * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit | |
100 | * /Local/Library/Frameworks/AppKit.framework/Appkit | |
101 | * /lib/libsys_s.A.dylib | |
102 | * /usr/lib/libsys_s.dylib | |
103 | */ | |
104 | basename = strrchr(install_name, '/'); | |
105 | if(basename == NULL) | |
106 | basename = install_name; | |
107 | else | |
108 | basename++; | |
109 | ||
110 | /* | |
111 | * By checking the base name matching the library name we take care | |
112 | * of the -framework cases. | |
113 | */ | |
114 | if(strcmp(basename, libraryName) == 0) | |
19894a12 | 115 | return true; |
0959b6d4 A |
116 | |
117 | /* | |
118 | * Now check the base name for "lib" if so proceed to check for the | |
119 | * -lx case dealing with a possible .X.dylib and a .dylib extension. | |
120 | */ | |
121 | if(strncmp(basename, "lib", 3) ==0){ | |
122 | n = strlen(libraryName); | |
123 | if(strncmp(basename+3, libraryName, n) == 0){ | |
124 | if(strncmp(basename+3+n, ".dylib", 6) == 0) | |
19894a12 | 125 | return true; |
0959b6d4 A |
126 | if(basename[3+n] == '.' && |
127 | basename[3+n+1] != '\0' && | |
128 | strncmp(basename+3+n+2, ".dylib", 6) == 0) | |
19894a12 | 129 | return true; |
0959b6d4 A |
130 | } |
131 | } | |
19894a12 | 132 | return false; |
0959b6d4 A |
133 | } |
134 | ||
39a8cd10 A |
135 | #if DEPRECATED_APIS_SUPPORTED |
136 | ||
0959b6d4 A |
137 | void NSInstallLinkEditErrorHandlers( |
138 | const NSLinkEditErrorHandlers* handlers) | |
139 | { | |
bac542e6 | 140 | DYLD_LOCK_THIS_BLOCK; |
412ebb8e A |
141 | typedef void (*ucallback_t)(const char* symbol_name); |
142 | typedef NSModule (*mcallback_t)(NSSymbol s, NSModule old, NSModule newhandler); | |
143 | typedef void (*lcallback_t)(NSLinkEditErrors c, int errorNumber, | |
144 | const char* fileName, const char* errorString); | |
145 | static void (*p)(ucallback_t undefined, mcallback_t multiple, lcallback_t linkEdit) = NULL; | |
0959b6d4 A |
146 | |
147 | if(p == NULL) | |
148 | _dyld_func_lookup("__dyld_install_handlers", (void**)&p); | |
412ebb8e A |
149 | mcallback_t m = handlers->multiple; |
150 | p(handlers->undefined, m, handlers->linkEdit); | |
0959b6d4 A |
151 | } |
152 | ||
153 | const char* | |
154 | NSNameOfModule( | |
155 | NSModule module) | |
156 | { | |
bac542e6 | 157 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
158 | static const char* (*p)(NSModule module) = NULL; |
159 | ||
160 | if(p == NULL) | |
161 | _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p); | |
162 | return(p(module)); | |
163 | } | |
164 | ||
165 | const char* | |
166 | NSLibraryNameForModule( | |
167 | NSModule module) | |
168 | { | |
bac542e6 | 169 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
170 | static const char* (*p)(NSModule module) = NULL; |
171 | ||
172 | if(p == NULL) | |
173 | _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p); | |
174 | return(p(module)); | |
175 | } | |
176 | ||
177 | bool | |
178 | NSIsSymbolNameDefined( | |
179 | const char* symbolName) | |
180 | { | |
bac542e6 | 181 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
182 | static bool (*p)(const char* symbolName) = NULL; |
183 | ||
184 | if(p == NULL) | |
185 | _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p); | |
186 | return(p(symbolName)); | |
187 | } | |
188 | ||
189 | bool | |
190 | NSIsSymbolNameDefinedWithHint( | |
191 | const char* symbolName, | |
192 | const char* libraryNameHint) | |
193 | { | |
bac542e6 | 194 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
195 | static bool (*p)(const char* symbolName, |
196 | const char* libraryNameHint) = NULL; | |
197 | ||
198 | if(p == NULL) | |
199 | _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p); | |
200 | return(p(symbolName, libraryNameHint)); | |
201 | } | |
202 | ||
203 | bool | |
204 | NSIsSymbolNameDefinedInImage( | |
205 | const struct mach_header *image, | |
206 | const char* symbolName) | |
207 | { | |
bac542e6 | 208 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
209 | static bool (*p)(const struct mach_header *image, |
210 | const char* symbolName) = NULL; | |
211 | ||
212 | if(p == NULL) | |
213 | _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p); | |
214 | return(p(image, symbolName)); | |
215 | } | |
216 | ||
217 | NSSymbol | |
218 | NSLookupAndBindSymbol( | |
219 | const char* symbolName) | |
220 | { | |
bac542e6 | 221 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
222 | static NSSymbol (*p)(const char* symbolName) = NULL; |
223 | ||
224 | if(p == NULL) | |
225 | _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p); | |
226 | return(p(symbolName)); | |
227 | } | |
228 | ||
229 | NSSymbol | |
230 | NSLookupAndBindSymbolWithHint( | |
231 | const char* symbolName, | |
232 | const char* libraryNameHint) | |
233 | { | |
bac542e6 | 234 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
235 | static NSSymbol (*p)(const char* symbolName, |
236 | const char* libraryNameHint) = NULL; | |
237 | ||
238 | if(p == NULL) | |
239 | _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p); | |
240 | return(p(symbolName, libraryNameHint)); | |
241 | } | |
242 | ||
243 | NSSymbol | |
244 | NSLookupSymbolInModule( | |
245 | NSModule module, | |
246 | const char* symbolName) | |
247 | { | |
bac542e6 | 248 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
249 | static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL; |
250 | ||
251 | if(p == NULL) | |
252 | _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p); | |
253 | return(p(module, symbolName)); | |
254 | } | |
255 | ||
256 | NSSymbol | |
257 | NSLookupSymbolInImage( | |
258 | const struct mach_header *image, | |
259 | const char* symbolName, | |
260 | uint32_t options) | |
261 | { | |
bac542e6 | 262 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
263 | static NSSymbol (*p)(const struct mach_header *image, |
264 | const char* symbolName, | |
265 | uint32_t options) = NULL; | |
266 | ||
267 | if(p == NULL) | |
268 | _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p); | |
269 | return(p(image, symbolName, options)); | |
270 | } | |
271 | ||
272 | const char* | |
273 | NSNameOfSymbol( | |
274 | NSSymbol symbol) | |
275 | { | |
bac542e6 | 276 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
277 | static char * (*p)(NSSymbol symbol) = NULL; |
278 | ||
279 | if(p == NULL) | |
280 | _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p); | |
281 | return(p(symbol)); | |
282 | } | |
283 | ||
284 | void * | |
285 | NSAddressOfSymbol( | |
286 | NSSymbol symbol) | |
287 | { | |
bac542e6 | 288 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
289 | static void * (*p)(NSSymbol symbol) = NULL; |
290 | ||
291 | if(p == NULL) | |
292 | _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p); | |
293 | return(p(symbol)); | |
294 | } | |
295 | ||
296 | NSModule | |
297 | NSModuleForSymbol( | |
298 | NSSymbol symbol) | |
299 | { | |
bac542e6 | 300 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
301 | static NSModule (*p)(NSSymbol symbol) = NULL; |
302 | ||
303 | if(p == NULL) | |
304 | _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p); | |
305 | return(p(symbol)); | |
306 | } | |
307 | ||
308 | bool | |
309 | NSAddLibrary( | |
310 | const char* pathName) | |
311 | { | |
bac542e6 | 312 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
313 | static bool (*p)(const char* pathName) = NULL; |
314 | ||
315 | if(p == NULL) | |
316 | _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p); | |
317 | return(p(pathName)); | |
318 | } | |
319 | ||
320 | bool | |
321 | NSAddLibraryWithSearching( | |
322 | const char* pathName) | |
323 | { | |
bac542e6 | 324 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
325 | static bool (*p)(const char* pathName) = NULL; |
326 | ||
327 | if(p == NULL) | |
328 | _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p); | |
329 | return(p(pathName)); | |
330 | } | |
331 | ||
332 | const struct mach_header * | |
333 | NSAddImage( | |
334 | const char* image_name, | |
335 | uint32_t options) | |
336 | { | |
bac542e6 | 337 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
338 | static const struct mach_header * (*p)(const char* image_name, |
339 | uint32_t options) = NULL; | |
340 | ||
341 | if(p == NULL) | |
342 | _dyld_func_lookup("__dyld_NSAddImage", (void**)&p); | |
343 | return(p(image_name, options)); | |
344 | } | |
39a8cd10 | 345 | #endif // DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
346 | |
347 | /* | |
348 | * This routine returns the current version of the named shared library the | |
349 | * executable it was built with. The libraryName parameter is the same as the | |
350 | * -lx or -framework Foo argument passed to the static link editor when building | |
351 | * the executable (with -lx it would be "x" and with -framework Foo it would be | |
352 | * "Foo"). If this the executable was not built against the specified library | |
353 | * it returns -1. It should be noted that if this only returns the value the | |
354 | * current version of the named shared library the executable was built with | |
355 | * and not a list of current versions that dependent libraries and bundles the | |
356 | * program is using were built with. | |
357 | */ | |
19894a12 | 358 | int32_t NSVersionOfLinkTimeLibrary(const char* libraryName) |
0959b6d4 | 359 | { |
19894a12 | 360 | // Lazily call _NSGetMachExecuteHeader() and cache result |
bac542e6 | 361 | #if __LP64__ |
19894a12 | 362 | static mach_header_64* mh = NULL; |
bac542e6 | 363 | #else |
19894a12 | 364 | static mach_header* mh = NULL; |
bac542e6 | 365 | #endif |
19894a12 | 366 | if ( mh == NULL ) |
0959b6d4 | 367 | mh = _NSGetMachExecuteHeader(); |
bac542e6 | 368 | #if __LP64__ |
19894a12 | 369 | const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64)); |
0959b6d4 | 370 | #else |
19894a12 | 371 | const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header)); |
0959b6d4 | 372 | #endif |
19894a12 | 373 | for(uint32_t i = 0; i < mh->ncmds; i++){ |
bac542e6 A |
374 | switch ( lc->cmd ) { |
375 | case LC_LOAD_DYLIB: | |
376 | case LC_LOAD_WEAK_DYLIB: | |
412ebb8e | 377 | case LC_LOAD_UPWARD_DYLIB: |
19894a12 A |
378 | const dylib_command* dl = (dylib_command *)lc; |
379 | const char* install_name = (char*)dl + dl->dylib.name.offset; | |
380 | if ( names_match(install_name, libraryName) ) | |
381 | return dl->dylib.current_version; | |
bac542e6 A |
382 | break; |
383 | } | |
19894a12 | 384 | lc = (load_command*)((char*)lc + lc->cmdsize); |
0959b6d4 | 385 | } |
19894a12 | 386 | return (-1); |
0959b6d4 A |
387 | } |
388 | ||
389 | /* | |
390 | * This routine returns the current version of the named shared library the | |
391 | * program it is running against. The libraryName parameter is the same as | |
392 | * would be static link editor using the -lx or -framework Foo flags (with -lx | |
393 | * it would be "x" and with -framework Foo it would be "Foo"). If the program | |
394 | * is not using the specified library it returns -1. | |
395 | */ | |
19894a12 A |
396 | int32_t NSVersionOfRunTimeLibrary(const char* libraryName) |
397 | { | |
398 | uint32_t n = _dyld_image_count(); | |
399 | for(uint32_t i = 0; i < n; i++){ | |
400 | const mach_header* mh = _dyld_get_image_header(i); | |
401 | if ( mh == NULL ) | |
402 | continue; | |
403 | if ( mh->filetype != MH_DYLIB ) | |
404 | continue; | |
bac542e6 | 405 | #if __LP64__ |
19894a12 | 406 | const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64)); |
bac542e6 | 407 | #else |
19894a12 | 408 | const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header)); |
bac542e6 | 409 | #endif |
19894a12 A |
410 | for(uint32_t j = 0; j < mh->ncmds; j++){ |
411 | if ( lc->cmd == LC_ID_DYLIB ) { | |
412 | const dylib_command* dl = (dylib_command*)lc; | |
413 | const char* install_name = (char *)dl + dl->dylib.name.offset; | |
414 | if ( names_match(install_name, libraryName) ) | |
415 | return dl->dylib.current_version; | |
416 | } | |
417 | lc = (load_command*)((char*)lc + lc->cmdsize); | |
0959b6d4 A |
418 | } |
419 | } | |
19894a12 | 420 | return (-1); |
0959b6d4 A |
421 | } |
422 | ||
df9d6cf7 | 423 | |
2fd3f4e8 A |
424 | #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff)) |
425 | ||
832b6fce | 426 | |
df9d6cf7 A |
427 | static bool getVersionLoadCommandInfo(const mach_header* mh, uint32_t* loadCommand, uint32_t* minOS, uint32_t* sdk) |
428 | { | |
429 | const load_command* startCmds = NULL; | |
430 | if ( mh->magic == MH_MAGIC_64 ) | |
431 | startCmds = (load_command*)((char *)mh + sizeof(mach_header_64)); | |
432 | else if ( mh->magic == MH_MAGIC ) | |
433 | startCmds = (load_command*)((char *)mh + sizeof(mach_header)); | |
434 | else | |
435 | return false; // not a mach-o file, or wrong endianness | |
436 | ||
437 | const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds); | |
438 | const load_command* cmd = startCmds; | |
439 | for(uint32_t i = 0; i < mh->ncmds; ++i) { | |
440 | const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize); | |
441 | if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) { | |
442 | return 0; | |
443 | } | |
444 | const version_min_command* versCmd; | |
445 | switch ( cmd->cmd ) { | |
446 | case LC_VERSION_MIN_IPHONEOS: | |
447 | case LC_VERSION_MIN_MACOSX: | |
448 | case LC_VERSION_MIN_TVOS: | |
449 | case LC_VERSION_MIN_WATCHOS: | |
450 | versCmd = (version_min_command*)cmd; | |
451 | *loadCommand = versCmd->cmd; | |
452 | *minOS = versCmd->version; | |
453 | *sdk = versCmd->sdk; | |
454 | return true; | |
455 | } | |
456 | cmd = nextCmd; | |
457 | } | |
458 | return false; | |
459 | } | |
460 | ||
461 | #if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED | |
462 | static uint32_t deriveSDKVersFromDylibs(const mach_header* mh) | |
832b6fce | 463 | { |
48479956 | 464 | const load_command* startCmds = NULL; |
2fd3f4e8 | 465 | if ( mh->magic == MH_MAGIC_64 ) |
48479956 | 466 | startCmds = (load_command*)((char *)mh + sizeof(mach_header_64)); |
2fd3f4e8 | 467 | else if ( mh->magic == MH_MAGIC ) |
48479956 | 468 | startCmds = (load_command*)((char *)mh + sizeof(mach_header)); |
2fd3f4e8 A |
469 | else |
470 | return 0; // not a mach-o file, or wrong endianness | |
471 | ||
48479956 | 472 | const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds); |
832b6fce | 473 | const dylib_command* dylibCmd; |
48479956 | 474 | const load_command* cmd = startCmds; |
2fd3f4e8 | 475 | const char* dylibName; |
df9d6cf7 | 476 | #if __IPHONE_OS_VERSION_MIN_REQUIRED |
2fd3f4e8 | 477 | uint32_t foundationVers = 0; |
df9d6cf7 | 478 | #else |
832b6fce | 479 | uint32_t libSystemVers = 0; |
df9d6cf7 | 480 | #endif |
832b6fce | 481 | for(uint32_t i = 0; i < mh->ncmds; ++i) { |
19894a12 A |
482 | const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize); |
483 | // <rdar://problem/14381579&16050962> sanity check size of command | |
484 | if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) { | |
485 | return 0; | |
486 | } | |
487 | switch ( cmd->cmd ) { | |
832b6fce A |
488 | case LC_LOAD_DYLIB: |
489 | case LC_LOAD_WEAK_DYLIB: | |
490 | case LC_LOAD_UPWARD_DYLIB: | |
491 | dylibCmd = (dylib_command*)cmd; | |
19894a12 A |
492 | // sanity check dylib command layout |
493 | if ( dylibCmd->dylib.name.offset > cmd->cmdsize ) | |
494 | return 0; | |
2fd3f4e8 | 495 | dylibName = (char*)dylibCmd + dylibCmd->dylib.name.offset; |
df9d6cf7 | 496 | #if __IPHONE_OS_VERSION_MIN_REQUIRED |
2fd3f4e8 A |
497 | if ( strcmp(dylibName, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 ) |
498 | foundationVers = dylibCmd->dylib.current_version; | |
df9d6cf7 | 499 | #else |
2fd3f4e8 | 500 | if ( strcmp(dylibName, "/usr/lib/libSystem.B.dylib") == 0 ) |
832b6fce | 501 | libSystemVers = dylibCmd->dylib.current_version; |
df9d6cf7 | 502 | #endif |
832b6fce A |
503 | break; |
504 | } | |
19894a12 | 505 | cmd = nextCmd; |
832b6fce | 506 | } |
2fd3f4e8 A |
507 | |
508 | struct DylibToOSMapping { | |
509 | uint32_t dylibVersion; | |
510 | uint32_t osVersion; | |
511 | }; | |
832b6fce | 512 | |
df9d6cf7 | 513 | #if __IPHONE_OS_VERSION_MIN_REQUIRED |
2fd3f4e8 A |
514 | static const DylibToOSMapping foundationMapping[] = { |
515 | { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0 }, | |
516 | { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1 }, | |
517 | { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2 }, | |
518 | { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0 }, | |
519 | { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1 }, | |
520 | { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2 }, | |
521 | { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0 }, | |
522 | { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1 }, | |
523 | { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2 }, | |
524 | { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3 }, | |
525 | { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0 }, | |
526 | { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1 }, | |
527 | { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0 }, | |
528 | { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1 }, | |
df9d6cf7 A |
529 | { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0 }, |
530 | { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0 } | |
531 | // We don't need to expand this table because all recent | |
532 | // binaries have LC_VERSION_MIN_ load command. | |
2fd3f4e8 A |
533 | }; |
534 | ||
535 | if ( foundationVers != 0 ) { | |
536 | uint32_t lastOsVersion = 0; | |
537 | for (const DylibToOSMapping* p=foundationMapping; ; ++p) { | |
538 | if ( p->dylibVersion == 0 ) | |
539 | return p->osVersion; | |
540 | if ( foundationVers < p->dylibVersion ) | |
541 | return lastOsVersion; | |
542 | lastOsVersion = p->osVersion; | |
543 | } | |
544 | } | |
545 | ||
df9d6cf7 | 546 | #else |
2fd3f4e8 A |
547 | // Note: versions are for the GM release. The last entry should |
548 | // always be zero. At the start of the next major version, | |
549 | // a new last entry needs to be added and the previous zero | |
550 | // updated to the GM dylib version. | |
551 | static const DylibToOSMapping libSystemMapping[] = { | |
552 | { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4 }, | |
553 | { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5 }, | |
554 | { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6 }, | |
555 | { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7 }, | |
556 | { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8 }, | |
557 | { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9 }, | |
558 | { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9 } | |
df9d6cf7 A |
559 | // We don't need to expand this table because all recent |
560 | // binaries have LC_VERSION_MIN_ load command. | |
2fd3f4e8 A |
561 | }; |
562 | ||
563 | if ( libSystemVers != 0 ) { | |
564 | uint32_t lastOsVersion = 0; | |
565 | for (const DylibToOSMapping* p=libSystemMapping; ; ++p) { | |
566 | if ( p->dylibVersion == 0 ) | |
567 | return p->osVersion; | |
568 | if ( libSystemVers < p->dylibVersion ) | |
569 | return lastOsVersion; | |
570 | lastOsVersion = p->osVersion; | |
571 | } | |
832b6fce | 572 | } |
df9d6cf7 A |
573 | #endif |
574 | return 0; | |
575 | } | |
2fd3f4e8 | 576 | #endif |
df9d6cf7 A |
577 | |
578 | ||
579 | #if __WATCH_OS_VERSION_MIN_REQUIRED | |
580 | static uint32_t watchVersToIOSVers(uint32_t vers) | |
581 | { | |
582 | return vers + 0x00070000; | |
583 | } | |
584 | ||
585 | uint32_t dyld_get_program_sdk_watch_os_version() | |
586 | { | |
587 | const mach_header* mh = (mach_header*)_NSGetMachExecuteHeader(); | |
588 | uint32_t loadCommand; | |
589 | uint32_t minOS; | |
590 | uint32_t sdk; | |
591 | ||
592 | if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) { | |
593 | if ( loadCommand == LC_VERSION_MIN_WATCHOS ) | |
594 | return sdk; | |
595 | } | |
596 | return 0; | |
597 | } | |
598 | #endif | |
599 | ||
600 | /* | |
601 | * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the | |
602 | * specified binary was built against. | |
603 | * | |
604 | * First looks for LC_VERSION_MIN_* in binary and if sdk field is | |
605 | * not zero, return that value. | |
606 | * Otherwise, looks for the libSystem.B.dylib the binary linked | |
607 | * against and uses a table to convert that to an sdk version. | |
608 | */ | |
609 | uint32_t dyld_get_sdk_version(const mach_header* mh) | |
610 | { | |
611 | uint32_t loadCommand; | |
612 | uint32_t minOS; | |
613 | uint32_t sdk; | |
614 | ||
615 | if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) { | |
616 | switch (loadCommand) { | |
617 | #if __WATCH_OS_VERSION_MIN_REQUIRED | |
618 | case LC_VERSION_MIN_WATCHOS: | |
619 | // new binary. sdk version looks like "2.0" but API wants "9.0" | |
620 | return watchVersToIOSVers(sdk); | |
621 | case LC_VERSION_MIN_IPHONEOS: | |
622 | // old binary. sdk matches API semantics so can return directly. | |
623 | return sdk; | |
624 | #elif __TV_OS_VERSION_MIN_REQUIRED | |
625 | case LC_VERSION_MIN_TVOS: | |
626 | case LC_VERSION_MIN_IPHONEOS: | |
627 | return sdk; | |
628 | #elif __IPHONE_OS_VERSION_MIN_REQUIRED | |
629 | case LC_VERSION_MIN_IPHONEOS: | |
630 | if ( sdk != 0 ) // old binaries might not have SDK set | |
631 | return sdk; | |
632 | break; | |
633 | #else | |
634 | case LC_VERSION_MIN_MACOSX: | |
635 | if ( sdk != 0 ) // old binaries might not have SDK set | |
636 | return sdk; | |
637 | break; | |
638 | #endif | |
639 | } | |
640 | } | |
641 | ||
642 | #if __WATCH_OS_VERSION_MIN_REQUIRED ||__TV_OS_VERSION_MIN_REQUIRED | |
643 | // All WatchOS and tv OS binaries should have version load command. | |
832b6fce | 644 | return 0; |
df9d6cf7 A |
645 | #else |
646 | // MacOSX and iOS have old binaries without version load commmand. | |
647 | return deriveSDKVersFromDylibs(mh); | |
648 | #endif | |
832b6fce A |
649 | } |
650 | ||
651 | uint32_t dyld_get_program_sdk_version() | |
652 | { | |
653 | return dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader()); | |
654 | } | |
655 | ||
832b6fce A |
656 | uint32_t dyld_get_min_os_version(const struct mach_header* mh) |
657 | { | |
df9d6cf7 A |
658 | uint32_t loadCommand; |
659 | uint32_t minOS; | |
660 | uint32_t sdk; | |
661 | ||
662 | if ( getVersionLoadCommandInfo(mh, &loadCommand, &minOS, &sdk) ) { | |
663 | switch (loadCommand) { | |
664 | #if __WATCH_OS_VERSION_MIN_REQUIRED | |
665 | case LC_VERSION_MIN_WATCHOS: | |
666 | // new binary. OS version looks like "2.0" but API wants "9.0" | |
667 | return watchVersToIOSVers(minOS); | |
668 | case LC_VERSION_MIN_IPHONEOS: | |
669 | // old binary. OS matches API semantics so can return directly. | |
670 | return minOS; | |
671 | #elif __TV_OS_VERSION_MIN_REQUIRED | |
672 | case LC_VERSION_MIN_TVOS: | |
673 | case LC_VERSION_MIN_IPHONEOS: | |
674 | return minOS; | |
675 | #elif __IPHONE_OS_VERSION_MIN_REQUIRED | |
832b6fce | 676 | case LC_VERSION_MIN_IPHONEOS: |
df9d6cf7 | 677 | return minOS; |
2fd3f4e8 A |
678 | #else |
679 | case LC_VERSION_MIN_MACOSX: | |
df9d6cf7 | 680 | return minOS; |
2fd3f4e8 | 681 | #endif |
832b6fce | 682 | } |
832b6fce A |
683 | } |
684 | return 0; | |
685 | } | |
686 | ||
687 | ||
688 | uint32_t dyld_get_program_min_os_version() | |
689 | { | |
690 | return dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader()); | |
691 | } | |
692 | ||
693 | ||
39a8cd10 | 694 | #if DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
695 | /* |
696 | * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the | |
697 | * specified file name if the file is a correct Mach-O file that can be loaded | |
698 | * with NSloadModule(). For return codes of NSObjectFileImageFailure and | |
699 | * NSObjectFileImageFormat an error message is printed to stderr. All | |
700 | * other codes cause no printing. | |
701 | */ | |
702 | NSObjectFileImageReturnCode | |
703 | NSCreateObjectFileImageFromFile( | |
704 | const char* pathName, | |
705 | NSObjectFileImage *objectFileImage) | |
706 | { | |
bac542e6 | 707 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
708 | static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL; |
709 | ||
710 | if(p == NULL) | |
711 | _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p); | |
712 | return p(pathName, objectFileImage); | |
713 | } | |
714 | ||
715 | ||
716 | /* | |
717 | * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the | |
718 | * object file mapped into memory at address of size length if the object file | |
719 | * is a correct Mach-O file that can be loaded with NSloadModule(). For return | |
720 | * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error | |
721 | * message is printed to stderr. All other codes cause no printing. | |
722 | */ | |
723 | NSObjectFileImageReturnCode | |
724 | NSCreateObjectFileImageFromMemory( | |
725 | const void* address, | |
726 | size_t size, | |
727 | NSObjectFileImage *objectFileImage) | |
728 | { | |
bac542e6 | 729 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
730 | static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL; |
731 | ||
732 | if(p == NULL) | |
733 | _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p); | |
734 | return p(address, size, objectFileImage); | |
735 | } | |
736 | ||
bac542e6 | 737 | #if OBSOLETE_DYLD_API |
0959b6d4 A |
738 | /* |
739 | * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the | |
740 | * specified core file name if the file is a correct Mach-O core file. | |
741 | * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat | |
742 | * an error message is printed to stderr. All other codes cause no printing. | |
743 | */ | |
744 | NSObjectFileImageReturnCode | |
745 | NSCreateCoreFileImageFromFile( | |
746 | const char* pathName, | |
747 | NSObjectFileImage *objectFileImage) | |
748 | { | |
bac542e6 | 749 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
750 | static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL; |
751 | ||
752 | if(p == NULL) | |
753 | _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p); | |
754 | return p(pathName, objectFileImage); | |
755 | } | |
bac542e6 | 756 | #endif |
0959b6d4 A |
757 | |
758 | bool | |
759 | NSDestroyObjectFileImage( | |
760 | NSObjectFileImage objectFileImage) | |
761 | { | |
bac542e6 | 762 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
763 | static bool (*p)(NSObjectFileImage) = NULL; |
764 | ||
765 | if(p == NULL) | |
766 | _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p); | |
767 | return p(objectFileImage); | |
768 | } | |
769 | ||
770 | ||
771 | NSModule | |
772 | NSLinkModule( | |
773 | NSObjectFileImage objectFileImage, | |
774 | const char* moduleName, | |
775 | uint32_t options) | |
776 | { | |
bac542e6 | 777 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
778 | static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL; |
779 | ||
780 | if(p == NULL) | |
781 | _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p); | |
782 | ||
783 | return p(objectFileImage, moduleName, options); | |
784 | } | |
785 | ||
786 | ||
0959b6d4 A |
787 | |
788 | ||
789 | /* | |
790 | * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol | |
791 | * definitions in the NSObjectFileImage. | |
792 | */ | |
793 | uint32_t | |
794 | NSSymbolDefinitionCountInObjectFileImage( | |
795 | NSObjectFileImage objectFileImage) | |
796 | { | |
bac542e6 | 797 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
798 | static unsigned long (*p)(NSObjectFileImage) = NULL; |
799 | ||
800 | if(p == NULL) | |
801 | _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p); | |
802 | ||
803 | return p(objectFileImage); | |
804 | } | |
805 | ||
806 | /* | |
807 | * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th | |
808 | * symbol definitions in the NSObjectFileImage. If the ordinal specified is | |
809 | * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will | |
810 | * be returned. | |
811 | */ | |
812 | const char* | |
813 | NSSymbolDefinitionNameInObjectFileImage( | |
814 | NSObjectFileImage objectFileImage, | |
815 | uint32_t ordinal) | |
816 | { | |
bac542e6 | 817 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
818 | static const char* (*p)(NSObjectFileImage, uint32_t) = NULL; |
819 | ||
820 | if(p == NULL) | |
821 | _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p); | |
822 | ||
823 | return p(objectFileImage, ordinal); | |
824 | } | |
825 | ||
826 | /* | |
827 | * NSSymbolReferenceCountInObjectFileImage() returns the number of references | |
828 | * to undefined symbols the NSObjectFileImage. | |
829 | */ | |
830 | uint32_t | |
831 | NSSymbolReferenceCountInObjectFileImage( | |
832 | NSObjectFileImage objectFileImage) | |
833 | { | |
bac542e6 | 834 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
835 | static unsigned long (*p)(NSObjectFileImage) = NULL; |
836 | ||
837 | if(p == NULL) | |
838 | _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p); | |
839 | ||
840 | return p(objectFileImage); | |
841 | } | |
842 | ||
843 | /* | |
844 | * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th | |
845 | * undefined symbol in the NSObjectFileImage. If the ordinal specified is | |
846 | * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be | |
847 | * returned. | |
848 | */ | |
849 | const char* | |
850 | NSSymbolReferenceNameInObjectFileImage( | |
851 | NSObjectFileImage objectFileImage, | |
852 | uint32_t ordinal, | |
853 | bool *tentative_definition) /* can be NULL */ | |
854 | { | |
bac542e6 | 855 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
856 | static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL; |
857 | ||
858 | if(p == NULL) | |
859 | _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p); | |
860 | ||
861 | return p(objectFileImage, ordinal, tentative_definition); | |
862 | } | |
863 | ||
864 | /* | |
865 | * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol | |
866 | * name has a definition in the NSObjectFileImage and FALSE otherwise. | |
867 | */ | |
868 | bool | |
869 | NSIsSymbolDefinedInObjectFileImage( | |
870 | NSObjectFileImage objectFileImage, | |
871 | const char* symbolName) | |
872 | { | |
bac542e6 | 873 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
874 | static bool (*p)(NSObjectFileImage, const char*) = NULL; |
875 | ||
876 | if(p == NULL) | |
877 | _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p); | |
878 | ||
879 | return p(objectFileImage, symbolName); | |
880 | } | |
881 | ||
882 | /* | |
883 | * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents | |
884 | * in the NSObjectFileImage for the specified segmentName and sectionName if | |
885 | * it exists and it is not a zerofill section. If not it returns NULL. If | |
886 | * the parameter size is not NULL the size of the section is also returned | |
887 | * indirectly through that pointer. | |
888 | */ | |
889 | void * | |
890 | NSGetSectionDataInObjectFileImage( | |
891 | NSObjectFileImage objectFileImage, | |
892 | const char* segmentName, | |
893 | const char* sectionName, | |
894 | unsigned long *size) /* can be NULL */ | |
895 | { | |
bac542e6 | 896 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
897 | static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL; |
898 | ||
899 | if(p == NULL) | |
900 | _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p); | |
901 | ||
902 | return p(objectFileImage, segmentName, sectionName, size); | |
903 | } | |
904 | ||
0959b6d4 A |
905 | |
906 | void | |
907 | NSLinkEditError( | |
908 | NSLinkEditErrors *c, | |
909 | int *errorNumber, | |
910 | const char* *fileName, | |
911 | const char* *errorString) | |
912 | { | |
bac542e6 | 913 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
914 | static void (*p)(NSLinkEditErrors *c, |
915 | int *errorNumber, | |
916 | const char* *fileName, | |
917 | const char* *errorString) = NULL; | |
918 | ||
919 | if(p == NULL) | |
920 | _dyld_func_lookup("__dyld_link_edit_error", (void**)&p); | |
921 | if(p != NULL) | |
922 | p(c, errorNumber, fileName, errorString); | |
923 | } | |
924 | ||
925 | bool | |
926 | NSUnLinkModule( | |
927 | NSModule module, | |
928 | uint32_t options) | |
929 | { | |
bac542e6 | 930 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
931 | static bool (*p)(NSModule module, uint32_t options) = NULL; |
932 | ||
933 | if(p == NULL) | |
934 | _dyld_func_lookup("__dyld_unlink_module", (void**)&p); | |
935 | ||
936 | return p(module, options); | |
937 | } | |
938 | ||
bac542e6 | 939 | #if OBSOLETE_DYLD_API |
0959b6d4 A |
940 | NSModule |
941 | NSReplaceModule( | |
942 | NSModule moduleToReplace, | |
943 | NSObjectFileImage newObjectFileImage, | |
944 | uint32_t options) | |
945 | { | |
946 | return(NULL); | |
947 | } | |
bac542e6 | 948 | #endif |
0959b6d4 | 949 | |
39a8cd10 A |
950 | |
951 | #endif // DEPRECATED_APIS_SUPPORTED | |
952 | ||
0959b6d4 A |
953 | /* |
954 | *_NSGetExecutablePath copies the path of the executable into the buffer and | |
955 | * returns 0 if the path was successfully copied in the provided buffer. If the | |
956 | * buffer is not large enough, -1 is returned and the expected buffer size is | |
957 | * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to | |
958 | * the executable not a "real path" to the executable. That is the path may be | |
959 | * a symbolic link and not the real file. And with deep directories the total | |
960 | * bufsize needed could be more than MAXPATHLEN. | |
961 | */ | |
962 | int | |
963 | _NSGetExecutablePath( | |
964 | char *buf, | |
965 | uint32_t *bufsize) | |
966 | { | |
bac542e6 | 967 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
968 | static int (*p)(char *buf, uint32_t *bufsize) = NULL; |
969 | ||
970 | if(p == NULL) | |
971 | _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p); | |
972 | return(p(buf, bufsize)); | |
973 | } | |
974 | ||
39a8cd10 | 975 | #if DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
976 | void |
977 | _dyld_lookup_and_bind( | |
978 | const char* symbol_name, | |
979 | void** address, | |
980 | NSModule* module) | |
981 | { | |
bac542e6 | 982 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
983 | static void (*p)(const char*, void** , NSModule*) = NULL; |
984 | ||
985 | if(p == NULL) | |
986 | _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p); | |
987 | p(symbol_name, address, module); | |
988 | } | |
989 | ||
990 | void | |
991 | _dyld_lookup_and_bind_with_hint( | |
992 | const char* symbol_name, | |
993 | const char* library_name_hint, | |
994 | void** address, | |
995 | NSModule* module) | |
996 | { | |
bac542e6 | 997 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
998 | static void (*p)(const char*, const char*, void**, NSModule*) = NULL; |
999 | ||
1000 | if(p == NULL) | |
1001 | _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p); | |
1002 | p(symbol_name, library_name_hint, address, module); | |
1003 | } | |
1004 | ||
bac542e6 | 1005 | #if OBSOLETE_DYLD_API |
0959b6d4 A |
1006 | void |
1007 | _dyld_lookup_and_bind_objc( | |
1008 | const char* symbol_name, | |
1009 | void** address, | |
1010 | NSModule* module) | |
1011 | { | |
bac542e6 | 1012 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1013 | static void (*p)(const char* , void**, NSModule*) = NULL; |
1014 | ||
1015 | if(p == NULL) | |
1016 | _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p); | |
1017 | p(symbol_name, address, module); | |
1018 | } | |
bac542e6 | 1019 | #endif |
0959b6d4 A |
1020 | |
1021 | void | |
1022 | _dyld_lookup_and_bind_fully( | |
1023 | const char* symbol_name, | |
1024 | void** address, | |
1025 | NSModule* module) | |
1026 | { | |
bac542e6 | 1027 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1028 | static void (*p)(const char*, void**, NSModule*) = NULL; |
1029 | ||
1030 | if(p == NULL) | |
1031 | _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p); | |
1032 | p(symbol_name, address, module); | |
1033 | } | |
1034 | ||
1035 | bool | |
1036 | _dyld_bind_fully_image_containing_address( | |
1037 | const void* address) | |
1038 | { | |
bac542e6 | 1039 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1040 | static bool (*p)(const void*) = NULL; |
1041 | ||
1042 | if(p == NULL) | |
1043 | _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p); | |
1044 | return p(address); | |
1045 | } | |
39a8cd10 | 1046 | #endif // DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
1047 | |
1048 | ||
1049 | /* | |
1050 | * _dyld_register_func_for_add_image registers the specified function to be | |
1051 | * called when a new image is added (a bundle or a dynamic shared library) to | |
1052 | * the program. When this function is first registered it is called for once | |
1053 | * for each image that is currently part of the program. | |
1054 | */ | |
1055 | void | |
1056 | _dyld_register_func_for_add_image( | |
1057 | void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) | |
1058 | { | |
bac542e6 | 1059 | DYLD_LOCK_THIS_BLOCK; |
412ebb8e A |
1060 | typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide); |
1061 | static void (*p)(callback_t func) = NULL; | |
0959b6d4 A |
1062 | |
1063 | if(p == NULL) | |
1064 | _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p); | |
1065 | p(func); | |
1066 | } | |
1067 | ||
1068 | /* | |
1069 | * _dyld_register_func_for_remove_image registers the specified function to be | |
1070 | * called when an image is removed (a bundle or a dynamic shared library) from | |
1071 | * the program. | |
1072 | */ | |
1073 | void | |
1074 | _dyld_register_func_for_remove_image( | |
1075 | void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) | |
1076 | { | |
bac542e6 | 1077 | DYLD_LOCK_THIS_BLOCK; |
412ebb8e A |
1078 | typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide); |
1079 | static void (*p)(callback_t func) = NULL; | |
0959b6d4 A |
1080 | |
1081 | if(p == NULL) | |
1082 | _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p); | |
1083 | p(func); | |
1084 | } | |
1085 | ||
bac542e6 | 1086 | #if OBSOLETE_DYLD_API |
0959b6d4 A |
1087 | /* |
1088 | * _dyld_register_func_for_link_module registers the specified function to be | |
1089 | * called when a module is bound into the program. When this function is first | |
1090 | * registered it is called for once for each module that is currently bound into | |
1091 | * the program. | |
1092 | */ | |
1093 | void | |
1094 | _dyld_register_func_for_link_module( | |
1095 | void (*func)(NSModule module)) | |
1096 | { | |
bac542e6 | 1097 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1098 | static void (*p)(void (*func)(NSModule module)) = NULL; |
1099 | ||
1100 | if(p == NULL) | |
1101 | _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p); | |
1102 | p(func); | |
1103 | } | |
1104 | ||
1105 | /* | |
1106 | * _dyld_register_func_for_unlink_module registers the specified function to be | |
1107 | * called when a module is unbound from the program. | |
1108 | */ | |
1109 | void | |
1110 | _dyld_register_func_for_unlink_module( | |
1111 | void (*func)(NSModule module)) | |
1112 | { | |
bac542e6 | 1113 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1114 | static void (*p)(void (*func)(NSModule module)) = NULL; |
1115 | ||
1116 | if(p == NULL) | |
1117 | _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p); | |
1118 | p(func); | |
1119 | } | |
1120 | ||
1121 | /* | |
1122 | * _dyld_register_func_for_replace_module registers the specified function to be | |
1123 | * called when a module is to be replace with another module in the program. | |
1124 | */ | |
1125 | void | |
1126 | _dyld_register_func_for_replace_module( | |
1127 | void (*func)(NSModule oldmodule, NSModule newmodule)) | |
1128 | { | |
bac542e6 | 1129 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1130 | static void (*p)(void (*func)(NSModule oldmodule, |
1131 | NSModule newmodule)) = NULL; | |
1132 | ||
1133 | if(p == NULL) | |
1134 | _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p); | |
1135 | p(func); | |
1136 | } | |
1137 | ||
1138 | ||
1139 | /* | |
1140 | * _dyld_get_objc_module_sect_for_module is passed a module and sets a | |
1141 | * pointer to the (__OBJC,__module) section and its size for the specified | |
1142 | * module. | |
1143 | */ | |
1144 | void | |
1145 | _dyld_get_objc_module_sect_for_module( | |
1146 | NSModule module, | |
1147 | void **objc_module, | |
1148 | unsigned long *size) | |
1149 | { | |
bac542e6 | 1150 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1151 | static void (*p)(NSModule module, |
1152 | void **objc_module, | |
1153 | unsigned long *size) = NULL; | |
1154 | ||
1155 | if(p == NULL) | |
1156 | _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p); | |
1157 | p(module, objc_module, size); | |
1158 | } | |
1159 | ||
1160 | /* | |
1161 | * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC, | |
1162 | * __module) section and causes the module that is associated with that address | |
1163 | * to be bound. | |
1164 | */ | |
1165 | void | |
bac542e6 | 1166 | _dyld_bind_objc_module(const void* objc_module) |
0959b6d4 | 1167 | { |
bac542e6 | 1168 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1169 | static void (*p)(const void *objc_module) = NULL; |
1170 | ||
1171 | if(p == NULL) | |
1172 | _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p); | |
1173 | p(objc_module); | |
1174 | } | |
bac542e6 | 1175 | #endif |
0959b6d4 | 1176 | |
39a8cd10 | 1177 | #if DEPRECATED_APIS_SUPPORTED |
0959b6d4 | 1178 | bool |
bac542e6 | 1179 | _dyld_present(void) |
0959b6d4 | 1180 | { |
bac542e6 | 1181 | // this function exists for compatiblity only |
0959b6d4 A |
1182 | return true; |
1183 | } | |
39a8cd10 | 1184 | #endif |
0959b6d4 A |
1185 | |
1186 | uint32_t | |
bac542e6 | 1187 | _dyld_image_count(void) |
0959b6d4 A |
1188 | { |
1189 | DYLD_NO_LOCK_THIS_BLOCK; | |
19894a12 | 1190 | static uint32_t (*p)(void) = NULL; |
0959b6d4 | 1191 | |
0959b6d4 A |
1192 | if(p == NULL) |
1193 | _dyld_func_lookup("__dyld_image_count", (void**)&p); | |
1194 | return(p()); | |
1195 | } | |
1196 | ||
1197 | const struct mach_header * | |
bac542e6 | 1198 | _dyld_get_image_header(uint32_t image_index) |
0959b6d4 A |
1199 | { |
1200 | DYLD_NO_LOCK_THIS_BLOCK; | |
1201 | static struct mach_header * (*p)(uint32_t image_index) = NULL; | |
1202 | ||
1203 | if(p == NULL) | |
1204 | _dyld_func_lookup("__dyld_get_image_header", (void**)&p); | |
1205 | return(p(image_index)); | |
1206 | } | |
1207 | ||
1208 | intptr_t | |
bac542e6 | 1209 | _dyld_get_image_vmaddr_slide(uint32_t image_index) |
0959b6d4 A |
1210 | { |
1211 | DYLD_NO_LOCK_THIS_BLOCK; | |
1212 | static unsigned long (*p)(uint32_t image_index) = NULL; | |
1213 | ||
1214 | if(p == NULL) | |
1215 | _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p); | |
1216 | return(p(image_index)); | |
1217 | } | |
1218 | ||
1219 | const char* | |
bac542e6 | 1220 | _dyld_get_image_name(uint32_t image_index) |
0959b6d4 A |
1221 | { |
1222 | DYLD_NO_LOCK_THIS_BLOCK; | |
1223 | static const char* (*p)(uint32_t image_index) = NULL; | |
1224 | ||
1225 | if(p == NULL) | |
1226 | _dyld_func_lookup("__dyld_get_image_name", (void**)&p); | |
1227 | return(p(image_index)); | |
1228 | } | |
1229 | ||
39a8cd10 A |
1230 | // SPI in Mac OS X 10.6 |
1231 | intptr_t _dyld_get_image_slide(const struct mach_header* mh) | |
1232 | { | |
1233 | DYLD_NO_LOCK_THIS_BLOCK; | |
1234 | static intptr_t (*p)(const struct mach_header*) = NULL; | |
1235 | ||
1236 | if(p == NULL) | |
1237 | _dyld_func_lookup("__dyld_get_image_slide", (void**)&p); | |
1238 | return(p(mh)); | |
1239 | } | |
1240 | ||
1241 | ||
0959b6d4 | 1242 | bool |
bac542e6 | 1243 | _dyld_image_containing_address(const void* address) |
0959b6d4 | 1244 | { |
bac542e6 | 1245 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1246 | static bool (*p)(const void*) = NULL; |
1247 | ||
1248 | if(p == NULL) | |
1249 | _dyld_func_lookup("__dyld_image_containing_address", (void**)&p); | |
1250 | return(p(address)); | |
1251 | } | |
1252 | ||
1253 | const struct mach_header * | |
1254 | _dyld_get_image_header_containing_address( | |
1255 | const void* address) | |
1256 | { | |
bac542e6 | 1257 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1258 | static const struct mach_header * (*p)(const void*) = NULL; |
1259 | ||
1260 | if(p == NULL) | |
1261 | _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p); | |
1262 | return p(address); | |
1263 | } | |
1264 | ||
0959b6d4 | 1265 | |
39a8cd10 | 1266 | #if DEPRECATED_APIS_SUPPORTED |
bac542e6 | 1267 | bool _dyld_launched_prebound(void) |
0959b6d4 | 1268 | { |
bac542e6 | 1269 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1270 | static bool (*p)(void) = NULL; |
1271 | ||
1272 | if(p == NULL) | |
1273 | _dyld_func_lookup("__dyld_launched_prebound", (void**)&p); | |
1274 | return(p()); | |
1275 | } | |
1276 | ||
bac542e6 | 1277 | bool _dyld_all_twolevel_modules_prebound(void) |
0959b6d4 | 1278 | { |
bac542e6 | 1279 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1280 | static bool (*p)(void) = NULL; |
1281 | ||
1282 | if(p == NULL) | |
1283 | _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p); | |
1284 | return(p()); | |
1285 | } | |
39a8cd10 | 1286 | #endif // DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
1287 | |
1288 | ||
1289 | #include <dlfcn.h> | |
1290 | #include <stddef.h> | |
1291 | #include <pthread.h> | |
1292 | #include <stdlib.h> | |
1293 | #include <mach-o/dyld.h> | |
bac542e6 A |
1294 | #include <servers/bootstrap.h> |
1295 | #include "dyldLibSystemInterface.h" | |
bac542e6 | 1296 | |
0959b6d4 A |
1297 | |
1298 | // pthread key used to access per-thread dlerror message | |
1299 | static pthread_key_t dlerrorPerThreadKey; | |
bac542e6 | 1300 | static bool dlerrorPerThreadKeyInitialized = false; |
0959b6d4 A |
1301 | |
1302 | // data kept per-thread | |
1303 | struct dlerrorPerThreadData | |
1304 | { | |
19894a12 | 1305 | size_t sizeAllocated; |
0959b6d4 A |
1306 | char message[1]; |
1307 | }; | |
1308 | ||
1309 | // function called by dyld to get buffer to store dlerror message | |
19894a12 | 1310 | static char* getPerThreadBufferFor_dlerror(size_t sizeRequired) |
0959b6d4 | 1311 | { |
bac542e6 A |
1312 | // ok to create key lazily because this function is called within dyld lock, so there is no race condition |
1313 | if (!dlerrorPerThreadKeyInitialized ) { | |
1314 | // create key and tell pthread package to call free() on any data associated with key if thread dies | |
1315 | pthread_key_create(&dlerrorPerThreadKey, &free); | |
1316 | dlerrorPerThreadKeyInitialized = true; | |
1317 | } | |
1318 | ||
19894a12 | 1319 | const size_t size = (sizeRequired < 256) ? 256 : sizeRequired; |
0959b6d4 A |
1320 | dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey); |
1321 | if ( data == NULL ) { | |
1322 | //int mallocSize = offsetof(dlerrorPerThreadData, message[size]); | |
19894a12 | 1323 | const size_t mallocSize = sizeof(dlerrorPerThreadData)+size; |
0959b6d4 A |
1324 | data = (dlerrorPerThreadData*)malloc(mallocSize); |
1325 | data->sizeAllocated = size; | |
1326 | pthread_setspecific(dlerrorPerThreadKey, data); | |
1327 | } | |
1328 | else if ( data->sizeAllocated < sizeRequired ) { | |
1329 | free(data); | |
1330 | //int mallocSize = offsetof(dlerrorPerThreadData, message[size]); | |
19894a12 | 1331 | const size_t mallocSize = sizeof(dlerrorPerThreadData)+size; |
0959b6d4 A |
1332 | data = (dlerrorPerThreadData*)malloc(mallocSize); |
1333 | data->sizeAllocated = size; | |
1334 | pthread_setspecific(dlerrorPerThreadKey, data); | |
1335 | } | |
1336 | return data->message; | |
1337 | } | |
1338 | ||
2fd3f4e8 A |
1339 | // <rdar://problem/10595338> dlerror buffer leak |
1340 | // Only allocate buffer if an actual error message needs to be set | |
1341 | static bool hasPerThreadBufferFor_dlerror() | |
1342 | { | |
1343 | if (!dlerrorPerThreadKeyInitialized ) | |
1344 | return false; | |
1345 | ||
1346 | return (pthread_getspecific(dlerrorPerThreadKey) != NULL); | |
1347 | } | |
1348 | ||
1349 | // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse | |
1350 | typedef vproc_err_t (*vswapproc)(vproc_t vp, vproc_gsk_t key,int64_t *inval, int64_t *outval); | |
1351 | static vswapproc swapProc = &vproc_swap_integer; | |
1352 | ||
1353 | static bool isLaunchdOwned() { | |
1354 | static bool first = true; | |
1355 | static bool result; | |
1356 | if ( first ) { | |
1357 | int64_t val = 0; | |
1358 | (*swapProc)(NULL, VPROC_GSK_IS_MANAGED, NULL, &val); | |
1359 | result = ( val != 0 ); | |
1360 | first = false; | |
1361 | } | |
1362 | return result; | |
1363 | } | |
1364 | ||
bac542e6 | 1365 | |
39a8cd10 | 1366 | #if DYLD_SHARED_CACHE_SUPPORT |
bac542e6 A |
1367 | static void shared_cache_missing() |
1368 | { | |
39a8cd10 | 1369 | // leave until dyld's that might call this are rare |
bac542e6 A |
1370 | } |
1371 | ||
1372 | static void shared_cache_out_of_date() | |
1373 | { | |
39a8cd10 | 1374 | // leave until dyld's that might call this are rare |
bac542e6 | 1375 | } |
39a8cd10 | 1376 | #endif // DYLD_SHARED_CACHE_SUPPORT |
bac542e6 A |
1377 | |
1378 | ||
39a8cd10 | 1379 | // the table passed to dyld containing thread helpers |
19894a12 | 1380 | static dyld::LibSystemHelpers sHelpers = { 13, &dyldGlobalLockAcquire, &dyldGlobalLockRelease, |
bac542e6 | 1381 | &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit, |
39a8cd10 | 1382 | #if DYLD_SHARED_CACHE_SUPPORT |
bac542e6 | 1383 | &shared_cache_missing, &shared_cache_out_of_date, |
39a8cd10 A |
1384 | #else |
1385 | NULL, NULL, | |
1386 | #endif | |
1387 | NULL, NULL, | |
1388 | &pthread_key_create, &pthread_setspecific, | |
412ebb8e A |
1389 | &malloc_size, |
1390 | &pthread_getspecific, | |
832b6fce | 1391 | &__cxa_finalize, |
2fd3f4e8 A |
1392 | address_of_start, |
1393 | &hasPerThreadBufferFor_dlerror, | |
1394 | &isLaunchdOwned, | |
1395 | &vm_allocate, | |
19894a12 A |
1396 | &mmap, |
1397 | &__cxa_finalize_ranges}; | |
bac542e6 | 1398 | |
0959b6d4 A |
1399 | |
1400 | // | |
1401 | // during initialization of libSystem this routine will run | |
bac542e6 | 1402 | // and call dyld, registering the helper functions. |
0959b6d4 | 1403 | // |
412ebb8e A |
1404 | extern "C" void tlv_initializer(); |
1405 | extern "C" void _dyld_initializer(); | |
bac542e6 | 1406 | void _dyld_initializer() |
2fd3f4e8 | 1407 | { |
bac542e6 A |
1408 | void (*p)(dyld::LibSystemHelpers*); |
1409 | ||
1410 | _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p); | |
0959b6d4 | 1411 | if(p != NULL) |
bac542e6 | 1412 | p(&sHelpers); |
412ebb8e A |
1413 | |
1414 | tlv_initializer(); | |
0959b6d4 A |
1415 | } |
1416 | ||
0959b6d4 A |
1417 | |
1418 | char* dlerror() | |
1419 | { | |
bac542e6 | 1420 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1421 | static char* (*p)() = NULL; |
1422 | ||
1423 | if(p == NULL) | |
1424 | _dyld_func_lookup("__dyld_dlerror", (void**)&p); | |
1425 | return(p()); | |
1426 | } | |
1427 | ||
1428 | int dladdr(const void* addr, Dl_info* info) | |
1429 | { | |
bac542e6 | 1430 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1431 | static int (*p)(const void* , Dl_info*) = NULL; |
1432 | ||
1433 | if(p == NULL) | |
1434 | _dyld_func_lookup("__dyld_dladdr", (void**)&p); | |
1435 | return(p(addr, info)); | |
1436 | } | |
1437 | ||
1438 | int dlclose(void* handle) | |
1439 | { | |
bac542e6 | 1440 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1441 | static int (*p)(void* handle) = NULL; |
1442 | ||
1443 | if(p == NULL) | |
1444 | _dyld_func_lookup("__dyld_dlclose", (void**)&p); | |
1445 | return(p(handle)); | |
1446 | } | |
1447 | ||
1448 | void* dlopen(const char* path, int mode) | |
bac542e6 A |
1449 | { |
1450 | // dlopen is special. locking is done inside dyld to allow initializer to run without lock | |
1451 | DYLD_NO_LOCK_THIS_BLOCK; | |
1452 | ||
0959b6d4 A |
1453 | static void* (*p)(const char* path, int) = NULL; |
1454 | ||
1455 | if(p == NULL) | |
1456 | _dyld_func_lookup("__dyld_dlopen", (void**)&p); | |
bac542e6 A |
1457 | void* result = p(path, mode); |
1458 | // use asm block to prevent tail call optimization | |
1459 | // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain | |
1460 | // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash> | |
1461 | __asm__ volatile(""); | |
1462 | ||
1463 | return result; | |
1464 | } | |
1465 | ||
1466 | bool dlopen_preflight(const char* path) | |
1467 | { | |
1468 | DYLD_LOCK_THIS_BLOCK; | |
1469 | static bool (*p)(const char* path) = NULL; | |
1470 | ||
1471 | if(p == NULL) | |
1472 | _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p); | |
1473 | return(p(path)); | |
0959b6d4 A |
1474 | } |
1475 | ||
1476 | void* dlsym(void* handle, const char* symbol) | |
1477 | { | |
bac542e6 | 1478 | DYLD_LOCK_THIS_BLOCK; |
0959b6d4 A |
1479 | static void* (*p)(void* handle, const char* symbol) = NULL; |
1480 | ||
1481 | if(p == NULL) | |
1482 | _dyld_func_lookup("__dyld_dlsym", (void**)&p); | |
1483 | return(p(handle, symbol)); | |
1484 | } | |
1485 | ||
bac542e6 A |
1486 | void dyld_register_image_state_change_handler(dyld_image_states state, |
1487 | bool batch, dyld_image_state_change_handler handler) | |
1488 | { | |
1489 | DYLD_LOCK_THIS_BLOCK; | |
1490 | static void* (*p)(dyld_image_states, bool, dyld_image_state_change_handler) = NULL; | |
1491 | ||
1492 | if(p == NULL) | |
1493 | _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p); | |
1494 | p(state, batch, handler); | |
1495 | } | |
1496 | ||
0959b6d4 | 1497 | |
39a8cd10 A |
1498 | const struct dyld_all_image_infos* _dyld_get_all_image_infos() |
1499 | { | |
1500 | DYLD_NO_LOCK_THIS_BLOCK; | |
1501 | static struct dyld_all_image_infos* (*p)() = NULL; | |
1502 | ||
1503 | if(p == NULL) | |
1504 | _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p); | |
1505 | return p(); | |
1506 | } | |
1507 | ||
19894a12 | 1508 | #if SUPPORT_ZERO_COST_EXCEPTIONS |
39a8cd10 A |
1509 | bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info) |
1510 | { | |
1511 | DYLD_NO_LOCK_THIS_BLOCK; | |
1512 | static void* (*p)(void*, dyld_unwind_sections*) = NULL; | |
1513 | ||
1514 | if(p == NULL) | |
1515 | _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p); | |
1516 | return p(addr, info); | |
1517 | } | |
1518 | #endif | |
1519 | ||
1520 | ||
19894a12 | 1521 | #if __i386__ || __x86_64__ || __arm__ || __arm64__ |
39a8cd10 A |
1522 | __attribute__((visibility("hidden"))) |
1523 | void* _dyld_fast_stub_entry(void* loadercache, long lazyinfo) | |
1524 | { | |
1525 | DYLD_NO_LOCK_THIS_BLOCK; | |
1526 | static void* (*p)(void*, long) = NULL; | |
1527 | ||
1528 | if(p == NULL) | |
1529 | _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p); | |
1530 | return p(loadercache, lazyinfo); | |
1531 | } | |
1532 | #endif | |
1533 | ||
1534 | ||
1535 | const char* dyld_image_path_containing_address(const void* addr) | |
1536 | { | |
1537 | DYLD_NO_LOCK_THIS_BLOCK; | |
1538 | static const char* (*p)(const void*) = NULL; | |
0959b6d4 | 1539 | |
39a8cd10 A |
1540 | if(p == NULL) |
1541 | _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p); | |
1542 | return p(addr); | |
1543 | } | |
0959b6d4 | 1544 | |
df9d6cf7 A |
1545 | const struct mach_header* dyld_image_header_containing_address(const void* addr) |
1546 | { | |
1547 | DYLD_NO_LOCK_THIS_BLOCK; | |
1548 | static const mach_header* (*p)(const void*) = NULL; | |
1549 | ||
1550 | if(p == NULL) | |
1551 | _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p); | |
1552 | return p(addr); | |
1553 | } | |
1554 | ||
1555 | ||
412ebb8e A |
1556 | bool dyld_shared_cache_some_image_overridden() |
1557 | { | |
1558 | DYLD_NO_LOCK_THIS_BLOCK; | |
1559 | static bool (*p)() = NULL; | |
1560 | ||
1561 | if(p == NULL) | |
1562 | _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p); | |
1563 | return p(); | |
1564 | } | |
412ebb8e A |
1565 | |
1566 | ||
2fd3f4e8 A |
1567 | bool dyld_process_is_restricted() |
1568 | { | |
1569 | DYLD_NO_LOCK_THIS_BLOCK; | |
1570 | static bool (*p)() = NULL; | |
1571 | ||
1572 | if(p == NULL) | |
1573 | _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p); | |
1574 | return p(); | |
1575 | } | |
1576 | ||
df9d6cf7 A |
1577 | #if DYLD_SHARED_CACHE_SUPPORT |
1578 | const char* dyld_shared_cache_file_path() | |
1579 | { | |
1580 | DYLD_NO_LOCK_THIS_BLOCK; | |
1581 | static const char* (*p)() = NULL; | |
1582 | ||
1583 | if(p == NULL) | |
1584 | _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p); | |
1585 | return p(); | |
1586 | } | |
1587 | #endif | |
2fd3f4e8 | 1588 | |
19894a12 A |
1589 | void dyld_dynamic_interpose(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count) |
1590 | { | |
1591 | DYLD_LOCK_THIS_BLOCK; | |
1592 | static void (*p)(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count) = NULL; | |
1593 | ||
1594 | if (p == NULL) | |
1595 | _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p); | |
1596 | p(mh, array, count); | |
1597 | } | |
2fd3f4e8 A |
1598 | |
1599 | ||
412ebb8e A |
1600 | // SPI called __fork |
1601 | void _dyld_fork_child() | |
1602 | { | |
1603 | DYLD_NO_LOCK_THIS_BLOCK; | |
1604 | static void (*p)() = NULL; | |
1605 | ||
1606 | if(p == NULL) | |
1607 | _dyld_func_lookup("__dyld_fork_child", (void**)&p); | |
1608 | return p(); | |
1609 | } | |
1610 | ||
1611 | ||
1612 | ||
0959b6d4 | 1613 |