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 #include <vproc_priv.h>
39 #include "mach-o/dyld_images.h"
40 #include "mach-o/dyld.h"
41 #include "mach-o/dyld_priv.h"
42 #include "dyld_cache_format.h"
44 #include "ImageLoader.h"
47 #include "../dyld3/APIs.h"
48 #include "../dyld3/AllImages.h"
49 #include "../dyld3/StartGlue.h"
50 #include "../dyld3/Tracing.h"
53 // this was in dyld_priv.h but it is no longer exported
55 const struct dyld_all_image_infos
* _dyld_get_all_image_infos() __attribute__((visibility("hidden")));
59 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
60 extern "C" void __cxa_finalize(const void *dso
);
61 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
);
64 // private interface between libSystem.dylib and dyld
66 extern "C" int _dyld_func_lookup(const char* dyld_func_name
, void **address
);
69 extern bool gUseDyld3
;
71 #ifndef LC_VERSION_MIN_MACOSX
72 #define LC_VERSION_MIN_MACOSX 0x24
73 struct version_min_command
{
74 uint32_t cmd
; /* LC_VERSION_MIN_MACOSX or
75 LC_VERSION_MIN_IPHONEOS */
76 uint32_t cmdsize
; /* sizeof(struct min_version_command) */
77 uint32_t version
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
78 uint32_t sdk
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
82 #ifndef LC_VERSION_MIN_IPHONEOS
83 #define LC_VERSION_MIN_IPHONEOS 0x25
86 #ifndef LC_VERSION_MIN_TVOS
87 #define LC_VERSION_MIN_TVOS 0x2F
90 #ifndef LC_VERSION_MIN_WATCHOS
91 #define LC_VERSION_MIN_WATCHOS 0x30
95 #ifndef LC_LOAD_UPWARD_DYLIB
96 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
99 #ifndef LC_BUILD_VERSION
100 #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */
103 * The build_version_command contains the min OS version on which this
104 * binary was built to run for its platform. The list of known platforms and
105 * tool values following it.
107 struct build_version_command
{
108 uint32_t cmd
; /* LC_BUILD_VERSION */
109 uint32_t cmdsize
; /* sizeof(struct build_version_command) plus */
110 /* ntools * sizeof(struct build_tool_version) */
111 uint32_t platform
; /* platform */
112 uint32_t minos
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
113 uint32_t sdk
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
114 uint32_t ntools
; /* number of tool entries following this */
117 struct build_tool_version
{
118 uint32_t tool
; /* enum for the tool */
119 uint32_t version
; /* version number of the tool */
122 /* Known values for the platform field above. */
123 #define PLATFORM_MACOS 1
124 #define PLATFORM_IOS 2
125 #define PLATFORM_TVOS 3
126 #define PLATFORM_WATCHOS 4
127 #define PLATFORM_BRIDGEOS 5
129 /* Known values for the tool field above. */
135 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
136 #if __IPHONE_OS_VERSION_MIN_REQUIRED
137 #define DEPRECATED_APIS_SUPPORTED 0
139 #define DEPRECATED_APIS_SUPPORTED 1
143 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
144 * libraryName (which is -lx or -framework Foo argument passed to the static
145 * link editor for the same library) and determines if they match. This depends
146 * on conventional use of names including major versioning.
151 const char *install_name
,
152 const char* libraryName
)
154 const char *basename
;
158 * Conventional install names have these forms:
159 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
160 * /Local/Library/Frameworks/AppKit.framework/Appkit
161 * /lib/libsys_s.A.dylib
162 * /usr/lib/libsys_s.dylib
164 basename
= strrchr(install_name
, '/');
166 basename
= install_name
;
171 * By checking the base name matching the library name we take care
172 * of the -framework cases.
174 if(strcmp(basename
, libraryName
) == 0)
178 * Now check the base name for "lib" if so proceed to check for the
179 * -lx case dealing with a possible .X.dylib and a .dylib extension.
181 if(strncmp(basename
, "lib", 3) ==0){
182 n
= strlen(libraryName
);
183 if(strncmp(basename
+3, libraryName
, n
) == 0){
184 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
186 if(basename
[3+n
] == '.' &&
187 basename
[3+n
+1] != '\0' &&
188 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
195 #if DEPRECATED_APIS_SUPPORTED
197 void NSInstallLinkEditErrorHandlers(
198 const NSLinkEditErrorHandlers
* handlers
)
201 return dyld3::NSInstallLinkEditErrorHandlers(handlers
);
203 DYLD_LOCK_THIS_BLOCK
;
204 typedef void (*ucallback_t
)(const char* symbol_name
);
205 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
206 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
207 const char* fileName
, const char* errorString
);
208 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
211 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
212 mcallback_t m
= handlers
->multiple
;
213 p(handlers
->undefined
, m
, handlers
->linkEdit
);
221 return dyld3::NSNameOfModule(module);
223 DYLD_LOCK_THIS_BLOCK
;
224 static const char* (*p
)(NSModule
module) = NULL
;
227 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
232 NSLibraryNameForModule(
236 return dyld3::NSLibraryNameForModule(module);
238 DYLD_LOCK_THIS_BLOCK
;
239 static const char* (*p
)(NSModule
module) = NULL
;
242 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
247 NSIsSymbolNameDefined(
248 const char* symbolName
)
251 return dyld3::NSIsSymbolNameDefined(symbolName
);
253 DYLD_LOCK_THIS_BLOCK
;
254 static bool (*p
)(const char* symbolName
) = NULL
;
257 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
258 return(p(symbolName
));
262 NSIsSymbolNameDefinedWithHint(
263 const char* symbolName
,
264 const char* libraryNameHint
)
267 return dyld3::NSIsSymbolNameDefinedWithHint(symbolName
, libraryNameHint
);
269 DYLD_LOCK_THIS_BLOCK
;
270 static bool (*p
)(const char* symbolName
,
271 const char* libraryNameHint
) = NULL
;
274 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
275 return(p(symbolName
, libraryNameHint
));
279 NSIsSymbolNameDefinedInImage(
280 const struct mach_header
*image
,
281 const char* symbolName
)
284 return dyld3::NSIsSymbolNameDefinedInImage(image
, symbolName
);
286 DYLD_LOCK_THIS_BLOCK
;
287 static bool (*p
)(const struct mach_header
*image
,
288 const char* symbolName
) = NULL
;
291 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
292 return(p(image
, symbolName
));
296 NSLookupAndBindSymbol(
297 const char* symbolName
)
300 return dyld3::NSLookupAndBindSymbol(symbolName
);
302 DYLD_LOCK_THIS_BLOCK
;
303 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
306 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
307 return(p(symbolName
));
311 NSLookupAndBindSymbolWithHint(
312 const char* symbolName
,
313 const char* libraryNameHint
)
316 return dyld3::NSLookupAndBindSymbolWithHint(symbolName
, libraryNameHint
);
318 DYLD_LOCK_THIS_BLOCK
;
319 static NSSymbol (*p
)(const char* symbolName
,
320 const char* libraryNameHint
) = NULL
;
323 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
324 return(p(symbolName
, libraryNameHint
));
328 NSLookupSymbolInModule(
330 const char* symbolName
)
333 return dyld3::NSLookupSymbolInModule(module, symbolName
);
335 DYLD_LOCK_THIS_BLOCK
;
336 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
339 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
340 return(p(module, symbolName
));
344 NSLookupSymbolInImage(
345 const struct mach_header
*image
,
346 const char* symbolName
,
350 return dyld3::NSLookupSymbolInImage(image
, symbolName
, options
);
352 DYLD_LOCK_THIS_BLOCK
;
353 static NSSymbol (*p
)(const struct mach_header
*image
,
354 const char* symbolName
,
355 uint32_t options
) = NULL
;
358 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
359 return(p(image
, symbolName
, options
));
367 return dyld3::NSNameOfSymbol(symbol
);
369 DYLD_LOCK_THIS_BLOCK
;
370 static char * (*p
)(NSSymbol symbol
) = NULL
;
373 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
382 return dyld3::NSAddressOfSymbol(symbol
);
384 DYLD_LOCK_THIS_BLOCK
;
385 static void * (*p
)(NSSymbol symbol
) = NULL
;
388 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
397 return dyld3::NSModuleForSymbol(symbol
);
399 DYLD_LOCK_THIS_BLOCK
;
400 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
403 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
409 const char* pathName
)
412 return dyld3::NSAddLibrary(pathName
);
414 DYLD_LOCK_THIS_BLOCK
;
415 static bool (*p
)(const char* pathName
) = NULL
;
418 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
423 NSAddLibraryWithSearching(
424 const char* pathName
)
427 return dyld3::NSAddLibrary(pathName
);
429 DYLD_LOCK_THIS_BLOCK
;
430 static bool (*p
)(const char* pathName
) = NULL
;
433 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
437 const struct mach_header
*
439 const char* image_name
,
443 return dyld3::NSAddImage(image_name
, options
);
445 DYLD_LOCK_THIS_BLOCK
;
446 static const struct mach_header
* (*p
)(const char* image_name
,
447 uint32_t options
) = NULL
;
450 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
451 return(p(image_name
, options
));
453 #endif // DEPRECATED_APIS_SUPPORTED
456 * This routine returns the current version of the named shared library the
457 * executable it was built with. The libraryName parameter is the same as the
458 * -lx or -framework Foo argument passed to the static link editor when building
459 * the executable (with -lx it would be "x" and with -framework Foo it would be
460 * "Foo"). If this the executable was not built against the specified library
461 * it returns -1. It should be noted that if this only returns the value the
462 * current version of the named shared library the executable was built with
463 * and not a list of current versions that dependent libraries and bundles the
464 * program is using were built with.
466 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
469 return dyld3::NSVersionOfLinkTimeLibrary(libraryName
);
471 // Lazily call _NSGetMachExecuteHeader() and cache result
473 static mach_header_64
* mh
= NULL
;
475 static mach_header
* mh
= NULL
;
478 mh
= _NSGetMachExecuteHeader();
480 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
482 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
484 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
487 case LC_LOAD_WEAK_DYLIB
:
488 case LC_LOAD_UPWARD_DYLIB
:
489 const dylib_command
* dl
= (dylib_command
*)lc
;
490 const char* install_name
= (char*)dl
+ dl
->dylib
.name
.offset
;
491 if ( names_match(install_name
, libraryName
) )
492 return dl
->dylib
.current_version
;
495 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
501 * This routine returns the current version of the named shared library the
502 * program it is running against. The libraryName parameter is the same as
503 * would be static link editor using the -lx or -framework Foo flags (with -lx
504 * it would be "x" and with -framework Foo it would be "Foo"). If the program
505 * is not using the specified library it returns -1.
507 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
510 return dyld3::NSVersionOfRunTimeLibrary(libraryName
);
512 uint32_t n
= _dyld_image_count();
513 for(uint32_t i
= 0; i
< n
; i
++){
514 const mach_header
* mh
= _dyld_get_image_header(i
);
517 if ( mh
->filetype
!= MH_DYLIB
)
520 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
522 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
524 for(uint32_t j
= 0; j
< mh
->ncmds
; j
++){
525 if ( lc
->cmd
== LC_ID_DYLIB
) {
526 const dylib_command
* dl
= (dylib_command
*)lc
;
527 const char* install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
528 if ( names_match(install_name
, libraryName
) )
529 return dl
->dylib
.current_version
;
531 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
538 uint32_t dyld_get_program_sdk_watch_os_version()
541 return dyld3::dyld_get_program_sdk_watch_os_version();
543 __block
uint32_t retval
= 0;
544 __block
bool versionFound
= false;
545 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
546 if (versionFound
) return;
548 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
550 retval
= sdk_version
;
557 uint32_t dyld_get_program_min_watch_os_version()
560 return dyld3::dyld_get_program_min_watch_os_version();
562 __block
uint32_t retval
= 0;
563 __block
bool versionFound
= false;
564 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
565 if (versionFound
) return;
567 if (dyld_get_base_platform(platform
) == PLATFORM_WATCHOS
) {
569 retval
= min_version
;
578 uint32_t dyld_get_program_sdk_bridge_os_version()
581 return dyld3::dyld_get_program_sdk_bridge_os_version();
583 __block
uint32_t retval
= 0;
584 __block
bool versionFound
= false;
585 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
586 if (versionFound
) return;
588 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
590 retval
= sdk_version
;
597 uint32_t dyld_get_program_min_bridge_os_version()
600 return dyld3::dyld_get_program_min_bridge_os_version();
602 __block
uint32_t retval
= 0;
603 __block
bool versionFound
= false;
604 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
605 if (versionFound
) return;
607 if (dyld_get_base_platform(platform
) == PLATFORM_BRIDGEOS
) {
609 retval
= min_version
;
618 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
619 * specified binary was built against.
621 * First looks for LC_VERSION_MIN_* in binary and if sdk field is
622 * not zero, return that value.
623 * Otherwise, looks for the libSystem.B.dylib the binary linked
624 * against and uses a table to convert that to an sdk version.
626 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
628 return dyld3::dyld_get_sdk_version(mh
);
631 uint32_t dyld_get_program_sdk_version()
633 return dyld3::dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
636 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
638 return dyld3::dyld_get_min_os_version(mh
);
642 uint32_t dyld_get_program_min_os_version()
644 return dyld3::dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
648 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
)
651 return dyld3::_dyld_get_image_uuid(mh
, uuid
);
653 const load_command
* startCmds
= NULL
;
654 if ( mh
->magic
== MH_MAGIC_64
)
655 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
656 else if ( mh
->magic
== MH_MAGIC
)
657 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
659 return false; // not a mach-o file, or wrong endianness
661 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
662 const load_command
* cmd
= startCmds
;
663 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
664 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
665 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
668 if ( cmd
->cmd
== LC_UUID
) {
669 const uuid_command
* uuidCmd
= (uuid_command
*)cmd
;
670 memcpy(uuid
, uuidCmd
->uuid
, 16);
679 dyld_platform_t
dyld_get_active_platform(void) {
681 return dyld3::dyld_get_active_platform();
684 // Most of the new version SPIs have pure dyld3 implementations, but
685 // They cannot get to the main executable, so we implement this here
686 // and they can use this by calling ::dyld_get_active_platform() in the root namespace
687 static dyld_platform_t sActivePlatform
= 0;
688 if (sActivePlatform
) return sActivePlatform
;
690 dyld3::dyld_get_image_versions((mach_header
*)_NSGetMachExecuteHeader(), ^(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
) {
691 sActivePlatform
= platform
;
692 //FIXME assert there is only one?
694 return sActivePlatform
;
697 dyld_platform_t
dyld_get_base_platform(dyld_platform_t platform
) {
698 return dyld3::dyld_get_base_platform(platform
);
701 bool dyld_is_simulator_platform(dyld_platform_t platform
) {
702 return dyld3::dyld_is_simulator_platform(platform
);
705 bool dyld_sdk_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
706 return dyld3::dyld_sdk_at_least(mh
, version
);
709 bool dyld_minos_at_least(const struct mach_header
* mh
, dyld_build_version_t version
) {
710 return dyld3::dyld_minos_at_least(mh
, version
);
713 bool dyld_program_sdk_at_least(dyld_build_version_t version
) {
714 return dyld3::dyld_sdk_at_least((mach_header
*)_NSGetMachExecuteHeader(),version
);
717 bool dyld_program_minos_at_least(dyld_build_version_t version
) {
718 return dyld3::dyld_minos_at_least((mach_header
*)_NSGetMachExecuteHeader(), version
);
721 // Function that walks through the load commands and calls the internal block for every version found
722 // Intended as a fallback for very complex (and rare) version checks, or for tools that need to
723 // print our everything for diagnostic reasons
724 void dyld_get_image_versions(const struct mach_header
* mh
, void (^callback
)(dyld_platform_t platform
, uint32_t sdk_version
, uint32_t min_version
)) {
725 dyld3::dyld_get_image_versions(mh
, callback
);
730 #if DEPRECATED_APIS_SUPPORTED
732 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
733 * specified file name if the file is a correct Mach-O file that can be loaded
734 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
735 * NSObjectFileImageFormat an error message is printed to stderr. All
736 * other codes cause no printing.
738 NSObjectFileImageReturnCode
739 NSCreateObjectFileImageFromFile(
740 const char* pathName
,
741 NSObjectFileImage
*objectFileImage
)
744 return dyld3::NSCreateObjectFileImageFromFile(pathName
, objectFileImage
);
746 DYLD_LOCK_THIS_BLOCK
;
747 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
750 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
751 return p(pathName
, objectFileImage
);
756 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
757 * object file mapped into memory at address of size length if the object file
758 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
759 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
760 * message is printed to stderr. All other codes cause no printing.
762 NSObjectFileImageReturnCode
763 NSCreateObjectFileImageFromMemory(
766 NSObjectFileImage
*objectFileImage
)
769 return dyld3::NSCreateObjectFileImageFromMemory(address
, size
, objectFileImage
);
771 DYLD_LOCK_THIS_BLOCK
;
772 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
775 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
776 return p(address
, size
, objectFileImage
);
779 #if OBSOLETE_DYLD_API
781 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
782 * specified core file name if the file is a correct Mach-O core file.
783 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
784 * an error message is printed to stderr. All other codes cause no printing.
786 NSObjectFileImageReturnCode
787 NSCreateCoreFileImageFromFile(
788 const char* pathName
,
789 NSObjectFileImage
*objectFileImage
)
791 DYLD_LOCK_THIS_BLOCK
;
792 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
795 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
796 return p(pathName
, objectFileImage
);
801 NSDestroyObjectFileImage(
802 NSObjectFileImage objectFileImage
)
805 return dyld3::NSDestroyObjectFileImage(objectFileImage
);
807 DYLD_LOCK_THIS_BLOCK
;
808 static bool (*p
)(NSObjectFileImage
) = NULL
;
811 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
812 return p(objectFileImage
);
818 NSObjectFileImage objectFileImage
,
819 const char* moduleName
,
823 return dyld3::NSLinkModule(objectFileImage
, moduleName
, options
);
825 DYLD_LOCK_THIS_BLOCK
;
826 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
829 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
831 return p(objectFileImage
, moduleName
, options
);
838 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
839 * definitions in the NSObjectFileImage.
842 NSSymbolDefinitionCountInObjectFileImage(
843 NSObjectFileImage objectFileImage
)
846 return dyld3::NSSymbolDefinitionCountInObjectFileImage(objectFileImage
);
848 DYLD_LOCK_THIS_BLOCK
;
849 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
852 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
854 return p(objectFileImage
);
858 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
859 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
860 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
864 NSSymbolDefinitionNameInObjectFileImage(
865 NSObjectFileImage objectFileImage
,
869 return dyld3::NSSymbolDefinitionNameInObjectFileImage(objectFileImage
, ordinal
);
871 DYLD_LOCK_THIS_BLOCK
;
872 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
875 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
877 return p(objectFileImage
, ordinal
);
881 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
882 * to undefined symbols the NSObjectFileImage.
885 NSSymbolReferenceCountInObjectFileImage(
886 NSObjectFileImage objectFileImage
)
889 return dyld3::NSSymbolReferenceCountInObjectFileImage(objectFileImage
);
891 DYLD_LOCK_THIS_BLOCK
;
892 static uint32_t (*p
)(NSObjectFileImage
) = NULL
;
895 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
897 return p(objectFileImage
);
901 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
902 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
903 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
907 NSSymbolReferenceNameInObjectFileImage(
908 NSObjectFileImage objectFileImage
,
910 bool *tentative_definition
) /* can be NULL */
913 return dyld3::NSSymbolReferenceNameInObjectFileImage(objectFileImage
, ordinal
, tentative_definition
);
915 DYLD_LOCK_THIS_BLOCK
;
916 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
919 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
921 return p(objectFileImage
, ordinal
, tentative_definition
);
925 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
926 * name has a definition in the NSObjectFileImage and FALSE otherwise.
929 NSIsSymbolDefinedInObjectFileImage(
930 NSObjectFileImage objectFileImage
,
931 const char* symbolName
)
934 return dyld3::NSIsSymbolDefinedInObjectFileImage(objectFileImage
, symbolName
);
936 DYLD_LOCK_THIS_BLOCK
;
937 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
940 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
942 return p(objectFileImage
, symbolName
);
946 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
947 * in the NSObjectFileImage for the specified segmentName and sectionName if
948 * it exists and it is not a zerofill section. If not it returns NULL. If
949 * the parameter size is not NULL the size of the section is also returned
950 * indirectly through that pointer.
953 NSGetSectionDataInObjectFileImage(
954 NSObjectFileImage objectFileImage
,
955 const char* segmentName
,
956 const char* sectionName
,
957 unsigned long *size
) /* can be NULL */
960 return dyld3::NSGetSectionDataInObjectFileImage(objectFileImage
, segmentName
, sectionName
, size
);
962 DYLD_LOCK_THIS_BLOCK
;
963 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
966 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
968 return p(objectFileImage
, segmentName
, sectionName
, size
);
976 const char* *fileName
,
977 const char* *errorString
)
980 return dyld3::NSLinkEditError(c
, errorNumber
, fileName
, errorString
);
982 DYLD_LOCK_THIS_BLOCK
;
983 static void (*p
)(NSLinkEditErrors
*c
,
985 const char* *fileName
,
986 const char* *errorString
) = NULL
;
989 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
991 p(c
, errorNumber
, fileName
, errorString
);
1000 return dyld3::NSUnLinkModule(module, options
);
1002 DYLD_LOCK_THIS_BLOCK
;
1003 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
1006 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
1008 return p(module, options
);
1011 #if OBSOLETE_DYLD_API
1014 NSModule moduleToReplace
,
1015 NSObjectFileImage newObjectFileImage
,
1023 #endif // DEPRECATED_APIS_SUPPORTED
1026 *_NSGetExecutablePath copies the path of the executable into the buffer and
1027 * returns 0 if the path was successfully copied in the provided buffer. If the
1028 * buffer is not large enough, -1 is returned and the expected buffer size is
1029 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
1030 * the executable not a "real path" to the executable. That is the path may be
1031 * a symbolic link and not the real file. And with deep directories the total
1032 * bufsize needed could be more than MAXPATHLEN.
1035 _NSGetExecutablePath(
1040 return dyld3::_NSGetExecutablePath(buf
, bufsize
);
1042 DYLD_NO_LOCK_THIS_BLOCK
;
1043 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
1046 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
1047 return(p(buf
, bufsize
));
1050 #if DEPRECATED_APIS_SUPPORTED
1052 _dyld_lookup_and_bind(
1053 const char* symbol_name
,
1057 DYLD_LOCK_THIS_BLOCK
;
1058 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
1061 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
1062 p(symbol_name
, address
, module);
1066 _dyld_lookup_and_bind_with_hint(
1067 const char* symbol_name
,
1068 const char* library_name_hint
,
1072 DYLD_LOCK_THIS_BLOCK
;
1073 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
1076 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
1077 p(symbol_name
, library_name_hint
, address
, module);
1080 #if OBSOLETE_DYLD_API
1082 _dyld_lookup_and_bind_objc(
1083 const char* symbol_name
,
1087 DYLD_LOCK_THIS_BLOCK
;
1088 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
1091 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
1092 p(symbol_name
, address
, module);
1097 _dyld_lookup_and_bind_fully(
1098 const char* symbol_name
,
1102 DYLD_LOCK_THIS_BLOCK
;
1103 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
1106 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
1107 p(symbol_name
, address
, module);
1111 _dyld_bind_fully_image_containing_address(
1112 const void* address
)
1114 DYLD_LOCK_THIS_BLOCK
;
1115 static bool (*p
)(const void*) = NULL
;
1118 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
1121 #endif // DEPRECATED_APIS_SUPPORTED
1125 * _dyld_register_func_for_add_image registers the specified function to be
1126 * called when a new image is added (a bundle or a dynamic shared library) to
1127 * the program. When this function is first registered it is called for once
1128 * for each image that is currently part of the program.
1131 _dyld_register_func_for_add_image(
1132 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1135 return dyld3::_dyld_register_func_for_add_image(func
);
1137 DYLD_LOCK_THIS_BLOCK
;
1138 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1139 static void (*p
)(callback_t func
) = NULL
;
1142 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
1147 * _dyld_register_func_for_remove_image registers the specified function to be
1148 * called when an image is removed (a bundle or a dynamic shared library) from
1152 _dyld_register_func_for_remove_image(
1153 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1156 return dyld3::_dyld_register_func_for_remove_image(func
);
1158 DYLD_LOCK_THIS_BLOCK
;
1159 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
1160 static void (*p
)(callback_t func
) = NULL
;
1163 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1167 #if OBSOLETE_DYLD_API
1169 * _dyld_register_func_for_link_module registers the specified function to be
1170 * called when a module is bound into the program. When this function is first
1171 * registered it is called for once for each module that is currently bound into
1175 _dyld_register_func_for_link_module(
1176 void (*func
)(NSModule
module))
1178 DYLD_LOCK_THIS_BLOCK
;
1179 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1182 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1187 * _dyld_register_func_for_unlink_module registers the specified function to be
1188 * called when a module is unbound from the program.
1191 _dyld_register_func_for_unlink_module(
1192 void (*func
)(NSModule
module))
1194 DYLD_LOCK_THIS_BLOCK
;
1195 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1198 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1203 * _dyld_register_func_for_replace_module registers the specified function to be
1204 * called when a module is to be replace with another module in the program.
1207 _dyld_register_func_for_replace_module(
1208 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1210 DYLD_LOCK_THIS_BLOCK
;
1211 static void (*p
)(void (*func
)(NSModule oldmodule
,
1212 NSModule newmodule
)) = NULL
;
1215 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1221 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1222 * pointer to the (__OBJC,__module) section and its size for the specified
1226 _dyld_get_objc_module_sect_for_module(
1229 unsigned long *size
)
1231 DYLD_LOCK_THIS_BLOCK
;
1232 static void (*p
)(NSModule
module,
1234 unsigned long *size
) = NULL
;
1237 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1238 p(module, objc_module
, size
);
1243 #if DEPRECATED_APIS_SUPPORTED
1247 // this function exists for compatiblity only
1253 _dyld_image_count(void)
1256 return dyld3::_dyld_image_count();
1258 DYLD_NO_LOCK_THIS_BLOCK
;
1259 static uint32_t (*p
)(void) = NULL
;
1262 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1266 const struct mach_header
*
1267 _dyld_get_image_header(uint32_t image_index
)
1270 return dyld3::_dyld_get_image_header(image_index
);
1272 DYLD_NO_LOCK_THIS_BLOCK
;
1273 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1276 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1277 return(p(image_index
));
1281 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1284 return dyld3::_dyld_get_image_vmaddr_slide(image_index
);
1286 DYLD_NO_LOCK_THIS_BLOCK
;
1287 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1290 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1291 return(p(image_index
));
1295 _dyld_get_image_name(uint32_t image_index
)
1298 return dyld3::_dyld_get_image_name(image_index
);
1300 DYLD_NO_LOCK_THIS_BLOCK
;
1301 static const char* (*p
)(uint32_t image_index
) = NULL
;
1304 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1305 return(p(image_index
));
1308 // SPI in Mac OS X 10.6
1309 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1312 return dyld3::_dyld_get_image_slide(mh
);
1314 DYLD_NO_LOCK_THIS_BLOCK
;
1315 static intptr_t (*p
)(const struct mach_header
*) = NULL
;
1318 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
);
1323 #if DEPRECATED_APIS_SUPPORTED
1325 _dyld_image_containing_address(const void* address
)
1328 return dyld3::_dyld_image_containing_address(address
);
1330 DYLD_LOCK_THIS_BLOCK
;
1331 static bool (*p
)(const void*) = NULL
;
1334 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1338 const struct mach_header
*
1339 _dyld_get_image_header_containing_address(
1340 const void* address
)
1343 return dyld3::_dyld_get_image_header_containing_address(address
);
1345 DYLD_LOCK_THIS_BLOCK
;
1346 static const struct mach_header
* (*p
)(const void*) = NULL
;
1349 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1353 bool _dyld_launched_prebound(void)
1355 DYLD_LOCK_THIS_BLOCK
;
1356 static bool (*p
)(void) = NULL
;
1359 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1363 bool _dyld_all_twolevel_modules_prebound(void)
1365 DYLD_LOCK_THIS_BLOCK
;
1366 static bool (*p
)(void) = NULL
;
1369 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1372 #endif // DEPRECATED_APIS_SUPPORTED
1377 #include <pthread.h>
1379 #include <mach-o/dyld.h>
1380 #include <servers/bootstrap.h>
1381 #include "dyldLibSystemInterface.h"
1384 // pthread key used to access per-thread dlerror message
1385 static pthread_key_t dlerrorPerThreadKey
;
1386 static bool dlerrorPerThreadKeyInitialized
= false;
1388 // data kept per-thread
1389 struct dlerrorPerThreadData
1391 size_t sizeAllocated
;
1395 // function called by dyld to get buffer to store dlerror message
1396 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
1398 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1399 if (!dlerrorPerThreadKeyInitialized
) {
1400 // create key and tell pthread package to call free() on any data associated with key if thread dies
1401 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1402 dlerrorPerThreadKeyInitialized
= true;
1405 const size_t size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1406 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1407 if ( data
== NULL
) {
1408 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1409 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1410 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1411 data
->sizeAllocated
= size
;
1412 pthread_setspecific(dlerrorPerThreadKey
, data
);
1414 else if ( data
->sizeAllocated
< sizeRequired
) {
1416 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1417 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1418 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1419 data
->sizeAllocated
= size
;
1420 pthread_setspecific(dlerrorPerThreadKey
, data
);
1422 return data
->message
;
1425 // <rdar://problem/10595338> dlerror buffer leak
1426 // Only allocate buffer if an actual error message needs to be set
1427 static bool hasPerThreadBufferFor_dlerror()
1429 if (!dlerrorPerThreadKeyInitialized
)
1432 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1435 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1436 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1437 static vswapproc swapProc
= &vproc_swap_integer
;
1439 static bool isLaunchdOwned()
1441 static bool checked
= false;
1442 static bool result
= false;
1446 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1447 result
= ( val
!= 0 );
1452 static void shared_cache_missing()
1454 // leave until dyld's that might call this are rare
1457 static void shared_cache_out_of_date()
1459 // leave until dyld's that might call this are rare
1463 // the table passed to dyld containing thread helpers
1464 static dyld::LibSystemHelpers sHelpers
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1465 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1466 &shared_cache_missing
, &shared_cache_out_of_date
,
1468 &pthread_key_create
, &pthread_setspecific
,
1470 &pthread_getspecific
,
1473 &hasPerThreadBufferFor_dlerror
,
1477 &__cxa_finalize_ranges
1482 // during initialization of libSystem this routine will run
1483 // and call dyld, registering the helper functions.
1485 extern "C" void tlv_initializer();
1486 void _dyld_initializer()
1488 void (*p
)(dyld::LibSystemHelpers
*);
1491 dyld3::gAllImages
.applyInitialImages();
1494 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1506 return dyld3::dlerror();
1508 DYLD_LOCK_THIS_BLOCK
;
1509 static char* (*p
)() = NULL
;
1512 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1516 int dladdr(const void* addr
, Dl_info
* info
)
1518 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLADDR
, (uint64_t)addr
, 0, 0);
1521 return dyld3::dladdr(addr
, info
);
1523 DYLD_LOCK_THIS_BLOCK
;
1524 static int (*p
)(const void* , Dl_info
*) = NULL
;
1527 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1528 result
= p(addr
, info
);
1529 timer
.setData4(result
);
1530 timer
.setData5(info
!= NULL
? info
->dli_fbase
: 0);
1531 timer
.setData6(info
!= NULL
? info
->dli_saddr
: 0);
1535 int dlclose(void* handle
)
1537 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLCLOSE
, (uint64_t)handle
, 0, 0);
1540 return dyld3::dlclose(handle
);
1542 DYLD_LOCK_THIS_BLOCK
;
1543 static int (*p
)(void* handle
) = NULL
;
1546 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1551 void* dlopen(const char* path
, int mode
)
1553 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN
, path
, mode
, 0);
1554 void* result
= nullptr;
1557 result
= dyld3::dlopen_internal(path
, mode
, __builtin_return_address(0));
1561 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1562 DYLD_NO_LOCK_THIS_BLOCK
;
1564 static void* (*p
)(const char* path
, int, void*) = NULL
;
1567 _dyld_func_lookup("__dyld_dlopen_internal", (void**)&p
);
1568 result
= p(path
, mode
, __builtin_return_address(0));
1569 // use asm block to prevent tail call optimization
1570 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1571 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1572 __asm__
volatile("");
1573 timer
.setData4(result
);
1576 // HACK for iOSMac bringup rdar://40945421
1577 if ( result
== nullptr && dyld_get_active_platform() == PLATFORM_IOSMAC
&& csr_check(CSR_ALLOW_APPLE_INTERNAL
) == 0) {
1578 if (hasPerThreadBufferFor_dlerror()) {
1579 // first char of buffer is flag whether string (starting at second char) is valid
1580 char* buffer
= getPerThreadBufferFor_dlerror(2);
1582 if ( buffer
[0] != '\0' && (strstr(&buffer
[1], "macOS dylib cannot be loaded into iOSMac process")
1583 || strstr(&buffer
[1], "mach-o, but not built for iOSMac")) ) {
1584 // if valid buffer and contains an iOSMac issue
1585 fprintf(stderr
, "dyld: iOSMac ERROR: process attempted to dlopen() dylib with macOS dependency: \n");
1586 fprintf(stderr
, "\tdlerror: %s\n", &buffer
[1]);
1587 fprintf(stderr
, "\tBacktrace:\n");
1589 void* stackPointers
[128];
1590 int stackPointersCnt
= backtrace(stackPointers
, 128);
1591 char** symbolicatedStack
= backtrace_symbols(stackPointers
, stackPointersCnt
);
1592 for (int32_t i
= 0; i
< stackPointersCnt
; ++i
) {
1593 fprintf(stderr
, "\t\t%s\n", symbolicatedStack
[i
]);
1595 free(symbolicatedStack
);
1604 bool dlopen_preflight(const char* path
)
1606 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLOPEN_PREFLIGHT
, path
, 0, 0);
1607 bool result
= false;
1610 result
= dyld3::dlopen_preflight_internal(path
);
1614 DYLD_LOCK_THIS_BLOCK
;
1615 static bool (*p
)(const char* path
, void* callerAddress
) = NULL
;
1618 _dyld_func_lookup("__dyld_dlopen_preflight_internal", (void**)&p
);
1619 result
= p(path
, __builtin_return_address(0));
1620 timer
.setData4(result
);
1624 void* dlsym(void* handle
, const char* symbol
)
1626 dyld3::ScopedTimer
timer(DBG_DYLD_TIMING_DLSYM
, handle
, symbol
, 0);
1627 void* result
= nullptr;
1630 result
= dyld3::dlsym_internal(handle
, symbol
, __builtin_return_address(0));
1634 DYLD_LOCK_THIS_BLOCK
;
1635 static void* (*p
)(void* handle
, const char* symbol
, void *callerAddress
) = NULL
;
1638 _dyld_func_lookup("__dyld_dlsym_internal", (void**)&p
);
1639 result
= p(handle
, symbol
, __builtin_return_address(0));
1640 timer
.setData4(result
);
1644 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1647 return dyld3::_dyld_get_all_image_infos();
1649 DYLD_NO_LOCK_THIS_BLOCK
;
1650 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1653 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1657 #if SUPPORT_ZERO_COST_EXCEPTIONS
1658 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1661 return dyld3::_dyld_find_unwind_sections(addr
, info
);
1663 DYLD_NO_LOCK_THIS_BLOCK
;
1664 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1667 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1668 return p(addr
, info
);
1673 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1674 __attribute__((visibility("hidden")))
1675 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1677 DYLD_NO_LOCK_THIS_BLOCK
;
1678 static void* (*p
)(void*, long) = NULL
;
1681 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1682 return p(loadercache
, lazyinfo
);
1687 const char* dyld_image_path_containing_address(const void* addr
)
1690 return dyld3::dyld_image_path_containing_address(addr
);
1692 DYLD_NO_LOCK_THIS_BLOCK
;
1693 static const char* (*p
)(const void*) = NULL
;
1696 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1700 const struct mach_header
* dyld_image_header_containing_address(const void* addr
)
1703 return dyld3::dyld_image_header_containing_address(addr
);
1705 DYLD_NO_LOCK_THIS_BLOCK
;
1706 static const mach_header
* (*p
)(const void*) = NULL
;
1709 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1714 bool dyld_shared_cache_some_image_overridden()
1717 return dyld3::dyld_shared_cache_some_image_overridden();
1719 DYLD_NO_LOCK_THIS_BLOCK
;
1720 static bool (*p
)() = NULL
;
1723 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1727 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
1730 return dyld3::_dyld_get_shared_cache_uuid(uuid
);
1732 DYLD_NO_LOCK_THIS_BLOCK
;
1733 static bool (*p
)(uuid_t
) = NULL
;
1736 _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
);
1740 const void* _dyld_get_shared_cache_range(size_t* length
)
1743 return dyld3::_dyld_get_shared_cache_range(length
);
1745 DYLD_NO_LOCK_THIS_BLOCK
;
1746 static const void* (*p
)(size_t*) = NULL
;
1749 _dyld_func_lookup("__dyld_get_shared_cache_range", (void**)&p
);
1753 void _dyld_images_for_addresses(unsigned count
, const void* addresses
[], struct dyld_image_uuid_offset infos
[])
1756 return dyld3::_dyld_images_for_addresses(count
, addresses
, infos
);
1758 DYLD_NO_LOCK_THIS_BLOCK
;
1759 static const void (*p
)(unsigned, const void*[], struct dyld_image_uuid_offset
[]) = NULL
;
1762 _dyld_func_lookup("__dyld_images_for_addresses", (void**)&p
);
1763 return p(count
, addresses
, infos
);
1766 void _dyld_register_for_image_loads(void (*func
)(const mach_header
* mh
, const char* path
, bool unloadable
))
1769 return dyld3::_dyld_register_for_image_loads(func
);
1771 DYLD_NO_LOCK_THIS_BLOCK
;
1772 static const void (*p
)(void (*)(const mach_header
* mh
, const char* path
, bool unloadable
)) = NULL
;
1775 _dyld_func_lookup("__dyld_register_for_image_loads", (void**)&p
);
1779 bool dyld_process_is_restricted()
1782 return dyld3::dyld_process_is_restricted();
1784 DYLD_NO_LOCK_THIS_BLOCK
;
1785 static bool (*p
)() = NULL
;
1788 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1792 const char* dyld_shared_cache_file_path()
1795 return dyld3::dyld_shared_cache_file_path();
1797 DYLD_NO_LOCK_THIS_BLOCK
;
1798 static const char* (*p
)() = NULL
;
1801 _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
);
1805 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1808 return dyld3::dyld_dynamic_interpose(mh
, array
, count
);
1810 DYLD_LOCK_THIS_BLOCK
;
1811 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1814 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1815 p(mh
, array
, count
);
1819 // SPI called __fork
1820 void _dyld_fork_child()
1823 return dyld3::_dyld_fork_child();
1825 DYLD_NO_LOCK_THIS_BLOCK
;
1826 static void (*p
)() = NULL
;
1829 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);
1835 static void* mapStartOfCache(const char* path
, size_t length
)
1837 struct stat statbuf
;
1838 if ( ::stat(path
, &statbuf
) == -1 )
1841 if ( (size_t)statbuf
.st_size
< length
)
1844 int cache_fd
= ::open(path
, O_RDONLY
);
1848 void* result
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
1851 if ( result
== MAP_FAILED
)
1858 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
)
1860 DIR* dirp
= ::opendir(dirPath
);
1861 if ( dirp
!= NULL
) {
1863 dirent
* entp
= NULL
;
1864 char cachePath
[PATH_MAX
];
1865 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) {
1868 if ( entp
->d_type
!= DT_REG
)
1870 if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX
)
1872 if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX
)
1874 if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX
)
1876 if ( const dyld_cache_header
* cacheHeader
= (dyld_cache_header
*)mapStartOfCache(cachePath
, 0x00100000) ) {
1877 if ( ::memcmp(cacheHeader
->uuid
, cacheUuid
, 16) != 0 ) {
1878 // wrong uuid, unmap and keep looking
1879 ::munmap((void*)cacheHeader
, 0x00100000);
1893 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid
, const char* extraSearchDirs
[], void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1896 return dyld3::dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
1898 const dyld_cache_header
* cacheHeader
= NULL
;
1899 bool needToUnmap
= true;
1901 // get info from dyld about this process, to see if requested cache is already mapped into this process
1902 const dyld_all_image_infos
* allInfo
= _dyld_get_all_image_infos();
1903 if ( (allInfo
!= NULL
) && (allInfo
->sharedCacheBaseAddress
!= 0) && (memcmp(allInfo
->sharedCacheUUID
, cacheUuid
, 16) == 0) ) {
1904 // requested cache is already mapped, just re-use it
1905 cacheHeader
= (dyld_cache_header
*)(allInfo
->sharedCacheBaseAddress
);
1906 needToUnmap
= false;
1909 // look first is default location for cache files
1910 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1911 const char* defaultSearchDir
= IPHONE_DYLD_SHARED_CACHE_DIR
;
1913 const char* defaultSearchDir
= MACOSX_DYLD_SHARED_CACHE_DIR
;
1915 cacheHeader
= findCacheInDirAndMap(cacheUuid
, defaultSearchDir
);
1916 // if not there, look in extra search locations
1917 if ( cacheHeader
== NULL
) {
1918 for (const char** p
= extraSearchDirs
; *p
!= NULL
; ++p
) {
1919 cacheHeader
= findCacheInDirAndMap(cacheUuid
, *p
);
1920 if ( cacheHeader
!= NULL
)
1926 if ( cacheHeader
== NULL
)
1929 if ( cacheHeader
->mappingOffset
< sizeof(dyld_cache_header
) ) {
1930 // old cache without imagesText array
1932 ::munmap((void*)cacheHeader
, 0x00100000);
1936 // walk imageText table and call callback for each entry
1937 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
1938 const uint64_t cacheUnslidBaseAddress
= mappings
[0].address
;
1939 const dyld_cache_image_text_info
* imagesText
= (dyld_cache_image_text_info
*)((char*)cacheHeader
+ cacheHeader
->imagesTextOffset
);
1940 const dyld_cache_image_text_info
* imagesTextEnd
= &imagesText
[cacheHeader
->imagesTextCount
];
1941 for (const dyld_cache_image_text_info
* p
=imagesText
; p
< imagesTextEnd
; ++p
) {
1942 dyld_shared_cache_dylib_text_info dylibTextInfo
;
1943 dylibTextInfo
.version
= 2;
1944 dylibTextInfo
.loadAddressUnslid
= p
->loadAddress
;
1945 dylibTextInfo
.textSegmentSize
= p
->textSegmentSize
;
1946 dylibTextInfo
.path
= (char*)cacheHeader
+ p
->pathOffset
;
1947 ::memcpy(dylibTextInfo
.dylibUuid
, p
->uuid
, 16);
1948 dylibTextInfo
.textSegmentOffset
= p
->loadAddress
- cacheUnslidBaseAddress
;
1949 callback(&dylibTextInfo
);
1953 ::munmap((void*)cacheHeader
, 0x00100000);
1958 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
))
1961 return dyld3::dyld_shared_cache_iterate_text(cacheUuid
, callback
);
1963 const char* extraSearchDirs
[] = { NULL
};
1964 return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
);
1968 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
1971 return dyld3::_dyld_is_memory_immutable(addr
, length
);
1973 DYLD_NO_LOCK_THIS_BLOCK
;
1974 static bool (*p
)(const void*, size_t) = NULL
;
1977 _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
);
1978 return p(addr
, length
);
1982 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
1983 _dyld_objc_notify_init init
,
1984 _dyld_objc_notify_unmapped unmapped
)
1987 return dyld3::_dyld_objc_notify_register(mapped
, init
, unmapped
);
1989 DYLD_LOCK_THIS_BLOCK
;
1990 static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
;
1993 _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
);
1994 p(mapped
, init
, unmapped
);