dyld-640.2.tar.gz
[apple/dyld.git] / src / dyldAPIsInLibSystem.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
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>
27 #include <malloc/malloc.h>
28 #include <sys/mman.h>
29 #include <execinfo.h>
30
31 #include <System/sys/csr.h>
32 #include <crt_externs.h>
33 #include <Availability.h>
34 #include <vproc_priv.h>
35
36 #include <dirent.h>
37 #include <sys/stat.h>
38
39 #include "mach-o/dyld_images.h"
40 #include "mach-o/dyld.h"
41 #include "mach-o/dyld_priv.h"
42 #include "dyld_cache_format.h"
43
44 #include "ImageLoader.h"
45 #include "dyldLock.h"
46
47 #include "../dyld3/APIs.h"
48 #include "../dyld3/AllImages.h"
49 #include "../dyld3/StartGlue.h"
50 #include "../dyld3/Tracing.h"
51
52
53 // this was in dyld_priv.h but it is no longer exported
54 extern "C" {
55 const struct dyld_all_image_infos* _dyld_get_all_image_infos() __attribute__((visibility("hidden")));
56 }
57
58
59 extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
60 extern "C" void __cxa_finalize(const void *dso);
61 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges[], int count);
62
63 //
64 // private interface between libSystem.dylib and dyld
65 //
66 extern "C" int _dyld_func_lookup(const char* dyld_func_name, void **address);
67
68
69 extern bool gUseDyld3;
70
71 #ifndef LC_VERSION_MIN_MACOSX
72 #define LC_VERSION_MIN_MACOSX 0x24
73 struct version_min_command {
74 uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
75 LC_VERSION_MIN_IPHONEOS */
76 uint32_t cmdsize; /* sizeof(struct min_version_command) */
77 uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
78 uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
79 };
80 #endif
81
82 #ifndef LC_VERSION_MIN_IPHONEOS
83 #define LC_VERSION_MIN_IPHONEOS 0x25
84 #endif
85
86 #ifndef LC_VERSION_MIN_TVOS
87 #define LC_VERSION_MIN_TVOS 0x2F
88 #endif
89
90 #ifndef LC_VERSION_MIN_WATCHOS
91 #define LC_VERSION_MIN_WATCHOS 0x30
92 #endif
93
94
95 #ifndef LC_LOAD_UPWARD_DYLIB
96 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
97 #endif
98
99 #ifndef LC_BUILD_VERSION
100 #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */
101
102 /*
103 * The build_version_command contains the min OS version on which this
104 * binary was built to run for its platform. The list of known platforms and
105 * tool values following it.
106 */
107 struct build_version_command {
108 uint32_t cmd; /* LC_BUILD_VERSION */
109 uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
110 /* ntools * sizeof(struct build_tool_version) */
111 uint32_t platform; /* platform */
112 uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
113 uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
114 uint32_t ntools; /* number of tool entries following this */
115 };
116
117 struct build_tool_version {
118 uint32_t tool; /* enum for the tool */
119 uint32_t version; /* version number of the tool */
120 };
121
122 /* Known values for the platform field above. */
123 #define PLATFORM_MACOS 1
124 #define PLATFORM_IOS 2
125 #define PLATFORM_TVOS 3
126 #define PLATFORM_WATCHOS 4
127 #define PLATFORM_BRIDGEOS 5
128
129 /* Known values for the tool field above. */
130 #define TOOL_CLANG 1
131 #define TOOL_SWIFT 2
132 #define TOOL_LD 3
133 #endif
134
135 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
136 #if __IPHONE_OS_VERSION_MIN_REQUIRED
137 #define DEPRECATED_APIS_SUPPORTED 0
138 #else
139 #define DEPRECATED_APIS_SUPPORTED 1
140 #endif
141
142 /*
143 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
144 * libraryName (which is -lx or -framework Foo argument passed to the static
145 * link editor for the same library) and determines if they match. This depends
146 * on conventional use of names including major versioning.
147 */
148 static
149 bool
150 names_match(
151 const char *install_name,
152 const char* libraryName)
153 {
154 const char *basename;
155 unsigned long n;
156
157 /*
158 * Conventional install names have these forms:
159 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
160 * /Local/Library/Frameworks/AppKit.framework/Appkit
161 * /lib/libsys_s.A.dylib
162 * /usr/lib/libsys_s.dylib
163 */
164 basename = strrchr(install_name, '/');
165 if(basename == NULL)
166 basename = install_name;
167 else
168 basename++;
169
170 /*
171 * By checking the base name matching the library name we take care
172 * of the -framework cases.
173 */
174 if(strcmp(basename, libraryName) == 0)
175 return true;
176
177 /*
178 * Now check the base name for "lib" if so proceed to check for the
179 * -lx case dealing with a possible .X.dylib and a .dylib extension.
180 */
181 if(strncmp(basename, "lib", 3) ==0){
182 n = strlen(libraryName);
183 if(strncmp(basename+3, libraryName, n) == 0){
184 if(strncmp(basename+3+n, ".dylib", 6) == 0)
185 return true;
186 if(basename[3+n] == '.' &&
187 basename[3+n+1] != '\0' &&
188 strncmp(basename+3+n+2, ".dylib", 6) == 0)
189 return true;
190 }
191 }
192 return false;
193 }
194
195 #if DEPRECATED_APIS_SUPPORTED
196
197 void NSInstallLinkEditErrorHandlers(
198 const NSLinkEditErrorHandlers* handlers)
199 {
200 if ( gUseDyld3 )
201 return dyld3::NSInstallLinkEditErrorHandlers(handlers);
202
203 DYLD_LOCK_THIS_BLOCK;
204 typedef void (*ucallback_t)(const char* symbol_name);
205 typedef NSModule (*mcallback_t)(NSSymbol s, NSModule old, NSModule newhandler);
206 typedef void (*lcallback_t)(NSLinkEditErrors c, int errorNumber,
207 const char* fileName, const char* errorString);
208 static void (*p)(ucallback_t undefined, mcallback_t multiple, lcallback_t linkEdit) = NULL;
209
210 if(p == NULL)
211 _dyld_func_lookup("__dyld_install_handlers", (void**)&p);
212 mcallback_t m = handlers->multiple;
213 p(handlers->undefined, m, handlers->linkEdit);
214 }
215
216 const char*
217 NSNameOfModule(
218 NSModule module)
219 {
220 if ( gUseDyld3 )
221 return dyld3::NSNameOfModule(module);
222
223 DYLD_LOCK_THIS_BLOCK;
224 static const char* (*p)(NSModule module) = NULL;
225
226 if(p == NULL)
227 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p);
228 return(p(module));
229 }
230
231 const char*
232 NSLibraryNameForModule(
233 NSModule module)
234 {
235 if ( gUseDyld3 )
236 return dyld3::NSLibraryNameForModule(module);
237
238 DYLD_LOCK_THIS_BLOCK;
239 static const char* (*p)(NSModule module) = NULL;
240
241 if(p == NULL)
242 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p);
243 return(p(module));
244 }
245
246 bool
247 NSIsSymbolNameDefined(
248 const char* symbolName)
249 {
250 if ( gUseDyld3 )
251 return dyld3::NSIsSymbolNameDefined(symbolName);
252
253 DYLD_LOCK_THIS_BLOCK;
254 static bool (*p)(const char* symbolName) = NULL;
255
256 if(p == NULL)
257 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p);
258 return(p(symbolName));
259 }
260
261 bool
262 NSIsSymbolNameDefinedWithHint(
263 const char* symbolName,
264 const char* libraryNameHint)
265 {
266 if ( gUseDyld3 )
267 return dyld3::NSIsSymbolNameDefinedWithHint(symbolName, libraryNameHint);
268
269 DYLD_LOCK_THIS_BLOCK;
270 static bool (*p)(const char* symbolName,
271 const char* libraryNameHint) = NULL;
272
273 if(p == NULL)
274 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p);
275 return(p(symbolName, libraryNameHint));
276 }
277
278 bool
279 NSIsSymbolNameDefinedInImage(
280 const struct mach_header *image,
281 const char* symbolName)
282 {
283 if ( gUseDyld3 )
284 return dyld3::NSIsSymbolNameDefinedInImage(image, symbolName);
285
286 DYLD_LOCK_THIS_BLOCK;
287 static bool (*p)(const struct mach_header *image,
288 const char* symbolName) = NULL;
289
290 if(p == NULL)
291 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p);
292 return(p(image, symbolName));
293 }
294
295 NSSymbol
296 NSLookupAndBindSymbol(
297 const char* symbolName)
298 {
299 if ( gUseDyld3 )
300 return dyld3::NSLookupAndBindSymbol(symbolName);
301
302 DYLD_LOCK_THIS_BLOCK;
303 static NSSymbol (*p)(const char* symbolName) = NULL;
304
305 if(p == NULL)
306 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p);
307 return(p(symbolName));
308 }
309
310 NSSymbol
311 NSLookupAndBindSymbolWithHint(
312 const char* symbolName,
313 const char* libraryNameHint)
314 {
315 if ( gUseDyld3 )
316 return dyld3::NSLookupAndBindSymbolWithHint(symbolName, libraryNameHint);
317
318 DYLD_LOCK_THIS_BLOCK;
319 static NSSymbol (*p)(const char* symbolName,
320 const char* libraryNameHint) = NULL;
321
322 if(p == NULL)
323 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p);
324 return(p(symbolName, libraryNameHint));
325 }
326
327 NSSymbol
328 NSLookupSymbolInModule(
329 NSModule module,
330 const char* symbolName)
331 {
332 if ( gUseDyld3 )
333 return dyld3::NSLookupSymbolInModule(module, symbolName);
334
335 DYLD_LOCK_THIS_BLOCK;
336 static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL;
337
338 if(p == NULL)
339 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p);
340 return(p(module, symbolName));
341 }
342
343 NSSymbol
344 NSLookupSymbolInImage(
345 const struct mach_header *image,
346 const char* symbolName,
347 uint32_t options)
348 {
349 if ( gUseDyld3 )
350 return dyld3::NSLookupSymbolInImage(image, symbolName, options);
351
352 DYLD_LOCK_THIS_BLOCK;
353 static NSSymbol (*p)(const struct mach_header *image,
354 const char* symbolName,
355 uint32_t options) = NULL;
356
357 if(p == NULL)
358 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p);
359 return(p(image, symbolName, options));
360 }
361
362 const char*
363 NSNameOfSymbol(
364 NSSymbol symbol)
365 {
366 if ( gUseDyld3 )
367 return dyld3::NSNameOfSymbol(symbol);
368
369 DYLD_LOCK_THIS_BLOCK;
370 static char * (*p)(NSSymbol symbol) = NULL;
371
372 if(p == NULL)
373 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p);
374 return(p(symbol));
375 }
376
377 void *
378 NSAddressOfSymbol(
379 NSSymbol symbol)
380 {
381 if ( gUseDyld3 )
382 return dyld3::NSAddressOfSymbol(symbol);
383
384 DYLD_LOCK_THIS_BLOCK;
385 static void * (*p)(NSSymbol symbol) = NULL;
386
387 if(p == NULL)
388 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p);
389 return(p(symbol));
390 }
391
392 NSModule
393 NSModuleForSymbol(
394 NSSymbol symbol)
395 {
396 if ( gUseDyld3 )
397 return dyld3::NSModuleForSymbol(symbol);
398
399 DYLD_LOCK_THIS_BLOCK;
400 static NSModule (*p)(NSSymbol symbol) = NULL;
401
402 if(p == NULL)
403 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p);
404 return(p(symbol));
405 }
406
407 bool
408 NSAddLibrary(
409 const char* pathName)
410 {
411 if ( gUseDyld3 )
412 return dyld3::NSAddLibrary(pathName);
413
414 DYLD_LOCK_THIS_BLOCK;
415 static bool (*p)(const char* pathName) = NULL;
416
417 if(p == NULL)
418 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p);
419 return(p(pathName));
420 }
421
422 bool
423 NSAddLibraryWithSearching(
424 const char* pathName)
425 {
426 if ( gUseDyld3 )
427 return dyld3::NSAddLibrary(pathName);
428
429 DYLD_LOCK_THIS_BLOCK;
430 static bool (*p)(const char* pathName) = NULL;
431
432 if(p == NULL)
433 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p);
434 return(p(pathName));
435 }
436
437 const struct mach_header *
438 NSAddImage(
439 const char* image_name,
440 uint32_t options)
441 {
442 if ( gUseDyld3 )
443 return dyld3::NSAddImage(image_name, options);
444
445 DYLD_LOCK_THIS_BLOCK;
446 static const struct mach_header * (*p)(const char* image_name,
447 uint32_t options) = NULL;
448
449 if(p == NULL)
450 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p);
451 return(p(image_name, options));
452 }
453 #endif // DEPRECATED_APIS_SUPPORTED
454
455 /*
456 * This routine returns the current version of the named shared library the
457 * executable it was built with. The libraryName parameter is the same as the
458 * -lx or -framework Foo argument passed to the static link editor when building
459 * the executable (with -lx it would be "x" and with -framework Foo it would be
460 * "Foo"). If this the executable was not built against the specified library
461 * it returns -1. It should be noted that if this only returns the value the
462 * current version of the named shared library the executable was built with
463 * and not a list of current versions that dependent libraries and bundles the
464 * program is using were built with.
465 */
466 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName)
467 {
468 if ( gUseDyld3 )
469 return dyld3::NSVersionOfLinkTimeLibrary(libraryName);
470
471 // Lazily call _NSGetMachExecuteHeader() and cache result
472 #if __LP64__
473 static mach_header_64* mh = NULL;
474 #else
475 static mach_header* mh = NULL;
476 #endif
477 if ( mh == NULL )
478 mh = _NSGetMachExecuteHeader();
479 #if __LP64__
480 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64));
481 #else
482 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header));
483 #endif
484 for(uint32_t i = 0; i < mh->ncmds; i++){
485 switch ( lc->cmd ) {
486 case LC_LOAD_DYLIB:
487 case LC_LOAD_WEAK_DYLIB:
488 case LC_LOAD_UPWARD_DYLIB:
489 const dylib_command* dl = (dylib_command *)lc;
490 const char* install_name = (char*)dl + dl->dylib.name.offset;
491 if ( names_match(install_name, libraryName) )
492 return dl->dylib.current_version;
493 break;
494 }
495 lc = (load_command*)((char*)lc + lc->cmdsize);
496 }
497 return (-1);
498 }
499
500 /*
501 * This routine returns the current version of the named shared library the
502 * program it is running against. The libraryName parameter is the same as
503 * would be static link editor using the -lx or -framework Foo flags (with -lx
504 * it would be "x" and with -framework Foo it would be "Foo"). If the program
505 * is not using the specified library it returns -1.
506 */
507 int32_t NSVersionOfRunTimeLibrary(const char* libraryName)
508 {
509 if ( gUseDyld3 )
510 return dyld3::NSVersionOfRunTimeLibrary(libraryName);
511
512 uint32_t n = _dyld_image_count();
513 for(uint32_t i = 0; i < n; i++){
514 const mach_header* mh = _dyld_get_image_header(i);
515 if ( mh == NULL )
516 continue;
517 if ( mh->filetype != MH_DYLIB )
518 continue;
519 #if __LP64__
520 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header_64));
521 #else
522 const load_command* lc = (load_command*)((char*)mh + sizeof(mach_header));
523 #endif
524 for(uint32_t j = 0; j < mh->ncmds; j++){
525 if ( lc->cmd == LC_ID_DYLIB ) {
526 const dylib_command* dl = (dylib_command*)lc;
527 const char* install_name = (char *)dl + dl->dylib.name.offset;
528 if ( names_match(install_name, libraryName) )
529 return dl->dylib.current_version;
530 }
531 lc = (load_command*)((char*)lc + lc->cmdsize);
532 }
533 }
534 return (-1);
535 }
536
537 #if TARGET_OS_WATCH
538 uint32_t dyld_get_program_sdk_watch_os_version()
539 {
540 if (gUseDyld3)
541 return dyld3::dyld_get_program_sdk_watch_os_version();
542
543 __block uint32_t retval = 0;
544 __block bool versionFound = false;
545 dyld3::dyld_get_image_versions((mach_header*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version) {
546 if (versionFound) return;
547
548 if (dyld_get_base_platform(platform) == PLATFORM_WATCHOS) {
549 versionFound = true;
550 retval = sdk_version;
551 }
552 });
553
554 return retval;
555 }
556
557 uint32_t dyld_get_program_min_watch_os_version()
558 {
559 if (gUseDyld3)
560 return dyld3::dyld_get_program_min_watch_os_version();
561
562 __block uint32_t retval = 0;
563 __block bool versionFound = false;
564 dyld3::dyld_get_image_versions((mach_header*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version) {
565 if (versionFound) return;
566
567 if (dyld_get_base_platform(platform) == PLATFORM_WATCHOS) {
568 versionFound = true;
569 retval = min_version;
570 }
571 });
572
573 return retval;
574 }
575 #endif
576
577 #if TARGET_OS_BRIDGE
578 uint32_t dyld_get_program_sdk_bridge_os_version()
579 {
580 if (gUseDyld3)
581 return dyld3::dyld_get_program_sdk_bridge_os_version();
582
583 __block uint32_t retval = 0;
584 __block bool versionFound = false;
585 dyld3::dyld_get_image_versions((mach_header*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version) {
586 if (versionFound) return;
587
588 if (dyld_get_base_platform(platform) == PLATFORM_BRIDGEOS) {
589 versionFound = true;
590 retval = sdk_version;
591 }
592 });
593
594 return retval;
595 }
596
597 uint32_t dyld_get_program_min_bridge_os_version()
598 {
599 if (gUseDyld3)
600 return dyld3::dyld_get_program_min_bridge_os_version();
601
602 __block uint32_t retval = 0;
603 __block bool versionFound = false;
604 dyld3::dyld_get_image_versions((mach_header*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version) {
605 if (versionFound) return;
606
607 if (dyld_get_base_platform(platform) == PLATFORM_BRIDGEOS) {
608 versionFound = true;
609 retval = min_version;
610 }
611 });
612
613 return retval;
614 }
615 #endif
616
617 /*
618 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
619 * specified binary was built against.
620 *
621 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
622 * not zero, return that value.
623 * Otherwise, looks for the libSystem.B.dylib the binary linked
624 * against and uses a table to convert that to an sdk version.
625 */
626 uint32_t dyld_get_sdk_version(const mach_header* mh)
627 {
628 return dyld3::dyld_get_sdk_version(mh);
629 }
630
631 uint32_t dyld_get_program_sdk_version()
632 {
633 return dyld3::dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader());
634 }
635
636 uint32_t dyld_get_min_os_version(const struct mach_header* mh)
637 {
638 return dyld3::dyld_get_min_os_version(mh);
639 }
640
641
642 uint32_t dyld_get_program_min_os_version()
643 {
644 return dyld3::dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader());
645 }
646
647
648 bool _dyld_get_image_uuid(const struct mach_header* mh, uuid_t uuid)
649 {
650 if ( gUseDyld3 )
651 return dyld3::_dyld_get_image_uuid(mh, uuid);
652
653 const load_command* startCmds = NULL;
654 if ( mh->magic == MH_MAGIC_64 )
655 startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
656 else if ( mh->magic == MH_MAGIC )
657 startCmds = (load_command*)((char *)mh + sizeof(mach_header));
658 else
659 return false; // not a mach-o file, or wrong endianness
660
661 const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
662 const load_command* cmd = startCmds;
663 for(uint32_t i = 0; i < mh->ncmds; ++i) {
664 const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
665 if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) {
666 return false;
667 }
668 if ( cmd->cmd == LC_UUID ) {
669 const uuid_command* uuidCmd = (uuid_command*)cmd;
670 memcpy(uuid, uuidCmd->uuid, 16);
671 return true;
672 }
673 cmd = nextCmd;
674 }
675 bzero(uuid, 16);
676 return false;
677 }
678
679 dyld_platform_t dyld_get_active_platform(void) {
680 if (gUseDyld3)
681 return dyld3::dyld_get_active_platform();
682
683 // HACK
684 // Most of the new version SPIs have pure dyld3 implementations, but
685 // They cannot get to the main executable, so we implement this here
686 // and they can use this by calling ::dyld_get_active_platform() in the root namespace
687 static dyld_platform_t sActivePlatform = 0;
688 if (sActivePlatform) return sActivePlatform;
689
690 dyld3::dyld_get_image_versions((mach_header*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version) {
691 sActivePlatform = platform;
692 //FIXME assert there is only one?
693 });
694 return sActivePlatform;
695 }
696
697 dyld_platform_t dyld_get_base_platform(dyld_platform_t platform) {
698 return dyld3::dyld_get_base_platform(platform);
699 }
700
701 bool dyld_is_simulator_platform(dyld_platform_t platform) {
702 return dyld3::dyld_is_simulator_platform(platform);
703 }
704
705 bool dyld_sdk_at_least(const struct mach_header* mh, dyld_build_version_t version) {
706 return dyld3::dyld_sdk_at_least(mh, version);
707 }
708
709 bool dyld_minos_at_least(const struct mach_header* mh, dyld_build_version_t version) {
710 return dyld3::dyld_minos_at_least(mh, version);
711 }
712
713 bool dyld_program_sdk_at_least(dyld_build_version_t version) {
714 return dyld3::dyld_sdk_at_least((mach_header*)_NSGetMachExecuteHeader(),version);
715 }
716
717 bool dyld_program_minos_at_least(dyld_build_version_t version) {
718 return dyld3::dyld_minos_at_least((mach_header*)_NSGetMachExecuteHeader(), version);
719 }
720
721 // Function that walks through the load commands and calls the internal block for every version found
722 // Intended as a fallback for very complex (and rare) version checks, or for tools that need to
723 // print our everything for diagnostic reasons
724 void dyld_get_image_versions(const struct mach_header* mh, void (^callback)(dyld_platform_t platform, uint32_t sdk_version, uint32_t min_version)) {
725 dyld3::dyld_get_image_versions(mh, callback);
726 }
727
728
729
730 #if DEPRECATED_APIS_SUPPORTED
731 /*
732 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
733 * specified file name if the file is a correct Mach-O file that can be loaded
734 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
735 * NSObjectFileImageFormat an error message is printed to stderr. All
736 * other codes cause no printing.
737 */
738 NSObjectFileImageReturnCode
739 NSCreateObjectFileImageFromFile(
740 const char* pathName,
741 NSObjectFileImage *objectFileImage)
742 {
743 if ( gUseDyld3 )
744 return dyld3::NSCreateObjectFileImageFromFile(pathName, objectFileImage);
745
746 DYLD_LOCK_THIS_BLOCK;
747 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
748
749 if(p == NULL)
750 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
751 return p(pathName, objectFileImage);
752 }
753
754
755 /*
756 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
757 * object file mapped into memory at address of size length if the object file
758 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
759 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
760 * message is printed to stderr. All other codes cause no printing.
761 */
762 NSObjectFileImageReturnCode
763 NSCreateObjectFileImageFromMemory(
764 const void* address,
765 size_t size,
766 NSObjectFileImage *objectFileImage)
767 {
768 if ( gUseDyld3 )
769 return dyld3::NSCreateObjectFileImageFromMemory(address, size, objectFileImage);
770
771 DYLD_LOCK_THIS_BLOCK;
772 static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
773
774 if(p == NULL)
775 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
776 return p(address, size, objectFileImage);
777 }
778
779 #if OBSOLETE_DYLD_API
780 /*
781 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
782 * specified core file name if the file is a correct Mach-O core file.
783 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
784 * an error message is printed to stderr. All other codes cause no printing.
785 */
786 NSObjectFileImageReturnCode
787 NSCreateCoreFileImageFromFile(
788 const char* pathName,
789 NSObjectFileImage *objectFileImage)
790 {
791 DYLD_LOCK_THIS_BLOCK;
792 static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
793
794 if(p == NULL)
795 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
796 return p(pathName, objectFileImage);
797 }
798 #endif
799
800 bool
801 NSDestroyObjectFileImage(
802 NSObjectFileImage objectFileImage)
803 {
804 if ( gUseDyld3 )
805 return dyld3::NSDestroyObjectFileImage(objectFileImage);
806
807 DYLD_LOCK_THIS_BLOCK;
808 static bool (*p)(NSObjectFileImage) = NULL;
809
810 if(p == NULL)
811 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
812 return p(objectFileImage);
813 }
814
815
816 NSModule
817 NSLinkModule(
818 NSObjectFileImage objectFileImage,
819 const char* moduleName,
820 uint32_t options)
821 {
822 if ( gUseDyld3 )
823 return dyld3::NSLinkModule(objectFileImage, moduleName, options);
824
825 DYLD_LOCK_THIS_BLOCK;
826 static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
827
828 if(p == NULL)
829 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
830
831 return p(objectFileImage, moduleName, options);
832 }
833
834
835
836
837 /*
838 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
839 * definitions in the NSObjectFileImage.
840 */
841 uint32_t
842 NSSymbolDefinitionCountInObjectFileImage(
843 NSObjectFileImage objectFileImage)
844 {
845 if ( gUseDyld3 )
846 return dyld3::NSSymbolDefinitionCountInObjectFileImage(objectFileImage);
847
848 DYLD_LOCK_THIS_BLOCK;
849 static uint32_t (*p)(NSObjectFileImage) = NULL;
850
851 if(p == NULL)
852 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
853
854 return p(objectFileImage);
855 }
856
857 /*
858 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
859 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
860 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
861 * be returned.
862 */
863 const char*
864 NSSymbolDefinitionNameInObjectFileImage(
865 NSObjectFileImage objectFileImage,
866 uint32_t ordinal)
867 {
868 if ( gUseDyld3 )
869 return dyld3::NSSymbolDefinitionNameInObjectFileImage(objectFileImage, ordinal);
870
871 DYLD_LOCK_THIS_BLOCK;
872 static const char* (*p)(NSObjectFileImage, uint32_t) = NULL;
873
874 if(p == NULL)
875 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
876
877 return p(objectFileImage, ordinal);
878 }
879
880 /*
881 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
882 * to undefined symbols the NSObjectFileImage.
883 */
884 uint32_t
885 NSSymbolReferenceCountInObjectFileImage(
886 NSObjectFileImage objectFileImage)
887 {
888 if ( gUseDyld3 )
889 return dyld3::NSSymbolReferenceCountInObjectFileImage(objectFileImage);
890
891 DYLD_LOCK_THIS_BLOCK;
892 static uint32_t (*p)(NSObjectFileImage) = NULL;
893
894 if(p == NULL)
895 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
896
897 return p(objectFileImage);
898 }
899
900 /*
901 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
902 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
903 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
904 * returned.
905 */
906 const char*
907 NSSymbolReferenceNameInObjectFileImage(
908 NSObjectFileImage objectFileImage,
909 uint32_t ordinal,
910 bool *tentative_definition) /* can be NULL */
911 {
912 if ( gUseDyld3 )
913 return dyld3::NSSymbolReferenceNameInObjectFileImage(objectFileImage, ordinal, tentative_definition);
914
915 DYLD_LOCK_THIS_BLOCK;
916 static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
917
918 if(p == NULL)
919 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
920
921 return p(objectFileImage, ordinal, tentative_definition);
922 }
923
924 /*
925 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
926 * name has a definition in the NSObjectFileImage and FALSE otherwise.
927 */
928 bool
929 NSIsSymbolDefinedInObjectFileImage(
930 NSObjectFileImage objectFileImage,
931 const char* symbolName)
932 {
933 if ( gUseDyld3 )
934 return dyld3::NSIsSymbolDefinedInObjectFileImage(objectFileImage, symbolName);
935
936 DYLD_LOCK_THIS_BLOCK;
937 static bool (*p)(NSObjectFileImage, const char*) = NULL;
938
939 if(p == NULL)
940 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
941
942 return p(objectFileImage, symbolName);
943 }
944
945 /*
946 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
947 * in the NSObjectFileImage for the specified segmentName and sectionName if
948 * it exists and it is not a zerofill section. If not it returns NULL. If
949 * the parameter size is not NULL the size of the section is also returned
950 * indirectly through that pointer.
951 */
952 void *
953 NSGetSectionDataInObjectFileImage(
954 NSObjectFileImage objectFileImage,
955 const char* segmentName,
956 const char* sectionName,
957 unsigned long *size) /* can be NULL */
958 {
959 if ( gUseDyld3 )
960 return dyld3::NSGetSectionDataInObjectFileImage(objectFileImage, segmentName, sectionName, size);
961
962 DYLD_LOCK_THIS_BLOCK;
963 static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
964
965 if(p == NULL)
966 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
967
968 return p(objectFileImage, segmentName, sectionName, size);
969 }
970
971
972 void
973 NSLinkEditError(
974 NSLinkEditErrors *c,
975 int *errorNumber,
976 const char* *fileName,
977 const char* *errorString)
978 {
979 if ( gUseDyld3 )
980 return dyld3::NSLinkEditError(c, errorNumber, fileName, errorString);
981
982 DYLD_LOCK_THIS_BLOCK;
983 static void (*p)(NSLinkEditErrors *c,
984 int *errorNumber,
985 const char* *fileName,
986 const char* *errorString) = NULL;
987
988 if(p == NULL)
989 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
990 if(p != NULL)
991 p(c, errorNumber, fileName, errorString);
992 }
993
994 bool
995 NSUnLinkModule(
996 NSModule module,
997 uint32_t options)
998 {
999 if ( gUseDyld3 )
1000 return dyld3::NSUnLinkModule(module, options);
1001
1002 DYLD_LOCK_THIS_BLOCK;
1003 static bool (*p)(NSModule module, uint32_t options) = NULL;
1004
1005 if(p == NULL)
1006 _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
1007
1008 return p(module, options);
1009 }
1010
1011 #if OBSOLETE_DYLD_API
1012 NSModule
1013 NSReplaceModule(
1014 NSModule moduleToReplace,
1015 NSObjectFileImage newObjectFileImage,
1016 uint32_t options)
1017 {
1018 return(NULL);
1019 }
1020 #endif
1021
1022
1023 #endif // DEPRECATED_APIS_SUPPORTED
1024
1025 /*
1026 *_NSGetExecutablePath copies the path of the executable into the buffer and
1027 * returns 0 if the path was successfully copied in the provided buffer. If the
1028 * buffer is not large enough, -1 is returned and the expected buffer size is
1029 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
1030 * the executable not a "real path" to the executable. That is the path may be
1031 * a symbolic link and not the real file. And with deep directories the total
1032 * bufsize needed could be more than MAXPATHLEN.
1033 */
1034 int
1035 _NSGetExecutablePath(
1036 char *buf,
1037 uint32_t *bufsize)
1038 {
1039 if ( gUseDyld3 )
1040 return dyld3::_NSGetExecutablePath(buf, bufsize);
1041
1042 DYLD_NO_LOCK_THIS_BLOCK;
1043 static int (*p)(char *buf, uint32_t *bufsize) = NULL;
1044
1045 if(p == NULL)
1046 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
1047 return(p(buf, bufsize));
1048 }
1049
1050 #if DEPRECATED_APIS_SUPPORTED
1051 void
1052 _dyld_lookup_and_bind(
1053 const char* symbol_name,
1054 void** address,
1055 NSModule* module)
1056 {
1057 DYLD_LOCK_THIS_BLOCK;
1058 static void (*p)(const char*, void** , NSModule*) = NULL;
1059
1060 if(p == NULL)
1061 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
1062 p(symbol_name, address, module);
1063 }
1064
1065 void
1066 _dyld_lookup_and_bind_with_hint(
1067 const char* symbol_name,
1068 const char* library_name_hint,
1069 void** address,
1070 NSModule* module)
1071 {
1072 DYLD_LOCK_THIS_BLOCK;
1073 static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
1074
1075 if(p == NULL)
1076 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
1077 p(symbol_name, library_name_hint, address, module);
1078 }
1079
1080 #if OBSOLETE_DYLD_API
1081 void
1082 _dyld_lookup_and_bind_objc(
1083 const char* symbol_name,
1084 void** address,
1085 NSModule* module)
1086 {
1087 DYLD_LOCK_THIS_BLOCK;
1088 static void (*p)(const char* , void**, NSModule*) = NULL;
1089
1090 if(p == NULL)
1091 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
1092 p(symbol_name, address, module);
1093 }
1094 #endif
1095
1096 void
1097 _dyld_lookup_and_bind_fully(
1098 const char* symbol_name,
1099 void** address,
1100 NSModule* module)
1101 {
1102 DYLD_LOCK_THIS_BLOCK;
1103 static void (*p)(const char*, void**, NSModule*) = NULL;
1104
1105 if(p == NULL)
1106 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
1107 p(symbol_name, address, module);
1108 }
1109
1110 bool
1111 _dyld_bind_fully_image_containing_address(
1112 const void* address)
1113 {
1114 DYLD_LOCK_THIS_BLOCK;
1115 static bool (*p)(const void*) = NULL;
1116
1117 if(p == NULL)
1118 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
1119 return p(address);
1120 }
1121 #endif // DEPRECATED_APIS_SUPPORTED
1122
1123
1124 /*
1125 * _dyld_register_func_for_add_image registers the specified function to be
1126 * called when a new image is added (a bundle or a dynamic shared library) to
1127 * the program. When this function is first registered it is called for once
1128 * for each image that is currently part of the program.
1129 */
1130 void
1131 _dyld_register_func_for_add_image(
1132 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1133 {
1134 if ( gUseDyld3 )
1135 return dyld3::_dyld_register_func_for_add_image(func);
1136
1137 DYLD_LOCK_THIS_BLOCK;
1138 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
1139 static void (*p)(callback_t func) = NULL;
1140
1141 if(p == NULL)
1142 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
1143 p(func);
1144 }
1145
1146 /*
1147 * _dyld_register_func_for_remove_image registers the specified function to be
1148 * called when an image is removed (a bundle or a dynamic shared library) from
1149 * the program.
1150 */
1151 void
1152 _dyld_register_func_for_remove_image(
1153 void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1154 {
1155 if ( gUseDyld3 )
1156 return dyld3::_dyld_register_func_for_remove_image(func);
1157
1158 DYLD_LOCK_THIS_BLOCK;
1159 typedef void (*callback_t)(const struct mach_header *mh, intptr_t vmaddr_slide);
1160 static void (*p)(callback_t func) = NULL;
1161
1162 if(p == NULL)
1163 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
1164 p(func);
1165 }
1166
1167 #if OBSOLETE_DYLD_API
1168 /*
1169 * _dyld_register_func_for_link_module registers the specified function to be
1170 * called when a module is bound into the program. When this function is first
1171 * registered it is called for once for each module that is currently bound into
1172 * the program.
1173 */
1174 void
1175 _dyld_register_func_for_link_module(
1176 void (*func)(NSModule module))
1177 {
1178 DYLD_LOCK_THIS_BLOCK;
1179 static void (*p)(void (*func)(NSModule module)) = NULL;
1180
1181 if(p == NULL)
1182 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
1183 p(func);
1184 }
1185
1186 /*
1187 * _dyld_register_func_for_unlink_module registers the specified function to be
1188 * called when a module is unbound from the program.
1189 */
1190 void
1191 _dyld_register_func_for_unlink_module(
1192 void (*func)(NSModule module))
1193 {
1194 DYLD_LOCK_THIS_BLOCK;
1195 static void (*p)(void (*func)(NSModule module)) = NULL;
1196
1197 if(p == NULL)
1198 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
1199 p(func);
1200 }
1201
1202 /*
1203 * _dyld_register_func_for_replace_module registers the specified function to be
1204 * called when a module is to be replace with another module in the program.
1205 */
1206 void
1207 _dyld_register_func_for_replace_module(
1208 void (*func)(NSModule oldmodule, NSModule newmodule))
1209 {
1210 DYLD_LOCK_THIS_BLOCK;
1211 static void (*p)(void (*func)(NSModule oldmodule,
1212 NSModule newmodule)) = NULL;
1213
1214 if(p == NULL)
1215 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
1216 p(func);
1217 }
1218
1219
1220 /*
1221 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1222 * pointer to the (__OBJC,__module) section and its size for the specified
1223 * module.
1224 */
1225 void
1226 _dyld_get_objc_module_sect_for_module(
1227 NSModule module,
1228 void **objc_module,
1229 unsigned long *size)
1230 {
1231 DYLD_LOCK_THIS_BLOCK;
1232 static void (*p)(NSModule module,
1233 void **objc_module,
1234 unsigned long *size) = NULL;
1235
1236 if(p == NULL)
1237 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
1238 p(module, objc_module, size);
1239 }
1240
1241 #endif
1242
1243 #if DEPRECATED_APIS_SUPPORTED
1244 bool
1245 _dyld_present(void)
1246 {
1247 // this function exists for compatiblity only
1248 return true;
1249 }
1250 #endif
1251
1252 uint32_t
1253 _dyld_image_count(void)
1254 {
1255 if ( gUseDyld3 )
1256 return dyld3::_dyld_image_count();
1257
1258 DYLD_NO_LOCK_THIS_BLOCK;
1259 static uint32_t (*p)(void) = NULL;
1260
1261 if(p == NULL)
1262 _dyld_func_lookup("__dyld_image_count", (void**)&p);
1263 return(p());
1264 }
1265
1266 const struct mach_header *
1267 _dyld_get_image_header(uint32_t image_index)
1268 {
1269 if ( gUseDyld3 )
1270 return dyld3::_dyld_get_image_header(image_index);
1271
1272 DYLD_NO_LOCK_THIS_BLOCK;
1273 static struct mach_header * (*p)(uint32_t image_index) = NULL;
1274
1275 if(p == NULL)
1276 _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
1277 return(p(image_index));
1278 }
1279
1280 intptr_t
1281 _dyld_get_image_vmaddr_slide(uint32_t image_index)
1282 {
1283 if ( gUseDyld3 )
1284 return dyld3::_dyld_get_image_vmaddr_slide(image_index);
1285
1286 DYLD_NO_LOCK_THIS_BLOCK;
1287 static unsigned long (*p)(uint32_t image_index) = NULL;
1288
1289 if(p == NULL)
1290 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
1291 return(p(image_index));
1292 }
1293
1294 const char*
1295 _dyld_get_image_name(uint32_t image_index)
1296 {
1297 if ( gUseDyld3 )
1298 return dyld3::_dyld_get_image_name(image_index);
1299
1300 DYLD_NO_LOCK_THIS_BLOCK;
1301 static const char* (*p)(uint32_t image_index) = NULL;
1302
1303 if(p == NULL)
1304 _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
1305 return(p(image_index));
1306 }
1307
1308 // SPI in Mac OS X 10.6
1309 intptr_t _dyld_get_image_slide(const struct mach_header* mh)
1310 {
1311 if ( gUseDyld3 )
1312 return dyld3::_dyld_get_image_slide(mh);
1313
1314 DYLD_NO_LOCK_THIS_BLOCK;
1315 static intptr_t (*p)(const struct mach_header*) = NULL;
1316
1317 if(p == NULL)
1318 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p);
1319 return(p(mh));
1320 }
1321
1322
1323 #if DEPRECATED_APIS_SUPPORTED
1324 bool
1325 _dyld_image_containing_address(const void* address)
1326 {
1327 if ( gUseDyld3 )
1328 return dyld3::_dyld_image_containing_address(address);
1329
1330 DYLD_LOCK_THIS_BLOCK;
1331 static bool (*p)(const void*) = NULL;
1332
1333 if(p == NULL)
1334 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
1335 return(p(address));
1336 }
1337
1338 const struct mach_header *
1339 _dyld_get_image_header_containing_address(
1340 const void* address)
1341 {
1342 if ( gUseDyld3 )
1343 return dyld3::_dyld_get_image_header_containing_address(address);
1344
1345 DYLD_LOCK_THIS_BLOCK;
1346 static const struct mach_header * (*p)(const void*) = NULL;
1347
1348 if(p == NULL)
1349 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1350 return p(address);
1351 }
1352
1353 bool _dyld_launched_prebound(void)
1354 {
1355 DYLD_LOCK_THIS_BLOCK;
1356 static bool (*p)(void) = NULL;
1357
1358 if(p == NULL)
1359 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
1360 return(p());
1361 }
1362
1363 bool _dyld_all_twolevel_modules_prebound(void)
1364 {
1365 DYLD_LOCK_THIS_BLOCK;
1366 static bool (*p)(void) = NULL;
1367
1368 if(p == NULL)
1369 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
1370 return(p());
1371 }
1372 #endif // DEPRECATED_APIS_SUPPORTED
1373
1374
1375 #include <dlfcn.h>
1376 #include <stddef.h>
1377 #include <pthread.h>
1378 #include <stdlib.h>
1379 #include <mach-o/dyld.h>
1380 #include <servers/bootstrap.h>
1381 #include "dyldLibSystemInterface.h"
1382
1383
1384 // pthread key used to access per-thread dlerror message
1385 static pthread_key_t dlerrorPerThreadKey;
1386 static bool dlerrorPerThreadKeyInitialized = false;
1387
1388 // data kept per-thread
1389 struct dlerrorPerThreadData
1390 {
1391 size_t sizeAllocated;
1392 char message[1];
1393 };
1394
1395 // function called by dyld to get buffer to store dlerror message
1396 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired)
1397 {
1398 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1399 if (!dlerrorPerThreadKeyInitialized ) {
1400 // create key and tell pthread package to call free() on any data associated with key if thread dies
1401 pthread_key_create(&dlerrorPerThreadKey, &free);
1402 dlerrorPerThreadKeyInitialized = true;
1403 }
1404
1405 const size_t size = (sizeRequired < 256) ? 256 : sizeRequired;
1406 dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
1407 if ( data == NULL ) {
1408 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1409 const size_t mallocSize = sizeof(dlerrorPerThreadData)+size;
1410 data = (dlerrorPerThreadData*)malloc(mallocSize);
1411 data->sizeAllocated = size;
1412 pthread_setspecific(dlerrorPerThreadKey, data);
1413 }
1414 else if ( data->sizeAllocated < sizeRequired ) {
1415 free(data);
1416 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1417 const size_t mallocSize = sizeof(dlerrorPerThreadData)+size;
1418 data = (dlerrorPerThreadData*)malloc(mallocSize);
1419 data->sizeAllocated = size;
1420 pthread_setspecific(dlerrorPerThreadKey, data);
1421 }
1422 return data->message;
1423 }
1424
1425 // <rdar://problem/10595338> dlerror buffer leak
1426 // Only allocate buffer if an actual error message needs to be set
1427 static bool hasPerThreadBufferFor_dlerror()
1428 {
1429 if (!dlerrorPerThreadKeyInitialized )
1430 return false;
1431
1432 return (pthread_getspecific(dlerrorPerThreadKey) != NULL);
1433 }
1434
1435 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1436 typedef vproc_err_t (*vswapproc)(vproc_t vp, vproc_gsk_t key,int64_t *inval, int64_t *outval);
1437 static vswapproc swapProc = &vproc_swap_integer;
1438
1439 static bool isLaunchdOwned()
1440 {
1441 static bool checked = false;
1442 static bool result = false;
1443 if ( !checked ) {
1444 checked = true;
1445 int64_t val = 0;
1446 (*swapProc)(NULL, VPROC_GSK_IS_MANAGED, NULL, &val);
1447 result = ( val != 0 );
1448 }
1449 return result;
1450 }
1451
1452 static void shared_cache_missing()
1453 {
1454 // leave until dyld's that might call this are rare
1455 }
1456
1457 static void shared_cache_out_of_date()
1458 {
1459 // leave until dyld's that might call this are rare
1460 }
1461
1462
1463 // the table passed to dyld containing thread helpers
1464 static dyld::LibSystemHelpers sHelpers = { 13, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,
1465 &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
1466 &shared_cache_missing, &shared_cache_out_of_date,
1467 NULL, NULL,
1468 &pthread_key_create, &pthread_setspecific,
1469 &malloc_size,
1470 &pthread_getspecific,
1471 &__cxa_finalize,
1472 address_of_start,
1473 &hasPerThreadBufferFor_dlerror,
1474 &isLaunchdOwned,
1475 &vm_allocate,
1476 &mmap,
1477 &__cxa_finalize_ranges
1478 };
1479
1480
1481 //
1482 // during initialization of libSystem this routine will run
1483 // and call dyld, registering the helper functions.
1484 //
1485 extern "C" void tlv_initializer();
1486 void _dyld_initializer()
1487 {
1488 void (*p)(dyld::LibSystemHelpers*);
1489
1490 if ( gUseDyld3 ) {
1491 dyld3::gAllImages.applyInitialImages();
1492 }
1493 else {
1494 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
1495 if(p != NULL)
1496 p(&sHelpers);
1497 }
1498
1499 tlv_initializer();
1500 }
1501
1502
1503 char* dlerror()
1504 {
1505 if ( gUseDyld3 )
1506 return dyld3::dlerror();
1507
1508 DYLD_LOCK_THIS_BLOCK;
1509 static char* (*p)() = NULL;
1510
1511 if(p == NULL)
1512 _dyld_func_lookup("__dyld_dlerror", (void**)&p);
1513 return(p());
1514 }
1515
1516 int dladdr(const void* addr, Dl_info* info)
1517 {
1518 dyld3::ScopedTimer timer(DBG_DYLD_TIMING_DLADDR, (uint64_t)addr, 0, 0);
1519 int result = 0;
1520 if ( gUseDyld3 )
1521 return dyld3::dladdr(addr, info);
1522
1523 DYLD_LOCK_THIS_BLOCK;
1524 static int (*p)(const void* , Dl_info*) = NULL;
1525
1526 if(p == NULL)
1527 _dyld_func_lookup("__dyld_dladdr", (void**)&p);
1528 result = p(addr, info);
1529 timer.setData4(result);
1530 timer.setData5(info != NULL ? info->dli_fbase : 0);
1531 timer.setData6(info != NULL ? info->dli_saddr : 0);
1532 return result;
1533 }
1534
1535 int dlclose(void* handle)
1536 {
1537 dyld3::ScopedTimer timer(DBG_DYLD_TIMING_DLCLOSE, (uint64_t)handle, 0, 0);
1538 int result = 0;
1539 if ( gUseDyld3 )
1540 return dyld3::dlclose(handle);
1541
1542 DYLD_LOCK_THIS_BLOCK;
1543 static int (*p)(void* handle) = NULL;
1544
1545 if(p == NULL)
1546 _dyld_func_lookup("__dyld_dlclose", (void**)&p);
1547 result = p(handle);
1548 return result;
1549 }
1550
1551 void* dlopen(const char* path, int mode)
1552 {
1553 dyld3::ScopedTimer timer(DBG_DYLD_TIMING_DLOPEN, path, mode, 0);
1554 void* result = nullptr;
1555
1556 if ( gUseDyld3 ) {
1557 result = dyld3::dlopen_internal(path, mode, __builtin_return_address(0));
1558 return result;
1559 }
1560
1561 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1562 DYLD_NO_LOCK_THIS_BLOCK;
1563
1564 static void* (*p)(const char* path, int, void*) = NULL;
1565
1566 if(p == NULL)
1567 _dyld_func_lookup("__dyld_dlopen_internal", (void**)&p);
1568 result = p(path, mode, __builtin_return_address(0));
1569 // use asm block to prevent tail call optimization
1570 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1571 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1572 __asm__ volatile("");
1573 timer.setData4(result);
1574
1575 #if TARGET_OS_OSX
1576 // HACK for iOSMac bringup rdar://40945421
1577 if ( result == nullptr && dyld_get_active_platform() == PLATFORM_IOSMAC && csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0) {
1578 if (hasPerThreadBufferFor_dlerror()) {
1579 // first char of buffer is flag whether string (starting at second char) is valid
1580 char* buffer = getPerThreadBufferFor_dlerror(2);
1581
1582 if ( buffer[0] != '\0' && (strstr(&buffer[1], "macOS dylib cannot be loaded into iOSMac process")
1583 || strstr(&buffer[1], "mach-o, but not built for iOSMac")) ) {
1584 // if valid buffer and contains an iOSMac issue
1585 fprintf(stderr, "dyld: iOSMac ERROR: process attempted to dlopen() dylib with macOS dependency: \n");
1586 fprintf(stderr, "\tdlerror: %s\n", &buffer[1]);
1587 fprintf(stderr, "\tBacktrace:\n");
1588
1589 void* stackPointers[128];
1590 int stackPointersCnt = backtrace(stackPointers, 128);
1591 char** symbolicatedStack = backtrace_symbols(stackPointers, stackPointersCnt);
1592 for (int32_t i = 0; i < stackPointersCnt; ++i) {
1593 fprintf(stderr, "\t\t%s\n", symbolicatedStack[i]);
1594 }
1595 free(symbolicatedStack);
1596 }
1597 }
1598 }
1599 #endif
1600
1601 return result;
1602 }
1603
1604 bool dlopen_preflight(const char* path)
1605 {
1606 dyld3::ScopedTimer timer(DBG_DYLD_TIMING_DLOPEN_PREFLIGHT, path, 0, 0);
1607 bool result = false;
1608
1609 if ( gUseDyld3 ) {
1610 result = dyld3::dlopen_preflight_internal(path);
1611 return result;
1612 }
1613
1614 DYLD_LOCK_THIS_BLOCK;
1615 static bool (*p)(const char* path, void* callerAddress) = NULL;
1616
1617 if(p == NULL)
1618 _dyld_func_lookup("__dyld_dlopen_preflight_internal", (void**)&p);
1619 result = p(path, __builtin_return_address(0));
1620 timer.setData4(result);
1621 return result;
1622 }
1623
1624 void* dlsym(void* handle, const char* symbol)
1625 {
1626 dyld3::ScopedTimer timer(DBG_DYLD_TIMING_DLSYM, handle, symbol, 0);
1627 void* result = nullptr;
1628
1629 if ( gUseDyld3 ) {
1630 result = dyld3::dlsym_internal(handle, symbol, __builtin_return_address(0));
1631 return result;
1632 }
1633
1634 DYLD_LOCK_THIS_BLOCK;
1635 static void* (*p)(void* handle, const char* symbol, void *callerAddress) = NULL;
1636
1637 if(p == NULL)
1638 _dyld_func_lookup("__dyld_dlsym_internal", (void**)&p);
1639 result = p(handle, symbol, __builtin_return_address(0));
1640 timer.setData4(result);
1641 return result;
1642 }
1643
1644 const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1645 {
1646 if ( gUseDyld3 )
1647 return dyld3::_dyld_get_all_image_infos();
1648
1649 DYLD_NO_LOCK_THIS_BLOCK;
1650 static struct dyld_all_image_infos* (*p)() = NULL;
1651
1652 if(p == NULL)
1653 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
1654 return p();
1655 }
1656
1657 #if SUPPORT_ZERO_COST_EXCEPTIONS
1658 bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
1659 {
1660 if ( gUseDyld3 )
1661 return dyld3::_dyld_find_unwind_sections(addr, info);
1662
1663 DYLD_NO_LOCK_THIS_BLOCK;
1664 static void* (*p)(void*, dyld_unwind_sections*) = NULL;
1665
1666 if(p == NULL)
1667 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
1668 return p(addr, info);
1669 }
1670 #endif
1671
1672
1673 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1674 __attribute__((visibility("hidden")))
1675 void* _dyld_fast_stub_entry(void* loadercache, long lazyinfo)
1676 {
1677 DYLD_NO_LOCK_THIS_BLOCK;
1678 static void* (*p)(void*, long) = NULL;
1679
1680 if(p == NULL)
1681 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p);
1682 return p(loadercache, lazyinfo);
1683 }
1684 #endif
1685
1686
1687 const char* dyld_image_path_containing_address(const void* addr)
1688 {
1689 if ( gUseDyld3 )
1690 return dyld3::dyld_image_path_containing_address(addr);
1691
1692 DYLD_NO_LOCK_THIS_BLOCK;
1693 static const char* (*p)(const void*) = NULL;
1694
1695 if(p == NULL)
1696 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p);
1697 return p(addr);
1698 }
1699
1700 const struct mach_header* dyld_image_header_containing_address(const void* addr)
1701 {
1702 if ( gUseDyld3 )
1703 return dyld3::dyld_image_header_containing_address(addr);
1704
1705 DYLD_NO_LOCK_THIS_BLOCK;
1706 static const mach_header* (*p)(const void*) = NULL;
1707
1708 if(p == NULL)
1709 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
1710 return p(addr);
1711 }
1712
1713
1714 bool dyld_shared_cache_some_image_overridden()
1715 {
1716 if ( gUseDyld3 )
1717 return dyld3::dyld_shared_cache_some_image_overridden();
1718
1719 DYLD_NO_LOCK_THIS_BLOCK;
1720 static bool (*p)() = NULL;
1721
1722 if(p == NULL)
1723 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p);
1724 return p();
1725 }
1726
1727 bool _dyld_get_shared_cache_uuid(uuid_t uuid)
1728 {
1729 if ( gUseDyld3 )
1730 return dyld3::_dyld_get_shared_cache_uuid(uuid);
1731
1732 DYLD_NO_LOCK_THIS_BLOCK;
1733 static bool (*p)(uuid_t) = NULL;
1734
1735 if(p == NULL)
1736 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p);
1737 return p(uuid);
1738 }
1739
1740 const void* _dyld_get_shared_cache_range(size_t* length)
1741 {
1742 if ( gUseDyld3 )
1743 return dyld3::_dyld_get_shared_cache_range(length);
1744
1745 DYLD_NO_LOCK_THIS_BLOCK;
1746 static const void* (*p)(size_t*) = NULL;
1747
1748 if(p == NULL)
1749 _dyld_func_lookup("__dyld_get_shared_cache_range", (void**)&p);
1750 return p(length);
1751 }
1752
1753 void _dyld_images_for_addresses(unsigned count, const void* addresses[], struct dyld_image_uuid_offset infos[])
1754 {
1755 if ( gUseDyld3 )
1756 return dyld3::_dyld_images_for_addresses(count, addresses, infos);
1757
1758 DYLD_NO_LOCK_THIS_BLOCK;
1759 static const void (*p)(unsigned, const void*[], struct dyld_image_uuid_offset[]) = NULL;
1760
1761 if(p == NULL)
1762 _dyld_func_lookup("__dyld_images_for_addresses", (void**)&p);
1763 return p(count, addresses, infos);
1764 }
1765
1766 void _dyld_register_for_image_loads(void (*func)(const mach_header* mh, const char* path, bool unloadable))
1767 {
1768 if ( gUseDyld3 )
1769 return dyld3::_dyld_register_for_image_loads(func);
1770
1771 DYLD_NO_LOCK_THIS_BLOCK;
1772 static const void (*p)(void (*)(const mach_header* mh, const char* path, bool unloadable)) = NULL;
1773
1774 if(p == NULL)
1775 _dyld_func_lookup("__dyld_register_for_image_loads", (void**)&p);
1776 return p(func);
1777 }
1778
1779 bool dyld_process_is_restricted()
1780 {
1781 if ( gUseDyld3 )
1782 return dyld3::dyld_process_is_restricted();
1783
1784 DYLD_NO_LOCK_THIS_BLOCK;
1785 static bool (*p)() = NULL;
1786
1787 if(p == NULL)
1788 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p);
1789 return p();
1790 }
1791
1792 const char* dyld_shared_cache_file_path()
1793 {
1794 if ( gUseDyld3 )
1795 return dyld3::dyld_shared_cache_file_path();
1796
1797 DYLD_NO_LOCK_THIS_BLOCK;
1798 static const char* (*p)() = NULL;
1799
1800 if(p == NULL)
1801 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p);
1802 return p();
1803 }
1804
1805 void dyld_dynamic_interpose(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count)
1806 {
1807 if ( gUseDyld3 )
1808 return dyld3::dyld_dynamic_interpose(mh, array, count);
1809
1810 DYLD_LOCK_THIS_BLOCK;
1811 static void (*p)(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count) = NULL;
1812
1813 if (p == NULL)
1814 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p);
1815 p(mh, array, count);
1816 }
1817
1818
1819 // SPI called __fork
1820 void _dyld_fork_child()
1821 {
1822 if ( gUseDyld3 )
1823 return dyld3::_dyld_fork_child();
1824
1825 DYLD_NO_LOCK_THIS_BLOCK;
1826 static void (*p)() = NULL;
1827
1828 if(p == NULL)
1829 _dyld_func_lookup("__dyld_fork_child", (void**)&p);
1830 return p();
1831 }
1832
1833
1834
1835 static void* mapStartOfCache(const char* path, size_t length)
1836 {
1837 struct stat statbuf;
1838 if ( ::stat(path, &statbuf) == -1 )
1839 return NULL;
1840
1841 if ( (size_t)statbuf.st_size < length )
1842 return NULL;
1843
1844 int cache_fd = ::open(path, O_RDONLY);
1845 if ( cache_fd < 0 )
1846 return NULL;
1847
1848 void* result = ::mmap(NULL, length, PROT_READ, MAP_PRIVATE, cache_fd, 0);
1849 close(cache_fd);
1850
1851 if ( result == MAP_FAILED )
1852 return NULL;
1853
1854 return result;
1855 }
1856
1857
1858 static const dyld_cache_header* findCacheInDirAndMap(const uuid_t cacheUuid, const char* dirPath)
1859 {
1860 DIR* dirp = ::opendir(dirPath);
1861 if ( dirp != NULL) {
1862 dirent entry;
1863 dirent* entp = NULL;
1864 char cachePath[PATH_MAX];
1865 while ( ::readdir_r(dirp, &entry, &entp) == 0 ) {
1866 if ( entp == NULL )
1867 break;
1868 if ( entp->d_type != DT_REG )
1869 continue;
1870 if ( strlcpy(cachePath, dirPath, PATH_MAX) >= PATH_MAX )
1871 continue;
1872 if ( strlcat(cachePath, "/", PATH_MAX) >= PATH_MAX )
1873 continue;
1874 if ( strlcat(cachePath, entp->d_name, PATH_MAX) >= PATH_MAX )
1875 continue;
1876 if ( const dyld_cache_header* cacheHeader = (dyld_cache_header*)mapStartOfCache(cachePath, 0x00100000) ) {
1877 if ( ::memcmp(cacheHeader->uuid, cacheUuid, 16) != 0 ) {
1878 // wrong uuid, unmap and keep looking
1879 ::munmap((void*)cacheHeader, 0x00100000);
1880 }
1881 else {
1882 // found cache
1883 closedir(dirp);
1884 return cacheHeader;
1885 }
1886 }
1887 }
1888 closedir(dirp);
1889 }
1890 return NULL;
1891 }
1892
1893 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid, const char* extraSearchDirs[], void (^callback)(const dyld_shared_cache_dylib_text_info* info))
1894 {
1895 if ( gUseDyld3 )
1896 return dyld3::dyld_shared_cache_find_iterate_text(cacheUuid, extraSearchDirs, callback);
1897
1898 const dyld_cache_header* cacheHeader = NULL;
1899 bool needToUnmap = true;
1900
1901 // get info from dyld about this process, to see if requested cache is already mapped into this process
1902 const dyld_all_image_infos* allInfo = _dyld_get_all_image_infos();
1903 if ( (allInfo != NULL) && (allInfo->sharedCacheBaseAddress != 0) && (memcmp(allInfo->sharedCacheUUID, cacheUuid, 16) == 0) ) {
1904 // requested cache is already mapped, just re-use it
1905 cacheHeader = (dyld_cache_header*)(allInfo->sharedCacheBaseAddress);
1906 needToUnmap = false;
1907 }
1908 else {
1909 // look first is default location for cache files
1910 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1911 const char* defaultSearchDir = IPHONE_DYLD_SHARED_CACHE_DIR;
1912 #else
1913 const char* defaultSearchDir = MACOSX_DYLD_SHARED_CACHE_DIR;
1914 #endif
1915 cacheHeader = findCacheInDirAndMap(cacheUuid, defaultSearchDir);
1916 // if not there, look in extra search locations
1917 if ( cacheHeader == NULL ) {
1918 for (const char** p = extraSearchDirs; *p != NULL; ++p) {
1919 cacheHeader = findCacheInDirAndMap(cacheUuid, *p);
1920 if ( cacheHeader != NULL )
1921 break;
1922 }
1923 }
1924 }
1925
1926 if ( cacheHeader == NULL )
1927 return -1;
1928
1929 if ( cacheHeader->mappingOffset < sizeof(dyld_cache_header) ) {
1930 // old cache without imagesText array
1931 if ( needToUnmap )
1932 ::munmap((void*)cacheHeader, 0x00100000);
1933 return -1;
1934 }
1935
1936 // walk imageText table and call callback for each entry
1937 const dyld_cache_mapping_info* mappings = (dyld_cache_mapping_info*)((char*)cacheHeader + cacheHeader->mappingOffset);
1938 const uint64_t cacheUnslidBaseAddress = mappings[0].address;
1939 const dyld_cache_image_text_info* imagesText = (dyld_cache_image_text_info*)((char*)cacheHeader + cacheHeader->imagesTextOffset);
1940 const dyld_cache_image_text_info* imagesTextEnd = &imagesText[cacheHeader->imagesTextCount];
1941 for (const dyld_cache_image_text_info* p=imagesText; p < imagesTextEnd; ++p) {
1942 dyld_shared_cache_dylib_text_info dylibTextInfo;
1943 dylibTextInfo.version = 2;
1944 dylibTextInfo.loadAddressUnslid = p->loadAddress;
1945 dylibTextInfo.textSegmentSize = p->textSegmentSize;
1946 dylibTextInfo.path = (char*)cacheHeader + p->pathOffset;
1947 ::memcpy(dylibTextInfo.dylibUuid, p->uuid, 16);
1948 dylibTextInfo.textSegmentOffset = p->loadAddress - cacheUnslidBaseAddress;
1949 callback(&dylibTextInfo);
1950 }
1951
1952 if ( needToUnmap )
1953 ::munmap((void*)cacheHeader, 0x00100000);
1954
1955 return 0;
1956 }
1957
1958 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid, void (^callback)(const dyld_shared_cache_dylib_text_info* info))
1959 {
1960 if ( gUseDyld3 )
1961 return dyld3::dyld_shared_cache_iterate_text(cacheUuid, callback);
1962
1963 const char* extraSearchDirs[] = { NULL };
1964 return dyld_shared_cache_find_iterate_text(cacheUuid, extraSearchDirs, callback);
1965 }
1966
1967
1968 bool _dyld_is_memory_immutable(const void* addr, size_t length)
1969 {
1970 if ( gUseDyld3 )
1971 return dyld3::_dyld_is_memory_immutable(addr, length);
1972
1973 DYLD_NO_LOCK_THIS_BLOCK;
1974 static bool (*p)(const void*, size_t) = NULL;
1975
1976 if(p == NULL)
1977 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p);
1978 return p(addr, length);
1979 }
1980
1981
1982 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped,
1983 _dyld_objc_notify_init init,
1984 _dyld_objc_notify_unmapped unmapped)
1985 {
1986 if ( gUseDyld3 )
1987 return dyld3::_dyld_objc_notify_register(mapped, init, unmapped);
1988
1989 DYLD_LOCK_THIS_BLOCK;
1990 static bool (*p)(_dyld_objc_notify_mapped, _dyld_objc_notify_init, _dyld_objc_notify_unmapped) = NULL;
1991
1992 if(p == NULL)
1993 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p);
1994 p(mapped, init, unmapped);
1995 }
1996
1997
1998