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