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"
38 #include "start_glue.h"
40 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
41 extern "C" void __cxa_finalize(const void *dso
);
44 #ifndef LC_VERSION_MIN_MACOSX
45 #define LC_VERSION_MIN_MACOSX 0x24
46 struct version_min_command
{
47 uint32_t cmd
; /* LC_VERSION_MIN_MACOSX or
48 LC_VERSION_MIN_IPHONEOS */
49 uint32_t cmdsize
; /* sizeof(struct min_version_command) */
50 uint32_t version
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
51 uint32_t sdk
; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
55 #ifndef LC_VERSION_MIN_IPHONEOS
56 #define LC_VERSION_MIN_IPHONEOS 0x25
60 #ifndef LC_LOAD_UPWARD_DYLIB
61 #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
64 #define DYLD_SHARED_CACHE_SUPPORT (__i386__ || __x86_64__ || __arm__)
66 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
67 #if __IPHONE_OS_VERSION_MIN_REQUIRED
68 #define DEPRECATED_APIS_SUPPORTED 0
70 #define DEPRECATED_APIS_SUPPORTED 1
74 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
75 * libraryName (which is -lx or -framework Foo argument passed to the static
76 * link editor for the same library) and determines if they match. This depends
77 * on conventional use of names including major versioning.
83 const char* libraryName
)
89 * Conventional install names have these forms:
90 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
91 * /Local/Library/Frameworks/AppKit.framework/Appkit
92 * /lib/libsys_s.A.dylib
93 * /usr/lib/libsys_s.dylib
95 basename
= strrchr(install_name
, '/');
97 basename
= install_name
;
102 * By checking the base name matching the library name we take care
103 * of the -framework cases.
105 if(strcmp(basename
, libraryName
) == 0)
109 * Now check the base name for "lib" if so proceed to check for the
110 * -lx case dealing with a possible .X.dylib and a .dylib extension.
112 if(strncmp(basename
, "lib", 3) ==0){
113 n
= strlen(libraryName
);
114 if(strncmp(basename
+3, libraryName
, n
) == 0){
115 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
117 if(basename
[3+n
] == '.' &&
118 basename
[3+n
+1] != '\0' &&
119 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
126 #if DEPRECATED_APIS_SUPPORTED
128 void NSInstallLinkEditErrorHandlers(
129 const NSLinkEditErrorHandlers
* handlers
)
131 DYLD_LOCK_THIS_BLOCK
;
132 typedef void (*ucallback_t
)(const char* symbol_name
);
133 typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
);
134 typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
,
135 const char* fileName
, const char* errorString
);
136 static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
;
139 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
140 mcallback_t m
= handlers
->multiple
;
141 p(handlers
->undefined
, m
, handlers
->linkEdit
);
148 DYLD_LOCK_THIS_BLOCK
;
149 static const char* (*p
)(NSModule
module) = NULL
;
152 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
157 NSLibraryNameForModule(
160 DYLD_LOCK_THIS_BLOCK
;
161 static const char* (*p
)(NSModule
module) = NULL
;
164 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
169 NSIsSymbolNameDefined(
170 const char* symbolName
)
172 DYLD_LOCK_THIS_BLOCK
;
173 static bool (*p
)(const char* symbolName
) = NULL
;
176 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
177 return(p(symbolName
));
181 NSIsSymbolNameDefinedWithHint(
182 const char* symbolName
,
183 const char* libraryNameHint
)
185 DYLD_LOCK_THIS_BLOCK
;
186 static bool (*p
)(const char* symbolName
,
187 const char* libraryNameHint
) = NULL
;
190 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
191 return(p(symbolName
, libraryNameHint
));
195 NSIsSymbolNameDefinedInImage(
196 const struct mach_header
*image
,
197 const char* symbolName
)
199 DYLD_LOCK_THIS_BLOCK
;
200 static bool (*p
)(const struct mach_header
*image
,
201 const char* symbolName
) = NULL
;
204 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
205 return(p(image
, symbolName
));
209 NSLookupAndBindSymbol(
210 const char* symbolName
)
212 DYLD_LOCK_THIS_BLOCK
;
213 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
216 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
217 return(p(symbolName
));
221 NSLookupAndBindSymbolWithHint(
222 const char* symbolName
,
223 const char* libraryNameHint
)
225 DYLD_LOCK_THIS_BLOCK
;
226 static NSSymbol (*p
)(const char* symbolName
,
227 const char* libraryNameHint
) = NULL
;
230 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
231 return(p(symbolName
, libraryNameHint
));
235 NSLookupSymbolInModule(
237 const char* symbolName
)
239 DYLD_LOCK_THIS_BLOCK
;
240 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
243 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
244 return(p(module, symbolName
));
248 NSLookupSymbolInImage(
249 const struct mach_header
*image
,
250 const char* symbolName
,
253 DYLD_LOCK_THIS_BLOCK
;
254 static NSSymbol (*p
)(const struct mach_header
*image
,
255 const char* symbolName
,
256 uint32_t options
) = NULL
;
259 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
260 return(p(image
, symbolName
, options
));
267 DYLD_LOCK_THIS_BLOCK
;
268 static char * (*p
)(NSSymbol symbol
) = NULL
;
271 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
279 DYLD_LOCK_THIS_BLOCK
;
280 static void * (*p
)(NSSymbol symbol
) = NULL
;
283 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
291 DYLD_LOCK_THIS_BLOCK
;
292 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
295 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
301 const char* pathName
)
303 DYLD_LOCK_THIS_BLOCK
;
304 static bool (*p
)(const char* pathName
) = NULL
;
307 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
312 NSAddLibraryWithSearching(
313 const char* pathName
)
315 DYLD_LOCK_THIS_BLOCK
;
316 static bool (*p
)(const char* pathName
) = NULL
;
319 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
323 const struct mach_header
*
325 const char* image_name
,
328 DYLD_LOCK_THIS_BLOCK
;
329 static const struct mach_header
* (*p
)(const char* image_name
,
330 uint32_t options
) = NULL
;
333 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
334 return(p(image_name
, options
));
336 #endif // DEPRECATED_APIS_SUPPORTED
339 * This routine returns the current version of the named shared library the
340 * executable it was built with. The libraryName parameter is the same as the
341 * -lx or -framework Foo argument passed to the static link editor when building
342 * the executable (with -lx it would be "x" and with -framework Foo it would be
343 * "Foo"). If this the executable was not built against the specified library
344 * it returns -1. It should be noted that if this only returns the value the
345 * current version of the named shared library the executable was built with
346 * and not a list of current versions that dependent libraries and bundles the
347 * program is using were built with.
350 NSVersionOfLinkTimeLibrary(
351 const char* libraryName
)
354 struct load_command
*load_commands
, *lc
;
355 struct dylib_command
*dl
;
358 static struct mach_header_64
*mh
= NULL
;
360 static struct mach_header
*mh
= NULL
;
363 mh
= _NSGetMachExecuteHeader();
364 load_commands
= (struct load_command
*)
366 ((char *)mh
+ sizeof(struct mach_header_64
));
368 ((char *)mh
+ sizeof(struct mach_header
));
371 for(i
= 0; i
< mh
->ncmds
; i
++){
374 case LC_LOAD_WEAK_DYLIB
:
375 case LC_LOAD_UPWARD_DYLIB
:
376 dl
= (struct dylib_command
*)lc
;
377 install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
378 if(names_match(install_name
, libraryName
) == TRUE
)
379 return(dl
->dylib
.current_version
);
382 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
388 * This routine returns the current version of the named shared library the
389 * program it is running against. The libraryName parameter is the same as
390 * would be static link editor using the -lx or -framework Foo flags (with -lx
391 * it would be "x" and with -framework Foo it would be "Foo"). If the program
392 * is not using the specified library it returns -1.
395 NSVersionOfRunTimeLibrary(
396 const char* libraryName
)
398 unsigned long i
, j
, n
;
400 struct load_command
*load_commands
, *lc
;
401 struct dylib_command
*dl
;
402 const struct mach_header
*mh
;
404 n
= _dyld_image_count();
405 for(i
= 0; i
< n
; i
++){
406 mh
= _dyld_get_image_header(i
);
407 if(mh
->filetype
!= MH_DYLIB
)
409 load_commands
= (struct load_command
*)
411 ((char *)mh
+ sizeof(struct mach_header_64
));
413 ((char *)mh
+ sizeof(struct mach_header
));
416 for(j
= 0; j
< mh
->ncmds
; j
++){
417 if(lc
->cmd
== LC_ID_DYLIB
){
418 dl
= (struct dylib_command
*)lc
;
419 install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
420 if(names_match(install_name
, libraryName
) == TRUE
)
421 return(dl
->dylib
.current_version
);
423 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
429 #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
433 * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
434 * specified binary was built against.
436 * First looks for LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS
437 * in binary and if sdk field is not zero, return that value.
438 * Otherwise, looks for the libSystem.B.dylib the binary linked
439 * against and uses a table to convert that to an sdk version.
441 uint32_t dyld_get_sdk_version(const mach_header
* mh
)
443 const load_command
* startCmds
= NULL
;
444 if ( mh
->magic
== MH_MAGIC_64
)
445 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
446 else if ( mh
->magic
== MH_MAGIC
)
447 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
449 return 0; // not a mach-o file, or wrong endianness
451 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
452 const version_min_command
* versCmd
;
453 const dylib_command
* dylibCmd
;
454 const load_command
* cmd
= startCmds
;
455 const char* dylibName
;
456 #if __IPHONE_OS_VERSION_MIN_REQUIRED
457 uint32_t foundationVers
= 0;
459 uint32_t libSystemVers
= 0;
461 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
462 switch ( cmd
->cmd
) {
463 #if __IPHONE_OS_VERSION_MIN_REQUIRED
464 case LC_VERSION_MIN_IPHONEOS
:
466 case LC_VERSION_MIN_MACOSX
:
468 versCmd
= (version_min_command
*)cmd
;
469 #ifdef DICE_KIND_DATA
470 if ( versCmd
->sdk
!= 0 )
471 return versCmd
->sdk
; // found explicit SDK version
473 if ( versCmd
->reserved
!= 0 )
474 return versCmd
->reserved
; // found explicit SDK version
478 case LC_LOAD_WEAK_DYLIB
:
479 case LC_LOAD_UPWARD_DYLIB
:
480 dylibCmd
= (dylib_command
*)cmd
;
481 dylibName
= (char*)dylibCmd
+ dylibCmd
->dylib
.name
.offset
;
482 #if __IPHONE_OS_VERSION_MIN_REQUIRED
483 if ( strcmp(dylibName
, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
484 foundationVers
= dylibCmd
->dylib
.current_version
;
486 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 )
487 libSystemVers
= dylibCmd
->dylib
.current_version
;
491 // <rdar://problem/14381579> sanity check size of command
492 if ( (cmd
->cmdsize
< 8) || (cmd
->cmdsize
> mh
->sizeofcmds
) )
494 cmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
495 // <rdar://problem/14381579> bounds check
496 if ( (cmd
> cmdsEnd
) || (cmd
< startCmds
) )
500 struct DylibToOSMapping
{
501 uint32_t dylibVersion
;
505 #if __IPHONE_OS_VERSION_MIN_REQUIRED
506 static const DylibToOSMapping foundationMapping
[] = {
507 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0
},
508 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1
},
509 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2
},
510 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0
},
511 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1
},
512 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2
},
513 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0
},
514 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1
},
515 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2
},
516 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3
},
517 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0
},
518 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1
},
519 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0
},
520 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1
},
521 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0
}, // check final
522 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0
}
525 if ( foundationVers
!= 0 ) {
526 uint32_t lastOsVersion
= 0;
527 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) {
528 if ( p
->dylibVersion
== 0 )
530 if ( foundationVers
< p
->dylibVersion
)
531 return lastOsVersion
;
532 lastOsVersion
= p
->osVersion
;
537 // Note: versions are for the GM release. The last entry should
538 // always be zero. At the start of the next major version,
539 // a new last entry needs to be added and the previous zero
540 // updated to the GM dylib version.
541 static const DylibToOSMapping libSystemMapping
[] = {
542 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4
},
543 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5
},
544 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6
},
545 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7
},
546 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8
},
547 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9
},
548 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9
}
551 if ( libSystemVers
!= 0 ) {
552 uint32_t lastOsVersion
= 0;
553 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) {
554 if ( p
->dylibVersion
== 0 )
556 if ( libSystemVers
< p
->dylibVersion
)
557 return lastOsVersion
;
558 lastOsVersion
= p
->osVersion
;
566 uint32_t dyld_get_program_sdk_version()
568 return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
571 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
573 const load_command
* startCmds
= NULL
;
574 if ( mh
->magic
== MH_MAGIC_64
)
575 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
576 else if ( mh
->magic
== MH_MAGIC
)
577 startCmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
579 return 0; // not a mach-o file, or wrong endianness
581 const load_command
* const cmdsEnd
= (load_command
*)((char*)startCmds
+ mh
->sizeofcmds
);
582 const version_min_command
* versCmd
;
583 const load_command
* cmd
= startCmds
;
584 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
585 switch ( cmd
->cmd
) {
586 #if __IPHONE_OS_VERSION_MIN_REQUIRED
587 case LC_VERSION_MIN_IPHONEOS
:
589 case LC_VERSION_MIN_MACOSX
:
591 versCmd
= (version_min_command
*)cmd
;
592 return versCmd
->version
; // found explicit min OS version
595 // <rdar://problem/14381579> sanity check size of command
596 if ( (cmd
->cmdsize
< 8) || (cmd
->cmdsize
> mh
->sizeofcmds
) )
598 cmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
599 // <rdar://problem/14381579> bounds check
600 if ( (cmd
> cmdsEnd
) || (cmd
< startCmds
) )
607 uint32_t dyld_get_program_min_os_version()
609 return dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader());
613 #if DEPRECATED_APIS_SUPPORTED
615 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
616 * specified file name if the file is a correct Mach-O file that can be loaded
617 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
618 * NSObjectFileImageFormat an error message is printed to stderr. All
619 * other codes cause no printing.
621 NSObjectFileImageReturnCode
622 NSCreateObjectFileImageFromFile(
623 const char* pathName
,
624 NSObjectFileImage
*objectFileImage
)
626 DYLD_LOCK_THIS_BLOCK
;
627 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
630 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
631 return p(pathName
, objectFileImage
);
636 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
637 * object file mapped into memory at address of size length if the object file
638 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
639 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
640 * message is printed to stderr. All other codes cause no printing.
642 NSObjectFileImageReturnCode
643 NSCreateObjectFileImageFromMemory(
646 NSObjectFileImage
*objectFileImage
)
648 DYLD_LOCK_THIS_BLOCK
;
649 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
652 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
653 return p(address
, size
, objectFileImage
);
656 #if OBSOLETE_DYLD_API
658 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
659 * specified core file name if the file is a correct Mach-O core file.
660 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
661 * an error message is printed to stderr. All other codes cause no printing.
663 NSObjectFileImageReturnCode
664 NSCreateCoreFileImageFromFile(
665 const char* pathName
,
666 NSObjectFileImage
*objectFileImage
)
668 DYLD_LOCK_THIS_BLOCK
;
669 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
672 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
673 return p(pathName
, objectFileImage
);
678 NSDestroyObjectFileImage(
679 NSObjectFileImage objectFileImage
)
681 DYLD_LOCK_THIS_BLOCK
;
682 static bool (*p
)(NSObjectFileImage
) = NULL
;
685 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
686 return p(objectFileImage
);
692 NSObjectFileImage objectFileImage
,
693 const char* moduleName
,
696 DYLD_LOCK_THIS_BLOCK
;
697 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
700 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
702 return p(objectFileImage
, moduleName
, options
);
709 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
710 * definitions in the NSObjectFileImage.
713 NSSymbolDefinitionCountInObjectFileImage(
714 NSObjectFileImage objectFileImage
)
716 DYLD_LOCK_THIS_BLOCK
;
717 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
720 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
722 return p(objectFileImage
);
726 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
727 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
728 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
732 NSSymbolDefinitionNameInObjectFileImage(
733 NSObjectFileImage objectFileImage
,
736 DYLD_LOCK_THIS_BLOCK
;
737 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
740 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
742 return p(objectFileImage
, ordinal
);
746 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
747 * to undefined symbols the NSObjectFileImage.
750 NSSymbolReferenceCountInObjectFileImage(
751 NSObjectFileImage objectFileImage
)
753 DYLD_LOCK_THIS_BLOCK
;
754 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
757 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
759 return p(objectFileImage
);
763 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
764 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
765 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
769 NSSymbolReferenceNameInObjectFileImage(
770 NSObjectFileImage objectFileImage
,
772 bool *tentative_definition
) /* can be NULL */
774 DYLD_LOCK_THIS_BLOCK
;
775 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
778 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
780 return p(objectFileImage
, ordinal
, tentative_definition
);
784 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
785 * name has a definition in the NSObjectFileImage and FALSE otherwise.
788 NSIsSymbolDefinedInObjectFileImage(
789 NSObjectFileImage objectFileImage
,
790 const char* symbolName
)
792 DYLD_LOCK_THIS_BLOCK
;
793 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
796 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
798 return p(objectFileImage
, symbolName
);
802 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
803 * in the NSObjectFileImage for the specified segmentName and sectionName if
804 * it exists and it is not a zerofill section. If not it returns NULL. If
805 * the parameter size is not NULL the size of the section is also returned
806 * indirectly through that pointer.
809 NSGetSectionDataInObjectFileImage(
810 NSObjectFileImage objectFileImage
,
811 const char* segmentName
,
812 const char* sectionName
,
813 unsigned long *size
) /* can be NULL */
815 DYLD_LOCK_THIS_BLOCK
;
816 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
819 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
821 return p(objectFileImage
, segmentName
, sectionName
, size
);
829 const char* *fileName
,
830 const char* *errorString
)
832 DYLD_LOCK_THIS_BLOCK
;
833 static void (*p
)(NSLinkEditErrors
*c
,
835 const char* *fileName
,
836 const char* *errorString
) = NULL
;
839 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
841 p(c
, errorNumber
, fileName
, errorString
);
849 DYLD_LOCK_THIS_BLOCK
;
850 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
853 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
855 return p(module, options
);
858 #if OBSOLETE_DYLD_API
861 NSModule moduleToReplace
,
862 NSObjectFileImage newObjectFileImage
,
870 #endif // DEPRECATED_APIS_SUPPORTED
873 *_NSGetExecutablePath copies the path of the executable into the buffer and
874 * returns 0 if the path was successfully copied in the provided buffer. If the
875 * buffer is not large enough, -1 is returned and the expected buffer size is
876 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
877 * the executable not a "real path" to the executable. That is the path may be
878 * a symbolic link and not the real file. And with deep directories the total
879 * bufsize needed could be more than MAXPATHLEN.
882 _NSGetExecutablePath(
886 DYLD_LOCK_THIS_BLOCK
;
887 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
890 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
891 return(p(buf
, bufsize
));
894 #if DEPRECATED_APIS_SUPPORTED
896 _dyld_lookup_and_bind(
897 const char* symbol_name
,
901 DYLD_LOCK_THIS_BLOCK
;
902 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
905 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
906 p(symbol_name
, address
, module);
910 _dyld_lookup_and_bind_with_hint(
911 const char* symbol_name
,
912 const char* library_name_hint
,
916 DYLD_LOCK_THIS_BLOCK
;
917 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
920 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
921 p(symbol_name
, library_name_hint
, address
, module);
924 #if OBSOLETE_DYLD_API
926 _dyld_lookup_and_bind_objc(
927 const char* symbol_name
,
931 DYLD_LOCK_THIS_BLOCK
;
932 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
935 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
936 p(symbol_name
, address
, module);
941 _dyld_lookup_and_bind_fully(
942 const char* symbol_name
,
946 DYLD_LOCK_THIS_BLOCK
;
947 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
950 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
951 p(symbol_name
, address
, module);
955 _dyld_bind_fully_image_containing_address(
958 DYLD_LOCK_THIS_BLOCK
;
959 static bool (*p
)(const void*) = NULL
;
962 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
965 #endif // DEPRECATED_APIS_SUPPORTED
969 * _dyld_register_func_for_add_image registers the specified function to be
970 * called when a new image is added (a bundle or a dynamic shared library) to
971 * the program. When this function is first registered it is called for once
972 * for each image that is currently part of the program.
975 _dyld_register_func_for_add_image(
976 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
978 DYLD_LOCK_THIS_BLOCK
;
979 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
980 static void (*p
)(callback_t func
) = NULL
;
983 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
988 * _dyld_register_func_for_remove_image registers the specified function to be
989 * called when an image is removed (a bundle or a dynamic shared library) from
993 _dyld_register_func_for_remove_image(
994 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
996 DYLD_LOCK_THIS_BLOCK
;
997 typedef void (*callback_t
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
);
998 static void (*p
)(callback_t func
) = NULL
;
1001 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
1005 #if OBSOLETE_DYLD_API
1007 * _dyld_register_func_for_link_module registers the specified function to be
1008 * called when a module is bound into the program. When this function is first
1009 * registered it is called for once for each module that is currently bound into
1013 _dyld_register_func_for_link_module(
1014 void (*func
)(NSModule
module))
1016 DYLD_LOCK_THIS_BLOCK
;
1017 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1020 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
1025 * _dyld_register_func_for_unlink_module registers the specified function to be
1026 * called when a module is unbound from the program.
1029 _dyld_register_func_for_unlink_module(
1030 void (*func
)(NSModule
module))
1032 DYLD_LOCK_THIS_BLOCK
;
1033 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
1036 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
1041 * _dyld_register_func_for_replace_module registers the specified function to be
1042 * called when a module is to be replace with another module in the program.
1045 _dyld_register_func_for_replace_module(
1046 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
1048 DYLD_LOCK_THIS_BLOCK
;
1049 static void (*p
)(void (*func
)(NSModule oldmodule
,
1050 NSModule newmodule
)) = NULL
;
1053 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
1059 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
1060 * pointer to the (__OBJC,__module) section and its size for the specified
1064 _dyld_get_objc_module_sect_for_module(
1067 unsigned long *size
)
1069 DYLD_LOCK_THIS_BLOCK
;
1070 static void (*p
)(NSModule
module,
1072 unsigned long *size
) = NULL
;
1075 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
1076 p(module, objc_module
, size
);
1080 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
1081 * __module) section and causes the module that is associated with that address
1085 _dyld_bind_objc_module(const void* objc_module
)
1087 DYLD_LOCK_THIS_BLOCK
;
1088 static void (*p
)(const void *objc_module
) = NULL
;
1091 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p
);
1096 #if DEPRECATED_APIS_SUPPORTED
1100 // this function exists for compatiblity only
1106 _dyld_image_count(void)
1108 DYLD_NO_LOCK_THIS_BLOCK
;
1109 static unsigned long (*p
)(void) = NULL
;
1112 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
1116 const struct mach_header
*
1117 _dyld_get_image_header(uint32_t image_index
)
1119 DYLD_NO_LOCK_THIS_BLOCK
;
1120 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
1123 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
1124 return(p(image_index
));
1128 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
1130 DYLD_NO_LOCK_THIS_BLOCK
;
1131 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
1134 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
1135 return(p(image_index
));
1139 _dyld_get_image_name(uint32_t image_index
)
1141 DYLD_NO_LOCK_THIS_BLOCK
;
1142 static const char* (*p
)(uint32_t image_index
) = NULL
;
1145 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
1146 return(p(image_index
));
1149 // SPI in Mac OS X 10.6
1150 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
1152 DYLD_NO_LOCK_THIS_BLOCK
;
1153 static intptr_t (*p
)(const struct mach_header
*) = NULL
;
1156 _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
);
1162 _dyld_image_containing_address(const void* address
)
1164 DYLD_LOCK_THIS_BLOCK
;
1165 static bool (*p
)(const void*) = NULL
;
1168 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
1172 const struct mach_header
*
1173 _dyld_get_image_header_containing_address(
1174 const void* address
)
1176 DYLD_LOCK_THIS_BLOCK
;
1177 static const struct mach_header
* (*p
)(const void*) = NULL
;
1180 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
1185 void (*monaddition
)(char *lowpc
, char *highpc
))
1187 DYLD_LOCK_THIS_BLOCK
;
1188 typedef void (*monproc
)(char *lowpc
, char *highpc
);
1189 static void (*p
)(monproc monaddition
) = NULL
;
1192 _dyld_func_lookup("__dyld_moninit", (void**)&p
);
1196 #if DEPRECATED_APIS_SUPPORTED
1197 bool _dyld_launched_prebound(void)
1199 DYLD_LOCK_THIS_BLOCK
;
1200 static bool (*p
)(void) = NULL
;
1203 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1207 bool _dyld_all_twolevel_modules_prebound(void)
1209 DYLD_LOCK_THIS_BLOCK
;
1210 static bool (*p
)(void) = NULL
;
1213 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1216 #endif // DEPRECATED_APIS_SUPPORTED
1221 #include <pthread.h>
1223 #include <mach-o/dyld.h>
1224 #include <servers/bootstrap.h>
1225 #include "dyldLibSystemInterface.h"
1228 // pthread key used to access per-thread dlerror message
1229 static pthread_key_t dlerrorPerThreadKey
;
1230 static bool dlerrorPerThreadKeyInitialized
= false;
1232 // data kept per-thread
1233 struct dlerrorPerThreadData
1235 uint32_t sizeAllocated
;
1239 // function called by dyld to get buffer to store dlerror message
1240 static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired
)
1242 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1243 if (!dlerrorPerThreadKeyInitialized
) {
1244 // create key and tell pthread package to call free() on any data associated with key if thread dies
1245 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1246 dlerrorPerThreadKeyInitialized
= true;
1249 const int size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1250 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1251 if ( data
== NULL
) {
1252 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1253 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1254 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1255 data
->sizeAllocated
= size
;
1256 pthread_setspecific(dlerrorPerThreadKey
, data
);
1258 else if ( data
->sizeAllocated
< sizeRequired
) {
1260 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1261 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1262 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1263 data
->sizeAllocated
= size
;
1264 pthread_setspecific(dlerrorPerThreadKey
, data
);
1266 return data
->message
;
1269 // <rdar://problem/10595338> dlerror buffer leak
1270 // Only allocate buffer if an actual error message needs to be set
1271 static bool hasPerThreadBufferFor_dlerror()
1273 if (!dlerrorPerThreadKeyInitialized
)
1276 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1279 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1280 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1281 static vswapproc swapProc
= &vproc_swap_integer
;
1283 static bool isLaunchdOwned() {
1284 static bool first
= true;
1288 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1289 result
= ( val
!= 0 );
1296 #if DYLD_SHARED_CACHE_SUPPORT
1297 static void shared_cache_missing()
1299 // leave until dyld's that might call this are rare
1302 static void shared_cache_out_of_date()
1304 // leave until dyld's that might call this are rare
1306 #endif // DYLD_SHARED_CACHE_SUPPORT
1309 // the table passed to dyld containing thread helpers
1310 static dyld::LibSystemHelpers sHelpers
= { 12, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1311 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1312 #if DYLD_SHARED_CACHE_SUPPORT
1313 &shared_cache_missing
, &shared_cache_out_of_date
,
1318 &pthread_key_create
, &pthread_setspecific
,
1320 &pthread_getspecific
,
1323 &hasPerThreadBufferFor_dlerror
,
1330 // during initialization of libSystem this routine will run
1331 // and call dyld, registering the helper functions.
1333 extern "C" void tlv_initializer();
1334 extern "C" void _dyld_initializer();
1335 void _dyld_initializer()
1337 void (*p
)(dyld::LibSystemHelpers
*);
1339 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1349 DYLD_LOCK_THIS_BLOCK
;
1350 static char* (*p
)() = NULL
;
1353 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1357 int dladdr(const void* addr
, Dl_info
* info
)
1359 DYLD_LOCK_THIS_BLOCK
;
1360 static int (*p
)(const void* , Dl_info
*) = NULL
;
1363 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1364 return(p(addr
, info
));
1367 int dlclose(void* handle
)
1369 DYLD_LOCK_THIS_BLOCK
;
1370 static int (*p
)(void* handle
) = NULL
;
1373 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1377 void* dlopen(const char* path
, int mode
)
1379 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1380 DYLD_NO_LOCK_THIS_BLOCK
;
1382 static void* (*p
)(const char* path
, int) = NULL
;
1385 _dyld_func_lookup("__dyld_dlopen", (void**)&p
);
1386 void* result
= p(path
, mode
);
1387 // use asm block to prevent tail call optimization
1388 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1389 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1390 __asm__
volatile("");
1395 bool dlopen_preflight(const char* path
)
1397 DYLD_LOCK_THIS_BLOCK
;
1398 static bool (*p
)(const char* path
) = NULL
;
1401 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1405 void* dlsym(void* handle
, const char* symbol
)
1407 DYLD_LOCK_THIS_BLOCK
;
1408 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1411 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1412 return(p(handle
, symbol
));
1415 void dyld_register_image_state_change_handler(dyld_image_states state
,
1416 bool batch
, dyld_image_state_change_handler handler
)
1418 DYLD_LOCK_THIS_BLOCK
;
1419 static void* (*p
)(dyld_image_states
, bool, dyld_image_state_change_handler
) = NULL
;
1422 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p
);
1423 p(state
, batch
, handler
);
1427 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1429 DYLD_NO_LOCK_THIS_BLOCK
;
1430 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1433 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1438 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1440 DYLD_NO_LOCK_THIS_BLOCK
;
1441 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1444 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1445 return p(addr
, info
);
1450 #if __i386__ || __x86_64__ || __arm__
1451 __attribute__((visibility("hidden")))
1452 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1454 DYLD_NO_LOCK_THIS_BLOCK
;
1455 static void* (*p
)(void*, long) = NULL
;
1458 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1459 return p(loadercache
, lazyinfo
);
1464 const char* dyld_image_path_containing_address(const void* addr
)
1466 DYLD_NO_LOCK_THIS_BLOCK
;
1467 static const char* (*p
)(const void*) = NULL
;
1470 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1474 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1475 bool dyld_shared_cache_some_image_overridden()
1477 DYLD_NO_LOCK_THIS_BLOCK
;
1478 static bool (*p
)() = NULL
;
1481 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1487 bool dyld_process_is_restricted()
1489 DYLD_NO_LOCK_THIS_BLOCK
;
1490 static bool (*p
)() = NULL
;
1493 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1500 // SPI called __fork
1501 void _dyld_fork_child()
1503 DYLD_NO_LOCK_THIS_BLOCK
;
1504 static void (*p
)() = NULL
;
1507 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);