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 #include "../dyld3/APIs.h"
47 #include "../dyld3/AllImages.h"
50 // this was in dyld_priv.h but it is no longer exported
52 const struct dyld_all_image_infos
* _dyld_get_all_image_infos() __attribute__((visibility("hidden")));
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
);
61 // private interface between libSystem.dylib and dyld
63 extern "C" int _dyld_func_lookup(const char* dyld_func_name
, void **address
);
66 extern bool gUseDyld3
;
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 */
79 #ifndef LC_VERSION_MIN_IPHONEOS
80 #define LC_VERSION_MIN_IPHONEOS 0x25
83 #ifndef LC_VERSION_MIN_TVOS
84 #define LC_VERSION_MIN_TVOS 0x2F
87 #ifndef LC_VERSION_MIN_WATCHOS
88 #define LC_VERSION_MIN_WATCHOS 0x30
92 #ifndef LC_LOAD_UPWARD_DYLIB
93 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
96 #ifndef LC_BUILD_VERSION
97 #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */
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.
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 */
114 struct build_tool_version
{
115 uint32_t tool
; /* enum for the tool */
116 uint32_t version
; /* version number of the tool */
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
126 /* Known values for the tool field above. */
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
137 #define DEPRECATED_APIS_SUPPORTED 1
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.
149 const char *install_name
,
150 const char* libraryName
)
152 const char *basename
;
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
162 basename
= strrchr(install_name
, '/');
164 basename
= install_name
;
169 * By checking the base name matching the library name we take care
170 * of the -framework cases.
172 if(strcmp(basename
, libraryName
) == 0)
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.
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)
184 if(basename
[3+n
] == '.' &&
185 basename
[3+n
+1] != '\0' &&
186 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
193 #if DEPRECATED_APIS_SUPPORTED
195 void NSInstallLinkEditErrorHandlers(
196 const NSLinkEditErrorHandlers
* handlers
)
199 return dyld3::NSInstallLinkEditErrorHandlers(handlers
);
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
;
209 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
210 mcallback_t m
= handlers
->multiple
;
211 p(handlers
->undefined
, m
, handlers
->linkEdit
);
219 return dyld3::NSNameOfModule(module);
221 DYLD_LOCK_THIS_BLOCK
;
222 static const char* (*p
)(NSModule
module) = NULL
;
225 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
230 NSLibraryNameForModule(
234 return dyld3::NSLibraryNameForModule(module);
236 DYLD_LOCK_THIS_BLOCK
;
237 static const char* (*p
)(NSModule
module) = NULL
;
240 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
245 NSIsSymbolNameDefined(
246 const char* symbolName
)
249 return dyld3::NSIsSymbolNameDefined(symbolName
);
251 DYLD_LOCK_THIS_BLOCK
;
252 static bool (*p
)(const char* symbolName
) = NULL
;
255 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
256 return(p(symbolName
));
260 NSIsSymbolNameDefinedWithHint(
261 const char* symbolName
,
262 const char* libraryNameHint
)
265 return dyld3::NSIsSymbolNameDefinedWithHint(symbolName
, libraryNameHint
);
267 DYLD_LOCK_THIS_BLOCK
;
268 static bool (*p
)(const char* symbolName
,
269 const char* libraryNameHint
) = NULL
;
272 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
273 return(p(symbolName
, libraryNameHint
));
277 NSIsSymbolNameDefinedInImage(
278 const struct mach_header
*image
,
279 const char* symbolName
)
282 return dyld3::NSIsSymbolNameDefinedInImage(image
, symbolName
);
284 DYLD_LOCK_THIS_BLOCK
;
285 static bool (*p
)(const struct mach_header
*image
,
286 const char* symbolName
) = NULL
;
289 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
290 return(p(image
, symbolName
));
294 NSLookupAndBindSymbol(
295 const char* symbolName
)
298 return dyld3::NSLookupAndBindSymbol(symbolName
);
300 DYLD_LOCK_THIS_BLOCK
;
301 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
304 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
305 return(p(symbolName
));
309 NSLookupAndBindSymbolWithHint(
310 const char* symbolName
,
311 const char* libraryNameHint
)
314 return dyld3::NSLookupAndBindSymbolWithHint(symbolName
, libraryNameHint
);
316 DYLD_LOCK_THIS_BLOCK
;
317 static NSSymbol (*p
)(const char* symbolName
,
318 const char* libraryNameHint
) = NULL
;
321 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
322 return(p(symbolName
, libraryNameHint
));
326 NSLookupSymbolInModule(
328 const char* symbolName
)
331 return dyld3::NSLookupSymbolInModule(module, symbolName
);
333 DYLD_LOCK_THIS_BLOCK
;
334 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
337 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
338 return(p(module, symbolName
));
342 NSLookupSymbolInImage(
343 const struct mach_header
*image
,
344 const char* symbolName
,
348 return dyld3::NSLookupSymbolInImage(image
, symbolName
, options
);
350 DYLD_LOCK_THIS_BLOCK
;
351 static NSSymbol (*p
)(const struct mach_header
*image
,
352 const char* symbolName
,
353 uint32_t options
) = NULL
;
356 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
357 return(p(image
, symbolName
, options
));
365 return dyld3::NSNameOfSymbol(symbol
);
367 DYLD_LOCK_THIS_BLOCK
;
368 static char * (*p
)(NSSymbol symbol
) = NULL
;
371 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
380 return dyld3::NSAddressOfSymbol(symbol
);
382 DYLD_LOCK_THIS_BLOCK
;
383 static void * (*p
)(NSSymbol symbol
) = NULL
;
386 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
395 return dyld3::NSModuleForSymbol(symbol
);
397 DYLD_LOCK_THIS_BLOCK
;
398 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
401 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
407 const char* pathName
)
410 return dyld3::NSAddLibrary(pathName
);
412 DYLD_LOCK_THIS_BLOCK
;
413 static bool (*p
)(const char* pathName
) = NULL
;
416 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
421 NSAddLibraryWithSearching(
422 const char* pathName
)
425 return dyld3::NSAddLibrary(pathName
);
427 DYLD_LOCK_THIS_BLOCK
;
428 static bool (*p
)(const char* pathName
) = NULL
;
431 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
435 const struct mach_header
*
437 const char* image_name
,
441 return dyld3::NSAddImage(image_name
, options
);
443 DYLD_LOCK_THIS_BLOCK
;
444 static const struct mach_header
* (*p
)(const char* image_name
,
445 uint32_t options
) = NULL
;
448 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
449 return(p(image_name
, options
));
451 #endif // DEPRECATED_APIS_SUPPORTED
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.
464 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
467 return dyld3::NSVersionOfLinkTimeLibrary(libraryName
);
469 // Lazily call _NSGetMachExecuteHeader() and cache result
471 static mach_header_64
* mh
= NULL
;
473 static mach_header
* mh
= NULL
;
476 mh
= _NSGetMachExecuteHeader();
478 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
480 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
482 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
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
;
493 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
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.
505 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
508 return dyld3::NSVersionOfRunTimeLibrary(libraryName
);
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
);
515 if ( mh
->filetype
!= MH_DYLIB
)
518 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
520 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
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
;
529 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
536 #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
539 static bool getVersionLoadCommandInfo(const mach_header
* mh
, uint32_t* platform
, uint32_t* minOS
, uint32_t* sdk
)
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
));
547 return false; // not a mach-o file, or wrong endianness
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
)) {
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
;
565 case LC_VERSION_MIN_MACOSX
:
566 versCmd
= (version_min_command
*)cmd
;
567 *platform
= PLATFORM_MACOS
;
568 *minOS
= versCmd
->version
;
571 case LC_VERSION_MIN_TVOS
:
572 versCmd
= (version_min_command
*)cmd
;
573 *platform
= PLATFORM_TVOS
;
574 *minOS
= versCmd
->version
;
577 case LC_VERSION_MIN_WATCHOS
:
578 versCmd
= (version_min_command
*)cmd
;
579 *platform
= PLATFORM_WATCHOS
;
580 *minOS
= versCmd
->version
;
583 case LC_BUILD_VERSION
:
584 buildVersCmd
= (build_version_command
*)cmd
;
585 *platform
= buildVersCmd
->platform
;
586 *minOS
= buildVersCmd
->minos
;
587 *sdk
= buildVersCmd
->sdk
;
595 #if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED
596 static uint32_t deriveSDKVersFromDylibs(const mach_header
* mh
)
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
));
604 return 0; // not a mach-o file, or wrong endianness
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;
613 uint32_t libSystemVers
= 0;
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
)) {
621 switch ( cmd
->cmd
) {
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
)
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
;
634 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 )
635 libSystemVers
= dylibCmd
->dylib
.current_version
;
642 struct DylibToOSMapping
{
643 uint32_t dylibVersion
;
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.
669 if ( foundationVers
!= 0 ) {
670 uint32_t lastOsVersion
= 0;
671 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) {
672 if ( p
->dylibVersion
== 0 )
674 if ( foundationVers
< p
->dylibVersion
)
675 return lastOsVersion
;
676 lastOsVersion
= p
->osVersion
;
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.
697 if ( libSystemVers
!= 0 ) {
698 uint32_t lastOsVersion
= 0;
699 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) {
700 if ( p
->dylibVersion
== 0 )
702 if ( libSystemVers
< p
->dylibVersion
)
703 return lastOsVersion
;
704 lastOsVersion
= p
->osVersion
;
713 #if __WATCH_OS_VERSION_MIN_REQUIRED
714 static uint32_t watchVersToIOSVers(uint32_t vers
)
716 return vers
+ 0x00070000;
719 uint32_t dyld_get_program_sdk_watch_os_version()
722 return dyld3::dyld_get_program_sdk_watch_os_version();
724 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
729 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
730 if ( platform
== PLATFORM_WATCHOS
)
736 uint32_t dyld_get_program_min_watch_os_version()
739 return dyld3::dyld_get_program_min_watch_os_version();
741 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
746 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
747 if ( platform
== PLATFORM_WATCHOS
)
748 return minOS
; // return raw minOS (not mapped to iOS version)
758 static uint32_t bridgeVersToIOSVers(uint32_t vers
)
760 return vers
+ 0x00090000;
763 uint32_t dyld_get_program_sdk_bridge_os_version()
765 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
770 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
771 if ( platform
== PLATFORM_BRIDGEOS
)
777 uint32_t dyld_get_program_min_bridge_os_version()
779 const mach_header
* mh
= (mach_header
*)_NSGetMachExecuteHeader();
784 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
785 if ( platform
== PLATFORM_BRIDGEOS
)
786 return minOS
; // return raw minOS (not mapped to iOS version)
794 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
795 * specified binary was built against.
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.
802 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
805 return dyld3::dyld_get_sdk_version(mh
);
811 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
814 case PLATFORM_BRIDGEOS
:
815 // new binary. sdk version looks like "2.0" but API wants "11.0"
816 return bridgeVersToIOSVers(sdk
);
818 // old binary. sdk matches API semantics so can return directly.
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
);
825 // old binary. sdk matches API semantics so can return directly.
827 #elif __TV_OS_VERSION_MIN_REQUIRED
831 #elif __IPHONE_OS_VERSION_MIN_REQUIRED
833 if ( sdk
!= 0 ) // old binaries might not have SDK set
838 if ( sdk
!= 0 ) // old binaries might not have SDK set
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.
849 // MacOSX and iOS have old binaries without version load commmand.
850 return deriveSDKVersFromDylibs(mh
);
854 uint32_t dyld_get_program_sdk_version()
857 return dyld3::dyld_get_program_sdk_version();
859 return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
862 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
865 return dyld3::dyld_get_min_os_version(mh
);
871 if ( getVersionLoadCommandInfo(mh
, &platform
, &minOS
, &sdk
) ) {
874 case PLATFORM_BRIDGEOS
:
875 // new binary. sdk version looks like "2.0" but API wants "11.0"
876 return bridgeVersToIOSVers(minOS
);
878 // old binary. sdk matches API semantics so can return directly.
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
);
885 // old binary. OS matches API semantics so can return directly.
887 #elif __TV_OS_VERSION_MIN_REQUIRED
891 #elif __IPHONE_OS_VERSION_MIN_REQUIRED
904 uint32_t dyld_get_program_min_os_version()
907 return dyld3::dyld_get_program_min_os_version();
909 return dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
913 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
)
916 return dyld3::_dyld_get_image_uuid(mh
, uuid
);
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
));
924 return false; // not a mach-o file, or wrong endianness
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
)) {
933 if ( cmd
->cmd
== LC_UUID
) {
934 const uuid_command
* uuidCmd
= (uuid_command
*)cmd
;
935 memcpy(uuid
, uuidCmd
->uuid
, 16);
946 #if DEPRECATED_APIS_SUPPORTED
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.
954 NSObjectFileImageReturnCode
955 NSCreateObjectFileImageFromFile(
956 const char* pathName
,
957 NSObjectFileImage
*objectFileImage
)
960 return dyld3::NSCreateObjectFileImageFromFile(pathName
, objectFileImage
);
962 DYLD_LOCK_THIS_BLOCK
;
963 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
966 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
967 return p(pathName
, objectFileImage
);
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.
978 NSObjectFileImageReturnCode
979 NSCreateObjectFileImageFromMemory(
982 NSObjectFileImage
*objectFileImage
)
985 return dyld3::NSCreateObjectFileImageFromMemory(address
, size
, objectFileImage
);
987 DYLD_LOCK_THIS_BLOCK
;
988 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
991 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
992 return p(address
, size
, objectFileImage
);
995 #if OBSOLETE_DYLD_API
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.
1002 NSObjectFileImageReturnCode
1003 NSCreateCoreFileImageFromFile(
1004 const char* pathName
,
1005 NSObjectFileImage
*objectFileImage
)
1007 DYLD_LOCK_THIS_BLOCK
;
1008 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
1011 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
1012 return p(pathName
, objectFileImage
);
1017 NSDestroyObjectFileImage(
1018 NSObjectFileImage objectFileImage
)
1021 return dyld3::NSDestroyObjectFileImage(objectFileImage
);
1023 DYLD_LOCK_THIS_BLOCK
;
1024 static bool (*p
)(NSObjectFileImage
) = NULL
;
1027 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
1028 return p(objectFileImage
);
1034 NSObjectFileImage objectFileImage
,
1035 const char* moduleName
,
1039 return dyld3::NSLinkModule(objectFileImage
, moduleName
, options
);
1041 DYLD_LOCK_THIS_BLOCK
;
1042 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
1045 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
1047 return p(objectFileImage
, moduleName
, options
);
1054 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
1055 * definitions in the NSObjectFileImage.
1058 NSSymbolDefinitionCountInObjectFileImage(
1059 NSObjectFileImage objectFileImage
)
1062 return dyld3::NSSymbolDefinitionCountInObjectFileImage(objectFileImage
);
1064 DYLD_LOCK_THIS_BLOCK
;
1065 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
1068 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
1070 return p(objectFileImage
);
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
1080 NSSymbolDefinitionNameInObjectFileImage(
1081 NSObjectFileImage objectFileImage
,
1085 return dyld3::NSSymbolDefinitionNameInObjectFileImage(objectFileImage
, ordinal
);
1087 DYLD_LOCK_THIS_BLOCK
;
1088 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
1091 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
1093 return p(objectFileImage
, ordinal
);
1097 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
1098 * to undefined symbols the NSObjectFileImage.
1101 NSSymbolReferenceCountInObjectFileImage(
1102 NSObjectFileImage objectFileImage
)
1105 return dyld3::NSSymbolReferenceCountInObjectFileImage(objectFileImage
);
1107 DYLD_LOCK_THIS_BLOCK
;
1108 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
1111 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
1113 return p(objectFileImage
);
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
1123 NSSymbolReferenceNameInObjectFileImage(
1124 NSObjectFileImage objectFileImage
,
1126 bool *tentative_definition
) /* can be NULL */
1129 return dyld3::NSSymbolReferenceNameInObjectFileImage(objectFileImage
, ordinal
, tentative_definition
);
1131 DYLD_LOCK_THIS_BLOCK
;
1132 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
1135 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
1137 return p(objectFileImage
, ordinal
, tentative_definition
);
1141 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
1142 * name has a definition in the NSObjectFileImage and FALSE otherwise.
1145 NSIsSymbolDefinedInObjectFileImage(
1146 NSObjectFileImage objectFileImage
,
1147 const char* symbolName
)
1150 return dyld3::NSIsSymbolDefinedInObjectFileImage(objectFileImage
, symbolName
);
1152 DYLD_LOCK_THIS_BLOCK
;
1153 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
1156 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
1158 return p(objectFileImage
, symbolName
);
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.
1169 NSGetSectionDataInObjectFileImage(
1170 NSObjectFileImage objectFileImage
,
1171 const char* segmentName
,
1172 const char* sectionName
,
1173 unsigned long *size
) /* can be NULL */
1176 return dyld3::NSGetSectionDataInObjectFileImage(objectFileImage
, segmentName
, sectionName
, size
);
1178 DYLD_LOCK_THIS_BLOCK
;
1179 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
1182 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
1184 return p(objectFileImage
, segmentName
, sectionName
, size
);
1190 NSLinkEditErrors
*c
,
1192 const char* *fileName
,
1193 const char* *errorString
)
1196 return dyld3::NSLinkEditError(c
, errorNumber
, fileName
, errorString
);
1198 DYLD_LOCK_THIS_BLOCK
;
1199 static void (*p
)(NSLinkEditErrors
*c
,
1201 const char* *fileName
,
1202 const char* *errorString
) = NULL
;
1205 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
1207 p(c
, errorNumber
, fileName
, errorString
);
1216 return dyld3::NSUnLinkModule(module, options
);
1218 DYLD_LOCK_THIS_BLOCK
;
1219 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
1222 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
1224 return p(module, options
);
1227 #if OBSOLETE_DYLD_API
1230 NSModule moduleToReplace
,
1231 NSObjectFileImage newObjectFileImage
,
1239 #endif // DEPRECATED_APIS_SUPPORTED
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.
1251 _NSGetExecutablePath(
1256 return dyld3::_NSGetExecutablePath(buf
, bufsize
);
1258 DYLD_NO_LOCK_THIS_BLOCK
;
1259 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
1262 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
1263 return(p(buf
, bufsize
));
1266 #if DEPRECATED_APIS_SUPPORTED
1268 _dyld_lookup_and_bind(
1269 const char* symbol_name
,
1273 DYLD_LOCK_THIS_BLOCK
;
1274 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
1277 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
1278 p(symbol_name
, address
, module);
1282 _dyld_lookup_and_bind_with_hint(
1283 const char* symbol_name
,
1284 const char* library_name_hint
,
1288 DYLD_LOCK_THIS_BLOCK
;
1289 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
1292 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
1293 p(symbol_name
, library_name_hint
, address
, module);
1296 #if OBSOLETE_DYLD_API
1298 _dyld_lookup_and_bind_objc(
1299 const char* symbol_name
,
1303 DYLD_LOCK_THIS_BLOCK
;
1304 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
1307 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
1308 p(symbol_name
, address
, module);
1313 _dyld_lookup_and_bind_fully(
1314 const char* symbol_name
,
1318 DYLD_LOCK_THIS_BLOCK
;
1319 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
1322 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
1323 p(symbol_name
, address
, module);
1327 _dyld_bind_fully_image_containing_address(
1328 const void* address
)
1330 DYLD_LOCK_THIS_BLOCK
;
1331 static bool (*p
)(const void*) = NULL
;
1334 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
1337 #endif // DEPRECATED_APIS_SUPPORTED
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.
1347 _dyld_register_func_for_add_image(
1348 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1351 return dyld3::_dyld_register_func_for_add_image(func
);
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
;
1358 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
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
1368 _dyld_register_func_for_remove_image(
1369 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1372 return dyld3::_dyld_register_func_for_remove_image(func
);
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
;
1379 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1383 #if OBSOLETE_DYLD_API
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
1391 _dyld_register_func_for_link_module(
1392 void (*func
)(NSModule
module))
1394 DYLD_LOCK_THIS_BLOCK
;
1395 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1398 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1403 * _dyld_register_func_for_unlink_module registers the specified function to be
1404 * called when a module is unbound from the program.
1407 _dyld_register_func_for_unlink_module(
1408 void (*func
)(NSModule
module))
1410 DYLD_LOCK_THIS_BLOCK
;
1411 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1414 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
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.
1423 _dyld_register_func_for_replace_module(
1424 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1426 DYLD_LOCK_THIS_BLOCK
;
1427 static void (*p
)(void (*func
)(NSModule oldmodule
,
1428 NSModule newmodule
)) = NULL
;
1431 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
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
1442 _dyld_get_objc_module_sect_for_module(
1445 unsigned long *size
)
1447 DYLD_LOCK_THIS_BLOCK
;
1448 static void (*p
)(NSModule
module,
1450 unsigned long *size
) = NULL
;
1453 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1454 p(module, objc_module
, size
);
1459 #if DEPRECATED_APIS_SUPPORTED
1463 // this function exists for compatiblity only
1469 _dyld_image_count(void)
1472 return dyld3::_dyld_image_count();
1474 DYLD_NO_LOCK_THIS_BLOCK
;
1475 static uint32_t (*p
)(void) = NULL
;
1478 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1482 const struct mach_header
*
1483 _dyld_get_image_header(uint32_t image_index
)
1486 return dyld3::_dyld_get_image_header(image_index
);
1488 DYLD_NO_LOCK_THIS_BLOCK
;
1489 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1492 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1493 return(p(image_index
));
1497 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1500 return dyld3::_dyld_get_image_vmaddr_slide(image_index
);
1502 DYLD_NO_LOCK_THIS_BLOCK
;
1503 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1506 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1507 return(p(image_index
));
1511 _dyld_get_image_name(uint32_t image_index
)
1514 return dyld3::_dyld_get_image_name(image_index
);
1516 DYLD_NO_LOCK_THIS_BLOCK
;
1517 static const char* (*p
)(uint32_t image_index
) = NULL
;
1520 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1521 return(p(image_index
));
1524 // SPI in Mac OS X 10.6
1525 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1528 return dyld3::_dyld_get_image_slide(mh
);
1530 DYLD_NO_LOCK_THIS_BLOCK
;
1531 static intptr_t (*p
)(const struct mach_header
*) = NULL
;
1534 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
);
1539 #if DEPRECATED_APIS_SUPPORTED
1541 _dyld_image_containing_address(const void* address
)
1544 return dyld3::_dyld_image_containing_address(address
);
1546 DYLD_LOCK_THIS_BLOCK
;
1547 static bool (*p
)(const void*) = NULL
;
1550 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1554 const struct mach_header
*
1555 _dyld_get_image_header_containing_address(
1556 const void* address
)
1559 return dyld3::_dyld_get_image_header_containing_address(address
);
1561 DYLD_LOCK_THIS_BLOCK
;
1562 static const struct mach_header
* (*p
)(const void*) = NULL
;
1565 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1569 bool _dyld_launched_prebound(void)
1571 DYLD_LOCK_THIS_BLOCK
;
1572 static bool (*p
)(void) = NULL
;
1575 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1579 bool _dyld_all_twolevel_modules_prebound(void)
1581 DYLD_LOCK_THIS_BLOCK
;
1582 static bool (*p
)(void) = NULL
;
1585 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1588 #endif // DEPRECATED_APIS_SUPPORTED
1593 #include <pthread.h>
1595 #include <mach-o/dyld.h>
1596 #include <servers/bootstrap.h>
1597 #include "dyldLibSystemInterface.h"
1600 // pthread key used to access per-thread dlerror message
1601 static pthread_key_t dlerrorPerThreadKey
;
1602 static bool dlerrorPerThreadKeyInitialized
= false;
1604 // data kept per-thread
1605 struct dlerrorPerThreadData
1607 size_t sizeAllocated
;
1611 // function called by dyld to get buffer to store dlerror message
1612 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
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;
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
);
1630 else if ( data
->sizeAllocated
< sizeRequired
) {
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
);
1638 return data
->message
;
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()
1645 if (!dlerrorPerThreadKeyInitialized
)
1648 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
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
;
1655 static bool isLaunchdOwned()
1658 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1659 return ( val
!= 0 );
1662 static void shared_cache_missing()
1664 // leave until dyld's that might call this are rare
1667 static void shared_cache_out_of_date()
1669 // leave until dyld's that might call this are rare
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
,
1678 &pthread_key_create
, &pthread_setspecific
,
1680 &pthread_getspecific
,
1683 &hasPerThreadBufferFor_dlerror
,
1687 &__cxa_finalize_ranges
1692 // during initialization of libSystem this routine will run
1693 // and call dyld, registering the helper functions.
1695 extern "C" void tlv_initializer();
1696 void _dyld_initializer()
1698 void (*p
)(dyld::LibSystemHelpers
*);
1701 dyld3::gAllImages
.applyInitialImages();
1704 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1716 return dyld3::dlerror();
1718 DYLD_LOCK_THIS_BLOCK
;
1719 static char* (*p
)() = NULL
;
1722 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1726 int dladdr(const void* addr
, Dl_info
* info
)
1729 return dyld3::dladdr(addr
, info
);
1731 DYLD_LOCK_THIS_BLOCK
;
1732 static int (*p
)(const void* , Dl_info
*) = NULL
;
1735 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1736 return(p(addr
, info
));
1739 int dlclose(void* handle
)
1742 return dyld3::dlclose(handle
);
1744 DYLD_LOCK_THIS_BLOCK
;
1745 static int (*p
)(void* handle
) = NULL
;
1748 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1752 void* dlopen(const char* path
, int mode
)
1755 return dyld3::dlopen(path
, mode
);
1757 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1758 DYLD_NO_LOCK_THIS_BLOCK
;
1760 static void* (*p
)(const char* path
, int) = 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("");
1773 bool dlopen_preflight(const char* path
)
1776 return dyld3::dlopen_preflight(path
);
1778 DYLD_LOCK_THIS_BLOCK
;
1779 static bool (*p
)(const char* path
) = NULL
;
1782 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1786 void* dlsym(void* handle
, const char* symbol
)
1789 return dyld3::dlsym(handle
, symbol
);
1791 DYLD_LOCK_THIS_BLOCK
;
1792 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1795 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1796 return(p(handle
, symbol
));
1799 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1802 return dyld3::_dyld_get_all_image_infos();
1804 DYLD_NO_LOCK_THIS_BLOCK
;
1805 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1808 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1812 #if SUPPORT_ZERO_COST_EXCEPTIONS
1813 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1816 return dyld3::_dyld_find_unwind_sections(addr
, info
);
1818 DYLD_NO_LOCK_THIS_BLOCK
;
1819 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1822 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1823 return p(addr
, info
);
1828 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1829 __attribute__((visibility("hidden")))
1830 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1832 DYLD_NO_LOCK_THIS_BLOCK
;
1833 static void* (*p
)(void*, long) = NULL
;
1836 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1837 return p(loadercache
, lazyinfo
);
1842 const char* dyld_image_path_containing_address(const void* addr
)
1845 return dyld3::dyld_image_path_containing_address(addr
);
1847 DYLD_NO_LOCK_THIS_BLOCK
;
1848 static const char* (*p
)(const void*) = NULL
;
1851 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1855 const struct mach_header
* dyld_image_header_containing_address(const void* addr
)
1858 return dyld3::dyld_image_header_containing_address(addr
);
1860 DYLD_NO_LOCK_THIS_BLOCK
;
1861 static const mach_header
* (*p
)(const void*) = NULL
;
1864 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1869 bool dyld_shared_cache_some_image_overridden()
1872 return dyld3::dyld_shared_cache_some_image_overridden();
1874 DYLD_NO_LOCK_THIS_BLOCK
;
1875 static bool (*p
)() = NULL
;
1878 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1882 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
1885 return dyld3::_dyld_get_shared_cache_uuid(uuid
);
1887 DYLD_NO_LOCK_THIS_BLOCK
;
1888 static bool (*p
)(uuid_t
) = NULL
;
1891 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
);
1895 const void* _dyld_get_shared_cache_range(size_t* length
)
1898 return dyld3::_dyld_get_shared_cache_range(length
);
1900 DYLD_NO_LOCK_THIS_BLOCK
;
1901 static const void* (*p
)(size_t*) = NULL
;
1904 _dyld_func_lookup("__dyld_get_shared_cache_range", (void**)&p
);
1909 bool dyld_process_is_restricted()
1912 return dyld3::dyld_process_is_restricted();
1914 DYLD_NO_LOCK_THIS_BLOCK
;
1915 static bool (*p
)() = NULL
;
1918 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1922 const char* dyld_shared_cache_file_path()
1925 return dyld3::dyld_shared_cache_file_path();
1927 DYLD_NO_LOCK_THIS_BLOCK
;
1928 static const char* (*p
)() = NULL
;
1931 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
);
1935 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1938 return dyld3::dyld_dynamic_interpose(mh
, array
, count
);
1940 DYLD_LOCK_THIS_BLOCK
;
1941 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1944 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1945 p(mh
, array
, count
);
1949 // SPI called __fork
1950 void _dyld_fork_child()
1953 return dyld3::_dyld_fork_child();
1955 DYLD_NO_LOCK_THIS_BLOCK
;
1956 static void (*p
)() = NULL
;
1959 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);
1965 static void* mapStartOfCache(const char* path
, size_t length
)
1967 struct stat statbuf
;
1968 if ( ::stat(path
, &statbuf
) == -1 )
1971 if ( statbuf
.st_size
< length
)
1974 int cache_fd
= ::open(path
, O_RDONLY
);
1978 void* result
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
1981 if ( result
== MAP_FAILED
)
1988 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
)
1990 DIR* dirp
= ::opendir(dirPath
);
1991 if ( dirp
!= NULL
) {
1993 dirent
* entp
= NULL
;
1994 char cachePath
[PATH_MAX
];
1995 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) {
1998 if ( entp
->d_type
!= DT_REG
)
2000 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
2002 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
2004 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
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);
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
))
2026 return dyld3::dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
2028 const dyld_cache_header
* cacheHeader
= NULL
;
2029 bool needToUnmap
= true;
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;
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
;
2043 const char* defaultSearchDir
= MACOSX_DYLD_SHARED_CACHE_DIR
;
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
)
2056 if ( cacheHeader
== NULL
)
2059 if ( cacheHeader
->mappingOffset
< sizeof(dyld_cache_header
) ) {
2060 // old cache without imagesText array
2062 ::munmap((void*)cacheHeader
, 0x00100000);
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
);
2083 ::munmap((void*)cacheHeader
, 0x00100000);
2088 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
2091 return dyld3::dyld_shared_cache_iterate_text(cacheUuid
, callback
);
2093 const char* extraSearchDirs
[] = { NULL
};
2094 return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
2098 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
2101 return dyld3::_dyld_is_memory_immutable(addr
, length
);
2103 DYLD_NO_LOCK_THIS_BLOCK
;
2104 static bool (*p
)(const void*, size_t) = NULL
;
2107 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
);
2108 return p(addr
, length
);
2112 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
2113 _dyld_objc_notify_init init
,
2114 _dyld_objc_notify_unmapped unmapped
)
2117 return dyld3::_dyld_objc_notify_register(mapped
, init
, unmapped
);
2119 DYLD_LOCK_THIS_BLOCK
;
2120 static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
;
2123 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
);
2124 p(mapped
, init
, unmapped
);