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 <TargetConditionals.h>
32 #include <System/sys/csr.h>
33 #include <crt_externs.h>
34 #include <Availability.h>
35 #if !TARGET_OS_DRIVERKIT
36 #include <vproc_priv.h>
39 #include <sys/types.h>
42 #include <System/sys/codesign.h>
43 #include <libc_private.h>
45 #include <mach-o/dyld_images.h>
46 #include <mach-o/dyld.h>
47 #include <mach-o/dyld_priv.h>
49 #include "dyld_cache_format.h"
50 #include "objc-shared-cache.h"
52 #include "ImageLoader.h"
56 #include "AllImages.h"
57 #include "StartGlue.h"
61 // this was in dyld_priv.h but it is no longer exported
63 const struct dyld_all_image_infos
* _dyld_get_all_image_infos() __attribute__((visibility("hidden")));
67 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
68 extern "C" void __cxa_finalize(const void *dso
);
69 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
);
72 // private interface between libSystem.dylib and dyld
74 extern "C" int _dyld_func_lookup(const char* dyld_func_name
, void **address
);
76 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
78 extern int compatFuncLookup(const char* name
, void** address
) __API_AVAILABLE(ios(13.0));
80 extern "C" void setLookupFunc(void*);
84 extern bool gUseDyld3
;
87 // <rdar://problem/61161069> libdyld.dylib should use abort_with_payload() for asserts
89 void abort_report_np(const char* format
, ...)
93 _SIMPLE_STRING s
= _simple_salloc();
95 va_start(list
, format
);
96 _simple_vsprintf(s
, format
, list
);
98 str
= _simple_string(s
);
101 // _simple_salloc failed, but at least format may have useful info by itself
108 void (*p
)(const char* msg
) __attribute__((__noreturn__
));
109 _dyld_func_lookup("__dyld_halt", (void**)&p
);
112 // halt() doesn't return, so we can't call _simple_sfree
115 // libc uses assert()
116 #pragma clang diagnostic push
117 #pragma clang diagnostic ignored "-Winvalid-noreturn"
119 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
122 abort_report_np("Assertion failed: (%s), file %s, line %d.\n", failedexpr
, file
, line
);
124 abort_report_np("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
127 #pragma clang diagnostic pop
130 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
132 #define DEPRECATED_APIS_SUPPORTED 1
134 #define DEPRECATED_APIS_SUPPORTED 0
138 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
139 * libraryName (which is -lx or -framework Foo argument passed to the static
140 * link editor for the same library) and determines if they match. This depends
141 * on conventional use of names including major versioning.
146 const char *install_name
,
147 const char* libraryName
)
149 const char *basename
;
153 * Conventional install names have these forms:
154 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
155 * /Local/Library/Frameworks/AppKit.framework/Appkit
156 * /lib/libsys_s.A.dylib
157 * /usr/lib/libsys_s.dylib
159 basename
= strrchr(install_name
, '/');
161 basename
= install_name
;
166 * By checking the base name matching the library name we take care
167 * of the -framework cases.
169 if(strcmp(basename
, libraryName
) == 0)
173 * Now check the base name for "lib" if so proceed to check for the
174 * -lx case dealing with a possible .X.dylib and a .dylib extension.
176 if(strncmp(basename
, "lib", 3) ==0){
177 n
= strlen(libraryName
);
178 if(strncmp(basename
+3, libraryName
, n
) == 0){
179 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
181 if(basename
[3+n
] == '.' &&
182 basename
[3+n
+1] != '\0' &&
183 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
190 #if DEPRECATED_APIS_SUPPORTED
192 void NSInstallLinkEditErrorHandlers(
193 const NSLinkEditErrorHandlers
* handlers
)
196 return dyld3::NSInstallLinkEditErrorHandlers(handlers
);
198 DYLD_LOCK_THIS_BLOCK
;
199 typedef void (*ucallback_t
)(const char* symbol_name
);
200 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
201 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
202 const char* fileName
, const char* errorString
);
203 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
206 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
207 mcallback_t m
= handlers
->multiple
;
208 p(handlers
->undefined
, m
, handlers
->linkEdit
);
216 return dyld3::NSNameOfModule(module);
218 DYLD_LOCK_THIS_BLOCK
;
219 static const char* (*p
)(NSModule
module) = NULL
;
222 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
227 NSLibraryNameForModule(
231 return dyld3::NSLibraryNameForModule(module);
233 DYLD_LOCK_THIS_BLOCK
;
234 static const char* (*p
)(NSModule
module) = NULL
;
237 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
242 NSIsSymbolNameDefined(
243 const char* symbolName
)
246 return dyld3::NSIsSymbolNameDefined(symbolName
);
248 DYLD_LOCK_THIS_BLOCK
;
249 static bool (*p
)(const char* symbolName
) = NULL
;
252 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
253 return(p(symbolName
));
257 NSIsSymbolNameDefinedWithHint(
258 const char* symbolName
,
259 const char* libraryNameHint
)
262 return dyld3::NSIsSymbolNameDefinedWithHint(symbolName
, libraryNameHint
);
264 DYLD_LOCK_THIS_BLOCK
;
265 static bool (*p
)(const char* symbolName
,
266 const char* libraryNameHint
) = NULL
;
269 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
270 return(p(symbolName
, libraryNameHint
));
274 NSIsSymbolNameDefinedInImage(
275 const struct mach_header
*image
,
276 const char* symbolName
)
279 return dyld3::NSIsSymbolNameDefinedInImage(image
, symbolName
);
281 DYLD_LOCK_THIS_BLOCK
;
282 static bool (*p
)(const struct mach_header
*image
,
283 const char* symbolName
) = NULL
;
286 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
287 return(p(image
, symbolName
));
291 NSLookupAndBindSymbol(
292 const char* symbolName
)
295 return dyld3::NSLookupAndBindSymbol(symbolName
);
297 DYLD_LOCK_THIS_BLOCK
;
298 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
301 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
302 return(p(symbolName
));
306 NSLookupAndBindSymbolWithHint(
307 const char* symbolName
,
308 const char* libraryNameHint
)
311 return dyld3::NSLookupAndBindSymbolWithHint(symbolName
, libraryNameHint
);
313 DYLD_LOCK_THIS_BLOCK
;
314 static NSSymbol (*p
)(const char* symbolName
,
315 const char* libraryNameHint
) = NULL
;
318 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
319 return(p(symbolName
, libraryNameHint
));
323 NSLookupSymbolInModule(
325 const char* symbolName
)
328 return dyld3::NSLookupSymbolInModule(module, symbolName
);
330 DYLD_LOCK_THIS_BLOCK
;
331 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
334 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
335 return(p(module, symbolName
));
339 NSLookupSymbolInImage(
340 const struct mach_header
*image
,
341 const char* symbolName
,
345 return dyld3::NSLookupSymbolInImage(image
, symbolName
, options
);
347 DYLD_LOCK_THIS_BLOCK
;
348 static NSSymbol (*p
)(const struct mach_header
*image
,
349 const char* symbolName
,
350 uint32_t options
) = NULL
;
353 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
354 return(p(image
, symbolName
, options
));
362 return dyld3::NSNameOfSymbol(symbol
);
364 DYLD_LOCK_THIS_BLOCK
;
365 static char * (*p
)(NSSymbol symbol
) = NULL
;
368 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
377 return dyld3::NSAddressOfSymbol(symbol
);
379 DYLD_LOCK_THIS_BLOCK
;
380 static void * (*p
)(NSSymbol symbol
) = NULL
;
383 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
392 return dyld3::NSModuleForSymbol(symbol
);
394 DYLD_LOCK_THIS_BLOCK
;
395 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
398 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
404 const char* pathName
)
407 return dyld3::NSAddLibrary(pathName
);
409 DYLD_LOCK_THIS_BLOCK
;
410 static bool (*p
)(const char* pathName
) = NULL
;
413 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
418 NSAddLibraryWithSearching(
419 const char* pathName
)
422 return dyld3::NSAddLibrary(pathName
);
424 DYLD_LOCK_THIS_BLOCK
;
425 static bool (*p
)(const char* pathName
) = NULL
;
428 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
432 const struct mach_header
*
434 const char* image_name
,
438 return dyld3::NSAddImage(image_name
, options
);
440 DYLD_LOCK_THIS_BLOCK
;
441 static const struct mach_header
* (*p
)(const char* image_name
,
442 uint32_t options
) = NULL
;
445 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
446 return(p(image_name
, options
));
448 #endif // DEPRECATED_APIS_SUPPORTED
451 * This routine returns the current version of the named shared library the
452 * executable it was built with. The libraryName parameter is the same as the
453 * -lx or -framework Foo argument passed to the static link editor when building
454 * the executable (with -lx it would be "x" and with -framework Foo it would be
455 * "Foo"). If this the executable was not built against the specified library
456 * it returns -1. It should be noted that if this only returns the value the
457 * current version of the named shared library the executable was built with
458 * and not a list of current versions that dependent libraries and bundles the
459 * program is using were built with.
461 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
464 return dyld3::NSVersionOfLinkTimeLibrary(libraryName
);
466 // Lazily call _NSGetMachExecuteHeader() and cache result
468 static mach_header_64
* mh
= NULL
;
470 static mach_header
* mh
= NULL
;
473 mh
= _NSGetMachExecuteHeader();
475 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
477 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
479 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
482 case LC_LOAD_WEAK_DYLIB
:
483 case LC_LOAD_UPWARD_DYLIB
:
484 const dylib_command
* dl
= (dylib_command
*)lc
;
485 const char* install_name
= (char*)dl
+ dl
->dylib
.name
.offset
;
486 if ( names_match(install_name
, libraryName
) )
487 return dl
->dylib
.current_version
;
490 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
496 * This routine returns the current version of the named shared library the
497 * program it is running against. The libraryName parameter is the same as
498 * would be static link editor using the -lx or -framework Foo flags (with -lx
499 * it would be "x" and with -framework Foo it would be "Foo"). If the program
500 * is not using the specified library it returns -1.
502 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
505 return dyld3::NSVersionOfRunTimeLibrary(libraryName
);
507 uint32_t n
= _dyld_image_count();
508 for(uint32_t i
= 0; i
< n
; i
++){
509 const mach_header
* mh
= _dyld_get_image_header(i
);
512 if ( mh
->filetype
!= MH_DYLIB
)
515 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
517 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
519 for(uint32_t j
= 0; j
< mh
->ncmds
; j
++){
520 if ( lc
->cmd
== LC_ID_DYLIB
) {
521 const dylib_command
* dl
= (dylib_command
*)lc
;
522 const char* install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
523 if ( names_match(install_name
, libraryName
) )
524 return dl
->dylib
.current_version
;
526 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
533 uint32_t dyld_get_program_sdk_watch_os_version()
536 return dyld3::dyld_get_program_sdk_watch_os_version();
538 __block
uint32_t retval
= 0;
539 __block
bool versionFound
= false;
540 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
541 if (versionFound
) return;
543 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
545 retval
= sdk_version
;
552 uint32_t dyld_get_program_min_watch_os_version()
555 return dyld3::dyld_get_program_min_watch_os_version();
557 __block
uint32_t retval
= 0;
558 __block
bool versionFound
= false;
559 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
560 if (versionFound
) return;
562 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
564 retval
= min_version
;
573 uint32_t dyld_get_program_sdk_bridge_os_version()
576 return dyld3::dyld_get_program_sdk_bridge_os_version();
578 __block
uint32_t retval
= 0;
579 __block
bool versionFound
= false;
580 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
581 if (versionFound
) return;
583 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
585 retval
= sdk_version
;
592 uint32_t dyld_get_program_min_bridge_os_version()
595 return dyld3::dyld_get_program_min_bridge_os_version();
597 __block
uint32_t retval
= 0;
598 __block
bool versionFound
= false;
599 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
600 if (versionFound
) return;
602 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
604 retval
= min_version
;
613 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
614 * specified binary was built against.
616 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
617 * not zero, return that value.
618 * Otherwise, looks for the libSystem.B.dylib the binary linked
619 * against and uses a table to convert that to an sdk version.
621 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
623 return dyld3::dyld_get_sdk_version(mh
);
626 uint32_t dyld_get_program_sdk_version()
628 return dyld3::dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
631 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
633 return dyld3::dyld_get_min_os_version(mh
);
637 uint32_t dyld_get_program_min_os_version()
639 return dyld3::dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
643 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
)
646 return dyld3::_dyld_get_image_uuid(mh
, uuid
);
648 const load_command
* startCmds
= NULL
;
649 if ( mh
->magic
== MH_MAGIC_64
)
650 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
651 else if ( mh
->magic
== MH_MAGIC
)
652 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
654 return false; // not a mach-o file, or wrong endianness
656 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
657 const load_command
* cmd
= startCmds
;
658 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
659 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
660 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
663 if ( cmd
->cmd
== LC_UUID
) {
664 const uuid_command
* uuidCmd
= (uuid_command
*)cmd
;
665 memcpy(uuid
, uuidCmd
->uuid
, 16);
674 dyld_platform_t
dyld_get_active_platform(void) {
676 return dyld3::dyld_get_active_platform();
678 return (dyld_platform_t
)_dyld_get_all_image_infos()->platform
;
681 dyld_platform_t
dyld_get_base_platform(dyld_platform_t platform
) {
682 return dyld3::dyld_get_base_platform(platform
);
685 bool dyld_is_simulator_platform(dyld_platform_t platform
) {
686 return dyld3::dyld_is_simulator_platform(platform
);
689 bool dyld_sdk_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
690 return dyld3::dyld_sdk_at_least(mh
, version
);
693 bool dyld_minos_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
694 return dyld3::dyld_minos_at_least(mh
, version
);
697 bool dyld_program_sdk_at_least(dyld_build_version_t version
) {
698 return dyld3::dyld_program_sdk_at_least(version
);
701 bool dyld_program_minos_at_least(dyld_build_version_t version
) {
702 return dyld3::dyld_program_minos_at_least(version
);
705 // Function that walks through the load commands and calls the internal block for every version found
706 // Intended as a fallback for very complex (and rare) version checks, or for tools that need to
707 // print our everything for diagnostic reasons
708 void dyld_get_image_versions(const struct mach_header
* mh
, void (^callback
)(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
)) {
709 dyld3::dyld_get_image_versions(mh
, callback
);
714 #if DEPRECATED_APIS_SUPPORTED
716 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
717 * specified file name if the file is a correct Mach-O file that can be loaded
718 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
719 * NSObjectFileImageFormat an error message is printed to stderr. All
720 * other codes cause no printing.
722 NSObjectFileImageReturnCode
723 NSCreateObjectFileImageFromFile(
724 const char* pathName
,
725 NSObjectFileImage
*objectFileImage
)
728 return dyld3::NSCreateObjectFileImageFromFile(pathName
, objectFileImage
);
730 DYLD_LOCK_THIS_BLOCK
;
731 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
734 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
735 return p(pathName
, objectFileImage
);
740 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
741 * object file mapped into memory at address of size length if the object file
742 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
743 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
744 * message is printed to stderr. All other codes cause no printing.
746 NSObjectFileImageReturnCode
747 NSCreateObjectFileImageFromMemory(
750 NSObjectFileImage
*objectFileImage
)
752 // <rdar://problem/51812762> NSCreatObjectFileImageFromMemory fail opaquely if Hardened runtime is enabled
754 if ( csops(0, CS_OPS_STATUS
, &flags
, sizeof(flags
)) != -1 ) {
755 if ( (flags
& (CS_ENFORCEMENT
|CS_KILL
)) == (CS_ENFORCEMENT
|CS_KILL
) ) {
756 //fprintf(stderr, "dyld: warning: NSCreatObjectFileImageFromMemory() cannot be used in harden process 0x%08X\n", flags);
757 return NSObjectFileImageAccess
;
762 return dyld3::NSCreateObjectFileImageFromMemory(address
, size
, objectFileImage
);
764 DYLD_LOCK_THIS_BLOCK
;
765 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
768 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
769 return p(address
, size
, objectFileImage
);
772 #if OBSOLETE_DYLD_API
774 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
775 * specified core file name if the file is a correct Mach-O core file.
776 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
777 * an error message is printed to stderr. All other codes cause no printing.
779 NSObjectFileImageReturnCode
780 NSCreateCoreFileImageFromFile(
781 const char* pathName
,
782 NSObjectFileImage
*objectFileImage
)
784 DYLD_LOCK_THIS_BLOCK
;
785 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
788 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
789 return p(pathName
, objectFileImage
);
794 NSDestroyObjectFileImage(
795 NSObjectFileImage objectFileImage
)
798 return dyld3::NSDestroyObjectFileImage(objectFileImage
);
800 DYLD_LOCK_THIS_BLOCK
;
801 static bool (*p
)(NSObjectFileImage
) = NULL
;
804 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
805 return p(objectFileImage
);
811 NSObjectFileImage objectFileImage
,
812 const char* moduleName
,
816 return dyld3::NSLinkModule(objectFileImage
, moduleName
, options
);
818 DYLD_LOCK_THIS_BLOCK
;
819 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
822 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
824 return p(objectFileImage
, moduleName
, options
);
831 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
832 * definitions in the NSObjectFileImage.
835 NSSymbolDefinitionCountInObjectFileImage(
836 NSObjectFileImage objectFileImage
)
839 return dyld3::NSSymbolDefinitionCountInObjectFileImage(objectFileImage
);
841 DYLD_LOCK_THIS_BLOCK
;
842 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
845 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
847 return p(objectFileImage
);
851 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
852 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
853 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
857 NSSymbolDefinitionNameInObjectFileImage(
858 NSObjectFileImage objectFileImage
,
862 return dyld3::NSSymbolDefinitionNameInObjectFileImage(objectFileImage
, ordinal
);
864 DYLD_LOCK_THIS_BLOCK
;
865 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
868 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
870 return p(objectFileImage
, ordinal
);
874 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
875 * to undefined symbols the NSObjectFileImage.
878 NSSymbolReferenceCountInObjectFileImage(
879 NSObjectFileImage objectFileImage
)
882 return dyld3::NSSymbolReferenceCountInObjectFileImage(objectFileImage
);
884 DYLD_LOCK_THIS_BLOCK
;
885 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
888 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
890 return p(objectFileImage
);
894 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
895 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
896 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
900 NSSymbolReferenceNameInObjectFileImage(
901 NSObjectFileImage objectFileImage
,
903 bool *tentative_definition
) /* can be NULL */
906 return dyld3::NSSymbolReferenceNameInObjectFileImage(objectFileImage
, ordinal
, tentative_definition
);
908 DYLD_LOCK_THIS_BLOCK
;
909 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
912 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
914 return p(objectFileImage
, ordinal
, tentative_definition
);
918 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
919 * name has a definition in the NSObjectFileImage and FALSE otherwise.
922 NSIsSymbolDefinedInObjectFileImage(
923 NSObjectFileImage objectFileImage
,
924 const char* symbolName
)
927 return dyld3::NSIsSymbolDefinedInObjectFileImage(objectFileImage
, symbolName
);
929 DYLD_LOCK_THIS_BLOCK
;
930 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
933 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
935 return p(objectFileImage
, symbolName
);
939 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
940 * in the NSObjectFileImage for the specified segmentName and sectionName if
941 * it exists and it is not a zerofill section. If not it returns NULL. If
942 * the parameter size is not NULL the size of the section is also returned
943 * indirectly through that pointer.
946 NSGetSectionDataInObjectFileImage(
947 NSObjectFileImage objectFileImage
,
948 const char* segmentName
,
949 const char* sectionName
,
950 unsigned long *size
) /* can be NULL */
953 return dyld3::NSGetSectionDataInObjectFileImage(objectFileImage
, segmentName
, sectionName
, size
);
955 DYLD_LOCK_THIS_BLOCK
;
956 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
959 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
961 return p(objectFileImage
, segmentName
, sectionName
, size
);
969 const char* *fileName
,
970 const char* *errorString
)
973 return dyld3::NSLinkEditError(c
, errorNumber
, fileName
, errorString
);
975 DYLD_LOCK_THIS_BLOCK
;
976 static void (*p
)(NSLinkEditErrors
*c
,
978 const char* *fileName
,
979 const char* *errorString
) = NULL
;
982 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
984 p(c
, errorNumber
, fileName
, errorString
);
993 return dyld3::NSUnLinkModule(module, options
);
995 DYLD_LOCK_THIS_BLOCK
;
996 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
999 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
1001 return p(module, options
);
1004 #if OBSOLETE_DYLD_API
1007 NSModule moduleToReplace
,
1008 NSObjectFileImage newObjectFileImage
,
1016 #endif // DEPRECATED_APIS_SUPPORTED
1019 *_NSGetExecutablePath copies the path of the executable into the buffer and
1020 * returns 0 if the path was successfully copied in the provided buffer. If the
1021 * buffer is not large enough, -1 is returned and the expected buffer size is
1022 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
1023 * the executable not a "real path" to the executable. That is the path may be
1024 * a symbolic link and not the real file. And with deep directories the total
1025 * bufsize needed could be more than MAXPATHLEN.
1028 _NSGetExecutablePath(
1033 return dyld3::_NSGetExecutablePath(buf
, bufsize
);
1035 DYLD_NO_LOCK_THIS_BLOCK
;
1036 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
1039 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
1040 return(p(buf
, bufsize
));
1043 #if DEPRECATED_APIS_SUPPORTED
1045 _dyld_lookup_and_bind(
1046 const char* symbol_name
,
1051 return dyld3::_dyld_lookup_and_bind(symbol_name
, address
, module);
1053 DYLD_LOCK_THIS_BLOCK
;
1054 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
1057 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
1058 p(symbol_name
, address
, module);
1062 _dyld_lookup_and_bind_with_hint(
1063 const char* symbol_name
,
1064 const char* library_name_hint
,
1068 DYLD_LOCK_THIS_BLOCK
;
1069 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
1072 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
1073 p(symbol_name
, library_name_hint
, address
, module);
1076 #if OBSOLETE_DYLD_API
1078 _dyld_lookup_and_bind_objc(
1079 const char* symbol_name
,
1083 DYLD_LOCK_THIS_BLOCK
;
1084 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
1087 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
1088 p(symbol_name
, address
, module);
1093 _dyld_lookup_and_bind_fully(
1094 const char* symbol_name
,
1098 DYLD_LOCK_THIS_BLOCK
;
1099 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
1102 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
1103 p(symbol_name
, address
, module);
1107 _dyld_bind_fully_image_containing_address(
1108 const void* address
)
1110 DYLD_LOCK_THIS_BLOCK
;
1111 static bool (*p
)(const void*) = NULL
;
1114 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
1117 #endif // DEPRECATED_APIS_SUPPORTED
1121 * _dyld_register_func_for_add_image registers the specified function to be
1122 * called when a new image is added (a bundle or a dynamic shared library) to
1123 * the program. When this function is first registered it is called for once
1124 * for each image that is currently part of the program.
1127 _dyld_register_func_for_add_image(
1128 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1131 return dyld3::_dyld_register_func_for_add_image(func
);
1133 DYLD_LOCK_THIS_BLOCK
;
1134 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1135 static void (*p
)(callback_t func
) = NULL
;
1138 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
1143 * _dyld_register_func_for_remove_image registers the specified function to be
1144 * called when an image is removed (a bundle or a dynamic shared library) from
1148 _dyld_register_func_for_remove_image(
1149 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1152 return dyld3::_dyld_register_func_for_remove_image(func
);
1154 DYLD_LOCK_THIS_BLOCK
;
1155 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1156 static void (*p
)(callback_t func
) = NULL
;
1159 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1163 #if OBSOLETE_DYLD_API
1165 * _dyld_register_func_for_link_module registers the specified function to be
1166 * called when a module is bound into the program. When this function is first
1167 * registered it is called for once for each module that is currently bound into
1171 _dyld_register_func_for_link_module(
1172 void (*func
)(NSModule
module))
1174 DYLD_LOCK_THIS_BLOCK
;
1175 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1178 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1183 * _dyld_register_func_for_unlink_module registers the specified function to be
1184 * called when a module is unbound from the program.
1187 _dyld_register_func_for_unlink_module(
1188 void (*func
)(NSModule
module))
1190 DYLD_LOCK_THIS_BLOCK
;
1191 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1194 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1199 * _dyld_register_func_for_replace_module registers the specified function to be
1200 * called when a module is to be replace with another module in the program.
1203 _dyld_register_func_for_replace_module(
1204 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1206 DYLD_LOCK_THIS_BLOCK
;
1207 static void (*p
)(void (*func
)(NSModule oldmodule
,
1208 NSModule newmodule
)) = NULL
;
1211 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1217 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1218 * pointer to the (__OBJC,__module) section and its size for the specified
1222 _dyld_get_objc_module_sect_for_module(
1225 unsigned long *size
)
1227 DYLD_LOCK_THIS_BLOCK
;
1228 static void (*p
)(NSModule
module,
1230 unsigned long *size
) = NULL
;
1233 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1234 p(module, objc_module
, size
);
1239 #if DEPRECATED_APIS_SUPPORTED
1243 // this function exists for compatiblity only
1249 _dyld_image_count(void)
1252 return dyld3::_dyld_image_count();
1254 DYLD_NO_LOCK_THIS_BLOCK
;
1255 static uint32_t (*p
)(void) = NULL
;
1258 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1262 const struct mach_header
*
1263 _dyld_get_image_header(uint32_t image_index
)
1266 return dyld3::_dyld_get_image_header(image_index
);
1268 DYLD_NO_LOCK_THIS_BLOCK
;
1269 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1272 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1273 return(p(image_index
));
1277 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1280 return dyld3::_dyld_get_image_vmaddr_slide(image_index
);
1282 DYLD_NO_LOCK_THIS_BLOCK
;
1283 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1286 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1287 return(p(image_index
));
1291 _dyld_get_image_name(uint32_t image_index
)
1294 return dyld3::_dyld_get_image_name(image_index
);
1296 DYLD_NO_LOCK_THIS_BLOCK
;
1297 static const char* (*p
)(uint32_t image_index
) = NULL
;
1300 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1301 return(p(image_index
));
1304 // SPI in Mac OS X 10.6
1305 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1307 // always use dyld3 version because it does better error handling
1308 return dyld3::_dyld_get_image_slide(mh
);
1311 const struct mach_header
*
1312 _dyld_get_prog_image_header()
1315 return dyld3::_dyld_get_prog_image_header();
1317 DYLD_LOCK_THIS_BLOCK
;
1318 static const struct mach_header
* (*p
)(void) = NULL
;
1321 _dyld_func_lookup("__dyld_get_prog_image_header", (void**)&p
);
1325 #if DEPRECATED_APIS_SUPPORTED
1327 _dyld_image_containing_address(const void* address
)
1330 return dyld3::_dyld_image_containing_address(address
);
1332 DYLD_LOCK_THIS_BLOCK
;
1333 static bool (*p
)(const void*) = NULL
;
1336 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1340 const struct mach_header
*
1341 _dyld_get_image_header_containing_address(
1342 const void* address
)
1345 return dyld3::_dyld_get_image_header_containing_address(address
);
1347 DYLD_LOCK_THIS_BLOCK
;
1348 static const struct mach_header
* (*p
)(const void*) = NULL
;
1351 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1355 bool _dyld_launched_prebound(void)
1357 DYLD_LOCK_THIS_BLOCK
;
1358 static bool (*p
)(void) = NULL
;
1361 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1365 bool _dyld_all_twolevel_modules_prebound(void)
1367 DYLD_LOCK_THIS_BLOCK
;
1368 static bool (*p
)(void) = NULL
;
1371 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1374 #endif // DEPRECATED_APIS_SUPPORTED
1377 #include <dlfcn_private.h>
1379 #include <pthread.h>
1381 #include <mach-o/dyld.h>
1382 #include "dyldLibSystemInterface.h"
1385 // pthread key used to access per-thread dlerror message
1386 static pthread_key_t dlerrorPerThreadKey
;
1387 static bool dlerrorPerThreadKeyInitialized
= false;
1389 // data kept per-thread
1390 struct dlerrorPerThreadData
1392 size_t sizeAllocated
;
1396 // function called by dyld to get buffer to store dlerror message
1397 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
1399 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1400 if (!dlerrorPerThreadKeyInitialized
) {
1401 // create key and tell pthread package to call free() on any data associated with key if thread dies
1402 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1403 dlerrorPerThreadKeyInitialized
= true;
1406 const size_t size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1407 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1408 if ( data
== NULL
) {
1409 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1410 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1411 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1412 data
->sizeAllocated
= size
;
1413 pthread_setspecific(dlerrorPerThreadKey
, data
);
1415 else if ( data
->sizeAllocated
< sizeRequired
) {
1417 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1418 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1419 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1420 data
->sizeAllocated
= size
;
1421 pthread_setspecific(dlerrorPerThreadKey
, data
);
1423 return data
->message
;
1426 // <rdar://problem/10595338> dlerror buffer leak
1427 // Only allocate buffer if an actual error message needs to be set
1428 static bool hasPerThreadBufferFor_dlerror()
1430 if (!dlerrorPerThreadKeyInitialized
)
1433 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1436 #if TARGET_OS_DRIVERKIT
1437 static bool isLaunchdOwned()
1442 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1443 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1444 static vswapproc swapProc
= &vproc_swap_integer
;
1446 static bool isLaunchdOwned()
1448 static bool checked
= false;
1449 static bool result
= false;
1453 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1454 result
= ( val
!= 0 );
1460 static void shared_cache_missing()
1462 // leave until dyld's that might call this are rare
1465 static void shared_cache_out_of_date()
1467 // leave until dyld's that might call this are rare
1471 // the table passed to dyld containing thread helpers
1472 static dyld::LibSystemHelpers sHelpers
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1473 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1474 &shared_cache_missing
, &shared_cache_out_of_date
,
1476 &pthread_key_create
, &pthread_setspecific
,
1478 &pthread_getspecific
,
1481 &hasPerThreadBufferFor_dlerror
,
1485 &__cxa_finalize_ranges
1488 static const objc_opt::objc_opt_t
* gObjCOpt
= nullptr;
1490 // during initialization of libSystem this routine will run
1491 // and call dyld, registering the helper functions.
1493 extern "C" void tlv_initializer();
1494 void _dyld_initializer()
1496 void (*p
)(dyld::LibSystemHelpers
*);
1498 // Get the optimized objc pointer now that the cache is loaded
1499 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1500 if ( allInfo
!= nullptr ) {
1501 const DyldSharedCache
* cache
= (const DyldSharedCache
*)(allInfo
->sharedCacheBaseAddress
);
1502 if ( cache
!= nullptr )
1503 gObjCOpt
= cache
->objcOpt();
1507 dyld3::gAllImages
.applyInitialImages();
1508 #if TARGET_OS_IOS && !TARGET_OS_SIMULATOR
1509 // For binaries built before 13.0, set the lookup function if they need it
1510 if (dyld_get_program_sdk_version() < DYLD_PACKED_VERSION(13,0,0))
1511 setLookupFunc((void*)&dyld3::compatFuncLookup
);
1515 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1523 int dladdr(const void* addr
, Dl_info
* info
)
1525 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLADDR
, (uint64_t)addr
, 0, 0);
1528 result
= dyld3::dladdr(addr
, info
);
1530 DYLD_LOCK_THIS_BLOCK
;
1531 static int (*p
)(const void* , Dl_info
*) = NULL
;
1534 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1535 result
= p(addr
, info
);
1537 timer
.setData4(result
);
1538 timer
.setData5(info
!= NULL
? info
->dli_fbase
: 0);
1539 timer
.setData6(info
!= NULL
? info
->dli_saddr
: 0);
1543 #if !TARGET_OS_DRIVERKIT
1547 return dyld3::dlerror();
1549 DYLD_LOCK_THIS_BLOCK
;
1550 static char* (*p
)() = NULL
;
1553 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1557 int dlclose(void* handle
)
1559 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLCLOSE
, (uint64_t)handle
, 0, 0);
1562 timer
.setData4(result
);
1563 return dyld3::dlclose(handle
);
1566 DYLD_LOCK_THIS_BLOCK
;
1567 static int (*p
)(void* handle
) = NULL
;
1570 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1572 timer
.setData4(result
);
1576 static void* dlopen_internal(const char* path
, int mode
, void* callerAddress
)
1578 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN
, path
, mode
, 0);
1579 void* result
= nullptr;
1581 result
= dyld3::dlopen_internal(path
, mode
, callerAddress
);
1582 timer
.setData4(result
);
1586 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1587 DYLD_NO_LOCK_THIS_BLOCK
;
1589 static void* (*p
)(const char* path
, int, void*) = NULL
;
1592 _dyld_func_lookup("__dyld_dlopen_internal", (void**)&p
);
1593 result
= p(path
, mode
, callerAddress
);
1594 // use asm block to prevent tail call optimization
1595 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1596 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1597 __asm__
volatile("");
1598 timer
.setData4(result
);
1603 void* dlopen(const char* path
, int mode
)
1605 void* result
= dlopen_internal(path
, mode
, __builtin_return_address(0));
1613 void* dlopen_from(const char* path
, int mode
, void* addressInCaller
)
1615 #if __has_feature(ptrauth_calls)
1616 addressInCaller
= __builtin_ptrauth_strip(addressInCaller
, ptrauth_key_asia
);
1618 return dlopen_internal(path
, mode
, addressInCaller
);
1622 void* dlopen_audited(const char* path
, int mode
)
1624 return dlopen(path
, mode
);
1628 bool dlopen_preflight(const char* path
)
1630 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN_PREFLIGHT
, path
, 0, 0);
1631 bool result
= false;
1634 result
= dyld3::dlopen_preflight_internal(path
);
1635 timer
.setData4(result
);
1639 DYLD_LOCK_THIS_BLOCK
;
1640 static bool (*p
)(const char* path
, void* callerAddress
) = NULL
;
1643 _dyld_func_lookup("__dyld_dlopen_preflight_internal", (void**)&p
);
1644 result
= p(path
, __builtin_return_address(0));
1645 timer
.setData4(result
);
1649 void* dlsym(void* handle
, const char* symbol
)
1651 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLSYM
, handle
, symbol
, 0);
1652 void* result
= nullptr;
1655 result
= dyld3::dlsym_internal(handle
, symbol
, __builtin_return_address(0));
1656 timer
.setData4(result
);
1660 DYLD_LOCK_THIS_BLOCK
;
1661 static void* (*p
)(void* handle
, const char* symbol
, void *callerAddress
) = NULL
;
1664 _dyld_func_lookup("__dyld_dlsym_internal", (void**)&p
);
1665 result
= p(handle
, symbol
, __builtin_return_address(0));
1666 timer
.setData4(result
);
1669 #endif // !TARGET_OS_DRIVERKIT
1672 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1675 return dyld3::_dyld_get_all_image_infos();
1677 DYLD_NO_LOCK_THIS_BLOCK
;
1678 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1681 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1685 #if SUPPORT_ZERO_COST_EXCEPTIONS
1686 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1689 return dyld3::_dyld_find_unwind_sections(addr
, info
);
1691 DYLD_NO_LOCK_THIS_BLOCK
;
1692 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1695 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1696 return p(addr
, info
);
1701 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1702 __attribute__((visibility("hidden")))
1703 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1705 DYLD_NO_LOCK_THIS_BLOCK
;
1706 static void* (*p
)(void*, long) = NULL
;
1709 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1710 return p(loadercache
, lazyinfo
);
1715 const char* dyld_image_path_containing_address(const void* addr
)
1718 return dyld3::dyld_image_path_containing_address(addr
);
1720 DYLD_NO_LOCK_THIS_BLOCK
;
1721 static const char* (*p
)(const void*) = NULL
;
1724 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1728 const struct mach_header
* dyld_image_header_containing_address(const void* addr
)
1731 return dyld3::dyld_image_header_containing_address(addr
);
1733 DYLD_NO_LOCK_THIS_BLOCK
;
1734 static const mach_header
* (*p
)(const void*) = NULL
;
1737 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1742 bool dyld_shared_cache_some_image_overridden()
1745 return dyld3::dyld_shared_cache_some_image_overridden();
1747 DYLD_NO_LOCK_THIS_BLOCK
;
1748 static bool (*p
)() = NULL
;
1751 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1755 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
1758 return dyld3::_dyld_get_shared_cache_uuid(uuid
);
1760 DYLD_NO_LOCK_THIS_BLOCK
;
1761 static bool (*p
)(uuid_t
) = NULL
;
1764 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
);
1768 const void* _dyld_get_shared_cache_range(size_t* length
)
1771 return dyld3::_dyld_get_shared_cache_range(length
);
1773 DYLD_NO_LOCK_THIS_BLOCK
;
1774 static const void* (*p
)(size_t*) = NULL
;
1777 _dyld_func_lookup("__dyld_get_shared_cache_range", (void**)&p
);
1781 bool _dyld_shared_cache_optimized()
1784 return dyld3::_dyld_shared_cache_optimized();
1786 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1787 if ( allInfo
!= nullptr ) {
1788 const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1789 if ( cacheHeader
!= nullptr )
1790 return (cacheHeader
->cacheType
== kDyldSharedCacheTypeProduction
);
1795 bool _dyld_shared_cache_is_locally_built()
1798 return dyld3::_dyld_shared_cache_is_locally_built();
1800 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1801 if ( allInfo
!= nullptr ) {
1802 const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1803 if ( cacheHeader
!= nullptr )
1804 return (cacheHeader
->locallyBuiltCache
== 1);
1809 const char* _dyld_shared_cache_real_path(const char* path
)
1811 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1812 if ( allInfo
!= nullptr ) {
1813 const DyldSharedCache
* cache
= (const DyldSharedCache
*)(allInfo
->sharedCacheBaseAddress
);
1814 if ( cache
!= nullptr )
1815 return cache
->getCanonicalPath(path
);
1820 bool _dyld_shared_cache_contains_path(const char* path
)
1822 return _dyld_shared_cache_real_path(path
) != nullptr;
1826 uint32_t _dyld_launch_mode()
1829 return dyld3::_dyld_launch_mode();
1831 // in dyld2 mode all flag bits are zero
1835 void _dyld_images_for_addresses(unsigned count
, const void* addresses
[], struct dyld_image_uuid_offset infos
[])
1838 return dyld3::_dyld_images_for_addresses(count
, addresses
, infos
);
1840 DYLD_NO_LOCK_THIS_BLOCK
;
1841 static const void (*p
)(unsigned, const void*[], struct dyld_image_uuid_offset
[]) = NULL
;
1844 _dyld_func_lookup("__dyld_images_for_addresses", (void**)&p
);
1845 return p(count
, addresses
, infos
);
1848 void _dyld_register_for_image_loads(void (*func
)(const mach_header
* mh
, const char* path
, bool unloadable
))
1851 return dyld3::_dyld_register_for_image_loads(func
);
1853 DYLD_NO_LOCK_THIS_BLOCK
;
1854 static const void (*p
)(void (*)(const mach_header
* mh
, const char* path
, bool unloadable
)) = NULL
;
1857 _dyld_func_lookup("__dyld_register_for_image_loads", (void**)&p
);
1861 void _dyld_register_for_bulk_image_loads(void (*func
)(unsigned imageCount
, const struct mach_header
* mhs
[], const char* paths
[]))
1864 return dyld3::_dyld_register_for_bulk_image_loads(func
);
1866 DYLD_NO_LOCK_THIS_BLOCK
;
1867 static const void (*p
)(void (*)(unsigned imageCount
, const mach_header
* mhs
[], const char* paths
[])) = NULL
;
1870 _dyld_func_lookup("__dyld_register_for_bulk_image_loads", (void**)&p
);
1874 bool dyld_need_closure(const char* execPath
, const char* dataContainerRootDir
)
1876 return dyld3::dyld_need_closure(execPath
, dataContainerRootDir
);
1879 bool dyld_process_is_restricted()
1882 return dyld3::dyld_process_is_restricted();
1884 DYLD_NO_LOCK_THIS_BLOCK
;
1885 static bool (*p
)() = NULL
;
1888 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1892 const char* dyld_shared_cache_file_path()
1895 return dyld3::dyld_shared_cache_file_path();
1897 DYLD_NO_LOCK_THIS_BLOCK
;
1898 static const char* (*p
)() = NULL
;
1901 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
);
1905 bool dyld_has_inserted_or_interposing_libraries()
1908 return dyld3::dyld_has_inserted_or_interposing_libraries();
1910 DYLD_NO_LOCK_THIS_BLOCK
;
1911 static bool (*p
)() = NULL
;
1914 _dyld_func_lookup("__dyld_has_inserted_or_interposing_libraries", (void**)&p
);
1918 bool _dyld_has_fix_for_radar(const char *rdar
) {
1919 // There is no point in shimming this to dyld3, actual functionality can exist purely in libSystem for
1920 // both dyld2 and dyld3.
1925 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1928 return dyld3::dyld_dynamic_interpose(mh
, array
, count
);
1930 DYLD_LOCK_THIS_BLOCK
;
1931 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1934 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1935 p(mh
, array
, count
);
1938 // SPI called __fork
1939 void _dyld_atfork_prepare()
1942 return dyld3::_dyld_atfork_prepare();
1945 // SPI called __fork
1946 void _dyld_atfork_parent()
1949 return dyld3::_dyld_atfork_parent();
1952 // SPI called __fork
1953 void _dyld_fork_child()
1956 return dyld3::_dyld_fork_child();
1958 DYLD_NO_LOCK_THIS_BLOCK
;
1959 static void (*p
)() = NULL
;
1962 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);
1968 static void* mapStartOfCache(const char* path
, size_t length
)
1970 struct stat statbuf
;
1971 if ( dyld3::stat(path
, &statbuf
) == -1 )
1974 if ( (size_t)statbuf
.st_size
< length
)
1977 int cache_fd
= dyld3::open(path
, O_RDONLY
, 0);
1981 void* result
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
1984 if ( result
== MAP_FAILED
)
1991 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
)
1993 DIR* dirp
= ::opendir(dirPath
);
1994 if ( dirp
!= NULL
) {
1996 dirent
* entp
= NULL
;
1997 char cachePath
[PATH_MAX
];
1998 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) {
2001 if ( entp
->d_type
!= DT_REG
)
2003 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
2005 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
2007 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
2009 if ( const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)mapStartOfCache(cachePath
, 0x00100000) ) {
2010 if ( (::memcmp(cacheHeader
, "dyld_", 5) != 0) || (::memcmp(cacheHeader
->uuid
, cacheUuid
, 16) != 0) ) {
2011 // wrong uuid, unmap and keep looking
2012 ::munmap((void*)cacheHeader
, 0x00100000);
2026 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid
, const char* extraSearchDirs
[], void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
2029 return dyld3::dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
2031 const dyld_cache_header
* cacheHeader
= NULL
;
2032 bool needToUnmap
= true;
2034 // get info from dyld about this process, to see if requested cache is already mapped into this process
2035 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
2036 if ( (allInfo
!= NULL
) && (allInfo
->sharedCacheBaseAddress
!= 0) && (memcmp(allInfo
->sharedCacheUUID
, cacheUuid
, 16) == 0) ) {
2037 // requested cache is already mapped, just re-use it
2038 cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
2039 needToUnmap
= false;
2042 // look first is default location for cache files
2043 #if TARGET_OS_IPHONE
2044 cacheHeader
= findCacheInDirAndMap(cacheUuid
, IPHONE_DYLD_SHARED_CACHE_DIR
);
2046 cacheHeader
= findCacheInDirAndMap(cacheUuid
, MACOSX_MRM_DYLD_SHARED_CACHE_DIR
);
2048 // if not there, look in extra search locations
2049 if ( cacheHeader
== NULL
) {
2050 for (const char** p
= extraSearchDirs
; *p
!= NULL
; ++p
) {
2051 cacheHeader
= findCacheInDirAndMap(cacheUuid
, *p
);
2052 if ( cacheHeader
!= NULL
)
2058 if ( cacheHeader
== NULL
)
2061 if ( cacheHeader
->mappingOffset
<= __offsetof(dyld_cache_header
, imagesTextOffset
) ) {
2062 // old cache without imagesText array
2064 ::munmap((void*)cacheHeader
, 0x00100000);
2068 // walk imageText table and call callback for each entry
2069 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
2070 const uint64_t cacheUnslidBaseAddress
= mappings
[0].address
;
2071 const dyld_cache_image_text_info
* imagesText
= (dyld_cache_image_text_info
*)((char*)cacheHeader
+ cacheHeader
->imagesTextOffset
);
2072 const dyld_cache_image_text_info
* imagesTextEnd
= &imagesText
[cacheHeader
->imagesTextCount
];
2073 for (const dyld_cache_image_text_info
* p
=imagesText
; p
< imagesTextEnd
; ++p
) {
2074 dyld_shared_cache_dylib_text_info dylibTextInfo
;
2075 dylibTextInfo
.version
= 2;
2076 dylibTextInfo
.loadAddressUnslid
= p
->loadAddress
;
2077 dylibTextInfo
.textSegmentSize
= p
->textSegmentSize
;
2078 dylibTextInfo
.path
= (char*)cacheHeader
+ p
->pathOffset
;
2079 ::memcpy(dylibTextInfo
.dylibUuid
, p
->uuid
, 16);
2080 dylibTextInfo
.textSegmentOffset
= p
->loadAddress
- cacheUnslidBaseAddress
;
2081 callback(&dylibTextInfo
);
2085 ::munmap((void*)cacheHeader
, 0x00100000);
2090 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
2093 return dyld3::dyld_shared_cache_iterate_text(cacheUuid
, callback
);
2095 const char* extraSearchDirs
[] = { NULL
};
2096 return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
2100 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
2103 return dyld3::_dyld_is_memory_immutable(addr
, length
);
2105 DYLD_NO_LOCK_THIS_BLOCK
;
2106 static bool (*p
)(const void*, size_t) = NULL
;
2109 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
);
2110 return p(addr
, length
);
2114 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
2115 _dyld_objc_notify_init init
,
2116 _dyld_objc_notify_unmapped unmapped
)
2119 return dyld3::_dyld_objc_notify_register(mapped
, init
, unmapped
);
2121 DYLD_LOCK_THIS_BLOCK
;
2122 static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
;
2125 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
);
2126 p(mapped
, init
, unmapped
);
2129 void _dyld_missing_symbol_abort()
2131 return dyld3::_dyld_missing_symbol_abort();
2134 const char* _dyld_get_objc_selector(const char* selName
)
2136 // Check the shared cache table if it exists.
2137 if ( gObjCOpt
!= nullptr ) {
2138 if ( const objc_opt::objc_selopt_t
* selopt
= gObjCOpt
->selopt() ) {
2139 const char* name
= selopt
->get(selName
);
2140 if (name
!= nullptr)
2146 return dyld3::_dyld_get_objc_selector(selName
);
2151 void _dyld_for_each_objc_class(const char* className
,
2152 void (^callback
)(void* classPtr
, bool isLoaded
, bool* stop
)) {
2154 return dyld3::_dyld_for_each_objc_class(className
, callback
);
2157 void _dyld_for_each_objc_protocol(const char* protocolName
,
2158 void (^callback
)(void* protocolPtr
, bool isLoaded
, bool* stop
)) {
2160 return dyld3::_dyld_for_each_objc_protocol(protocolName
, callback
);
2163 void _dyld_register_driverkit_main(void (*mainFunc
)(void))
2166 return dyld3::_dyld_register_driverkit_main(mainFunc
);
2168 static bool (*p
)(void (*mainFunc
)(void)) = NULL
;
2171 _dyld_func_lookup("__dyld_register_driverkit_main", (void**)&p
);
2175 // This is populated in the shared cache builder, so that the ranges are protected by __DATA_CONST
2176 // If we have a root, we can find this range in the shared cache libdyld at runtime
2177 typedef std::pair
<const uint8_t*, const uint8_t*> ObjCConstantRange
;
2180 __attribute__((section(("__DATA, __objc_ranges"))))
2182 __attribute__((section(("__DATA_CONST, __objc_ranges"))))
2184 __attribute__((used
))
2185 static ObjCConstantRange gSharedCacheObjCConstantRanges
[dyld_objc_string_kind
+ 1];
2187 static std::pair
<const void*, uint64_t> getDyldCacheConstantRanges() {
2188 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
2189 if ( allInfo
!= nullptr ) {
2190 const DyldSharedCache
* cache
= (const DyldSharedCache
*)(allInfo
->sharedCacheBaseAddress
);
2191 if ( cache
!= nullptr ) {
2192 return cache
->getObjCConstantRange();
2195 return { nullptr, 0 };
2198 bool _dyld_is_objc_constant(DyldObjCConstantKind kind
, const void* addr
) {
2199 assert(kind
<= dyld_objc_string_kind
);
2200 // The common case should be that the value is in range, as this is a security
2201 // check, so first test against the values in the struct. If we have a root then
2202 // we'll take the slow path later
2203 if ( (addr
>= gSharedCacheObjCConstantRanges
[kind
].first
) && (addr
< gSharedCacheObjCConstantRanges
[kind
].second
) ) {
2204 // Make sure that we are pointing at the start of a constant object, not in to the middle of it
2205 uint64_t offset
= (uint64_t)addr
- (uint64_t)gSharedCacheObjCConstantRanges
[kind
].first
;
2206 return (offset
% (uint64_t)DyldSharedCache::ConstantClasses::cfStringAtomSize
) == 0;
2209 // If we are in the shared cache, then the above check was sufficient, so this really isn't a valid constant address
2210 extern void* __dso_handle
;
2211 const dyld3::MachOAnalyzer
* ma
= (const dyld3::MachOAnalyzer
*)&__dso_handle
;
2212 if ( ma
->inDyldCache() )
2215 // We now know we are a root, so use the pointers in the shared cache libdyld version of gSharedCacheObjCConstantRanges
2216 static std::pair
<const void*, uint64_t> sharedCacheRanges
= { nullptr, ~0ULL };
2218 // FIXME: Should we fold this in as an inititalizer above?
2219 // That would mean we need to link against somewhere to get ___cxa_guard_acquire/___cxa_guard_release
2220 if ( sharedCacheRanges
.second
== ~0ULL )
2221 sharedCacheRanges
= getDyldCacheConstantRanges();
2223 // We have the range of the section in libdyld in the shared cache, now get an array of ranges from it
2224 uint64_t numRanges
= sharedCacheRanges
.second
/ sizeof(ObjCConstantRange
);
2225 if ( kind
>= numRanges
)
2228 const ObjCConstantRange
* rangeArrayBase
= (const ObjCConstantRange
*)sharedCacheRanges
.first
;
2229 if ( (addr
>= rangeArrayBase
[kind
].first
) && (addr
< rangeArrayBase
[kind
].second
) ) {
2230 // Make sure that we are pointing at the start of a constant object, not in to the middle of it
2231 uint64_t offset
= (uint64_t)addr
- (uint64_t)rangeArrayBase
[kind
].first
;
2232 return (offset
% (uint64_t)DyldSharedCache::ConstantClasses::cfStringAtomSize
) == 0;