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
* cmds
= NULL
;
444 if ( mh
->magic
== MH_MAGIC_64
)
445 cmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
446 else if ( mh
->magic
== MH_MAGIC
)
447 cmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
449 return 0; // not a mach-o file, or wrong endianness
451 const version_min_command
* versCmd
;
452 const dylib_command
* dylibCmd
;
453 const load_command
* cmd
= cmds
;
454 const char* dylibName
;
455 #if __IPHONE_OS_VERSION_MIN_REQUIRED
456 uint32_t foundationVers
= 0;
458 uint32_t libSystemVers
= 0;
460 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
461 switch ( cmd
->cmd
) {
462 #if __IPHONE_OS_VERSION_MIN_REQUIRED
463 case LC_VERSION_MIN_IPHONEOS
:
465 case LC_VERSION_MIN_MACOSX
:
467 versCmd
= (version_min_command
*)cmd
;
468 #ifdef DICE_KIND_DATA
469 if ( versCmd
->sdk
!= 0 )
470 return versCmd
->sdk
; // found explicit SDK version
472 if ( versCmd
->reserved
!= 0 )
473 return versCmd
->reserved
; // found explicit SDK version
477 case LC_LOAD_WEAK_DYLIB
:
478 case LC_LOAD_UPWARD_DYLIB
:
479 dylibCmd
= (dylib_command
*)cmd
;
480 dylibName
= (char*)dylibCmd
+ dylibCmd
->dylib
.name
.offset
;
481 #if __IPHONE_OS_VERSION_MIN_REQUIRED
482 if ( strcmp(dylibName
, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
483 foundationVers
= dylibCmd
->dylib
.current_version
;
485 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 )
486 libSystemVers
= dylibCmd
->dylib
.current_version
;
490 cmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
493 struct DylibToOSMapping
{
494 uint32_t dylibVersion
;
498 #if __IPHONE_OS_VERSION_MIN_REQUIRED
499 static const DylibToOSMapping foundationMapping
[] = {
500 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0
},
501 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1
},
502 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2
},
503 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0
},
504 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1
},
505 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2
},
506 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0
},
507 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1
},
508 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2
},
509 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3
},
510 { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0
},
511 { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1
},
512 { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0
},
513 { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1
},
514 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0
}, // check final
515 { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0
}
518 if ( foundationVers
!= 0 ) {
519 uint32_t lastOsVersion
= 0;
520 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) {
521 if ( p
->dylibVersion
== 0 )
523 if ( foundationVers
< p
->dylibVersion
)
524 return lastOsVersion
;
525 lastOsVersion
= p
->osVersion
;
530 // Note: versions are for the GM release. The last entry should
531 // always be zero. At the start of the next major version,
532 // a new last entry needs to be added and the previous zero
533 // updated to the GM dylib version.
534 static const DylibToOSMapping libSystemMapping
[] = {
535 { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4
},
536 { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5
},
537 { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6
},
538 { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7
},
539 { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8
},
540 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9
},
541 { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9
}
544 if ( libSystemVers
!= 0 ) {
545 uint32_t lastOsVersion
= 0;
546 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) {
547 if ( p
->dylibVersion
== 0 )
549 if ( libSystemVers
< p
->dylibVersion
)
550 return lastOsVersion
;
551 lastOsVersion
= p
->osVersion
;
559 uint32_t dyld_get_program_sdk_version()
561 return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader());
565 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
)
567 const load_command
* cmds
= NULL
;
568 if ( mh
->magic
== MH_MAGIC_64
)
569 cmds
= (load_command
*)((char *)mh
+ sizeof(mach_header_64
));
570 else if ( mh
->magic
== MH_MAGIC
)
571 cmds
= (load_command
*)((char *)mh
+ sizeof(mach_header
));
573 return 0; // not a mach-o file, or wrong endianness
575 const version_min_command
* versCmd
;
576 const load_command
* cmd
= cmds
;
577 for(uint32_t i
= 0; i
< mh
->ncmds
; ++i
) {
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
588 cmd
= (load_command
*)((char *)cmd
+ cmd
->cmdsize
);
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 unsigned long (*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 void (*monaddition
)(char *lowpc
, char *highpc
))
1174 DYLD_LOCK_THIS_BLOCK
;
1175 typedef void (*monproc
)(char *lowpc
, char *highpc
);
1176 static void (*p
)(monproc monaddition
) = NULL
;
1179 _dyld_func_lookup("__dyld_moninit", (void**)&p
);
1183 #if DEPRECATED_APIS_SUPPORTED
1184 bool _dyld_launched_prebound(void)
1186 DYLD_LOCK_THIS_BLOCK
;
1187 static bool (*p
)(void) = NULL
;
1190 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1194 bool _dyld_all_twolevel_modules_prebound(void)
1196 DYLD_LOCK_THIS_BLOCK
;
1197 static bool (*p
)(void) = NULL
;
1200 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1203 #endif // DEPRECATED_APIS_SUPPORTED
1208 #include <pthread.h>
1210 #include <mach-o/dyld.h>
1211 #include <servers/bootstrap.h>
1212 #include "dyldLibSystemInterface.h"
1215 // pthread key used to access per-thread dlerror message
1216 static pthread_key_t dlerrorPerThreadKey
;
1217 static bool dlerrorPerThreadKeyInitialized
= false;
1219 // data kept per-thread
1220 struct dlerrorPerThreadData
1222 uint32_t sizeAllocated
;
1226 // function called by dyld to get buffer to store dlerror message
1227 static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired
)
1229 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1230 if (!dlerrorPerThreadKeyInitialized
) {
1231 // create key and tell pthread package to call free() on any data associated with key if thread dies
1232 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1233 dlerrorPerThreadKeyInitialized
= true;
1236 const int size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1237 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1238 if ( data
== NULL
) {
1239 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1240 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1241 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1242 data
->sizeAllocated
= size
;
1243 pthread_setspecific(dlerrorPerThreadKey
, data
);
1245 else if ( data
->sizeAllocated
< sizeRequired
) {
1247 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1248 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1249 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1250 data
->sizeAllocated
= size
;
1251 pthread_setspecific(dlerrorPerThreadKey
, data
);
1253 return data
->message
;
1256 // <rdar://problem/10595338> dlerror buffer leak
1257 // Only allocate buffer if an actual error message needs to be set
1258 static bool hasPerThreadBufferFor_dlerror()
1260 if (!dlerrorPerThreadKeyInitialized
)
1263 return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
);
1266 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse
1267 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
);
1268 static vswapproc swapProc
= &vproc_swap_integer
;
1270 static bool isLaunchdOwned() {
1271 static bool first
= true;
1275 (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
);
1276 result
= ( val
!= 0 );
1283 #if DYLD_SHARED_CACHE_SUPPORT
1284 static void shared_cache_missing()
1286 // leave until dyld's that might call this are rare
1289 static void shared_cache_out_of_date()
1291 // leave until dyld's that might call this are rare
1293 #endif // DYLD_SHARED_CACHE_SUPPORT
1296 // the table passed to dyld containing thread helpers
1297 static dyld::LibSystemHelpers sHelpers
= { 12, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1298 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1299 #if DYLD_SHARED_CACHE_SUPPORT
1300 &shared_cache_missing
, &shared_cache_out_of_date
,
1305 &pthread_key_create
, &pthread_setspecific
,
1307 &pthread_getspecific
,
1310 &hasPerThreadBufferFor_dlerror
,
1317 // during initialization of libSystem this routine will run
1318 // and call dyld, registering the helper functions.
1320 extern "C" void tlv_initializer();
1321 extern "C" void _dyld_initializer();
1322 void _dyld_initializer()
1324 void (*p
)(dyld::LibSystemHelpers
*);
1326 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1336 DYLD_LOCK_THIS_BLOCK
;
1337 static char* (*p
)() = NULL
;
1340 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1344 int dladdr(const void* addr
, Dl_info
* info
)
1346 DYLD_LOCK_THIS_BLOCK
;
1347 static int (*p
)(const void* , Dl_info
*) = NULL
;
1350 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1351 return(p(addr
, info
));
1354 int dlclose(void* handle
)
1356 DYLD_LOCK_THIS_BLOCK
;
1357 static int (*p
)(void* handle
) = NULL
;
1360 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1364 void* dlopen(const char* path
, int mode
)
1366 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1367 DYLD_NO_LOCK_THIS_BLOCK
;
1369 static void* (*p
)(const char* path
, int) = NULL
;
1372 _dyld_func_lookup("__dyld_dlopen", (void**)&p
);
1373 void* result
= p(path
, mode
);
1374 // use asm block to prevent tail call optimization
1375 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1376 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1377 __asm__
volatile("");
1382 bool dlopen_preflight(const char* path
)
1384 DYLD_LOCK_THIS_BLOCK
;
1385 static bool (*p
)(const char* path
) = NULL
;
1388 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1392 void* dlsym(void* handle
, const char* symbol
)
1394 DYLD_LOCK_THIS_BLOCK
;
1395 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1398 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1399 return(p(handle
, symbol
));
1402 void dyld_register_image_state_change_handler(dyld_image_states state
,
1403 bool batch
, dyld_image_state_change_handler handler
)
1405 DYLD_LOCK_THIS_BLOCK
;
1406 static void* (*p
)(dyld_image_states
, bool, dyld_image_state_change_handler
) = NULL
;
1409 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p
);
1410 p(state
, batch
, handler
);
1414 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1416 DYLD_NO_LOCK_THIS_BLOCK
;
1417 static struct dyld_all_image_infos
* (*p
)() = NULL
;
1420 _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
);
1425 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1427 DYLD_NO_LOCK_THIS_BLOCK
;
1428 static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
;
1431 _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
);
1432 return p(addr
, info
);
1437 #if __i386__ || __x86_64__ || __arm__
1438 __attribute__((visibility("hidden")))
1439 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
)
1441 DYLD_NO_LOCK_THIS_BLOCK
;
1442 static void* (*p
)(void*, long) = NULL
;
1445 _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
);
1446 return p(loadercache
, lazyinfo
);
1451 const char* dyld_image_path_containing_address(const void* addr
)
1453 DYLD_NO_LOCK_THIS_BLOCK
;
1454 static const char* (*p
)(const void*) = NULL
;
1457 _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
);
1461 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1462 bool dyld_shared_cache_some_image_overridden()
1464 DYLD_NO_LOCK_THIS_BLOCK
;
1465 static bool (*p
)() = NULL
;
1468 _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
);
1474 bool dyld_process_is_restricted()
1476 DYLD_NO_LOCK_THIS_BLOCK
;
1477 static bool (*p
)() = NULL
;
1480 _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
);
1487 // SPI called __fork
1488 void _dyld_fork_child()
1490 DYLD_NO_LOCK_THIS_BLOCK
;
1491 static void (*p
)() = NULL
;
1494 _dyld_func_lookup("__dyld_fork_child", (void**)&p
);