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>
31 #include <System/sys/csr.h>
32 #include <crt_externs.h>
33 #include <Availability.h>
34 #if !TARGET_OS_DRIVERKIT
35 #include <vproc_priv.h>
38 #include <sys/types.h>
41 #include <System/sys/codesign.h>
43 #include <mach-o/dyld_images.h>
44 #include <mach-o/dyld.h>
45 #include <mach-o/dyld_priv.h>
47 #include "dyld_cache_format.h"
48 #include "objc-shared-cache.h"
50 #include "ImageLoader.h"
54 #include "AllImages.h"
55 #include "StartGlue.h"
59 // this was in dyld_priv.h but it is no longer exported
61 const struct dyld_all_image_infos
* _dyld_get_all_image_infos() __attribute__((visibility("hidden")));
65 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
66 extern "C" void __cxa_finalize(const void *dso
);
67 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
);
70 // private interface between libSystem.dylib and dyld
72 extern "C" int _dyld_func_lookup(const char* dyld_func_name
, void **address
);
74 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
76 extern int compatFuncLookup(const char* name
, void** address
) __API_AVAILABLE(ios(13.0));
78 extern "C" void setLookupFunc(void*);
82 extern bool gUseDyld3
;
84 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
85 #if __IPHONE_OS_VERSION_MIN_REQUIRED || TARGET_OS_DRIVERKIT
86 #define DEPRECATED_APIS_SUPPORTED 0
88 #define DEPRECATED_APIS_SUPPORTED 1
92 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
93 * libraryName (which is -lx or -framework Foo argument passed to the static
94 * link editor for the same library) and determines if they match. This depends
95 * on conventional use of names including major versioning.
100 const char *install_name
,
101 const char* libraryName
)
103 const char *basename
;
107 * Conventional install names have these forms:
108 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
109 * /Local/Library/Frameworks/AppKit.framework/Appkit
110 * /lib/libsys_s.A.dylib
111 * /usr/lib/libsys_s.dylib
113 basename
= strrchr(install_name
, '/');
115 basename
= install_name
;
120 * By checking the base name matching the library name we take care
121 * of the -framework cases.
123 if(strcmp(basename
, libraryName
) == 0)
127 * Now check the base name for "lib" if so proceed to check for the
128 * -lx case dealing with a possible .X.dylib and a .dylib extension.
130 if(strncmp(basename
, "lib", 3) ==0){
131 n
= strlen(libraryName
);
132 if(strncmp(basename
+3, libraryName
, n
) == 0){
133 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
135 if(basename
[3+n
] == '.' &&
136 basename
[3+n
+1] != '\0' &&
137 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
144 #if DEPRECATED_APIS_SUPPORTED
146 void NSInstallLinkEditErrorHandlers(
147 const NSLinkEditErrorHandlers
* handlers
)
150 return dyld3::NSInstallLinkEditErrorHandlers(handlers
);
152 DYLD_LOCK_THIS_BLOCK
;
153 typedef void (*ucallback_t
)(const char* symbol_name
);
154 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
155 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
156 const char* fileName
, const char* errorString
);
157 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
160 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
161 mcallback_t m
= handlers
->multiple
;
162 p(handlers
->undefined
, m
, handlers
->linkEdit
);
170 return dyld3::NSNameOfModule(module);
172 DYLD_LOCK_THIS_BLOCK
;
173 static const char* (*p
)(NSModule
module) = NULL
;
176 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
181 NSLibraryNameForModule(
185 return dyld3::NSLibraryNameForModule(module);
187 DYLD_LOCK_THIS_BLOCK
;
188 static const char* (*p
)(NSModule
module) = NULL
;
191 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
196 NSIsSymbolNameDefined(
197 const char* symbolName
)
200 return dyld3::NSIsSymbolNameDefined(symbolName
);
202 DYLD_LOCK_THIS_BLOCK
;
203 static bool (*p
)(const char* symbolName
) = NULL
;
206 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
207 return(p(symbolName
));
211 NSIsSymbolNameDefinedWithHint(
212 const char* symbolName
,
213 const char* libraryNameHint
)
216 return dyld3::NSIsSymbolNameDefinedWithHint(symbolName
, libraryNameHint
);
218 DYLD_LOCK_THIS_BLOCK
;
219 static bool (*p
)(const char* symbolName
,
220 const char* libraryNameHint
) = NULL
;
223 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
224 return(p(symbolName
, libraryNameHint
));
228 NSIsSymbolNameDefinedInImage(
229 const struct mach_header
*image
,
230 const char* symbolName
)
233 return dyld3::NSIsSymbolNameDefinedInImage(image
, symbolName
);
235 DYLD_LOCK_THIS_BLOCK
;
236 static bool (*p
)(const struct mach_header
*image
,
237 const char* symbolName
) = NULL
;
240 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
241 return(p(image
, symbolName
));
245 NSLookupAndBindSymbol(
246 const char* symbolName
)
249 return dyld3::NSLookupAndBindSymbol(symbolName
);
251 DYLD_LOCK_THIS_BLOCK
;
252 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
255 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
256 return(p(symbolName
));
260 NSLookupAndBindSymbolWithHint(
261 const char* symbolName
,
262 const char* libraryNameHint
)
265 return dyld3::NSLookupAndBindSymbolWithHint(symbolName
, libraryNameHint
);
267 DYLD_LOCK_THIS_BLOCK
;
268 static NSSymbol (*p
)(const char* symbolName
,
269 const char* libraryNameHint
) = NULL
;
272 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
273 return(p(symbolName
, libraryNameHint
));
277 NSLookupSymbolInModule(
279 const char* symbolName
)
282 return dyld3::NSLookupSymbolInModule(module, symbolName
);
284 DYLD_LOCK_THIS_BLOCK
;
285 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
288 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
289 return(p(module, symbolName
));
293 NSLookupSymbolInImage(
294 const struct mach_header
*image
,
295 const char* symbolName
,
299 return dyld3::NSLookupSymbolInImage(image
, symbolName
, options
);
301 DYLD_LOCK_THIS_BLOCK
;
302 static NSSymbol (*p
)(const struct mach_header
*image
,
303 const char* symbolName
,
304 uint32_t options
) = NULL
;
307 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
308 return(p(image
, symbolName
, options
));
316 return dyld3::NSNameOfSymbol(symbol
);
318 DYLD_LOCK_THIS_BLOCK
;
319 static char * (*p
)(NSSymbol symbol
) = NULL
;
322 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
331 return dyld3::NSAddressOfSymbol(symbol
);
333 DYLD_LOCK_THIS_BLOCK
;
334 static void * (*p
)(NSSymbol symbol
) = NULL
;
337 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
346 return dyld3::NSModuleForSymbol(symbol
);
348 DYLD_LOCK_THIS_BLOCK
;
349 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
352 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
358 const char* pathName
)
361 return dyld3::NSAddLibrary(pathName
);
363 DYLD_LOCK_THIS_BLOCK
;
364 static bool (*p
)(const char* pathName
) = NULL
;
367 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
372 NSAddLibraryWithSearching(
373 const char* pathName
)
376 return dyld3::NSAddLibrary(pathName
);
378 DYLD_LOCK_THIS_BLOCK
;
379 static bool (*p
)(const char* pathName
) = NULL
;
382 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
386 const struct mach_header
*
388 const char* image_name
,
392 return dyld3::NSAddImage(image_name
, options
);
394 DYLD_LOCK_THIS_BLOCK
;
395 static const struct mach_header
* (*p
)(const char* image_name
,
396 uint32_t options
) = NULL
;
399 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
400 return(p(image_name
, options
));
402 #endif // DEPRECATED_APIS_SUPPORTED
405 * This routine returns the current version of the named shared library the
406 * executable it was built with. The libraryName parameter is the same as the
407 * -lx or -framework Foo argument passed to the static link editor when building
408 * the executable (with -lx it would be "x" and with -framework Foo it would be
409 * "Foo"). If this the executable was not built against the specified library
410 * it returns -1. It should be noted that if this only returns the value the
411 * current version of the named shared library the executable was built with
412 * and not a list of current versions that dependent libraries and bundles the
413 * program is using were built with.
415 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
418 return dyld3::NSVersionOfLinkTimeLibrary(libraryName
);
420 // Lazily call _NSGetMachExecuteHeader() and cache result
422 static mach_header_64
* mh
= NULL
;
424 static mach_header
* mh
= NULL
;
427 mh
= _NSGetMachExecuteHeader();
429 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
431 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
433 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
436 case LC_LOAD_WEAK_DYLIB
:
437 case LC_LOAD_UPWARD_DYLIB
:
438 const dylib_command
* dl
= (dylib_command
*)lc
;
439 const char* install_name
= (char*)dl
+ dl
->dylib
.name
.offset
;
440 if ( names_match(install_name
, libraryName
) )
441 return dl
->dylib
.current_version
;
444 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
450 * This routine returns the current version of the named shared library the
451 * program it is running against. The libraryName parameter is the same as
452 * would be static link editor using the -lx or -framework Foo flags (with -lx
453 * it would be "x" and with -framework Foo it would be "Foo"). If the program
454 * is not using the specified library it returns -1.
456 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
459 return dyld3::NSVersionOfRunTimeLibrary(libraryName
);
461 uint32_t n
= _dyld_image_count();
462 for(uint32_t i
= 0; i
< n
; i
++){
463 const mach_header
* mh
= _dyld_get_image_header(i
);
466 if ( mh
->filetype
!= MH_DYLIB
)
469 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
471 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
473 for(uint32_t j
= 0; j
< mh
->ncmds
; j
++){
474 if ( lc
->cmd
== LC_ID_DYLIB
) {
475 const dylib_command
* dl
= (dylib_command
*)lc
;
476 const char* install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
477 if ( names_match(install_name
, libraryName
) )
478 return dl
->dylib
.current_version
;
480 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
487 uint32_t dyld_get_program_sdk_watch_os_version()
490 return dyld3::dyld_get_program_sdk_watch_os_version();
492 __block
uint32_t retval
= 0;
493 __block
bool versionFound
= false;
494 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
495 if (versionFound
) return;
497 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
499 retval
= sdk_version
;
506 uint32_t dyld_get_program_min_watch_os_version()
509 return dyld3::dyld_get_program_min_watch_os_version();
511 __block
uint32_t retval
= 0;
512 __block
bool versionFound
= false;
513 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
514 if (versionFound
) return;
516 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
518 retval
= min_version
;
527 uint32_t dyld_get_program_sdk_bridge_os_version()
530 return dyld3::dyld_get_program_sdk_bridge_os_version();
532 __block
uint32_t retval
= 0;
533 __block
bool versionFound
= false;
534 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
535 if (versionFound
) return;
537 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
539 retval
= sdk_version
;
546 uint32_t dyld_get_program_min_bridge_os_version()
549 return dyld3::dyld_get_program_min_bridge_os_version();
551 __block
uint32_t retval
= 0;
552 __block
bool versionFound
= false;
553 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
554 if (versionFound
) return;
556 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
558 retval
= min_version
;
567 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
568 * specified binary was built against.
570 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
571 * not zero, return that value.
572 * Otherwise, looks for the libSystem.B.dylib the binary linked
573 * against and uses a table to convert that to an sdk version.
575 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
577 return dyld3::dyld_get_sdk_version(mh
);
580 uint32_t dyld_get_program_sdk_version()
582 return dyld3::dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
585 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
587 return dyld3::dyld_get_min_os_version(mh
);
591 uint32_t dyld_get_program_min_os_version()
593 return dyld3::dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
597 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
)
600 return dyld3::_dyld_get_image_uuid(mh
, uuid
);
602 const load_command
* startCmds
= NULL
;
603 if ( mh
->magic
== MH_MAGIC_64
)
604 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
605 else if ( mh
->magic
== MH_MAGIC
)
606 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
608 return false; // not a mach-o file, or wrong endianness
610 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
611 const load_command
* cmd
= startCmds
;
612 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
613 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
614 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
617 if ( cmd
->cmd
== LC_UUID
) {
618 const uuid_command
* uuidCmd
= (uuid_command
*)cmd
;
619 memcpy(uuid
, uuidCmd
->uuid
, 16);
628 dyld_platform_t
dyld_get_active_platform(void) {
629 if (gUseDyld3
) { return dyld3::dyld_get_active_platform(); }
630 if (_dyld_get_all_image_infos()->version
>= 16) { return (dyld_platform_t
)_dyld_get_all_image_infos()->platform
; }
632 __block dyld_platform_t result
;
633 // FIXME: Remove this once we only care about version 16 or greater all image infos
634 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
640 dyld_platform_t
dyld_get_base_platform(dyld_platform_t platform
) {
641 return dyld3::dyld_get_base_platform(platform
);
644 bool dyld_is_simulator_platform(dyld_platform_t platform
) {
645 return dyld3::dyld_is_simulator_platform(platform
);
648 bool dyld_sdk_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
649 return dyld3::dyld_sdk_at_least(mh
, version
);
652 bool dyld_minos_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
653 return dyld3::dyld_minos_at_least(mh
, version
);
656 bool dyld_program_sdk_at_least(dyld_build_version_t version
) {
657 return dyld3::dyld_sdk_at_least((mach_header
*)_NSGetMachExecuteHeader(),version
);
660 bool dyld_program_minos_at_least(dyld_build_version_t version
) {
661 return dyld3::dyld_minos_at_least((mach_header
*)_NSGetMachExecuteHeader(), version
);
664 // Function that walks through the load commands and calls the internal block for every version found
665 // Intended as a fallback for very complex (and rare) version checks, or for tools that need to
666 // print our everything for diagnostic reasons
667 void dyld_get_image_versions(const struct mach_header
* mh
, void (^callback
)(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
)) {
668 dyld3::dyld_get_image_versions(mh
, callback
);
673 #if DEPRECATED_APIS_SUPPORTED
675 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
676 * specified file name if the file is a correct Mach-O file that can be loaded
677 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
678 * NSObjectFileImageFormat an error message is printed to stderr. All
679 * other codes cause no printing.
681 NSObjectFileImageReturnCode
682 NSCreateObjectFileImageFromFile(
683 const char* pathName
,
684 NSObjectFileImage
*objectFileImage
)
687 return dyld3::NSCreateObjectFileImageFromFile(pathName
, objectFileImage
);
689 DYLD_LOCK_THIS_BLOCK
;
690 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
693 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
694 return p(pathName
, objectFileImage
);
699 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
700 * object file mapped into memory at address of size length if the object file
701 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
702 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
703 * message is printed to stderr. All other codes cause no printing.
705 NSObjectFileImageReturnCode
706 NSCreateObjectFileImageFromMemory(
709 NSObjectFileImage
*objectFileImage
)
711 // <rdar://problem/51812762> NSCreatObjectFileImageFromMemory fail opaquely if Hardened runtime is enabled
713 if ( csops(0, CS_OPS_STATUS
, &flags
, sizeof(flags
)) != -1 ) {
714 if ( (flags
& (CS_ENFORCEMENT
|CS_KILL
)) == (CS_ENFORCEMENT
|CS_KILL
) ) {
715 //fprintf(stderr, "dyld: warning: NSCreatObjectFileImageFromMemory() cannot be used in harden process 0x%08X\n", flags);
716 return NSObjectFileImageAccess
;
721 return dyld3::NSCreateObjectFileImageFromMemory(address
, size
, objectFileImage
);
723 DYLD_LOCK_THIS_BLOCK
;
724 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
727 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
728 return p(address
, size
, objectFileImage
);
731 #if OBSOLETE_DYLD_API
733 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
734 * specified core file name if the file is a correct Mach-O core file.
735 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
736 * an error message is printed to stderr. All other codes cause no printing.
738 NSObjectFileImageReturnCode
739 NSCreateCoreFileImageFromFile(
740 const char* pathName
,
741 NSObjectFileImage
*objectFileImage
)
743 DYLD_LOCK_THIS_BLOCK
;
744 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
747 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
748 return p(pathName
, objectFileImage
);
753 NSDestroyObjectFileImage(
754 NSObjectFileImage objectFileImage
)
757 return dyld3::NSDestroyObjectFileImage(objectFileImage
);
759 DYLD_LOCK_THIS_BLOCK
;
760 static bool (*p
)(NSObjectFileImage
) = NULL
;
763 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
764 return p(objectFileImage
);
770 NSObjectFileImage objectFileImage
,
771 const char* moduleName
,
775 return dyld3::NSLinkModule(objectFileImage
, moduleName
, options
);
777 DYLD_LOCK_THIS_BLOCK
;
778 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
781 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
783 return p(objectFileImage
, moduleName
, options
);
790 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
791 * definitions in the NSObjectFileImage.
794 NSSymbolDefinitionCountInObjectFileImage(
795 NSObjectFileImage objectFileImage
)
798 return dyld3::NSSymbolDefinitionCountInObjectFileImage(objectFileImage
);
800 DYLD_LOCK_THIS_BLOCK
;
801 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
804 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
806 return p(objectFileImage
);
810 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
811 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
812 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
816 NSSymbolDefinitionNameInObjectFileImage(
817 NSObjectFileImage objectFileImage
,
821 return dyld3::NSSymbolDefinitionNameInObjectFileImage(objectFileImage
, ordinal
);
823 DYLD_LOCK_THIS_BLOCK
;
824 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
827 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
829 return p(objectFileImage
, ordinal
);
833 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
834 * to undefined symbols the NSObjectFileImage.
837 NSSymbolReferenceCountInObjectFileImage(
838 NSObjectFileImage objectFileImage
)
841 return dyld3::NSSymbolReferenceCountInObjectFileImage(objectFileImage
);
843 DYLD_LOCK_THIS_BLOCK
;
844 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
847 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
849 return p(objectFileImage
);
853 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
854 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
855 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
859 NSSymbolReferenceNameInObjectFileImage(
860 NSObjectFileImage objectFileImage
,
862 bool *tentative_definition
) /* can be NULL */
865 return dyld3::NSSymbolReferenceNameInObjectFileImage(objectFileImage
, ordinal
, tentative_definition
);
867 DYLD_LOCK_THIS_BLOCK
;
868 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
871 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
873 return p(objectFileImage
, ordinal
, tentative_definition
);
877 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
878 * name has a definition in the NSObjectFileImage and FALSE otherwise.
881 NSIsSymbolDefinedInObjectFileImage(
882 NSObjectFileImage objectFileImage
,
883 const char* symbolName
)
886 return dyld3::NSIsSymbolDefinedInObjectFileImage(objectFileImage
, symbolName
);
888 DYLD_LOCK_THIS_BLOCK
;
889 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
892 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
894 return p(objectFileImage
, symbolName
);
898 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
899 * in the NSObjectFileImage for the specified segmentName and sectionName if
900 * it exists and it is not a zerofill section. If not it returns NULL. If
901 * the parameter size is not NULL the size of the section is also returned
902 * indirectly through that pointer.
905 NSGetSectionDataInObjectFileImage(
906 NSObjectFileImage objectFileImage
,
907 const char* segmentName
,
908 const char* sectionName
,
909 unsigned long *size
) /* can be NULL */
912 return dyld3::NSGetSectionDataInObjectFileImage(objectFileImage
, segmentName
, sectionName
, size
);
914 DYLD_LOCK_THIS_BLOCK
;
915 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
918 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
920 return p(objectFileImage
, segmentName
, sectionName
, size
);
928 const char* *fileName
,
929 const char* *errorString
)
932 return dyld3::NSLinkEditError(c
, errorNumber
, fileName
, errorString
);
934 DYLD_LOCK_THIS_BLOCK
;
935 static void (*p
)(NSLinkEditErrors
*c
,
937 const char* *fileName
,
938 const char* *errorString
) = NULL
;
941 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
943 p(c
, errorNumber
, fileName
, errorString
);
952 return dyld3::NSUnLinkModule(module, options
);
954 DYLD_LOCK_THIS_BLOCK
;
955 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
958 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
960 return p(module, options
);
963 #if OBSOLETE_DYLD_API
966 NSModule moduleToReplace
,
967 NSObjectFileImage newObjectFileImage
,
975 #endif // DEPRECATED_APIS_SUPPORTED
978 *_NSGetExecutablePath copies the path of the executable into the buffer and
979 * returns 0 if the path was successfully copied in the provided buffer. If the
980 * buffer is not large enough, -1 is returned and the expected buffer size is
981 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
982 * the executable not a "real path" to the executable. That is the path may be
983 * a symbolic link and not the real file. And with deep directories the total
984 * bufsize needed could be more than MAXPATHLEN.
987 _NSGetExecutablePath(
992 return dyld3::_NSGetExecutablePath(buf
, bufsize
);
994 DYLD_NO_LOCK_THIS_BLOCK
;
995 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
998 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
999 return(p(buf
, bufsize
));
1002 #if DEPRECATED_APIS_SUPPORTED
1004 _dyld_lookup_and_bind(
1005 const char* symbol_name
,
1009 DYLD_LOCK_THIS_BLOCK
;
1010 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
1013 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
1014 p(symbol_name
, address
, module);
1018 _dyld_lookup_and_bind_with_hint(
1019 const char* symbol_name
,
1020 const char* library_name_hint
,
1024 DYLD_LOCK_THIS_BLOCK
;
1025 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
1028 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
1029 p(symbol_name
, library_name_hint
, address
, module);
1032 #if OBSOLETE_DYLD_API
1034 _dyld_lookup_and_bind_objc(
1035 const char* symbol_name
,
1039 DYLD_LOCK_THIS_BLOCK
;
1040 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
1043 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
1044 p(symbol_name
, address
, module);
1049 _dyld_lookup_and_bind_fully(
1050 const char* symbol_name
,
1054 DYLD_LOCK_THIS_BLOCK
;
1055 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
1058 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
1059 p(symbol_name
, address
, module);
1063 _dyld_bind_fully_image_containing_address(
1064 const void* address
)
1066 DYLD_LOCK_THIS_BLOCK
;
1067 static bool (*p
)(const void*) = NULL
;
1070 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
1073 #endif // DEPRECATED_APIS_SUPPORTED
1077 * _dyld_register_func_for_add_image registers the specified function to be
1078 * called when a new image is added (a bundle or a dynamic shared library) to
1079 * the program. When this function is first registered it is called for once
1080 * for each image that is currently part of the program.
1083 _dyld_register_func_for_add_image(
1084 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1087 return dyld3::_dyld_register_func_for_add_image(func
);
1089 DYLD_LOCK_THIS_BLOCK
;
1090 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1091 static void (*p
)(callback_t func
) = NULL
;
1094 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
1099 * _dyld_register_func_for_remove_image registers the specified function to be
1100 * called when an image is removed (a bundle or a dynamic shared library) from
1104 _dyld_register_func_for_remove_image(
1105 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1108 return dyld3::_dyld_register_func_for_remove_image(func
);
1110 DYLD_LOCK_THIS_BLOCK
;
1111 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1112 static void (*p
)(callback_t func
) = NULL
;
1115 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1119 #if OBSOLETE_DYLD_API
1121 * _dyld_register_func_for_link_module registers the specified function to be
1122 * called when a module is bound into the program. When this function is first
1123 * registered it is called for once for each module that is currently bound into
1127 _dyld_register_func_for_link_module(
1128 void (*func
)(NSModule
module))
1130 DYLD_LOCK_THIS_BLOCK
;
1131 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1134 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1139 * _dyld_register_func_for_unlink_module registers the specified function to be
1140 * called when a module is unbound from the program.
1143 _dyld_register_func_for_unlink_module(
1144 void (*func
)(NSModule
module))
1146 DYLD_LOCK_THIS_BLOCK
;
1147 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1150 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1155 * _dyld_register_func_for_replace_module registers the specified function to be
1156 * called when a module is to be replace with another module in the program.
1159 _dyld_register_func_for_replace_module(
1160 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1162 DYLD_LOCK_THIS_BLOCK
;
1163 static void (*p
)(void (*func
)(NSModule oldmodule
,
1164 NSModule newmodule
)) = NULL
;
1167 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1173 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1174 * pointer to the (__OBJC,__module) section and its size for the specified
1178 _dyld_get_objc_module_sect_for_module(
1181 unsigned long *size
)
1183 DYLD_LOCK_THIS_BLOCK
;
1184 static void (*p
)(NSModule
module,
1186 unsigned long *size
) = NULL
;
1189 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1190 p(module, objc_module
, size
);
1195 #if DEPRECATED_APIS_SUPPORTED
1199 // this function exists for compatiblity only
1205 _dyld_image_count(void)
1208 return dyld3::_dyld_image_count();
1210 DYLD_NO_LOCK_THIS_BLOCK
;
1211 static uint32_t (*p
)(void) = NULL
;
1214 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1218 const struct mach_header
*
1219 _dyld_get_image_header(uint32_t image_index
)
1222 return dyld3::_dyld_get_image_header(image_index
);
1224 DYLD_NO_LOCK_THIS_BLOCK
;
1225 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1228 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1229 return(p(image_index
));
1233 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1236 return dyld3::_dyld_get_image_vmaddr_slide(image_index
);
1238 DYLD_NO_LOCK_THIS_BLOCK
;
1239 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1242 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1243 return(p(image_index
));
1247 _dyld_get_image_name(uint32_t image_index
)
1250 return dyld3::_dyld_get_image_name(image_index
);
1252 DYLD_NO_LOCK_THIS_BLOCK
;
1253 static const char* (*p
)(uint32_t image_index
) = NULL
;
1256 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1257 return(p(image_index
));
1260 // SPI in Mac OS X 10.6
1261 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1263 // always use dyld3 version because it does better error handling
1264 return dyld3::_dyld_get_image_slide(mh
);
1268 #if DEPRECATED_APIS_SUPPORTED
1270 _dyld_image_containing_address(const void* address
)
1273 return dyld3::_dyld_image_containing_address(address
);
1275 DYLD_LOCK_THIS_BLOCK
;
1276 static bool (*p
)(const void*) = NULL
;
1279 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1283 const struct mach_header
*
1284 _dyld_get_image_header_containing_address(
1285 const void* address
)
1288 return dyld3::_dyld_get_image_header_containing_address(address
);
1290 DYLD_LOCK_THIS_BLOCK
;
1291 static const struct mach_header
* (*p
)(const void*) = NULL
;
1294 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1298 bool _dyld_launched_prebound(void)
1300 DYLD_LOCK_THIS_BLOCK
;
1301 static bool (*p
)(void) = NULL
;
1304 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1308 bool _dyld_all_twolevel_modules_prebound(void)
1310 DYLD_LOCK_THIS_BLOCK
;
1311 static bool (*p
)(void) = NULL
;
1314 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1317 #endif // DEPRECATED_APIS_SUPPORTED
1322 #include <pthread.h>
1324 #include <mach-o/dyld.h>
1325 #include "dyldLibSystemInterface.h"
1328 // pthread key used to access per-thread dlerror message
1329 static pthread_key_t dlerrorPerThreadKey
;
1330 static bool dlerrorPerThreadKeyInitialized
= false;
1332 // data kept per-thread
1333 struct dlerrorPerThreadData
1335 size_t sizeAllocated
;
1339 // function called by dyld to get buffer to store dlerror message
1340 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
1342 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1343 if (!dlerrorPerThreadKeyInitialized
) {
1344 // create key and tell pthread package to call free() on any data associated with key if thread dies
1345 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1346 dlerrorPerThreadKeyInitialized
= true;
1349 const size_t size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1350 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1351 if ( data
== NULL
) {
1352 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1353 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1354 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1355 data
->sizeAllocated
= size
;
1356 pthread_setspecific(dlerrorPerThreadKey
, data
);
1358 else if ( data
->sizeAllocated
< sizeRequired
) {
1360 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1361 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1362 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1363 data
->sizeAllocated
= size
;
1364 pthread_setspecific(dlerrorPerThreadKey
, data
);
1366 return data
->message
;
1369 // <rdar://problem/10595338> dlerror buffer leak
1370 // Only allocate buffer if an actual error message needs to be set
1371 static bool hasPerThreadBufferFor_dlerror()
1373 if (!dlerrorPerThreadKeyInitialized
)
1376 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1379 #if TARGET_OS_DRIVERKIT
1380 static bool isLaunchdOwned()
1385 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1386 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1387 static vswapproc swapProc
= &vproc_swap_integer
;
1389 static bool isLaunchdOwned()
1391 static bool checked
= false;
1392 static bool result
= false;
1396 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1397 result
= ( val
!= 0 );
1403 static void shared_cache_missing()
1405 // leave until dyld's that might call this are rare
1408 static void shared_cache_out_of_date()
1410 // leave until dyld's that might call this are rare
1414 // the table passed to dyld containing thread helpers
1415 static dyld::LibSystemHelpers sHelpers
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1416 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1417 &shared_cache_missing
, &shared_cache_out_of_date
,
1419 &pthread_key_create
, &pthread_setspecific
,
1421 &pthread_getspecific
,
1424 &hasPerThreadBufferFor_dlerror
,
1428 &__cxa_finalize_ranges
1431 static const objc_opt::objc_opt_t
* gObjCOpt
= nullptr;
1433 // during initialization of libSystem this routine will run
1434 // and call dyld, registering the helper functions.
1436 extern "C" void tlv_initializer();
1437 void _dyld_initializer()
1439 void (*p
)(dyld::LibSystemHelpers
*);
1441 // Get the optimized objc pointer now that the cache is loaded
1442 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1443 if ( allInfo
!= nullptr ) {
1444 const DyldSharedCache
* cache
= (const DyldSharedCache
*)(allInfo
->sharedCacheBaseAddress
);
1445 if ( cache
!= nullptr )
1446 gObjCOpt
= cache
->objcOpt();
1450 dyld3::gAllImages
.applyInitialImages();
1451 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
1452 // For binaries built before 13.0, set the lookup function if they need it
1453 if (dyld_get_program_sdk_version() < DYLD_PACKED_VERSION(13,0,0))
1454 setLookupFunc((void*)&dyld3::compatFuncLookup
);
1458 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1466 int dladdr(const void* addr
, Dl_info
* info
)
1468 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLADDR
, (uint64_t)addr
, 0, 0);
1471 result
= dyld3::dladdr(addr
, info
);
1473 DYLD_LOCK_THIS_BLOCK
;
1474 static int (*p
)(const void* , Dl_info
*) = NULL
;
1477 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1478 result
= p(addr
, info
);
1480 timer
.setData4(result
);
1481 timer
.setData5(info
!= NULL
? info
->dli_fbase
: 0);
1482 timer
.setData6(info
!= NULL
? info
->dli_saddr
: 0);
1486 #if !TARGET_OS_DRIVERKIT
1490 return dyld3::dlerror();
1492 DYLD_LOCK_THIS_BLOCK
;
1493 static char* (*p
)() = NULL
;
1496 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1500 int dlclose(void* handle
)
1502 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLCLOSE
, (uint64_t)handle
, 0, 0);
1505 timer
.setData4(result
);
1506 return dyld3::dlclose(handle
);
1509 DYLD_LOCK_THIS_BLOCK
;
1510 static int (*p
)(void* handle
) = NULL
;
1513 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1515 timer
.setData4(result
);
1519 void* dlopen(const char* path
, int mode
)
1521 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN
, path
, mode
, 0);
1522 void* result
= nullptr;
1525 result
= dyld3::dlopen_internal(path
, mode
, __builtin_return_address(0));
1526 timer
.setData4(result
);
1530 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1531 DYLD_NO_LOCK_THIS_BLOCK
;
1533 static void* (*p
)(const char* path
, int, void*) = NULL
;
1536 _dyld_func_lookup("__dyld_dlopen_internal", (void**)&p
);
1537 result
= p(path
, mode
, __builtin_return_address(0));
1538 // use asm block to prevent tail call optimization
1539 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1540 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1541 __asm__
volatile("");
1542 timer
.setData4(result
);
1547 bool dlopen_preflight(const char* path
)
1549 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN_PREFLIGHT
, path
, 0, 0);
1550 bool result
= false;
1553 result
= dyld3::dlopen_preflight_internal(path
);
1554 timer
.setData4(result
);
1558 DYLD_LOCK_THIS_BLOCK
;
1559 static bool (*p
)(const char* path
, void* callerAddress
) = NULL
;
1562 _dyld_func_lookup("__dyld_dlopen_preflight_internal", (void**)&p
);
1563 result
= p(path
, __builtin_return_address(0));
1564 timer
.setData4(result
);
1568 void* dlsym(void* handle
, const char* symbol
)
1570 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLSYM
, handle
, symbol
, 0);
1571 void* result
= nullptr;
1574 result
= dyld3::dlsym_internal(handle
, symbol
, __builtin_return_address(0));
1575 timer
.setData4(result
);
1579 DYLD_LOCK_THIS_BLOCK
;
1580 static void* (*p
)(void* handle
, const char* symbol
, void *callerAddress
) = NULL
;
1583 _dyld_func_lookup("__dyld_dlsym_internal", (void**)&p
);
1584 result
= p(handle
, symbol
, __builtin_return_address(0));
1585 timer
.setData4(result
);
1588 #endif // !TARGET_OS_DRIVERKIT
1591 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1594 return dyld3::_dyld_get_all_image_infos();
1596 DYLD_NO_LOCK_THIS_BLOCK
;
1597 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1600 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1604 #if SUPPORT_ZERO_COST_EXCEPTIONS
1605 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1608 return dyld3::_dyld_find_unwind_sections(addr
, info
);
1610 DYLD_NO_LOCK_THIS_BLOCK
;
1611 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1614 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1615 return p(addr
, info
);
1620 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1621 __attribute__((visibility("hidden")))
1622 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1624 DYLD_NO_LOCK_THIS_BLOCK
;
1625 static void* (*p
)(void*, long) = NULL
;
1628 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1629 return p(loadercache
, lazyinfo
);
1634 const char* dyld_image_path_containing_address(const void* addr
)
1637 return dyld3::dyld_image_path_containing_address(addr
);
1639 DYLD_NO_LOCK_THIS_BLOCK
;
1640 static const char* (*p
)(const void*) = NULL
;
1643 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1647 const struct mach_header
* dyld_image_header_containing_address(const void* addr
)
1650 return dyld3::dyld_image_header_containing_address(addr
);
1652 DYLD_NO_LOCK_THIS_BLOCK
;
1653 static const mach_header
* (*p
)(const void*) = NULL
;
1656 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1661 bool dyld_shared_cache_some_image_overridden()
1664 return dyld3::dyld_shared_cache_some_image_overridden();
1666 DYLD_NO_LOCK_THIS_BLOCK
;
1667 static bool (*p
)() = NULL
;
1670 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1674 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
1677 return dyld3::_dyld_get_shared_cache_uuid(uuid
);
1679 DYLD_NO_LOCK_THIS_BLOCK
;
1680 static bool (*p
)(uuid_t
) = NULL
;
1683 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
);
1687 const void* _dyld_get_shared_cache_range(size_t* length
)
1690 return dyld3::_dyld_get_shared_cache_range(length
);
1692 DYLD_NO_LOCK_THIS_BLOCK
;
1693 static const void* (*p
)(size_t*) = NULL
;
1696 _dyld_func_lookup("__dyld_get_shared_cache_range", (void**)&p
);
1700 bool _dyld_shared_cache_optimized()
1703 return dyld3::_dyld_shared_cache_optimized();
1705 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1706 if ( allInfo
!= nullptr ) {
1707 const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1708 if ( cacheHeader
!= nullptr )
1709 return (cacheHeader
->cacheType
== kDyldSharedCacheTypeProduction
);
1714 bool _dyld_shared_cache_is_locally_built()
1717 return dyld3::_dyld_shared_cache_is_locally_built();
1719 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1720 if ( allInfo
!= nullptr ) {
1721 const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1722 if ( cacheHeader
!= nullptr )
1723 return (cacheHeader
->locallyBuiltCache
== 1);
1728 void _dyld_images_for_addresses(unsigned count
, const void* addresses
[], struct dyld_image_uuid_offset infos
[])
1731 return dyld3::_dyld_images_for_addresses(count
, addresses
, infos
);
1733 DYLD_NO_LOCK_THIS_BLOCK
;
1734 static const void (*p
)(unsigned, const void*[], struct dyld_image_uuid_offset
[]) = NULL
;
1737 _dyld_func_lookup("__dyld_images_for_addresses", (void**)&p
);
1738 return p(count
, addresses
, infos
);
1741 void _dyld_register_for_image_loads(void (*func
)(const mach_header
* mh
, const char* path
, bool unloadable
))
1744 return dyld3::_dyld_register_for_image_loads(func
);
1746 DYLD_NO_LOCK_THIS_BLOCK
;
1747 static const void (*p
)(void (*)(const mach_header
* mh
, const char* path
, bool unloadable
)) = NULL
;
1750 _dyld_func_lookup("__dyld_register_for_image_loads", (void**)&p
);
1754 void _dyld_register_for_bulk_image_loads(void (*func
)(unsigned imageCount
, const struct mach_header
* mhs
[], const char* paths
[]))
1757 return dyld3::_dyld_register_for_bulk_image_loads(func
);
1759 DYLD_NO_LOCK_THIS_BLOCK
;
1760 static const void (*p
)(void (*)(unsigned imageCount
, const mach_header
* mhs
[], const char* paths
[])) = NULL
;
1763 _dyld_func_lookup("__dyld_register_for_bulk_image_loads", (void**)&p
);
1767 bool dyld_need_closure(const char* execPath
, const char* tempDir
)
1769 return dyld3::dyld_need_closure(execPath
, tempDir
);
1772 bool dyld_process_is_restricted()
1775 return dyld3::dyld_process_is_restricted();
1777 DYLD_NO_LOCK_THIS_BLOCK
;
1778 static bool (*p
)() = NULL
;
1781 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1785 const char* dyld_shared_cache_file_path()
1788 return dyld3::dyld_shared_cache_file_path();
1790 DYLD_NO_LOCK_THIS_BLOCK
;
1791 static const char* (*p
)() = NULL
;
1794 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
);
1798 bool dyld_has_inserted_or_interposing_libraries()
1801 return dyld3::dyld_has_inserted_or_interposing_libraries();
1803 DYLD_NO_LOCK_THIS_BLOCK
;
1804 static bool (*p
)() = NULL
;
1807 _dyld_func_lookup("__dyld_has_inserted_or_interposing_libraries", (void**)&p
);
1811 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1814 return dyld3::dyld_dynamic_interpose(mh
, array
, count
);
1816 DYLD_LOCK_THIS_BLOCK
;
1817 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1820 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1821 p(mh
, array
, count
);
1824 // SPI called __fork
1825 void _dyld_atfork_prepare()
1828 return dyld3::_dyld_atfork_prepare();
1831 // SPI called __fork
1832 void _dyld_atfork_parent()
1835 return dyld3::_dyld_atfork_parent();
1838 // SPI called __fork
1839 void _dyld_fork_child()
1842 return dyld3::_dyld_fork_child();
1844 DYLD_NO_LOCK_THIS_BLOCK
;
1845 static void (*p
)() = NULL
;
1848 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);
1854 static void* mapStartOfCache(const char* path
, size_t length
)
1856 struct stat statbuf
;
1857 if ( ::stat(path
, &statbuf
) == -1 )
1860 if ( (size_t)statbuf
.st_size
< length
)
1863 int cache_fd
= ::open(path
, O_RDONLY
);
1867 void* result
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
1870 if ( result
== MAP_FAILED
)
1877 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
)
1879 DIR* dirp
= ::opendir(dirPath
);
1880 if ( dirp
!= NULL
) {
1882 dirent
* entp
= NULL
;
1883 char cachePath
[PATH_MAX
];
1884 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) {
1887 if ( entp
->d_type
!= DT_REG
)
1889 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
1891 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
1893 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
1895 if ( const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)mapStartOfCache(cachePath
, 0x00100000) ) {
1896 if ( ::memcmp(cacheHeader
->uuid
, cacheUuid
, 16) != 0 ) {
1897 // wrong uuid, unmap and keep looking
1898 ::munmap((void*)cacheHeader
, 0x00100000);
1912 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid
, const char* extraSearchDirs
[], void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1915 return dyld3::dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
1917 const dyld_cache_header
* cacheHeader
= NULL
;
1918 bool needToUnmap
= true;
1920 // get info from dyld about this process, to see if requested cache is already mapped into this process
1921 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1922 if ( (allInfo
!= NULL
) && (allInfo
->sharedCacheBaseAddress
!= 0) && (memcmp(allInfo
->sharedCacheUUID
, cacheUuid
, 16) == 0) ) {
1923 // requested cache is already mapped, just re-use it
1924 cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1925 needToUnmap
= false;
1928 // look first is default location for cache files
1929 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1930 const char* defaultSearchDir
= IPHONE_DYLD_SHARED_CACHE_DIR
;
1932 const char* defaultSearchDir
= MACOSX_DYLD_SHARED_CACHE_DIR
;
1934 cacheHeader
= findCacheInDirAndMap(cacheUuid
, defaultSearchDir
);
1935 // if not there, look in extra search locations
1936 if ( cacheHeader
== NULL
) {
1937 for (const char** p
= extraSearchDirs
; *p
!= NULL
; ++p
) {
1938 cacheHeader
= findCacheInDirAndMap(cacheUuid
, *p
);
1939 if ( cacheHeader
!= NULL
)
1945 if ( cacheHeader
== NULL
)
1948 if ( cacheHeader
->mappingOffset
< sizeof(dyld_cache_header
) ) {
1949 // old cache without imagesText array
1951 ::munmap((void*)cacheHeader
, 0x00100000);
1955 // walk imageText table and call callback for each entry
1956 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
1957 const uint64_t cacheUnslidBaseAddress
= mappings
[0].address
;
1958 const dyld_cache_image_text_info
* imagesText
= (dyld_cache_image_text_info
*)((char*)cacheHeader
+ cacheHeader
->imagesTextOffset
);
1959 const dyld_cache_image_text_info
* imagesTextEnd
= &imagesText
[cacheHeader
->imagesTextCount
];
1960 for (const dyld_cache_image_text_info
* p
=imagesText
; p
< imagesTextEnd
; ++p
) {
1961 dyld_shared_cache_dylib_text_info dylibTextInfo
;
1962 dylibTextInfo
.version
= 2;
1963 dylibTextInfo
.loadAddressUnslid
= p
->loadAddress
;
1964 dylibTextInfo
.textSegmentSize
= p
->textSegmentSize
;
1965 dylibTextInfo
.path
= (char*)cacheHeader
+ p
->pathOffset
;
1966 ::memcpy(dylibTextInfo
.dylibUuid
, p
->uuid
, 16);
1967 dylibTextInfo
.textSegmentOffset
= p
->loadAddress
- cacheUnslidBaseAddress
;
1968 callback(&dylibTextInfo
);
1972 ::munmap((void*)cacheHeader
, 0x00100000);
1977 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1980 return dyld3::dyld_shared_cache_iterate_text(cacheUuid
, callback
);
1982 const char* extraSearchDirs
[] = { NULL
};
1983 return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
1987 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
1990 return dyld3::_dyld_is_memory_immutable(addr
, length
);
1992 DYLD_NO_LOCK_THIS_BLOCK
;
1993 static bool (*p
)(const void*, size_t) = NULL
;
1996 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
);
1997 return p(addr
, length
);
2001 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
2002 _dyld_objc_notify_init init
,
2003 _dyld_objc_notify_unmapped unmapped
)
2006 return dyld3::_dyld_objc_notify_register(mapped
, init
, unmapped
);
2008 DYLD_LOCK_THIS_BLOCK
;
2009 static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
;
2012 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
);
2013 p(mapped
, init
, unmapped
);
2016 void _dyld_missing_symbol_abort()
2018 return dyld3::_dyld_missing_symbol_abort();
2021 const char* _dyld_get_objc_selector(const char* selName
)
2023 // Check the shared cache table if it exists.
2024 if ( gObjCOpt
!= nullptr ) {
2025 if ( const objc_opt::objc_selopt_t
* selopt
= gObjCOpt
->selopt() ) {
2026 const char* name
= selopt
->get(selName
);
2027 if (name
!= nullptr)
2033 return dyld3::_dyld_get_objc_selector(selName
);
2038 void _dyld_for_each_objc_class(const char* className
,
2039 void (^callback
)(void* classPtr
, bool isLoaded
, bool* stop
)) {
2041 return dyld3::_dyld_for_each_objc_class(className
, callback
);
2044 void _dyld_for_each_objc_protocol(const char* protocolName
,
2045 void (^callback
)(void* protocolPtr
, bool isLoaded
, bool* stop
)) {
2047 return dyld3::_dyld_for_each_objc_protocol(protocolName
, callback
);
2050 void _dyld_register_driverkit_main(void (*mainFunc
)(void))
2052 static bool (*p
)(void (*mainFunc
)(void)) = NULL
;
2055 _dyld_func_lookup("__dyld_register_driverkit_main", (void**)&p
);