1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2007 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 <crt_externs.h>
29 #include "mach-o/dyld.h"
30 #include "mach-o/dyld_priv.h"
34 extern "C" int __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
);
38 * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
39 * libraryName (which is -lx or -framework Foo argument passed to the static
40 * link editor for the same library) and determines if they match. This depends
41 * on conventional use of names including major versioning.
47 const char* libraryName
)
53 * Conventional install names have these forms:
54 * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
55 * /Local/Library/Frameworks/AppKit.framework/Appkit
56 * /lib/libsys_s.A.dylib
57 * /usr/lib/libsys_s.dylib
59 basename
= strrchr(install_name
, '/');
61 basename
= install_name
;
66 * By checking the base name matching the library name we take care
67 * of the -framework cases.
69 if(strcmp(basename
, libraryName
) == 0)
73 * Now check the base name for "lib" if so proceed to check for the
74 * -lx case dealing with a possible .X.dylib and a .dylib extension.
76 if(strncmp(basename
, "lib", 3) ==0){
77 n
= strlen(libraryName
);
78 if(strncmp(basename
+3, libraryName
, n
) == 0){
79 if(strncmp(basename
+3+n
, ".dylib", 6) == 0)
81 if(basename
[3+n
] == '.' &&
82 basename
[3+n
+1] != '\0' &&
83 strncmp(basename
+3+n
+2, ".dylib", 6) == 0)
90 void NSInstallLinkEditErrorHandlers(
91 const NSLinkEditErrorHandlers
* handlers
)
95 void (*undefined
)(const char* symbol_name
),
96 NSModule (*multiple
)(NSSymbol s
, NSModule old
, NSModule newhandler
),
97 void (*linkEdit
)(NSLinkEditErrors c
, int errorNumber
,
98 const char* fileName
, const char* errorString
)) = NULL
;
101 _dyld_func_lookup("__dyld_install_handlers", (void**)&p
);
102 p(handlers
->undefined
, handlers
->multiple
, handlers
->linkEdit
);
109 DYLD_LOCK_THIS_BLOCK
;
110 static const char* (*p
)(NSModule
module) = NULL
;
113 _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
);
118 NSLibraryNameForModule(
121 DYLD_LOCK_THIS_BLOCK
;
122 static const char* (*p
)(NSModule
module) = NULL
;
125 _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
);
130 NSIsSymbolNameDefined(
131 const char* symbolName
)
133 DYLD_LOCK_THIS_BLOCK
;
134 static bool (*p
)(const char* symbolName
) = NULL
;
137 _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
);
138 return(p(symbolName
));
142 NSIsSymbolNameDefinedWithHint(
143 const char* symbolName
,
144 const char* libraryNameHint
)
146 DYLD_LOCK_THIS_BLOCK
;
147 static bool (*p
)(const char* symbolName
,
148 const char* libraryNameHint
) = NULL
;
151 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
);
152 return(p(symbolName
, libraryNameHint
));
156 NSIsSymbolNameDefinedInImage(
157 const struct mach_header
*image
,
158 const char* symbolName
)
160 DYLD_LOCK_THIS_BLOCK
;
161 static bool (*p
)(const struct mach_header
*image
,
162 const char* symbolName
) = NULL
;
165 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
);
166 return(p(image
, symbolName
));
170 NSLookupAndBindSymbol(
171 const char* symbolName
)
173 DYLD_LOCK_THIS_BLOCK
;
174 static NSSymbol (*p
)(const char* symbolName
) = NULL
;
177 _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
);
178 return(p(symbolName
));
182 NSLookupAndBindSymbolWithHint(
183 const char* symbolName
,
184 const char* libraryNameHint
)
186 DYLD_LOCK_THIS_BLOCK
;
187 static NSSymbol (*p
)(const char* symbolName
,
188 const char* libraryNameHint
) = NULL
;
191 _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
);
192 return(p(symbolName
, libraryNameHint
));
196 NSLookupSymbolInModule(
198 const char* symbolName
)
200 DYLD_LOCK_THIS_BLOCK
;
201 static NSSymbol (*p
)(NSModule
module, const char* symbolName
) = NULL
;
204 _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
);
205 return(p(module, symbolName
));
209 NSLookupSymbolInImage(
210 const struct mach_header
*image
,
211 const char* symbolName
,
214 DYLD_LOCK_THIS_BLOCK
;
215 static NSSymbol (*p
)(const struct mach_header
*image
,
216 const char* symbolName
,
217 uint32_t options
) = NULL
;
220 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
);
221 return(p(image
, symbolName
, options
));
228 DYLD_LOCK_THIS_BLOCK
;
229 static char * (*p
)(NSSymbol symbol
) = NULL
;
232 _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
);
240 DYLD_LOCK_THIS_BLOCK
;
241 static void * (*p
)(NSSymbol symbol
) = NULL
;
244 _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
);
252 DYLD_LOCK_THIS_BLOCK
;
253 static NSModule (*p
)(NSSymbol symbol
) = NULL
;
256 _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
);
262 const char* pathName
)
264 DYLD_LOCK_THIS_BLOCK
;
265 static bool (*p
)(const char* pathName
) = NULL
;
268 _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
);
273 NSAddLibraryWithSearching(
274 const char* pathName
)
276 DYLD_LOCK_THIS_BLOCK
;
277 static bool (*p
)(const char* pathName
) = NULL
;
280 _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
);
284 const struct mach_header
*
286 const char* image_name
,
289 DYLD_LOCK_THIS_BLOCK
;
290 static const struct mach_header
* (*p
)(const char* image_name
,
291 uint32_t options
) = NULL
;
294 _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
);
295 return(p(image_name
, options
));
299 * This routine returns the current version of the named shared library the
300 * executable it was built with. The libraryName parameter is the same as the
301 * -lx or -framework Foo argument passed to the static link editor when building
302 * the executable (with -lx it would be "x" and with -framework Foo it would be
303 * "Foo"). If this the executable was not built against the specified library
304 * it returns -1. It should be noted that if this only returns the value the
305 * current version of the named shared library the executable was built with
306 * and not a list of current versions that dependent libraries and bundles the
307 * program is using were built with.
310 NSVersionOfLinkTimeLibrary(
311 const char* libraryName
)
314 struct load_command
*load_commands
, *lc
;
315 struct dylib_command
*dl
;
318 static struct mach_header_64
*mh
= NULL
;
320 static struct mach_header
*mh
= NULL
;
323 mh
= _NSGetMachExecuteHeader();
324 load_commands
= (struct load_command
*)
326 ((char *)mh
+ sizeof(struct mach_header_64
));
328 ((char *)mh
+ sizeof(struct mach_header
));
331 for(i
= 0; i
< mh
->ncmds
; i
++){
334 case LC_LOAD_WEAK_DYLIB
:
335 dl
= (struct dylib_command
*)lc
;
336 install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
337 if(names_match(install_name
, libraryName
) == TRUE
)
338 return(dl
->dylib
.current_version
);
341 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
347 * This routine returns the current version of the named shared library the
348 * program it is running against. The libraryName parameter is the same as
349 * would be static link editor using the -lx or -framework Foo flags (with -lx
350 * it would be "x" and with -framework Foo it would be "Foo"). If the program
351 * is not using the specified library it returns -1.
354 NSVersionOfRunTimeLibrary(
355 const char* libraryName
)
357 unsigned long i
, j
, n
;
359 struct load_command
*load_commands
, *lc
;
360 struct dylib_command
*dl
;
361 const struct mach_header
*mh
;
363 n
= _dyld_image_count();
364 for(i
= 0; i
< n
; i
++){
365 mh
= _dyld_get_image_header(i
);
366 if(mh
->filetype
!= MH_DYLIB
)
368 load_commands
= (struct load_command
*)
370 ((char *)mh
+ sizeof(struct mach_header_64
));
372 ((char *)mh
+ sizeof(struct mach_header
));
375 for(j
= 0; j
< mh
->ncmds
; j
++){
376 if(lc
->cmd
== LC_ID_DYLIB
){
377 dl
= (struct dylib_command
*)lc
;
378 install_name
= (char *)dl
+ dl
->dylib
.name
.offset
;
379 if(names_match(install_name
, libraryName
) == TRUE
)
380 return(dl
->dylib
.current_version
);
382 lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
);
389 * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
390 * specified file name if the file is a correct Mach-O file that can be loaded
391 * with NSloadModule(). For return codes of NSObjectFileImageFailure and
392 * NSObjectFileImageFormat an error message is printed to stderr. All
393 * other codes cause no printing.
395 NSObjectFileImageReturnCode
396 NSCreateObjectFileImageFromFile(
397 const char* pathName
,
398 NSObjectFileImage
*objectFileImage
)
400 DYLD_LOCK_THIS_BLOCK
;
401 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
404 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
);
405 return p(pathName
, objectFileImage
);
410 * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
411 * object file mapped into memory at address of size length if the object file
412 * is a correct Mach-O file that can be loaded with NSloadModule(). For return
413 * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
414 * message is printed to stderr. All other codes cause no printing.
416 NSObjectFileImageReturnCode
417 NSCreateObjectFileImageFromMemory(
420 NSObjectFileImage
*objectFileImage
)
422 DYLD_LOCK_THIS_BLOCK
;
423 static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
;
426 _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
);
427 return p(address
, size
, objectFileImage
);
430 #if OBSOLETE_DYLD_API
432 * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
433 * specified core file name if the file is a correct Mach-O core file.
434 * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
435 * an error message is printed to stderr. All other codes cause no printing.
437 NSObjectFileImageReturnCode
438 NSCreateCoreFileImageFromFile(
439 const char* pathName
,
440 NSObjectFileImage
*objectFileImage
)
442 DYLD_LOCK_THIS_BLOCK
;
443 static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
;
446 _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
);
447 return p(pathName
, objectFileImage
);
452 NSDestroyObjectFileImage(
453 NSObjectFileImage objectFileImage
)
455 DYLD_LOCK_THIS_BLOCK
;
456 static bool (*p
)(NSObjectFileImage
) = NULL
;
459 _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
);
460 return p(objectFileImage
);
466 NSObjectFileImage objectFileImage
,
467 const char* moduleName
,
470 DYLD_LOCK_THIS_BLOCK
;
471 static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
;
474 _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
);
476 return p(objectFileImage
, moduleName
, options
);
481 * NSFindSectionAndOffsetInObjectFileImage() takes the specified imageOffset
482 * into the specified ObjectFileImage and returns the segment/section name and
483 * offset into that section of that imageOffset. Returns FALSE if the
484 * imageOffset is not in any section. You can used the resulting sectionOffset
485 * to index into the data returned by NSGetSectionDataInObjectFileImage.
487 * SPI: currently only used by ZeroLink to detect +load methods
490 NSFindSectionAndOffsetInObjectFileImage(
491 NSObjectFileImage objectFileImage
,
492 unsigned long imageOffset
,
493 const char** segmentName
, /* can be NULL */
494 const char** sectionName
, /* can be NULL */
495 unsigned long* sectionOffset
) /* can be NULL */
497 DYLD_LOCK_THIS_BLOCK
;
498 static bool (*p
)(NSObjectFileImage
, unsigned long, const char**, const char**, unsigned long*) = NULL
;
501 _dyld_func_lookup("__dyld_NSFindSectionAndOffsetInObjectFileImage", (void**)&p
);
503 return p(objectFileImage
, imageOffset
, segmentName
, sectionName
, sectionOffset
);
508 * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
509 * definitions in the NSObjectFileImage.
512 NSSymbolDefinitionCountInObjectFileImage(
513 NSObjectFileImage objectFileImage
)
515 DYLD_LOCK_THIS_BLOCK
;
516 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
519 _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
);
521 return p(objectFileImage
);
525 * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
526 * symbol definitions in the NSObjectFileImage. If the ordinal specified is
527 * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
531 NSSymbolDefinitionNameInObjectFileImage(
532 NSObjectFileImage objectFileImage
,
535 DYLD_LOCK_THIS_BLOCK
;
536 static const char* (*p
)(NSObjectFileImage
, uint32_t) = NULL
;
539 _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
);
541 return p(objectFileImage
, ordinal
);
545 * NSSymbolReferenceCountInObjectFileImage() returns the number of references
546 * to undefined symbols the NSObjectFileImage.
549 NSSymbolReferenceCountInObjectFileImage(
550 NSObjectFileImage objectFileImage
)
552 DYLD_LOCK_THIS_BLOCK
;
553 static unsigned long (*p
)(NSObjectFileImage
) = NULL
;
556 _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
);
558 return p(objectFileImage
);
562 * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
563 * undefined symbol in the NSObjectFileImage. If the ordinal specified is
564 * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
568 NSSymbolReferenceNameInObjectFileImage(
569 NSObjectFileImage objectFileImage
,
571 bool *tentative_definition
) /* can be NULL */
573 DYLD_LOCK_THIS_BLOCK
;
574 static const char* (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
;
577 _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
);
579 return p(objectFileImage
, ordinal
, tentative_definition
);
583 * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
584 * name has a definition in the NSObjectFileImage and FALSE otherwise.
587 NSIsSymbolDefinedInObjectFileImage(
588 NSObjectFileImage objectFileImage
,
589 const char* symbolName
)
591 DYLD_LOCK_THIS_BLOCK
;
592 static bool (*p
)(NSObjectFileImage
, const char*) = NULL
;
595 _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
);
597 return p(objectFileImage
, symbolName
);
601 * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
602 * in the NSObjectFileImage for the specified segmentName and sectionName if
603 * it exists and it is not a zerofill section. If not it returns NULL. If
604 * the parameter size is not NULL the size of the section is also returned
605 * indirectly through that pointer.
608 NSGetSectionDataInObjectFileImage(
609 NSObjectFileImage objectFileImage
,
610 const char* segmentName
,
611 const char* sectionName
,
612 unsigned long *size
) /* can be NULL */
614 DYLD_LOCK_THIS_BLOCK
;
615 static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
;
618 _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
);
620 return p(objectFileImage
, segmentName
, sectionName
, size
);
624 * NSHasModInitObjectFileImage() returns TRUE if the NSObjectFileImage has any
625 * module initialization sections and FALSE it it does not.
627 * SPI: currently only used by ZeroLink to detect C++ initializers
630 NSHasModInitObjectFileImage(
631 NSObjectFileImage objectFileImage
)
633 DYLD_LOCK_THIS_BLOCK
;
634 static bool (*p
)(NSObjectFileImage
) = NULL
;
637 _dyld_func_lookup("__dyld_NSHasModInitObjectFileImage", (void**)&p
);
639 return p(objectFileImage
);
646 const char* *fileName
,
647 const char* *errorString
)
649 DYLD_LOCK_THIS_BLOCK
;
650 static void (*p
)(NSLinkEditErrors
*c
,
652 const char* *fileName
,
653 const char* *errorString
) = NULL
;
656 _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
);
658 p(c
, errorNumber
, fileName
, errorString
);
666 DYLD_LOCK_THIS_BLOCK
;
667 static bool (*p
)(NSModule
module, uint32_t options
) = NULL
;
670 _dyld_func_lookup("__dyld_unlink_module", (void**)&p
);
672 return p(module, options
);
675 #if OBSOLETE_DYLD_API
678 NSModule moduleToReplace
,
679 NSObjectFileImage newObjectFileImage
,
687 *_NSGetExecutablePath copies the path of the executable into the buffer and
688 * returns 0 if the path was successfully copied in the provided buffer. If the
689 * buffer is not large enough, -1 is returned and the expected buffer size is
690 * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
691 * the executable not a "real path" to the executable. That is the path may be
692 * a symbolic link and not the real file. And with deep directories the total
693 * bufsize needed could be more than MAXPATHLEN.
696 _NSGetExecutablePath(
700 DYLD_LOCK_THIS_BLOCK
;
701 static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
;
704 _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
);
705 return(p(buf
, bufsize
));
709 _dyld_lookup_and_bind(
710 const char* symbol_name
,
714 DYLD_LOCK_THIS_BLOCK
;
715 static void (*p
)(const char*, void** , NSModule
*) = NULL
;
718 _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
);
719 p(symbol_name
, address
, module);
723 _dyld_lookup_and_bind_with_hint(
724 const char* symbol_name
,
725 const char* library_name_hint
,
729 DYLD_LOCK_THIS_BLOCK
;
730 static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
;
733 _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
);
734 p(symbol_name
, library_name_hint
, address
, module);
737 #if OBSOLETE_DYLD_API
739 _dyld_lookup_and_bind_objc(
740 const char* symbol_name
,
744 DYLD_LOCK_THIS_BLOCK
;
745 static void (*p
)(const char* , void**, NSModule
*) = NULL
;
748 _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
);
749 p(symbol_name
, address
, module);
754 _dyld_lookup_and_bind_fully(
755 const char* symbol_name
,
759 DYLD_LOCK_THIS_BLOCK
;
760 static void (*p
)(const char*, void**, NSModule
*) = NULL
;
763 _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
);
764 p(symbol_name
, address
, module);
768 _dyld_bind_fully_image_containing_address(
771 DYLD_LOCK_THIS_BLOCK
;
772 static bool (*p
)(const void*) = NULL
;
775 _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
);
781 * _dyld_register_func_for_add_image registers the specified function to be
782 * called when a new image is added (a bundle or a dynamic shared library) to
783 * the program. When this function is first registered it is called for once
784 * for each image that is currently part of the program.
787 _dyld_register_func_for_add_image(
788 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
790 DYLD_LOCK_THIS_BLOCK
;
791 static void (*p
)(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
)) = NULL
;
794 _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
);
799 * _dyld_register_func_for_remove_image registers the specified function to be
800 * called when an image is removed (a bundle or a dynamic shared library) from
804 _dyld_register_func_for_remove_image(
805 void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
807 DYLD_LOCK_THIS_BLOCK
;
808 static void (*p
)(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
)) = NULL
;
811 _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
);
815 #if OBSOLETE_DYLD_API
817 * _dyld_register_func_for_link_module registers the specified function to be
818 * called when a module is bound into the program. When this function is first
819 * registered it is called for once for each module that is currently bound into
823 _dyld_register_func_for_link_module(
824 void (*func
)(NSModule
module))
826 DYLD_LOCK_THIS_BLOCK
;
827 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
830 _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
);
835 * _dyld_register_func_for_unlink_module registers the specified function to be
836 * called when a module is unbound from the program.
839 _dyld_register_func_for_unlink_module(
840 void (*func
)(NSModule
module))
842 DYLD_LOCK_THIS_BLOCK
;
843 static void (*p
)(void (*func
)(NSModule
module)) = NULL
;
846 _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
);
851 * _dyld_register_func_for_replace_module registers the specified function to be
852 * called when a module is to be replace with another module in the program.
855 _dyld_register_func_for_replace_module(
856 void (*func
)(NSModule oldmodule
, NSModule newmodule
))
858 DYLD_LOCK_THIS_BLOCK
;
859 static void (*p
)(void (*func
)(NSModule oldmodule
,
860 NSModule newmodule
)) = NULL
;
863 _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
);
869 * _dyld_get_objc_module_sect_for_module is passed a module and sets a
870 * pointer to the (__OBJC,__module) section and its size for the specified
874 _dyld_get_objc_module_sect_for_module(
879 DYLD_LOCK_THIS_BLOCK
;
880 static void (*p
)(NSModule
module,
882 unsigned long *size
) = NULL
;
885 _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
);
886 p(module, objc_module
, size
);
890 * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
891 * __module) section and causes the module that is associated with that address
895 _dyld_bind_objc_module(const void* objc_module
)
897 DYLD_LOCK_THIS_BLOCK
;
898 static void (*p
)(const void *objc_module
) = NULL
;
901 _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p
);
909 // this function exists for compatiblity only
914 _dyld_image_count(void)
916 DYLD_NO_LOCK_THIS_BLOCK
;
917 static unsigned long (*p
)(void) = NULL
;
920 _dyld_func_lookup("__dyld_image_count", (void**)&p
);
924 const struct mach_header
*
925 _dyld_get_image_header(uint32_t image_index
)
927 DYLD_NO_LOCK_THIS_BLOCK
;
928 static struct mach_header
* (*p
)(uint32_t image_index
) = NULL
;
931 _dyld_func_lookup("__dyld_get_image_header", (void**)&p
);
932 return(p(image_index
));
936 _dyld_get_image_vmaddr_slide(uint32_t image_index
)
938 DYLD_NO_LOCK_THIS_BLOCK
;
939 static unsigned long (*p
)(uint32_t image_index
) = NULL
;
942 _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
);
943 return(p(image_index
));
947 _dyld_get_image_name(uint32_t image_index
)
949 DYLD_NO_LOCK_THIS_BLOCK
;
950 static const char* (*p
)(uint32_t image_index
) = NULL
;
953 _dyld_func_lookup("__dyld_get_image_name", (void**)&p
);
954 return(p(image_index
));
958 _dyld_image_containing_address(const void* address
)
960 DYLD_LOCK_THIS_BLOCK
;
961 static bool (*p
)(const void*) = NULL
;
964 _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
);
968 const struct mach_header
*
969 _dyld_get_image_header_containing_address(
972 DYLD_LOCK_THIS_BLOCK
;
973 static const struct mach_header
* (*p
)(const void*) = NULL
;
976 _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
);
981 void (*monaddition
)(char *lowpc
, char *highpc
))
983 DYLD_LOCK_THIS_BLOCK
;
984 static void (*p
)(void (*monaddition
)(char *lowpc
, char *highpc
)) = NULL
;
987 _dyld_func_lookup("__dyld_moninit", (void**)&p
);
991 bool _dyld_launched_prebound(void)
993 DYLD_LOCK_THIS_BLOCK
;
994 static bool (*p
)(void) = NULL
;
997 _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
);
1001 bool _dyld_all_twolevel_modules_prebound(void)
1003 DYLD_LOCK_THIS_BLOCK
;
1004 static bool (*p
)(void) = NULL
;
1007 _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
);
1014 #include <pthread.h>
1016 #include <mach-o/dyld.h>
1017 #include <servers/bootstrap.h>
1018 #include "dyldLibSystemInterface.h"
1019 #include "dyld_shared_cache_user.h"
1022 // pthread key used to access per-thread dlerror message
1023 static pthread_key_t dlerrorPerThreadKey
;
1024 static bool dlerrorPerThreadKeyInitialized
= false;
1026 // data kept per-thread
1027 struct dlerrorPerThreadData
1029 uint32_t sizeAllocated
;
1033 // function called by dyld to get buffer to store dlerror message
1034 static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired
)
1036 // ok to create key lazily because this function is called within dyld lock, so there is no race condition
1037 if (!dlerrorPerThreadKeyInitialized
) {
1038 // create key and tell pthread package to call free() on any data associated with key if thread dies
1039 pthread_key_create(&dlerrorPerThreadKey
, &free
);
1040 dlerrorPerThreadKeyInitialized
= true;
1043 const int size
= (sizeRequired
< 256) ? 256 : sizeRequired
;
1044 dlerrorPerThreadData
* data
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
);
1045 if ( data
== NULL
) {
1046 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1047 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1048 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1049 data
->sizeAllocated
= size
;
1050 pthread_setspecific(dlerrorPerThreadKey
, data
);
1052 else if ( data
->sizeAllocated
< sizeRequired
) {
1054 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
1055 const int mallocSize
= sizeof(dlerrorPerThreadData
)+size
;
1056 data
= (dlerrorPerThreadData
*)malloc(mallocSize
);
1057 data
->sizeAllocated
= size
;
1058 pthread_setspecific(dlerrorPerThreadKey
, data
);
1060 return data
->message
;
1065 static bool get_update_dyld_shared_cache_bootstrap_port(mach_port_t
& mp
)
1067 static bool found
= false;
1068 static mach_port_t port
;
1073 if ( bootstrap_look_up(bootstrap_port
, "com.apple.dyld", &port
) == KERN_SUCCESS
) {
1082 #define CUR_ARCH CPU_TYPE_POWERPC
1084 #define CUR_ARCH CPU_TYPE_POWERPC64
1086 #define CUR_ARCH CPU_TYPE_I386
1088 #define CUR_ARCH CPU_TYPE_X86_64
1091 static void shared_cache_missing()
1094 if ( get_update_dyld_shared_cache_bootstrap_port(mp
) )
1095 dyld_shared_cache_missing(mp
, CUR_ARCH
, 0);
1098 static void shared_cache_out_of_date()
1101 if ( get_update_dyld_shared_cache_bootstrap_port(mp
) )
1102 dyld_shared_cache_out_of_date(mp
, CUR_ARCH
, 0);
1107 // that table passed to dyld containing thread helpers
1108 static dyld::LibSystemHelpers sHelpers
= { 4, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
,
1109 &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
,
1110 &shared_cache_missing
, &shared_cache_out_of_date
,
1115 // during initialization of libSystem this routine will run
1116 // and call dyld, registering the helper functions.
1118 extern "C" void _dyld_initializer() __attribute__((visibility("hidden")));
1119 void _dyld_initializer()
1121 DYLD_LOCK_INITIALIZER
;
1123 void (*p
)(dyld::LibSystemHelpers
*);
1125 _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
);
1133 DYLD_LOCK_THIS_BLOCK
;
1134 static char* (*p
)() = NULL
;
1137 _dyld_func_lookup("__dyld_dlerror", (void**)&p
);
1141 int dladdr(const void* addr
, Dl_info
* info
)
1143 DYLD_LOCK_THIS_BLOCK
;
1144 static int (*p
)(const void* , Dl_info
*) = NULL
;
1147 _dyld_func_lookup("__dyld_dladdr", (void**)&p
);
1148 return(p(addr
, info
));
1151 int dlclose(void* handle
)
1153 DYLD_LOCK_THIS_BLOCK
;
1154 static int (*p
)(void* handle
) = NULL
;
1157 _dyld_func_lookup("__dyld_dlclose", (void**)&p
);
1161 void* dlopen(const char* path
, int mode
)
1163 // dlopen is special. locking is done inside dyld to allow initializer to run without lock
1164 DYLD_NO_LOCK_THIS_BLOCK
;
1166 static void* (*p
)(const char* path
, int) = NULL
;
1169 _dyld_func_lookup("__dyld_dlopen", (void**)&p
);
1170 void* result
= p(path
, mode
);
1171 // use asm block to prevent tail call optimization
1172 // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain
1173 // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash>
1174 __asm__
volatile("");
1179 bool dlopen_preflight(const char* path
)
1181 DYLD_LOCK_THIS_BLOCK
;
1182 static bool (*p
)(const char* path
) = NULL
;
1185 _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
);
1189 void* dlsym(void* handle
, const char* symbol
)
1191 DYLD_LOCK_THIS_BLOCK
;
1192 static void* (*p
)(void* handle
, const char* symbol
) = NULL
;
1195 _dyld_func_lookup("__dyld_dlsym", (void**)&p
);
1196 return(p(handle
, symbol
));
1199 void dyld_register_image_state_change_handler(dyld_image_states state
,
1200 bool batch
, dyld_image_state_change_handler handler
)
1202 DYLD_LOCK_THIS_BLOCK
;
1203 static void* (*p
)(dyld_image_states
, bool, dyld_image_state_change_handler
) = NULL
;
1206 _dyld_func_lookup("__dyld_dyld_register_image_state_change_handler", (void**)&p
);
1207 p(state
, batch
, handler
);