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