1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
27 #include <malloc/malloc.h>
30 #include <crt_externs.h>
31 #include <Availability.h>
32 #include <vproc_priv.h>
34 #include "mach-o/dyld.h"
35 #include "mach-o/dyld_priv.h"
37 #include "ImageLoader.h"
39 #include "start_glue.h"
41 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
42 extern "C" void __cxa_finalize(const void *dso
);
43 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
);
46 #ifndef LC_VERSION_MIN_MACOSX
47 #define LC_VERSION_MIN_MACOSX 0x24
48 struct version_min_command
{
49 uint32_t cmd
; /* LC_VERSION_MIN_MACOSX or
50 LC_VERSION_MIN_IPHONEOS */
51 uint32_t cmdsize
; /* sizeof(struct min_version_command) */
52 uint32_t version
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
53 uint32_t sdk
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
57 #ifndef LC_VERSION_MIN_IPHONEOS
58 #define LC_VERSION_MIN_IPHONEOS 0x25
62 #ifndef LC_LOAD_UPWARD_DYLIB
63 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
67 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
68 #if __IPHONE_OS_VERSION_MIN_REQUIRED
69 #define DEPRECATED_APIS_SUPPORTED 0
71 #define DEPRECATED_APIS_SUPPORTED 1
75 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
76 * libraryName (which is -lx or -framework Foo argument passed to the static
77 * link editor for the same library) and determines if they match. This depends
78 * on conventional use of names including major versioning.
83 const char *install_name
,
84 const char* libraryName
)
90 * Conventional install names have these forms:
91 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
92 * /Local/Library/Frameworks/AppKit.framework/Appkit
93 * /lib/libsys_s.A.dylib
94 * /usr/lib/libsys_s.dylib
96 basename
= strrchr(install_name
, '/');
98 basename
= install_name
;
103 * By checking the base name matching the library name we take care
104 * of the -framework cases.
106 if(strcmp(basename
, libraryName
) == 0)
110 * Now check the base name for "lib" if so proceed to check for the
111 * -lx case dealing with a possible .X.dylib and a .dylib extension.
113 if(strncmp(basename
, "lib", 3) ==0){
114 n
= strlen(libraryName
);
115 if(strncmp(basename
+3, libraryName
, n
) == 0){
116 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
118 if(basename
[3+n
] == '.' &&
119 basename
[3+n
+1] != '\0' &&
120 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
127 #if DEPRECATED_APIS_SUPPORTED
129 void NSInstallLinkEditErrorHandlers(
130 const NSLinkEditErrorHandlers
* handlers
)
132 DYLD_LOCK_THIS_BLOCK
;
133 typedef void (*ucallback_t
)(const char* symbol_name
);
134 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
135 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
136 const char* fileName
, const char* errorString
);
137 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
140 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
141 mcallback_t m
= handlers
->multiple
;
142 p(handlers
->undefined
, m
, handlers
->linkEdit
);
149 DYLD_LOCK_THIS_BLOCK
;
150 static const char* (*p
)(NSModule
module) = NULL
;
153 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
158 NSLibraryNameForModule(
161 DYLD_LOCK_THIS_BLOCK
;
162 static const char* (*p
)(NSModule
module) = NULL
;
165 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
170 NSIsSymbolNameDefined(
171 const char* symbolName
)
173 DYLD_LOCK_THIS_BLOCK
;
174 static bool (*p
)(const char* symbolName
) = NULL
;
177 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
178 return(p(symbolName
));
182 NSIsSymbolNameDefinedWithHint(
183 const char* symbolName
,
184 const char* libraryNameHint
)
186 DYLD_LOCK_THIS_BLOCK
;
187 static bool (*p
)(const char* symbolName
,
188 const char* libraryNameHint
) = NULL
;
191 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
192 return(p(symbolName
, libraryNameHint
));
196 NSIsSymbolNameDefinedInImage(
197 const struct mach_header
*image
,
198 const char* symbolName
)
200 DYLD_LOCK_THIS_BLOCK
;
201 static bool (*p
)(const struct mach_header
*image
,
202 const char* symbolName
) = NULL
;
205 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
206 return(p(image
, symbolName
));
210 NSLookupAndBindSymbol(
211 const char* symbolName
)
213 DYLD_LOCK_THIS_BLOCK
;
214 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
217 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
218 return(p(symbolName
));
222 NSLookupAndBindSymbolWithHint(
223 const char* symbolName
,
224 const char* libraryNameHint
)
226 DYLD_LOCK_THIS_BLOCK
;
227 static NSSymbol (*p
)(const char* symbolName
,
228 const char* libraryNameHint
) = NULL
;
231 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
232 return(p(symbolName
, libraryNameHint
));
236 NSLookupSymbolInModule(
238 const char* symbolName
)
240 DYLD_LOCK_THIS_BLOCK
;
241 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
244 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
245 return(p(module, symbolName
));
249 NSLookupSymbolInImage(
250 const struct mach_header
*image
,
251 const char* symbolName
,
254 DYLD_LOCK_THIS_BLOCK
;
255 static NSSymbol (*p
)(const struct mach_header
*image
,
256 const char* symbolName
,
257 uint32_t options
) = NULL
;
260 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
261 return(p(image
, symbolName
, options
));
268 DYLD_LOCK_THIS_BLOCK
;
269 static char * (*p
)(NSSymbol symbol
) = NULL
;
272 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
280 DYLD_LOCK_THIS_BLOCK
;
281 static void * (*p
)(NSSymbol symbol
) = NULL
;
284 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
292 DYLD_LOCK_THIS_BLOCK
;
293 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
296 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
302 const char* pathName
)
304 DYLD_LOCK_THIS_BLOCK
;
305 static bool (*p
)(const char* pathName
) = NULL
;
308 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
313 NSAddLibraryWithSearching(
314 const char* pathName
)
316 DYLD_LOCK_THIS_BLOCK
;
317 static bool (*p
)(const char* pathName
) = NULL
;
320 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
324 const struct mach_header
*
326 const char* image_name
,
329 DYLD_LOCK_THIS_BLOCK
;
330 static const struct mach_header
* (*p
)(const char* image_name
,
331 uint32_t options
) = NULL
;
334 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
335 return(p(image_name
, options
));
337 #endif // DEPRECATED_APIS_SUPPORTED
340 * This routine returns the current version of the named shared library the
341 * executable it was built with. The libraryName parameter is the same as the
342 * -lx or -framework Foo argument passed to the static link editor when building
343 * the executable (with -lx it would be "x" and with -framework Foo it would be
344 * "Foo"). If this the executable was not built against the specified library
345 * it returns -1. It should be noted that if this only returns the value the
346 * current version of the named shared library the executable was built with
347 * and not a list of current versions that dependent libraries and bundles the
348 * program is using were built with.
350 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
)
352 // Lazily call _NSGetMachExecuteHeader() and cache result
354 static mach_header_64
* mh
= NULL
;
356 static mach_header
* mh
= NULL
;
359 mh
= _NSGetMachExecuteHeader();
361 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
363 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
365 for(uint32_t i
= 0; i
< mh
->ncmds
; i
++){
368 case LC_LOAD_WEAK_DYLIB
:
369 case LC_LOAD_UPWARD_DYLIB
:
370 const dylib_command
* dl
= (dylib_command
*)lc
;
371 const char* install_name
= (char*)dl
+ dl
->dylib
.name
.offset
;
372 if ( names_match(install_name
, libraryName
) )
373 return dl
->dylib
.current_version
;
376 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
382 * This routine returns the current version of the named shared library the
383 * program it is running against. The libraryName parameter is the same as
384 * would be static link editor using the -lx or -framework Foo flags (with -lx
385 * it would be "x" and with -framework Foo it would be "Foo"). If the program
386 * is not using the specified library it returns -1.
388 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
)
390 uint32_t n
= _dyld_image_count();
391 for(uint32_t i
= 0; i
< n
; i
++){
392 const mach_header
* mh
= _dyld_get_image_header(i
);
395 if ( mh
->filetype
!= MH_DYLIB
)
398 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header_64
));
400 const load_command
* lc
= (load_command
*)((char*)mh
+ sizeof(mach_header
));
402 for(uint32_t j
= 0; j
< mh
->ncmds
; j
++){
403 if ( lc
->cmd
== LC_ID_DYLIB
) {
404 const dylib_command
* dl
= (dylib_command
*)lc
;
405 const char* install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
406 if ( names_match(install_name
, libraryName
) )
407 return dl
->dylib
.current_version
;
409 lc
= (load_command
*)((char*)lc
+ lc
->cmdsize
);
415 #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
419 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
420 * specified binary was built against.
422 * First looks for LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS
423 * in binary and if sdk field is not zero, return that value.
424 * Otherwise, looks for the libSystem.B.dylib the binary linked
425 * against and uses a table to convert that to an sdk version.
427 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
429 const load_command
* startCmds
= NULL
;
430 if ( mh
->magic
== MH_MAGIC_64
)
431 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
432 else if ( mh
->magic
== MH_MAGIC
)
433 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
435 return 0; // not a mach-o file, or wrong endianness
437 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
438 const version_min_command
* versCmd
;
439 const dylib_command
* dylibCmd
;
440 const load_command
* cmd
= startCmds
;
441 const char* dylibName
;
442 #if __IPHONE_OS_VERSION_MIN_REQUIRED
443 uint32_t foundationVers
= 0;
445 uint32_t libSystemVers
= 0;
447 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
448 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
449 // <rdar://problem/14381579&16050962> sanity check size of command
450 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
453 switch ( cmd
->cmd
) {
454 #if __IPHONE_OS_VERSION_MIN_REQUIRED
455 case LC_VERSION_MIN_IPHONEOS
:
457 case LC_VERSION_MIN_MACOSX
:
459 versCmd
= (version_min_command
*)cmd
;
460 #ifdef DICE_KIND_DATA
461 if ( versCmd
->sdk
!= 0 )
462 return versCmd
->sdk
; // found explicit SDK version
464 if ( versCmd
->reserved
!= 0 )
465 return versCmd
->reserved
; // found explicit SDK version
469 case LC_LOAD_WEAK_DYLIB
:
470 case LC_LOAD_UPWARD_DYLIB
:
471 dylibCmd
= (dylib_command
*)cmd
;
472 // sanity check dylib command layout
473 if ( dylibCmd
->dylib
.name
.offset
> cmd
->cmdsize
)
475 dylibName
= (char*)dylibCmd
+ dylibCmd
->dylib
.name
.offset
;
476 #if __IPHONE_OS_VERSION_MIN_REQUIRED
477 if ( strcmp(dylibName
, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
478 foundationVers
= dylibCmd
->dylib
.current_version
;
480 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 )
481 libSystemVers
= dylibCmd
->dylib
.current_version
;
488 struct DylibToOSMapping
{
489 uint32_t dylibVersion
;
493 #if __IPHONE_OS_VERSION_MIN_REQUIRED
494 static const DylibToOSMapping foundationMapping
[] = {
495 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0
},
496 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1
},
497 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2
},
498 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0
},
499 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1
},
500 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2
},
501 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0
},
502 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1
},
503 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2
},
504 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3
},
505 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0
},
506 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1
},
507 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0
},
508 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1
},
509 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0
}, // check final
510 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0
}
513 if ( foundationVers
!= 0 ) {
514 uint32_t lastOsVersion
= 0;
515 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) {
516 if ( p
->dylibVersion
== 0 )
518 if ( foundationVers
< p
->dylibVersion
)
519 return lastOsVersion
;
520 lastOsVersion
= p
->osVersion
;
525 // Note: versions are for the GM release. The last entry should
526 // always be zero. At the start of the next major version,
527 // a new last entry needs to be added and the previous zero
528 // updated to the GM dylib version.
529 static const DylibToOSMapping libSystemMapping
[] = {
530 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4
},
531 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5
},
532 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6
},
533 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7
},
534 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8
},
535 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9
},
536 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9
}
539 if ( libSystemVers
!= 0 ) {
540 uint32_t lastOsVersion
= 0;
541 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) {
542 if ( p
->dylibVersion
== 0 )
544 if ( libSystemVers
< p
->dylibVersion
)
545 return lastOsVersion
;
546 lastOsVersion
= p
->osVersion
;
554 uint32_t dyld_get_program_sdk_version()
556 return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
559 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
561 const load_command
* startCmds
= NULL
;
562 if ( mh
->magic
== MH_MAGIC_64
)
563 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
564 else if ( mh
->magic
== MH_MAGIC
)
565 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
567 return 0; // not a mach-o file, or wrong endianness
569 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
570 const version_min_command
* versCmd
;
571 const load_command
* cmd
= startCmds
;
572 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
573 const load_command
* nextCmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
574 // <rdar://problem/14381579&16050962> sanity check size of command
575 if ( (cmd
->cmdsize
< 8) || (nextCmd
> cmdsEnd
) || (nextCmd
< startCmds
)) {
578 switch ( cmd
->cmd
) {
579 #if __IPHONE_OS_VERSION_MIN_REQUIRED
580 case LC_VERSION_MIN_IPHONEOS
:
582 case LC_VERSION_MIN_MACOSX
:
584 versCmd
= (version_min_command
*)cmd
;
585 return versCmd
->version
; // found explicit min OS version
594 uint32_t dyld_get_program_min_os_version()
596 return dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
600 #if DEPRECATED_APIS_SUPPORTED
602 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
603 * specified file name if the file is a correct Mach-O file that can be loaded
604 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
605 * NSObjectFileImageFormat an error message is printed to stderr. All
606 * other codes cause no printing.
608 NSObjectFileImageReturnCode
609 NSCreateObjectFileImageFromFile(
610 const char* pathName
,
611 NSObjectFileImage
*objectFileImage
)
613 DYLD_LOCK_THIS_BLOCK
;
614 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
617 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
618 return p(pathName
, objectFileImage
);
623 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
624 * object file mapped into memory at address of size length if the object file
625 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
626 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
627 * message is printed to stderr. All other codes cause no printing.
629 NSObjectFileImageReturnCode
630 NSCreateObjectFileImageFromMemory(
633 NSObjectFileImage
*objectFileImage
)
635 DYLD_LOCK_THIS_BLOCK
;
636 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
639 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
640 return p(address
, size
, objectFileImage
);
643 #if OBSOLETE_DYLD_API
645 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
646 * specified core file name if the file is a correct Mach-O core file.
647 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
648 * an error message is printed to stderr. All other codes cause no printing.
650 NSObjectFileImageReturnCode
651 NSCreateCoreFileImageFromFile(
652 const char* pathName
,
653 NSObjectFileImage
*objectFileImage
)
655 DYLD_LOCK_THIS_BLOCK
;
656 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
659 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
660 return p(pathName
, objectFileImage
);
665 NSDestroyObjectFileImage(
666 NSObjectFileImage objectFileImage
)
668 DYLD_LOCK_THIS_BLOCK
;
669 static bool (*p
)(NSObjectFileImage
) = NULL
;
672 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
673 return p(objectFileImage
);
679 NSObjectFileImage objectFileImage
,
680 const char* moduleName
,
683 DYLD_LOCK_THIS_BLOCK
;
684 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
687 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
689 return p(objectFileImage
, moduleName
, options
);
696 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
697 * definitions in the NSObjectFileImage.
700 NSSymbolDefinitionCountInObjectFileImage(
701 NSObjectFileImage objectFileImage
)
703 DYLD_LOCK_THIS_BLOCK
;
704 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
707 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
709 return p(objectFileImage
);
713 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
714 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
715 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
719 NSSymbolDefinitionNameInObjectFileImage(
720 NSObjectFileImage objectFileImage
,
723 DYLD_LOCK_THIS_BLOCK
;
724 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
727 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
729 return p(objectFileImage
, ordinal
);
733 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
734 * to undefined symbols the NSObjectFileImage.
737 NSSymbolReferenceCountInObjectFileImage(
738 NSObjectFileImage objectFileImage
)
740 DYLD_LOCK_THIS_BLOCK
;
741 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
744 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
746 return p(objectFileImage
);
750 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
751 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
752 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
756 NSSymbolReferenceNameInObjectFileImage(
757 NSObjectFileImage objectFileImage
,
759 bool *tentative_definition
) /* can be NULL */
761 DYLD_LOCK_THIS_BLOCK
;
762 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
765 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
767 return p(objectFileImage
, ordinal
, tentative_definition
);
771 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
772 * name has a definition in the NSObjectFileImage and FALSE otherwise.
775 NSIsSymbolDefinedInObjectFileImage(
776 NSObjectFileImage objectFileImage
,
777 const char* symbolName
)
779 DYLD_LOCK_THIS_BLOCK
;
780 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
783 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
785 return p(objectFileImage
, symbolName
);
789 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
790 * in the NSObjectFileImage for the specified segmentName and sectionName if
791 * it exists and it is not a zerofill section. If not it returns NULL. If
792 * the parameter size is not NULL the size of the section is also returned
793 * indirectly through that pointer.
796 NSGetSectionDataInObjectFileImage(
797 NSObjectFileImage objectFileImage
,
798 const char* segmentName
,
799 const char* sectionName
,
800 unsigned long *size
) /* can be NULL */
802 DYLD_LOCK_THIS_BLOCK
;
803 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
806 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
808 return p(objectFileImage
, segmentName
, sectionName
, size
);
816 const char* *fileName
,
817 const char* *errorString
)
819 DYLD_LOCK_THIS_BLOCK
;
820 static void (*p
)(NSLinkEditErrors
*c
,
822 const char* *fileName
,
823 const char* *errorString
) = NULL
;
826 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
828 p(c
, errorNumber
, fileName
, errorString
);
836 DYLD_LOCK_THIS_BLOCK
;
837 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
840 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
842 return p(module, options
);
845 #if OBSOLETE_DYLD_API
848 NSModule moduleToReplace
,
849 NSObjectFileImage newObjectFileImage
,
857 #endif // DEPRECATED_APIS_SUPPORTED
860 *_NSGetExecutablePath copies the path of the executable into the buffer and
861 * returns 0 if the path was successfully copied in the provided buffer. If the
862 * buffer is not large enough, -1 is returned and the expected buffer size is
863 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
864 * the executable not a "real path" to the executable. That is the path may be
865 * a symbolic link and not the real file. And with deep directories the total
866 * bufsize needed could be more than MAXPATHLEN.
869 _NSGetExecutablePath(
873 DYLD_LOCK_THIS_BLOCK
;
874 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
877 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
878 return(p(buf
, bufsize
));
881 #if DEPRECATED_APIS_SUPPORTED
883 _dyld_lookup_and_bind(
884 const char* symbol_name
,
888 DYLD_LOCK_THIS_BLOCK
;
889 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
892 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
893 p(symbol_name
, address
, module);
897 _dyld_lookup_and_bind_with_hint(
898 const char* symbol_name
,
899 const char* library_name_hint
,
903 DYLD_LOCK_THIS_BLOCK
;
904 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
907 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
908 p(symbol_name
, library_name_hint
, address
, module);
911 #if OBSOLETE_DYLD_API
913 _dyld_lookup_and_bind_objc(
914 const char* symbol_name
,
918 DYLD_LOCK_THIS_BLOCK
;
919 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
922 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
923 p(symbol_name
, address
, module);
928 _dyld_lookup_and_bind_fully(
929 const char* symbol_name
,
933 DYLD_LOCK_THIS_BLOCK
;
934 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
937 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
938 p(symbol_name
, address
, module);
942 _dyld_bind_fully_image_containing_address(
945 DYLD_LOCK_THIS_BLOCK
;
946 static bool (*p
)(const void*) = NULL
;
949 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
952 #endif // DEPRECATED_APIS_SUPPORTED
956 * _dyld_register_func_for_add_image registers the specified function to be
957 * called when a new image is added (a bundle or a dynamic shared library) to
958 * the program. When this function is first registered it is called for once
959 * for each image that is currently part of the program.
962 _dyld_register_func_for_add_image(
963 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
965 DYLD_LOCK_THIS_BLOCK
;
966 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
967 static void (*p
)(callback_t func
) = NULL
;
970 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
975 * _dyld_register_func_for_remove_image registers the specified function to be
976 * called when an image is removed (a bundle or a dynamic shared library) from
980 _dyld_register_func_for_remove_image(
981 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
983 DYLD_LOCK_THIS_BLOCK
;
984 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
985 static void (*p
)(callback_t func
) = NULL
;
988 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
992 #if OBSOLETE_DYLD_API
994 * _dyld_register_func_for_link_module registers the specified function to be
995 * called when a module is bound into the program. When this function is first
996 * registered it is called for once for each module that is currently bound into
1000 _dyld_register_func_for_link_module(
1001 void (*func
)(NSModule
module))
1003 DYLD_LOCK_THIS_BLOCK
;
1004 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1007 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1012 * _dyld_register_func_for_unlink_module registers the specified function to be
1013 * called when a module is unbound from the program.
1016 _dyld_register_func_for_unlink_module(
1017 void (*func
)(NSModule
module))
1019 DYLD_LOCK_THIS_BLOCK
;
1020 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1023 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1028 * _dyld_register_func_for_replace_module registers the specified function to be
1029 * called when a module is to be replace with another module in the program.
1032 _dyld_register_func_for_replace_module(
1033 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1035 DYLD_LOCK_THIS_BLOCK
;
1036 static void (*p
)(void (*func
)(NSModule oldmodule
,
1037 NSModule newmodule
)) = NULL
;
1040 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1046 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1047 * pointer to the (__OBJC,__module) section and its size for the specified
1051 _dyld_get_objc_module_sect_for_module(
1054 unsigned long *size
)
1056 DYLD_LOCK_THIS_BLOCK
;
1057 static void (*p
)(NSModule
module,
1059 unsigned long *size
) = NULL
;
1062 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1063 p(module, objc_module
, size
);
1067 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1068 * __module) section and causes the module that is associated with that address
1072 _dyld_bind_objc_module(const void* objc_module
)
1074 DYLD_LOCK_THIS_BLOCK
;
1075 static void (*p
)(const void *objc_module
) = NULL
;
1078 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p
);
1083 #if DEPRECATED_APIS_SUPPORTED
1087 // this function exists for compatiblity only
1093 _dyld_image_count(void)
1095 DYLD_NO_LOCK_THIS_BLOCK
;
1096 static uint32_t (*p
)(void) = NULL
;
1099 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1103 const struct mach_header
*
1104 _dyld_get_image_header(uint32_t image_index
)
1106 DYLD_NO_LOCK_THIS_BLOCK
;
1107 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1110 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1111 return(p(image_index
));
1115 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1117 DYLD_NO_LOCK_THIS_BLOCK
;
1118 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1121 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1122 return(p(image_index
));
1126 _dyld_get_image_name(uint32_t image_index
)
1128 DYLD_NO_LOCK_THIS_BLOCK
;
1129 static const char* (*p
)(uint32_t image_index
) = NULL
;
1132 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1133 return(p(image_index
));
1136 // SPI in Mac OS X 10.6
1137 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1139 DYLD_NO_LOCK_THIS_BLOCK
;
1140 static intptr_t (*p
)(const struct mach_header
*) = NULL
;
1143 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
);
1149 _dyld_image_containing_address(const void* address
)
1151 DYLD_LOCK_THIS_BLOCK
;
1152 static bool (*p
)(const void*) = NULL
;
1155 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1159 const struct mach_header
*
1160 _dyld_get_image_header_containing_address(
1161 const void* address
)
1163 DYLD_LOCK_THIS_BLOCK
;
1164 static const struct mach_header
* (*p
)(const void*) = NULL
;
1167 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1172 #if DEPRECATED_APIS_SUPPORTED
1173 bool _dyld_launched_prebound(void)
1175 DYLD_LOCK_THIS_BLOCK
;
1176 static bool (*p
)(void) = NULL
;
1179 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1183 bool _dyld_all_twolevel_modules_prebound(void)
1185 DYLD_LOCK_THIS_BLOCK
;
1186 static bool (*p
)(void) = NULL
;
1189 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1192 #endif // DEPRECATED_APIS_SUPPORTED
1197 #include <pthread.h>
1199 #include <mach-o/dyld.h>
1200 #include <servers/bootstrap.h>
1201 #include "dyldLibSystemInterface.h"
1204 // pthread key used to access per-thread dlerror message
1205 static pthread_key_t dlerrorPerThreadKey
;
1206 static bool dlerrorPerThreadKeyInitialized
= false;
1208 // data kept per-thread
1209 struct dlerrorPerThreadData
1211 size_t sizeAllocated
;
1215 // function called by dyld to get buffer to store dlerror message
1216 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
)
1218 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1219 if (!dlerrorPerThreadKeyInitialized
) {
1220 // create key and tell pthread package to call free() on any data associated with key if thread dies
1221 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1222 dlerrorPerThreadKeyInitialized
= true;
1225 const size_t size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1226 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1227 if ( data
== NULL
) {
1228 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1229 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1230 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1231 data
->sizeAllocated
= size
;
1232 pthread_setspecific(dlerrorPerThreadKey
, data
);
1234 else if ( data
->sizeAllocated
< sizeRequired
) {
1236 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1237 const size_t mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1238 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1239 data
->sizeAllocated
= size
;
1240 pthread_setspecific(dlerrorPerThreadKey
, data
);
1242 return data
->message
;
1245 // <rdar://problem/10595338> dlerror buffer leak
1246 // Only allocate buffer if an actual error message needs to be set
1247 static bool hasPerThreadBufferFor_dlerror()
1249 if (!dlerrorPerThreadKeyInitialized
)
1252 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1255 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1256 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1257 static vswapproc swapProc
= &vproc_swap_integer
;
1259 static bool isLaunchdOwned() {
1260 static bool first
= true;
1264 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1265 result
= ( val
!= 0 );
1272 #if DYLD_SHARED_CACHE_SUPPORT
1273 static void shared_cache_missing()
1275 // leave until dyld's that might call this are rare
1278 static void shared_cache_out_of_date()
1280 // leave until dyld's that might call this are rare
1282 #endif // DYLD_SHARED_CACHE_SUPPORT
1285 // the table passed to dyld containing thread helpers
1286 static dyld::LibSystemHelpers sHelpers
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1287 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1288 #if DYLD_SHARED_CACHE_SUPPORT
1289 &shared_cache_missing
, &shared_cache_out_of_date
,
1294 &pthread_key_create
, &pthread_setspecific
,
1296 &pthread_getspecific
,
1299 &hasPerThreadBufferFor_dlerror
,
1303 &__cxa_finalize_ranges
};
1307 // during initialization of libSystem this routine will run
1308 // and call dyld, registering the helper functions.
1310 extern "C" void tlv_initializer();
1311 extern "C" void _dyld_initializer();
1312 void _dyld_initializer()
1314 void (*p
)(dyld::LibSystemHelpers
*);
1316 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1326 DYLD_LOCK_THIS_BLOCK
;
1327 static char* (*p
)() = NULL
;
1330 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1334 int dladdr(const void* addr
, Dl_info
* info
)
1336 DYLD_LOCK_THIS_BLOCK
;
1337 static int (*p
)(const void* , Dl_info
*) = NULL
;
1340 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1341 return(p(addr
, info
));
1344 int dlclose(void* handle
)
1346 DYLD_LOCK_THIS_BLOCK
;
1347 static int (*p
)(void* handle
) = NULL
;
1350 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1354 void* dlopen(const char* path
, int mode
)
1356 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1357 DYLD_NO_LOCK_THIS_BLOCK
;
1359 static void* (*p
)(const char* path
, int) = NULL
;
1362 _dyld_func_lookup("__dyld_dlopen", (void**)&p
);
1363 void* result
= p(path
, mode
);
1364 // use asm block to prevent tail call optimization
1365 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1366 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1367 __asm__
volatile("");
1372 bool dlopen_preflight(const char* path
)
1374 DYLD_LOCK_THIS_BLOCK
;
1375 static bool (*p
)(const char* path
) = NULL
;
1378 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1382 void* dlsym(void* handle
, const char* symbol
)
1384 DYLD_LOCK_THIS_BLOCK
;
1385 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1388 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1389 return(p(handle
, symbol
));
1392 void dyld_register_image_state_change_handler(dyld_image_states state
,
1393 bool batch
, dyld_image_state_change_handler handler
)
1395 DYLD_LOCK_THIS_BLOCK
;
1396 static void* (*p
)(dyld_image_states
, bool, dyld_image_state_change_handler
) = NULL
;
1399 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p
);
1400 p(state
, batch
, handler
);
1404 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1406 DYLD_NO_LOCK_THIS_BLOCK
;
1407 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1410 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1414 #if SUPPORT_ZERO_COST_EXCEPTIONS
1415 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1417 DYLD_NO_LOCK_THIS_BLOCK
;
1418 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1421 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1422 return p(addr
, info
);
1427 #if __i386__ || __x86_64__ || __arm__ || __arm64__
1428 __attribute__((visibility("hidden")))
1429 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1431 DYLD_NO_LOCK_THIS_BLOCK
;
1432 static void* (*p
)(void*, long) = NULL
;
1435 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1436 return p(loadercache
, lazyinfo
);
1441 const char* dyld_image_path_containing_address(const void* addr
)
1443 DYLD_NO_LOCK_THIS_BLOCK
;
1444 static const char* (*p
)(const void*) = NULL
;
1447 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1451 bool dyld_shared_cache_some_image_overridden()
1453 DYLD_NO_LOCK_THIS_BLOCK
;
1454 static bool (*p
)() = NULL
;
1457 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1462 bool dyld_process_is_restricted()
1464 DYLD_NO_LOCK_THIS_BLOCK
;
1465 static bool (*p
)() = NULL
;
1468 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1473 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1475 DYLD_LOCK_THIS_BLOCK
;
1476 static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
;
1479 _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
);
1480 p(mh
, array
, count
);
1484 // SPI called __fork
1485 void _dyld_fork_child()
1487 DYLD_NO_LOCK_THIS_BLOCK
;
1488 static void (*p
)() = NULL
;
1491 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);