1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
27 #include <malloc/malloc.h>
30 #include <crt_externs.h>
31 #include <Availability.h>
32 #include <vproc_priv.h>
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"
42 #include "ImageLoader.h"
44 #include "start_glue.h"
46 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
47 extern "C" void __cxa_finalize(const void *dso
);
48 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
);
51 #ifndef LC_VERSION_MIN_MACOSX
52 #define LC_VERSION_MIN_MACOSX 0x24
53 struct version_min_command
{
54 uint32_t cmd
; /* LC_VERSION_MIN_MACOSX or
55 LC_VERSION_MIN_IPHONEOS */
56 uint32_t cmdsize
; /* sizeof(struct min_version_command) */
57 uint32_t version
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
58 uint32_t sdk
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
62 #ifndef LC_VERSION_MIN_IPHONEOS
63 #define LC_VERSION_MIN_IPHONEOS 0x25
66 #ifndef LC_VERSION_MIN_TVOS
67 #define LC_VERSION_MIN_TVOS 0x2F
70 #ifndef LC_VERSION_MIN_WATCHOS
71 #define LC_VERSION_MIN_WATCHOS 0x30
75 #ifndef LC_LOAD_UPWARD_DYLIB
76 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
80 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
81 #if __IPHONE_OS_VERSION_MIN_REQUIRED
82 #define DEPRECATED_APIS_SUPPORTED 0
84 #define DEPRECATED_APIS_SUPPORTED 1
88 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
89 * libraryName (which is -lx or -framework Foo argument passed to the static
90 * link editor for the same library) and determines if they match. This depends
91 * on conventional use of names including major versioning.
96 const char *install_name
,
97 const char* libraryName
)
103 * Conventional install names have these forms:
104 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
105 * /Local/Library/Frameworks/AppKit.framework/Appkit
106 * /lib/libsys_s.A.dylib
107 * /usr/lib/libsys_s.dylib
109 basename
= strrchr(install_name
, '/');
111 basename
= install_name
;
116 * By checking the base name matching the library name we take care
117 * of the -framework cases.
119 if(strcmp(basename
, libraryName
) == 0)
123 * Now check the base name for "lib" if so proceed to check for the
124 * -lx case dealing with a possible .X.dylib and a .dylib extension.
126 if(strncmp(basename
, "lib", 3) ==0){
127 n
= strlen(libraryName
);
128 if(strncmp(basename
+3, libraryName
, n
) == 0){
129 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
131 if(basename
[3+n
] == '.' &&
132 basename
[3+n
+1] != '\0' &&
133 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
140 #if DEPRECATED_APIS_SUPPORTED
142 void NSInstallLinkEditErrorHandlers(
143 const NSLinkEditErrorHandlers
* handlers
)
145 DYLD_LOCK_THIS_BLOCK
;
146 typedef void (*ucallback_t
)(const char* symbol_name
);
147 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
148 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
149 const char* fileName
, const char* errorString
);
150 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
153 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
154 mcallback_t m
= handlers
->multiple
;
155 p(handlers
->undefined
, m
, handlers
->linkEdit
);
162 DYLD_LOCK_THIS_BLOCK
;
163 static const char* (*p
)(NSModule
module) = NULL
;
166 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
171 NSLibraryNameForModule(
174 DYLD_LOCK_THIS_BLOCK
;
175 static const char* (*p
)(NSModule
module) = NULL
;
178 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
183 NSIsSymbolNameDefined(
184 const char* symbolName
)
186 DYLD_LOCK_THIS_BLOCK
;
187 static bool (*p
)(const char* symbolName
) = NULL
;
190 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
191 return(p(symbolName
));
195 NSIsSymbolNameDefinedWithHint(
196 const char* symbolName
,
197 const char* libraryNameHint
)
199 DYLD_LOCK_THIS_BLOCK
;
200 static bool (*p
)(const char* symbolName
,
201 const char* libraryNameHint
) = NULL
;
204 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
205 return(p(symbolName
, libraryNameHint
));
209 NSIsSymbolNameDefinedInImage(
210 const struct mach_header
*image
,
211 const char* symbolName
)
213 DYLD_LOCK_THIS_BLOCK
;
214 static bool (*p
)(const struct mach_header
*image
,
215 const char* symbolName
) = NULL
;
218 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
219 return(p(image
, symbolName
));
223 NSLookupAndBindSymbol(
224 const char* symbolName
)
226 DYLD_LOCK_THIS_BLOCK
;
227 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
230 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
231 return(p(symbolName
));
235 NSLookupAndBindSymbolWithHint(
236 const char* symbolName
,
237 const char* libraryNameHint
)
239 DYLD_LOCK_THIS_BLOCK
;
240 static NSSymbol (*p
)(const char* symbolName
,
241 const char* libraryNameHint
) = NULL
;
244 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
245 return(p(symbolName
, libraryNameHint
));
249 NSLookupSymbolInModule(
251 const char* symbolName
)
253 DYLD_LOCK_THIS_BLOCK
;
254 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
257 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
258 return(p(module, symbolName
));
262 NSLookupSymbolInImage(
263 const struct mach_header
*image
,
264 const char* symbolName
,
267 DYLD_LOCK_THIS_BLOCK
;
268 static NSSymbol (*p
)(const struct mach_header
*image
,
269 const char* symbolName
,
270 uint32_t options
) = NULL
;
273 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
274 return(p(image
, symbolName
, options
));
281 DYLD_LOCK_THIS_BLOCK
;
282 static char * (*p
)(NSSymbol symbol
) = NULL
;
285 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
293 DYLD_LOCK_THIS_BLOCK
;
294 static void * (*p
)(NSSymbol symbol
) = NULL
;
297 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
305 DYLD_LOCK_THIS_BLOCK
;
306 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
309 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
315 const char* pathName
)
317 DYLD_LOCK_THIS_BLOCK
;
318 static bool (*p
)(const char* pathName
) = NULL
;
321 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
326 NSAddLibraryWithSearching(
327 const char* pathName
)
329 DYLD_LOCK_THIS_BLOCK
;
330 static bool (*p
)(const char* pathName
) = NULL
;
333 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
337 const struct mach_header
*
339 const char* image_name
,
342 DYLD_LOCK_THIS_BLOCK
;
343 static const struct mach_header
* (*p
)(const char* image_name
,
344 uint32_t options
) = NULL
;
347 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
348 return(p(image_name
, options
));
350 #endif // DEPRECATED_APIS_SUPPORTED
353 * This routine returns the current version of the named shared library the
354 * executable it was built with. The libraryName parameter is the same as the
355 * -lx or -framework Foo argument passed to the static link editor when building
356 * the executable (with -lx it would be "x" and with -framework Foo it would be
357 * "Foo"). If this the executable was not built against the specified library
358 * it returns -1. It should be noted that if this only returns the value the
359 * current version of the named shared library the executable was built with
360 * and not a list of current versions that dependent libraries and bundles the
361 * program is using were built with.
363 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
365 // Lazily call _NSGetMachExecuteHeader() and cache result
367 static mach_header_64
* mh
= NULL
;
369 static mach_header
* mh
= NULL
;
372 mh
= _NSGetMachExecuteHeader();
374 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
376 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
378 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
381 case LC_LOAD_WEAK_DYLIB
:
382 case LC_LOAD_UPWARD_DYLIB
:
383 const dylib_command
* dl
= (dylib_command
*)lc
;
384 const char* install_name
= (char*)dl
+ dl
->dylib
.name
.offset
;
385 if ( names_match(install_name
, libraryName
) )
386 return dl
->dylib
.current_version
;
389 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
395 * This routine returns the current version of the named shared library the
396 * program it is running against. The libraryName parameter is the same as
397 * would be static link editor using the -lx or -framework Foo flags (with -lx
398 * it would be "x" and with -framework Foo it would be "Foo"). If the program
399 * is not using the specified library it returns -1.
401 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
403 uint32_t n
= _dyld_image_count();
404 for(uint32_t i
= 0; i
< n
; i
++){
405 const mach_header
* mh
= _dyld_get_image_header(i
);
408 if ( mh
->filetype
!= MH_DYLIB
)
411 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
413 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
415 for(uint32_t j
= 0; j
< mh
->ncmds
; j
++){
416 if ( lc
->cmd
== LC_ID_DYLIB
) {
417 const dylib_command
* dl
= (dylib_command
*)lc
;
418 const char* install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
419 if ( names_match(install_name
, libraryName
) )
420 return dl
->dylib
.current_version
;
422 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
429 #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
432 static bool getVersionLoadCommandInfo(const mach_header
* mh
, uint32_t* loadCommand
, uint32_t* minOS
, uint32_t* sdk
)
434 const load_command
* startCmds
= NULL
;
435 if ( mh
->magic
== MH_MAGIC_64
)
436 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
437 else if ( mh
->magic
== MH_MAGIC
)
438 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
440 return false; // not a mach-o file, or wrong endianness
442 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
443 const load_command
* cmd
= startCmds
;
444 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
445 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
446 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
449 const version_min_command
* versCmd
;
450 switch ( cmd
->cmd
) {
451 case LC_VERSION_MIN_IPHONEOS
:
452 case LC_VERSION_MIN_MACOSX
:
453 case LC_VERSION_MIN_TVOS
:
454 case LC_VERSION_MIN_WATCHOS
:
455 versCmd
= (version_min_command
*)cmd
;
456 *loadCommand
= versCmd
->cmd
;
457 *minOS
= versCmd
->version
;
466 #if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED
467 static uint32_t deriveSDKVersFromDylibs(const mach_header
* mh
)
469 const load_command
* startCmds
= NULL
;
470 if ( mh
->magic
== MH_MAGIC_64
)
471 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
472 else if ( mh
->magic
== MH_MAGIC
)
473 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
475 return 0; // not a mach-o file, or wrong endianness
477 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
478 const dylib_command
* dylibCmd
;
479 const load_command
* cmd
= startCmds
;
480 const char* dylibName
;
481 #if __IPHONE_OS_VERSION_MIN_REQUIRED
482 uint32_t foundationVers
= 0;
484 uint32_t libSystemVers
= 0;
486 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
487 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
488 // <rdar://problem/14381579&16050962> sanity check size of command
489 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
492 switch ( cmd
->cmd
) {
494 case LC_LOAD_WEAK_DYLIB
:
495 case LC_LOAD_UPWARD_DYLIB
:
496 dylibCmd
= (dylib_command
*)cmd
;
497 // sanity check dylib command layout
498 if ( dylibCmd
->dylib
.name
.offset
> cmd
->cmdsize
)
500 dylibName
= (char*)dylibCmd
+ dylibCmd
->dylib
.name
.offset
;
501 #if __IPHONE_OS_VERSION_MIN_REQUIRED
502 if ( strcmp(dylibName
, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
503 foundationVers
= dylibCmd
->dylib
.current_version
;
505 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 )
506 libSystemVers
= dylibCmd
->dylib
.current_version
;
513 struct DylibToOSMapping
{
514 uint32_t dylibVersion
;
518 #if __IPHONE_OS_VERSION_MIN_REQUIRED
519 static const DylibToOSMapping foundationMapping
[] = {
520 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0
},
521 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1
},
522 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2
},
523 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0
},
524 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1
},
525 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2
},
526 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0
},
527 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1
},
528 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2
},
529 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3
},
530 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0
},
531 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1
},
532 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0
},
533 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1
},
534 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0
},
535 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0
}
536 // We don't need to expand this table because all recent
537 // binaries have LC_VERSION_MIN_ load command.
540 if ( foundationVers
!= 0 ) {
541 uint32_t lastOsVersion
= 0;
542 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) {
543 if ( p
->dylibVersion
== 0 )
545 if ( foundationVers
< p
->dylibVersion
)
546 return lastOsVersion
;
547 lastOsVersion
= p
->osVersion
;
552 // Note: versions are for the GM release. The last entry should
553 // always be zero. At the start of the next major version,
554 // a new last entry needs to be added and the previous zero
555 // updated to the GM dylib version.
556 static const DylibToOSMapping libSystemMapping
[] = {
557 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4
},
558 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5
},
559 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6
},
560 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7
},
561 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8
},
562 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9
},
563 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9
}
564 // We don't need to expand this table because all recent
565 // binaries have LC_VERSION_MIN_ load command.
568 if ( libSystemVers
!= 0 ) {
569 uint32_t lastOsVersion
= 0;
570 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) {
571 if ( p
->dylibVersion
== 0 )
573 if ( libSystemVers
< p
->dylibVersion
)
574 return lastOsVersion
;
575 lastOsVersion
= p
->osVersion
;
584 #if __WATCH_OS_VERSION_MIN_REQUIRED
585 static uint32_t watchVersToIOSVers(uint32_t vers
)
587 return vers
+ 0x00070000;
590 uint32_t dyld_get_program_sdk_watch_os_version()
592 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
593 uint32_t loadCommand
;
597 if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) {
598 if ( loadCommand
== LC_VERSION_MIN_WATCHOS
)
604 uint32_t dyld_get_program_min_watch_os_version()
606 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
607 uint32_t loadCommand
;
611 if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) {
612 if ( loadCommand
== LC_VERSION_MIN_WATCHOS
)
613 return minOS
; // return raw minOS (not mapped to iOS version)
621 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
622 * specified binary was built against.
624 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
625 * not zero, return that value.
626 * Otherwise, looks for the libSystem.B.dylib the binary linked
627 * against and uses a table to convert that to an sdk version.
629 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
631 uint32_t loadCommand
;
635 if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) {
636 switch (loadCommand
) {
637 #if __WATCH_OS_VERSION_MIN_REQUIRED
638 case LC_VERSION_MIN_WATCHOS
:
639 // new binary. sdk version looks like "2.0" but API wants "9.0"
640 return watchVersToIOSVers(sdk
);
641 case LC_VERSION_MIN_IPHONEOS
:
642 // old binary. sdk matches API semantics so can return directly.
644 #elif __TV_OS_VERSION_MIN_REQUIRED
645 case LC_VERSION_MIN_TVOS
:
646 case LC_VERSION_MIN_IPHONEOS
:
648 #elif __IPHONE_OS_VERSION_MIN_REQUIRED
649 case LC_VERSION_MIN_IPHONEOS
:
650 if ( sdk
!= 0 ) // old binaries might not have SDK set
654 case LC_VERSION_MIN_MACOSX
:
655 if ( sdk
!= 0 ) // old binaries might not have SDK set
662 #if __WATCH_OS_VERSION_MIN_REQUIRED ||__TV_OS_VERSION_MIN_REQUIRED
663 // All WatchOS and tv OS binaries should have version load command.
666 // MacOSX and iOS have old binaries without version load commmand.
667 return deriveSDKVersFromDylibs(mh
);
671 uint32_t dyld_get_program_sdk_version()
673 return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
676 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
678 uint32_t loadCommand
;
682 if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) {
683 switch (loadCommand
) {
684 #if __WATCH_OS_VERSION_MIN_REQUIRED
685 case LC_VERSION_MIN_WATCHOS
:
686 // new binary. OS version looks like "2.0" but API wants "9.0"
687 return watchVersToIOSVers(minOS
);
688 case LC_VERSION_MIN_IPHONEOS
:
689 // old binary. OS matches API semantics so can return directly.
691 #elif __TV_OS_VERSION_MIN_REQUIRED
692 case LC_VERSION_MIN_TVOS
:
693 case LC_VERSION_MIN_IPHONEOS
:
695 #elif __IPHONE_OS_VERSION_MIN_REQUIRED
696 case LC_VERSION_MIN_IPHONEOS
:
699 case LC_VERSION_MIN_MACOSX
:
708 uint32_t dyld_get_program_min_os_version()
710 return dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
714 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
)
716 const load_command
* startCmds
= NULL
;
717 if ( mh
->magic
== MH_MAGIC_64
)
718 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
719 else if ( mh
->magic
== MH_MAGIC
)
720 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
722 return false; // not a mach-o file, or wrong endianness
724 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
725 const load_command
* cmd
= startCmds
;
726 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
727 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
728 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
731 if ( cmd
->cmd
== LC_UUID
) {
732 const uuid_command
* uuidCmd
= (uuid_command
*)cmd
;
733 memcpy(uuid
, uuidCmd
->uuid
, 16);
744 #if DEPRECATED_APIS_SUPPORTED
746 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
747 * specified file name if the file is a correct Mach-O file that can be loaded
748 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
749 * NSObjectFileImageFormat an error message is printed to stderr. All
750 * other codes cause no printing.
752 NSObjectFileImageReturnCode
753 NSCreateObjectFileImageFromFile(
754 const char* pathName
,
755 NSObjectFileImage
*objectFileImage
)
757 DYLD_LOCK_THIS_BLOCK
;
758 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
761 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
762 return p(pathName
, objectFileImage
);
767 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
768 * object file mapped into memory at address of size length if the object file
769 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
770 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
771 * message is printed to stderr. All other codes cause no printing.
773 NSObjectFileImageReturnCode
774 NSCreateObjectFileImageFromMemory(
777 NSObjectFileImage
*objectFileImage
)
779 DYLD_LOCK_THIS_BLOCK
;
780 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
783 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
784 return p(address
, size
, objectFileImage
);
787 #if OBSOLETE_DYLD_API
789 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
790 * specified core file name if the file is a correct Mach-O core file.
791 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
792 * an error message is printed to stderr. All other codes cause no printing.
794 NSObjectFileImageReturnCode
795 NSCreateCoreFileImageFromFile(
796 const char* pathName
,
797 NSObjectFileImage
*objectFileImage
)
799 DYLD_LOCK_THIS_BLOCK
;
800 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
803 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
804 return p(pathName
, objectFileImage
);
809 NSDestroyObjectFileImage(
810 NSObjectFileImage objectFileImage
)
812 DYLD_LOCK_THIS_BLOCK
;
813 static bool (*p
)(NSObjectFileImage
) = NULL
;
816 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
817 return p(objectFileImage
);
823 NSObjectFileImage objectFileImage
,
824 const char* moduleName
,
827 DYLD_LOCK_THIS_BLOCK
;
828 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
831 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
833 return p(objectFileImage
, moduleName
, options
);
840 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
841 * definitions in the NSObjectFileImage.
844 NSSymbolDefinitionCountInObjectFileImage(
845 NSObjectFileImage objectFileImage
)
847 DYLD_LOCK_THIS_BLOCK
;
848 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
851 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
853 return p(objectFileImage
);
857 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
858 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
859 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
863 NSSymbolDefinitionNameInObjectFileImage(
864 NSObjectFileImage objectFileImage
,
867 DYLD_LOCK_THIS_BLOCK
;
868 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
871 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
873 return p(objectFileImage
, ordinal
);
877 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
878 * to undefined symbols the NSObjectFileImage.
881 NSSymbolReferenceCountInObjectFileImage(
882 NSObjectFileImage objectFileImage
)
884 DYLD_LOCK_THIS_BLOCK
;
885 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
888 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
890 return p(objectFileImage
);
894 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
895 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
896 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
900 NSSymbolReferenceNameInObjectFileImage(
901 NSObjectFileImage objectFileImage
,
903 bool *tentative_definition
) /* can be NULL */
905 DYLD_LOCK_THIS_BLOCK
;
906 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
909 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
911 return p(objectFileImage
, ordinal
, tentative_definition
);
915 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
916 * name has a definition in the NSObjectFileImage and FALSE otherwise.
919 NSIsSymbolDefinedInObjectFileImage(
920 NSObjectFileImage objectFileImage
,
921 const char* symbolName
)
923 DYLD_LOCK_THIS_BLOCK
;
924 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
927 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
929 return p(objectFileImage
, symbolName
);
933 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
934 * in the NSObjectFileImage for the specified segmentName and sectionName if
935 * it exists and it is not a zerofill section. If not it returns NULL. If
936 * the parameter size is not NULL the size of the section is also returned
937 * indirectly through that pointer.
940 NSGetSectionDataInObjectFileImage(
941 NSObjectFileImage objectFileImage
,
942 const char* segmentName
,
943 const char* sectionName
,
944 unsigned long *size
) /* can be NULL */
946 DYLD_LOCK_THIS_BLOCK
;
947 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
950 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
952 return p(objectFileImage
, segmentName
, sectionName
, size
);
960 const char* *fileName
,
961 const char* *errorString
)
963 DYLD_LOCK_THIS_BLOCK
;
964 static void (*p
)(NSLinkEditErrors
*c
,
966 const char* *fileName
,
967 const char* *errorString
) = NULL
;
970 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
972 p(c
, errorNumber
, fileName
, errorString
);
980 DYLD_LOCK_THIS_BLOCK
;
981 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
984 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
986 return p(module, options
);
989 #if OBSOLETE_DYLD_API
992 NSModule moduleToReplace
,
993 NSObjectFileImage newObjectFileImage
,
1001 #endif // DEPRECATED_APIS_SUPPORTED
1004 *_NSGetExecutablePath copies the path of the executable into the buffer and
1005 * returns 0 if the path was successfully copied in the provided buffer. If the
1006 * buffer is not large enough, -1 is returned and the expected buffer size is
1007 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
1008 * the executable not a "real path" to the executable. That is the path may be
1009 * a symbolic link and not the real file. And with deep directories the total
1010 * bufsize needed could be more than MAXPATHLEN.
1013 _NSGetExecutablePath(
1017 DYLD_NO_LOCK_THIS_BLOCK
;
1018 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
1021 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
1022 return(p(buf
, bufsize
));
1025 #if DEPRECATED_APIS_SUPPORTED
1027 _dyld_lookup_and_bind(
1028 const char* symbol_name
,
1032 DYLD_LOCK_THIS_BLOCK
;
1033 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
1036 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
1037 p(symbol_name
, address
, module);
1041 _dyld_lookup_and_bind_with_hint(
1042 const char* symbol_name
,
1043 const char* library_name_hint
,
1047 DYLD_LOCK_THIS_BLOCK
;
1048 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
1051 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
1052 p(symbol_name
, library_name_hint
, address
, module);
1055 #if OBSOLETE_DYLD_API
1057 _dyld_lookup_and_bind_objc(
1058 const char* symbol_name
,
1062 DYLD_LOCK_THIS_BLOCK
;
1063 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
1066 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
1067 p(symbol_name
, address
, module);
1072 _dyld_lookup_and_bind_fully(
1073 const char* symbol_name
,
1077 DYLD_LOCK_THIS_BLOCK
;
1078 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
1081 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
1082 p(symbol_name
, address
, module);
1086 _dyld_bind_fully_image_containing_address(
1087 const void* address
)
1089 DYLD_LOCK_THIS_BLOCK
;
1090 static bool (*p
)(const void*) = NULL
;
1093 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
1096 #endif // DEPRECATED_APIS_SUPPORTED
1100 * _dyld_register_func_for_add_image registers the specified function to be
1101 * called when a new image is added (a bundle or a dynamic shared library) to
1102 * the program. When this function is first registered it is called for once
1103 * for each image that is currently part of the program.
1106 _dyld_register_func_for_add_image(
1107 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1109 DYLD_LOCK_THIS_BLOCK
;
1110 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1111 static void (*p
)(callback_t func
) = NULL
;
1114 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
1119 * _dyld_register_func_for_remove_image registers the specified function to be
1120 * called when an image is removed (a bundle or a dynamic shared library) from
1124 _dyld_register_func_for_remove_image(
1125 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1127 DYLD_LOCK_THIS_BLOCK
;
1128 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1129 static void (*p
)(callback_t func
) = NULL
;
1132 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1136 #if OBSOLETE_DYLD_API
1138 * _dyld_register_func_for_link_module registers the specified function to be
1139 * called when a module is bound into the program. When this function is first
1140 * registered it is called for once for each module that is currently bound into
1144 _dyld_register_func_for_link_module(
1145 void (*func
)(NSModule
module))
1147 DYLD_LOCK_THIS_BLOCK
;
1148 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1151 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1156 * _dyld_register_func_for_unlink_module registers the specified function to be
1157 * called when a module is unbound from the program.
1160 _dyld_register_func_for_unlink_module(
1161 void (*func
)(NSModule
module))
1163 DYLD_LOCK_THIS_BLOCK
;
1164 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1167 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1172 * _dyld_register_func_for_replace_module registers the specified function to be
1173 * called when a module is to be replace with another module in the program.
1176 _dyld_register_func_for_replace_module(
1177 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1179 DYLD_LOCK_THIS_BLOCK
;
1180 static void (*p
)(void (*func
)(NSModule oldmodule
,
1181 NSModule newmodule
)) = NULL
;
1184 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1190 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1191 * pointer to the (__OBJC,__module) section and its size for the specified
1195 _dyld_get_objc_module_sect_for_module(
1198 unsigned long *size
)
1200 DYLD_LOCK_THIS_BLOCK
;
1201 static void (*p
)(NSModule
module,
1203 unsigned long *size
) = NULL
;
1206 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1207 p(module, objc_module
, size
);
1211 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1212 * __module) section and causes the module that is associated with that address
1216 _dyld_bind_objc_module(const void* objc_module
)
1218 DYLD_LOCK_THIS_BLOCK
;
1219 static void (*p
)(const void *objc_module
) = NULL
;
1222 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p
);
1227 #if DEPRECATED_APIS_SUPPORTED
1231 // this function exists for compatiblity only
1237 _dyld_image_count(void)
1239 DYLD_NO_LOCK_THIS_BLOCK
;
1240 static uint32_t (*p
)(void) = NULL
;
1243 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1247 const struct mach_header
*
1248 _dyld_get_image_header(uint32_t image_index
)
1250 DYLD_NO_LOCK_THIS_BLOCK
;
1251 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1254 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1255 return(p(image_index
));
1259 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1261 DYLD_NO_LOCK_THIS_BLOCK
;
1262 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1265 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1266 return(p(image_index
));
1270 _dyld_get_image_name(uint32_t image_index
)
1272 DYLD_NO_LOCK_THIS_BLOCK
;
1273 static const char* (*p
)(uint32_t image_index
) = NULL
;
1276 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1277 return(p(image_index
));
1280 // SPI in Mac OS X 10.6
1281 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1283 DYLD_NO_LOCK_THIS_BLOCK
;
1284 static intptr_t (*p
)(const struct mach_header
*) = NULL
;
1287 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
);
1293 _dyld_image_containing_address(const void* address
)
1295 DYLD_LOCK_THIS_BLOCK
;
1296 static bool (*p
)(const void*) = NULL
;
1299 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1303 const struct mach_header
*
1304 _dyld_get_image_header_containing_address(
1305 const void* address
)
1307 DYLD_LOCK_THIS_BLOCK
;
1308 static const struct mach_header
* (*p
)(const void*) = NULL
;
1311 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1316 #if DEPRECATED_APIS_SUPPORTED
1317 bool _dyld_launched_prebound(void)
1319 DYLD_LOCK_THIS_BLOCK
;
1320 static bool (*p
)(void) = NULL
;
1323 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1327 bool _dyld_all_twolevel_modules_prebound(void)
1329 DYLD_LOCK_THIS_BLOCK
;
1330 static bool (*p
)(void) = NULL
;
1333 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1336 #endif // DEPRECATED_APIS_SUPPORTED
1341 #include <pthread.h>
1343 #include <mach-o/dyld.h>
1344 #include <servers/bootstrap.h>
1345 #include "dyldLibSystemInterface.h"
1348 // pthread key used to access per-thread dlerror message
1349 static pthread_key_t dlerrorPerThreadKey
;
1350 static bool dlerrorPerThreadKeyInitialized
= false;
1352 // data kept per-thread
1353 struct dlerrorPerThreadData
1355 size_t sizeAllocated
;
1359 // function called by dyld to get buffer to store dlerror message
1360 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
1362 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1363 if (!dlerrorPerThreadKeyInitialized
) {
1364 // create key and tell pthread package to call free() on any data associated with key if thread dies
1365 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1366 dlerrorPerThreadKeyInitialized
= true;
1369 const size_t size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1370 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1371 if ( data
== NULL
) {
1372 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1373 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1374 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1375 data
->sizeAllocated
= size
;
1376 pthread_setspecific(dlerrorPerThreadKey
, data
);
1378 else if ( data
->sizeAllocated
< sizeRequired
) {
1380 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1381 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1382 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1383 data
->sizeAllocated
= size
;
1384 pthread_setspecific(dlerrorPerThreadKey
, data
);
1386 return data
->message
;
1389 // <rdar://problem/10595338> dlerror buffer leak
1390 // Only allocate buffer if an actual error message needs to be set
1391 static bool hasPerThreadBufferFor_dlerror()
1393 if (!dlerrorPerThreadKeyInitialized
)
1396 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1399 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1400 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1401 static vswapproc swapProc
= &vproc_swap_integer
;
1403 static bool isLaunchdOwned()
1406 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1407 return ( val
!= 0 );
1410 #if DYLD_SHARED_CACHE_SUPPORT
1411 static void shared_cache_missing()
1413 // leave until dyld's that might call this are rare
1416 static void shared_cache_out_of_date()
1418 // leave until dyld's that might call this are rare
1420 #endif // DYLD_SHARED_CACHE_SUPPORT
1423 // the table passed to dyld containing thread helpers
1424 static dyld::LibSystemHelpers sHelpers
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1425 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1426 #if DYLD_SHARED_CACHE_SUPPORT
1427 &shared_cache_missing
, &shared_cache_out_of_date
,
1432 &pthread_key_create
, &pthread_setspecific
,
1434 &pthread_getspecific
,
1437 &hasPerThreadBufferFor_dlerror
,
1441 &__cxa_finalize_ranges
1446 // during initialization of libSystem this routine will run
1447 // and call dyld, registering the helper functions.
1449 extern "C" void tlv_initializer();
1450 extern "C" void _dyld_initializer();
1451 void _dyld_initializer()
1453 void (*p
)(dyld::LibSystemHelpers
*);
1455 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1465 DYLD_LOCK_THIS_BLOCK
;
1466 static char* (*p
)() = NULL
;
1469 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1473 int dladdr(const void* addr
, Dl_info
* info
)
1475 DYLD_LOCK_THIS_BLOCK
;
1476 static int (*p
)(const void* , Dl_info
*) = NULL
;
1479 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1480 return(p(addr
, info
));
1483 int dlclose(void* handle
)
1485 DYLD_LOCK_THIS_BLOCK
;
1486 static int (*p
)(void* handle
) = NULL
;
1489 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1493 void* dlopen(const char* path
, int mode
)
1495 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1496 DYLD_NO_LOCK_THIS_BLOCK
;
1498 static void* (*p
)(const char* path
, int) = NULL
;
1501 _dyld_func_lookup("__dyld_dlopen", (void**)&p
);
1502 void* result
= p(path
, mode
);
1503 // use asm block to prevent tail call optimization
1504 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1505 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1506 __asm__
volatile("");
1511 bool dlopen_preflight(const char* path
)
1513 DYLD_LOCK_THIS_BLOCK
;
1514 static bool (*p
)(const char* path
) = NULL
;
1517 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1521 void* dlsym(void* handle
, const char* symbol
)
1523 DYLD_LOCK_THIS_BLOCK
;
1524 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1527 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1528 return(p(handle
, symbol
));
1532 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1534 DYLD_NO_LOCK_THIS_BLOCK
;
1535 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1538 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1542 #if SUPPORT_ZERO_COST_EXCEPTIONS
1543 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1545 DYLD_NO_LOCK_THIS_BLOCK
;
1546 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1549 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1550 return p(addr
, info
);
1555 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1556 __attribute__((visibility("hidden")))
1557 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1559 DYLD_NO_LOCK_THIS_BLOCK
;
1560 static void* (*p
)(void*, long) = NULL
;
1563 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1564 return p(loadercache
, lazyinfo
);
1569 const char* dyld_image_path_containing_address(const void* addr
)
1571 DYLD_NO_LOCK_THIS_BLOCK
;
1572 static const char* (*p
)(const void*) = NULL
;
1575 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1579 const struct mach_header
* dyld_image_header_containing_address(const void* addr
)
1581 DYLD_NO_LOCK_THIS_BLOCK
;
1582 static const mach_header
* (*p
)(const void*) = NULL
;
1585 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1590 bool dyld_shared_cache_some_image_overridden()
1592 DYLD_NO_LOCK_THIS_BLOCK
;
1593 static bool (*p
)() = NULL
;
1596 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1600 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
1602 DYLD_NO_LOCK_THIS_BLOCK
;
1603 static bool (*p
)(uuid_t
) = NULL
;
1606 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
);
1611 bool dyld_process_is_restricted()
1613 DYLD_NO_LOCK_THIS_BLOCK
;
1614 static bool (*p
)() = NULL
;
1617 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1621 #if DYLD_SHARED_CACHE_SUPPORT
1622 const char* dyld_shared_cache_file_path()
1624 DYLD_NO_LOCK_THIS_BLOCK
;
1625 static const char* (*p
)() = NULL
;
1628 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
);
1633 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1635 DYLD_LOCK_THIS_BLOCK
;
1636 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1639 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1640 p(mh
, array
, count
);
1644 // SPI called __fork
1645 void _dyld_fork_child()
1647 DYLD_NO_LOCK_THIS_BLOCK
;
1648 static void (*p
)() = NULL
;
1651 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);
1657 static void* mapStartOfCache(const char* path
, size_t length
)
1659 struct stat statbuf
;
1660 if ( ::stat(path
, &statbuf
) == -1 )
1663 if ( statbuf
.st_size
< length
)
1666 int cache_fd
= ::open(path
, O_RDONLY
);
1670 void* result
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
1673 if ( result
== MAP_FAILED
)
1680 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
)
1682 DIR* dirp
= ::opendir(dirPath
);
1683 if ( dirp
!= NULL
) {
1685 dirent
* entp
= NULL
;
1686 char cachePath
[PATH_MAX
];
1687 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) {
1690 if ( entp
->d_type
!= DT_REG
)
1692 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
1694 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
1696 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
1698 if ( const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)mapStartOfCache(cachePath
, 0x00100000) ) {
1699 if ( ::memcmp(cacheHeader
->uuid
, cacheUuid
, 16) != 0 ) {
1700 // wrong uuid, unmap and keep looking
1701 ::munmap((void*)cacheHeader
, 0x00100000);
1715 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid
, const char* extraSearchDirs
[], void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1717 const dyld_cache_header
* cacheHeader
= NULL
;
1718 bool needToUnmap
= true;
1720 // get info from dyld about this process, to see if requested cache is already mapped into this process
1721 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1722 if ( (allInfo
!= NULL
) && (memcmp(allInfo
->sharedCacheUUID
, cacheUuid
, 16) == 0) ) {
1723 // requested cache is already mapped, just re-use it
1724 cacheHeader
= (dyld_cache_header
*)(SHARED_REGION_BASE
+ allInfo
->sharedCacheSlide
);
1725 needToUnmap
= false;
1728 // look first is default location for cache files
1729 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1730 const char* defaultSearchDir
= IPHONE_DYLD_SHARED_CACHE_DIR
;
1732 const char* defaultSearchDir
= MACOSX_DYLD_SHARED_CACHE_DIR
;
1734 cacheHeader
= findCacheInDirAndMap(cacheUuid
, defaultSearchDir
);
1735 // if not there, look in extra search locations
1736 if ( cacheHeader
== NULL
) {
1737 for (const char** p
= extraSearchDirs
; *p
!= NULL
; ++p
) {
1738 cacheHeader
= findCacheInDirAndMap(cacheUuid
, *p
);
1739 if ( cacheHeader
!= NULL
)
1745 if ( cacheHeader
== NULL
)
1748 if ( cacheHeader
->mappingOffset
< sizeof(dyld_cache_header
) ) {
1749 // old cache without imagesText array
1751 ::munmap((void*)cacheHeader
, 0x00100000);
1755 // walk imageText table and call callback for each entry
1756 const dyld_cache_image_text_info
* imagesText
= (dyld_cache_image_text_info
*)((char*)cacheHeader
+ cacheHeader
->imagesTextOffset
);
1757 const dyld_cache_image_text_info
* imagesTextEnd
= &imagesText
[cacheHeader
->imagesTextCount
];
1758 for (const dyld_cache_image_text_info
* p
=imagesText
; p
< imagesTextEnd
; ++p
) {
1759 dyld_shared_cache_dylib_text_info dylibTextInfo
;
1760 dylibTextInfo
.version
= 1;
1761 dylibTextInfo
.loadAddressUnslid
= p
->loadAddress
;
1762 dylibTextInfo
.textSegmentSize
= p
->textSegmentSize
;
1763 dylibTextInfo
.path
= (char*)cacheHeader
+ p
->pathOffset
;
1764 ::memcpy(dylibTextInfo
.dylibUuid
, p
->uuid
, 16);
1765 callback(&dylibTextInfo
);
1769 ::munmap((void*)cacheHeader
, 0x00100000);
1774 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1776 const char* extraSearchDirs
[] = { NULL
};
1777 return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
1781 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
1783 DYLD_NO_LOCK_THIS_BLOCK
;
1784 static bool (*p
)(const void*, size_t) = NULL
;
1787 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
);
1788 return p(addr
, length
);
1792 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
1793 _dyld_objc_notify_init init
,
1794 _dyld_objc_notify_unmapped unmapped
)
1796 DYLD_LOCK_THIS_BLOCK
;
1797 static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
;
1800 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
);
1801 p(mapped
, init
, unmapped
);