1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2005 Apple Computer, 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@
26 // This file implements that API's in <mach-o/dyld.h>
34 #include <mach/mach.h>
36 #include <sys/sysctl.h>
38 extern "C" mach_port_name_t
task_self_trap(void); // can't include <System/mach/mach_traps.h> because it is missing extern C
40 #include "mach-o/dyld_gdb.h"
41 #include "mach-o/dyld.h"
42 #include "mach-o/dyld_priv.h"
45 #include "ImageLoader.h"
47 #include "dyldLibSystemThreadHelpers.h"
49 static char sLastErrorFilePath
[1024];
50 static NSLinkEditErrors sLastErrorFileCode
;
51 static int sLastErrorNo
;
54 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
55 // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
56 // This conditional keeps support for old libSystem's which needed some help implementing the API's
57 #define OLD_LIBSYSTEM_SUPPORT 1
60 // The following functions have no prototype in any header. They are special cases
61 // where _dyld_func_lookup() is used directly.
62 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
);
63 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
);
64 static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions
);
65 static void _dyld_fork_prepare();
66 static void _dyld_fork_parent();
67 static void _dyld_fork_child();
68 static void _dyld_fork_child_final();
69 static void _dyld_make_delayed_module_initializer_calls();
70 static void _dyld_mod_term_funcs();
71 static bool NSMakePrivateModulePublic(NSModule
module);
72 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
);
73 static void registerThreadHelpers(const dyld::ThreadingHelpers
*);
74 static void _dyld_update_prebinding(int pathCount
, const char* paths
[], uint32_t flags
);
75 static const struct dyld_all_image_infos
* _dyld_get_all_image_infos();
77 // The following functions are dyld API's, but since dyld links with a static copy of libc.a
78 // the public name cannot be used.
79 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module);
80 static bool client_NSIsSymbolNameDefined(const char* symbolName
);
83 static void unimplemented()
85 dyld::halt("unimplemented dyld function\n");
93 static struct dyld_func dyld_funcs
[] = {
94 {"__dyld_image_count", (void*)_dyld_image_count
},
95 {"__dyld_get_image_header", (void*)_dyld_get_image_header
},
96 {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide
},
97 {"__dyld_get_image_name", (void*)_dyld_get_image_name
},
98 {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind
},
99 {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint
},
100 {"__dyld_lookup_and_bind_objc", (void*)unimplemented
},
101 {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully
},
102 {"__dyld_install_handlers", (void*)_dyld_install_handlers
},
103 {"__dyld_link_edit_error", (void*)NSLinkEditError
},
104 #if OLD_LIBSYSTEM_SUPPORT
105 {"__dyld_link_module", (void*)_dyld_link_module
},
107 {"__dyld_unlink_module", (void*)NSUnLinkModule
},
108 {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image
},
109 {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image
},
110 {"__dyld_register_func_for_link_module", (void*)unimplemented
},
111 {"__dyld_register_func_for_unlink_module", (void*)unimplemented
},
112 {"__dyld_register_func_for_replace_module", (void*)unimplemented
},
113 {"__dyld_get_objc_module_sect_for_module", (void*)unimplemented
},
114 {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module
},
115 {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address
},
116 {"__dyld_image_containing_address", (void*)_dyld_image_containing_address
},
117 {"__dyld_get_image_header_containing_address", (void*)_dyld_get_image_header_containing_address
},
118 {"__dyld_moninit", (void*)_dyld_moninit
},
119 {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler
},
120 {"__dyld_fork_prepare", (void*)_dyld_fork_prepare
},
121 {"__dyld_fork_parent", (void*)_dyld_fork_parent
},
122 {"__dyld_fork_child", (void*)_dyld_fork_child
},
123 {"__dyld_fork_child_final", (void*)_dyld_fork_child_final
},
124 {"__dyld_fork_mach_init", (void*)unimplemented
},
125 {"__dyld_make_delayed_module_initializer_calls",(void*)_dyld_make_delayed_module_initializer_calls
},
126 {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol
},
127 {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol
},
128 {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol
},
129 {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol
},
130 {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint
},
131 {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule
},
132 {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage
},
133 {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic
},
134 {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined
},
135 {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint
},
136 {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage
},
137 {"__dyld_NSNameOfModule", (void*)NSNameOfModule
},
138 {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule
},
139 {"__dyld_NSAddLibrary", (void*)NSAddLibrary
},
140 {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching
},
141 {"__dyld_NSAddImage", (void*)NSAddImage
},
142 {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath
},
143 {"__dyld_launched_prebound", (void*)_dyld_launched_prebound
},
144 {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound
},
145 {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib
},
146 {"__dyld_mod_term_funcs", (void*)_dyld_mod_term_funcs
},
147 {"__dyld_install_link_edit_symbol_handlers", (void*)dyld::registerZeroLinkHandlers
},
148 {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile
},
149 {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory
},
150 {"__dyld_NSCreateCoreFileImageFromFile", (void*)unimplemented
},
151 {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage
},
152 {"__dyld_NSLinkModule", (void*)NSLinkModule
},
153 {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage
},
154 {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage
},
155 {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage
},
156 {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage
},
157 {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage
},
158 {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage
},
159 {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage
},
160 {"__dyld_NSFindSectionAndOffsetInObjectFileImage", (void*)NSFindSectionAndOffsetInObjectFileImage
},
161 {"__dyld_register_thread_helpers", (void*)registerThreadHelpers
},
162 {"__dyld_dladdr", (void*)dladdr
},
163 {"__dyld_dlclose", (void*)dlclose
},
164 {"__dyld_dlerror", (void*)dlerror
},
165 {"__dyld_dlopen", (void*)dlopen
},
166 {"__dyld_dlsym", (void*)dlsym
},
167 {"__dyld_update_prebinding", (void*)_dyld_update_prebinding
},
168 {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos
},
174 // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
175 inline NSSymbol
SymbolToNSSymbol(const ImageLoader::Symbol
* sym
)
177 return (NSSymbol
)sym
;
179 inline const ImageLoader::Symbol
* NSSymbolToSymbol(NSSymbol sym
)
181 return (const ImageLoader::Symbol
*)sym
;
184 // dyld's abstract type NSModule is implemented as ImageLoader*
185 inline NSModule
ImageLoaderToNSModule(ImageLoader
* image
)
187 return (NSModule
)image
;
189 inline ImageLoader
* NSModuleToImageLoader(NSModule
module)
191 ImageLoader
* image
= (ImageLoader
*)module;
192 if ( dyld::validImage(image
) )
197 // actual definition for opaque type
198 struct __NSObjectFileImage
201 const void* imageBaseAddress
; // not used with OFI created from files
202 size_t imageLength
; // not used with OFI created from files
204 static std::vector
<NSObjectFileImage
> sObjectFileImages
;
209 // __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
210 // The contained image is delete in one of two places:
211 // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
212 // NSDestroyObjectFileImage deletes the image if image is not in list of valid images
216 static void dyldAPIhalt(const char* apiName
, const char* errorMsg
)
218 fprintf(stderr
, "dyld: %s() error\n", apiName
);
219 dyld::halt(errorMsg
);
224 static void setLastError(NSLinkEditErrors code
, int errnum
, const char* file
, const char* message
)
226 dyld::setErrorMessage(message
);
227 strncpy(sLastErrorFilePath
, file
, 1024);
228 sLastErrorFilePath
[1023] = '\0';
229 sLastErrorFileCode
= code
;
230 sLastErrorNo
= errnum
;
235 *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
236 * copies the path of the executable into the buffer and returns 0 if the path
237 * was successfully copied in the provided buffer. If the buffer is not large
238 * enough, -1 is returned and the expected buffer size is copied in *bufsize.
239 * Note that _NSGetExecutablePath will return "a path" to the executable not a
240 * "real path" to the executable. That is the path may be a symbolic link and
241 * not the real file. And with deep directories the total bufsize needed could
242 * be more than MAXPATHLEN.
244 int _NSGetExecutablePath(char* buf
, uint32_t *bufsize
)
246 if ( dyld::gLogAPIs
)
247 fprintf(stderr
, "%s(...)\n", __func__
);
248 const char* exePath
= dyld::getExecutablePath();
249 if(*bufsize
< strlen(exePath
) + 1){
250 *bufsize
= strlen(exePath
) + 1;
253 strcpy(buf
, exePath
);
259 // _dyld_call_module_initializers_for_dylib() is the dyld side of
260 // __initialize_Cplusplus() which is in dylib1.o.
261 // It is intended to only be called inside -init rouintes.
262 // -init routines are called before module initializers (what C++
263 // initializers use). Calling __initialize_Cplusplus() in a -init
264 // routine causes the module initializers for an image to be called
265 // which then allows C++ to be used inside a -init routine
267 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
)
269 if ( dyld::gLogAPIs
)
270 fprintf(stderr
, "__initialize_Cplusplus()\n");
272 // for now, do nothing...
276 void _dyld_lookup_and_bind_fully(const char* symbolName
, void** address
, NSModule
* module)
278 if ( dyld::gLogAPIs
)
279 fprintf(stderr
, "%s(\"%s\", %p, %p)\n", __func__
, symbolName
, address
, module);
281 const ImageLoader::Symbol
* sym
;
282 dyld::clearErrorMessage();
283 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
285 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
286 if ( address
!= NULL
)
287 *address
= (void*)image
->getExportedSymbolAddress(sym
);
289 *module = ImageLoaderToNSModule(image
);
291 catch (const char* msg
) {
292 dyldAPIhalt(__func__
, msg
);
296 // on failure to find symbol return NULLs
297 if ( address
!= NULL
)
304 // Note: This cannot have public name because dyld is built with a static copy of libc.a
305 // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
306 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module)
308 if ( dyld::gLogAPIs
)
309 fprintf(stderr
, "_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName
, address
, module);
311 const ImageLoader::Symbol
* sym
;
312 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
313 if ( address
!= NULL
)
314 *address
= (void*)image
->getExportedSymbolAddress(sym
);
316 *module = ImageLoaderToNSModule(image
);
319 // on failure to find symbol return NULLs
320 if ( address
!= NULL
)
327 void _dyld_lookup_and_bind_with_hint(const char* symbolName
, const char* library_name_hint
, void** address
, NSModule
* module)
329 if ( dyld::gLogAPIs
)
330 fprintf(stderr
, "%s(\"%s\", \"%s\", %p, %p)\n", __func__
, symbolName
, library_name_hint
, address
, module);
332 const ImageLoader::Symbol
* sym
;
333 // Look for library whose path contains the hint. If that fails search everywhere
334 if ( dyld::flatFindExportedSymbolWithHint(symbolName
, library_name_hint
, &sym
, &image
)
335 || dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
336 if ( address
!= NULL
)
337 *address
= (void*)image
->getExportedSymbolAddress(sym
);
339 *module = ImageLoaderToNSModule(image
);
342 // on failure to find symbol return NULLs
343 if ( address
!= NULL
)
351 NSSymbol
NSLookupAndBindSymbol(const char *symbolName
)
353 if ( dyld::gLogAPIs
)
354 fprintf(stderr
, "%s(\"%s\")\n", __func__
, symbolName
);
356 const ImageLoader::Symbol
* sym
;
357 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
358 return SymbolToNSSymbol(sym
);
360 // return NULL on failure
364 NSSymbol
NSLookupAndBindSymbolWithHint(const char* symbolName
, const char* libraryNameHint
)
366 if ( dyld::gLogAPIs
)
367 fprintf(stderr
, "%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
369 const ImageLoader::Symbol
* sym
;
370 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
372 // hint failed, do slow search of all images
373 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
376 return SymbolToNSSymbol(sym
);
378 // return NULL on failure and log
379 if ( dyld::gLogAPIs
)
380 fprintf(stderr
, "%s(\"%s\", \"%s\") => NULL \n", __func__
, symbolName
, libraryNameHint
);
384 uint32_t _dyld_image_count(void)
386 if ( dyld::gLogAPIs
)
387 fprintf(stderr
, "%s()\n", __func__
);
388 return dyld::getImageCount();
391 const struct mach_header
* _dyld_get_image_header(uint32_t image_index
)
393 if ( dyld::gLogAPIs
)
394 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
395 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
397 return (struct mach_header
*)image
->machHeader();
403 static __attribute__((noinline
))
404 const struct mach_header
* addImage(void* callerAddress
, const char* path
, bool search
, bool dontLoad
, bool matchInstallName
, bool abortOnError
)
406 ImageLoader
* image
= NULL
;
408 dyld::clearErrorMessage();
409 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
410 dyld::LoadContext context
;
411 context
.useSearchPaths
= search
;
412 context
.useLdLibraryPath
= false;
413 context
.matchByInstallName
= matchInstallName
;
414 context
.dontLoad
= dontLoad
;
415 context
.mustBeBundle
= false;
416 context
.mustBeDylib
= true;
417 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
418 context
.rpath
= NULL
; // support not yet implemented
420 image
= load(path
, context
);
421 if ( image
!= NULL
) {
422 if ( context
.matchByInstallName
)
423 image
->setMatchInstallPath(true);
424 dyld::link(image
, ImageLoader::kNonLazyOnly
, ImageLoader::kRunInitializers
);
425 return image
->machHeader();
428 catch (const char* msg
) {
430 char pathMsg
[strlen(msg
)+strlen(path
)+4];
431 strcpy(pathMsg
, msg
);
432 strcat(pathMsg
, " ");
433 strcat(pathMsg
, path
);
434 dyldAPIhalt("NSAddImage", pathMsg
);
436 // not halting, so set error state for NSLinkEditError to find
437 setLastError(NSLinkEditOtherError
, 0, path
, msg
);
442 const struct mach_header
* NSAddImage(const char* path
, uint32_t options
)
444 if ( dyld::gLogAPIs
)
445 fprintf(stderr
, "%s(\"%s\", 0x%08X)\n", __func__
, path
, options
);
446 const bool dontLoad
= ( (options
& NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
) != 0 );
447 const bool search
= ( (options
& NSADDIMAGE_OPTION_WITH_SEARCHING
) != 0 );
448 const bool matchInstallName
= ( (options
& NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
) != 0 );
449 const bool abortOnError
= ( (options
& NSADDIMAGE_OPTION_RETURN_ON_ERROR
) == 0 );
450 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
451 return addImage(callerAddress
, path
, search
, dontLoad
, matchInstallName
, abortOnError
);
454 bool NSAddLibrary(const char* path
)
456 if ( dyld::gLogAPIs
)
457 fprintf(stderr
, "%s(\"%s\")\n", __func__
, path
);
458 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
459 return (addImage(callerAddress
, path
, false, false, false, false) != NULL
);
462 bool NSAddLibraryWithSearching(const char* path
)
464 if ( dyld::gLogAPIs
)
465 fprintf(stderr
, "%s(\"%s\")\n", __func__
, path
);
466 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
467 return (addImage(callerAddress
, path
, true, false, false, false) != NULL
);
472 //#define NSADDIMAGE_OPTION_NONE 0x0
473 //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
474 //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
476 bool NSIsSymbolNameDefinedInImage(const struct mach_header
* mh
, const char* symbolName
)
478 if ( dyld::gLogAPIs
)
479 fprintf(stderr
, "%s(%p, \"%s\")\n", __func__
, (void *)mh
, symbolName
);
480 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
481 if ( image
!= NULL
) {
482 if ( image
->findExportedSymbol(symbolName
, NULL
, true, NULL
) != NULL
)
488 NSSymbol
NSLookupSymbolInImage(const struct mach_header
* mh
, const char* symbolName
, uint32_t options
)
490 if ( dyld::gLogAPIs
)
491 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", __func__
, mh
, symbolName
, options
);
492 const ImageLoader::Symbol
* symbol
= NULL
;
493 dyld::clearErrorMessage();
494 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
495 if ( image
!= NULL
) {
497 if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
) {
498 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
500 else if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
) {
501 dyld::link(image
, ImageLoader::kLazyOnlyNoDependents
, ImageLoader::kDontRunInitializers
);
504 catch (const char* msg
) {
505 if ( (options
& NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
) == 0 ) {
506 dyldAPIhalt(__func__
, msg
);
509 symbol
= image
->findExportedSymbol(symbolName
, NULL
, true, NULL
);
511 if ( dyld::gLogAPIs
&& (symbol
== NULL
) )
512 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__
, mh
, symbolName
, options
);
513 return SymbolToNSSymbol(symbol
);
517 // Note: This cannot have public name because dyld is built with a static copy of libc.a
518 // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
519 static bool client_NSIsSymbolNameDefined(const char* symbolName
)
521 if ( dyld::gLogAPIs
)
522 fprintf(stderr
, "NSIsSymbolNameDefined(\"%s\")\n", symbolName
);
524 const ImageLoader::Symbol
* sym
;
525 return dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
528 bool NSIsSymbolNameDefinedWithHint(const char* symbolName
, const char* libraryNameHint
)
530 if ( dyld::gLogAPIs
)
531 fprintf(stderr
, "%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
533 const ImageLoader::Symbol
* sym
;
534 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
536 // hint failed, do slow search of all images
537 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
539 if ( !found
&& dyld::gLogAPIs
)
540 fprintf(stderr
, "%s(\"%s\", \"%s\") => false \n", __func__
, symbolName
, libraryNameHint
);
544 const char* NSNameOfSymbol(NSSymbol symbol
)
546 if ( dyld::gLogAPIs
)
547 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
548 const char* result
= NULL
;
549 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
551 result
= image
->getExportedSymbolName(NSSymbolToSymbol(symbol
));
555 void* NSAddressOfSymbol(NSSymbol symbol
)
557 if ( dyld::gLogAPIs
)
558 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
560 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
562 result
= (void*)image
->getExportedSymbolAddress(NSSymbolToSymbol(symbol
));
566 NSModule
NSModuleForSymbol(NSSymbol symbol
)
568 if ( dyld::gLogAPIs
)
569 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
570 NSModule result
= NULL
;
571 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
573 result
= ImageLoaderToNSModule(image
);
578 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index
)
580 if ( dyld::gLogAPIs
)
581 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
582 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
584 return image
->getSlide();
589 const char* _dyld_get_image_name(uint32_t image_index
)
591 if ( dyld::gLogAPIs
)
592 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
593 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
595 return image
->getLogicalPath();
602 bool _dyld_all_twolevel_modules_prebound(void)
604 if ( dyld::gLogAPIs
)
605 fprintf(stderr
, "%s()\n", __func__
);
606 return FALSE
; // fixme
609 void _dyld_bind_objc_module(const void *objc_module
)
611 if ( dyld::gLogAPIs
)
612 fprintf(stderr
, "%s(%p)\n", __func__
, objc_module
);
613 // do nothing, with new dyld everything already bound
617 bool _dyld_bind_fully_image_containing_address(const void* address
)
619 if ( dyld::gLogAPIs
)
620 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
621 dyld::clearErrorMessage();
622 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
623 if ( image
!= NULL
) {
625 dyld::link(image
, ImageLoader::kLazyAndNonLazy
, ImageLoader::kDontRunInitializers
);
628 catch (const char* msg
) {
629 dyldAPIhalt(__func__
, msg
);
635 bool _dyld_image_containing_address(const void* address
)
637 if ( dyld::gLogAPIs
)
638 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
639 ImageLoader
*imageLoader
= dyld::findImageContainingAddress(address
);
640 return (NULL
!= imageLoader
);
643 static NSObjectFileImage
createObjectImageFile(ImageLoader
* image
, const void* address
= NULL
, size_t len
=0)
645 NSObjectFileImage result
= new __NSObjectFileImage();
646 result
->image
= image
;
647 result
->imageBaseAddress
= address
;
648 result
->imageLength
= len
;
649 sObjectFileImages
.push_back(result
);
653 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromFile(const char* pathName
, NSObjectFileImage
*objectFileImage
)
655 if ( dyld::gLogAPIs
)
656 fprintf(stderr
, "%s(\"%s\", ...)\n", __func__
, pathName
);
658 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
659 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
661 dyld::LoadContext context
;
662 context
.useSearchPaths
= false;
663 context
.useLdLibraryPath
= false;
664 context
.matchByInstallName
= false;
665 context
.dontLoad
= false;
666 context
.mustBeBundle
= true;
667 context
.mustBeDylib
= false;
668 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
669 context
.rpath
= NULL
; // support not yet implemented
671 ImageLoader
* image
= dyld::load(pathName
, context
);
672 // Note: We DO NOT link the image! NSLinkModule will do that
673 if ( image
!= NULL
) {
674 if ( !image
->isBundle() ) {
675 // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
676 return NSObjectFileImageInappropriateFile
;
678 *objectFileImage
= createObjectImageFile(image
);
679 return NSObjectFileImageSuccess
;
682 catch (const char* msg
) {
683 //fprintf(stderr, "dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
684 return NSObjectFileImageInappropriateFile
;
686 return NSObjectFileImageFailure
;
690 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromMemory(const void* address
, size_t size
, NSObjectFileImage
*objectFileImage
)
692 if ( dyld::gLogAPIs
)
693 fprintf(stderr
, "%s(%p, %lu, %p)\n", __func__
, address
, size
, objectFileImage
);
696 ImageLoader
* image
= dyld::loadFromMemory((const uint8_t*)address
, size
, NULL
);
697 if ( ! image
->isBundle() ) {
698 // this API can only be used with bundles...
700 return NSObjectFileImageInappropriateFile
;
702 // Note: We DO NOT link the image! NSLinkModule will do that
703 if ( image
!= NULL
) {
704 *objectFileImage
= createObjectImageFile(image
, address
, size
);
705 return NSObjectFileImageSuccess
;
708 catch (const char* msg
) {
709 fprintf(stderr
, "dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg
);
711 return NSObjectFileImageFailure
;
714 static bool validOFI(NSObjectFileImage objectFileImage
)
716 const int ofiCount
= sObjectFileImages
.size();
717 for (int i
=0; i
< ofiCount
; ++i
) {
718 if ( sObjectFileImages
[i
] == objectFileImage
)
724 bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage
)
726 if ( dyld::gLogAPIs
)
727 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
729 if ( validOFI(objectFileImage
) ) {
730 // if the image has never been linked or has been unlinked, the image is not in the list of valid images
731 // and we should delete it
732 bool linkedImage
= dyld::validImage(objectFileImage
->image
);
734 delete objectFileImage
->image
;
736 // remove from list of ofi's
737 for (std::vector
<NSObjectFileImage
>::iterator it
=sObjectFileImages
.begin(); it
!= sObjectFileImages
.end(); it
++) {
738 if ( *it
== objectFileImage
) {
739 sObjectFileImages
.erase(it
);
744 // if object was created from a memory, release that memory
745 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
746 if ( objectFileImage
->imageBaseAddress
!= NULL
) {
747 vm_deallocate(mach_task_self(), (vm_address_t
)objectFileImage
->imageBaseAddress
, objectFileImage
->imageLength
);
751 delete objectFileImage
;
758 bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage
)
760 if ( dyld::gLogAPIs
)
761 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
762 return objectFileImage
->image
->needsInitialization();
765 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage
)
767 if ( dyld::gLogAPIs
)
768 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
769 return objectFileImage
->image
->getExportedSymbolCount();
772 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
)
774 if ( dyld::gLogAPIs
)
775 fprintf(stderr
, "%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
776 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedExportedSymbol(ordinal
);
777 return objectFileImage
->image
->getExportedSymbolName(sym
);
780 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage
)
782 if ( dyld::gLogAPIs
)
783 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
784 return objectFileImage
->image
->getImportedSymbolCount();
787 const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
,
788 bool* tentative_definition
)
790 if ( dyld::gLogAPIs
)
791 fprintf(stderr
, "%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
792 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedImportedSymbol(ordinal
);
793 if ( tentative_definition
!= NULL
) {
794 ImageLoader::ReferenceFlags flags
= objectFileImage
->image
->geImportedSymbolInfo(sym
);
795 if ( (flags
& ImageLoader::kTentativeDefinition
) != 0 )
796 *tentative_definition
= true;
798 *tentative_definition
= false;
800 return objectFileImage
->image
->getImportedSymbolName(sym
);
803 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage
,
804 const char* segmentName
, const char* sectionName
, unsigned long* size
)
806 if ( dyld::gLogAPIs
)
807 fprintf(stderr
, "%s(%p,%s, %s)\n", __func__
, objectFileImage
, segmentName
, sectionName
);
811 if ( objectFileImage
->image
->getSectionContent(segmentName
, sectionName
, &start
, &length
) ) {
821 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage
, const char* symbolName
)
823 if ( dyld::gLogAPIs
)
824 fprintf(stderr
, "%s(%p,%s)\n", __func__
, objectFileImage
, symbolName
);
825 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->findExportedSymbol(symbolName
, NULL
, true, NULL
);
826 return ( sym
!= NULL
);
830 * Given an imageOffset into an ObjectFileImage, returns
831 * the segment/section name and offset into that section of
832 * that imageOffset. Returns FALSE if the imageOffset is not
833 * in any section. You can used the resulting sectionOffset to
834 * index into the data returned by NSGetSectionDataInObjectFileImage.
836 * First appeared in Mac OS X 10.3
838 * SPI: currently only used by ZeroLink to detect +load methods
841 NSFindSectionAndOffsetInObjectFileImage(NSObjectFileImage objectFileImage
,
842 unsigned long imageOffset
,
843 const char** segmentName
, /* can be NULL */
844 const char** sectionName
, /* can be NULL */
845 unsigned long* sectionOffset
) /* can be NULL */
847 if ( dyld::gLogAPIs
)
848 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
850 return objectFileImage
->image
->findSection((char*)(objectFileImage
->image
->getBaseAddress())+imageOffset
, segmentName
, sectionName
, sectionOffset
);
855 NSModule
NSLinkModule(NSObjectFileImage objectFileImage
, const char* moduleName
, uint32_t options
)
857 if ( dyld::gLogAPIs
)
858 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", __func__
, objectFileImage
, moduleName
, options
);
860 dyld::clearErrorMessage();
862 // NSLinkModule allows a bundle to be link multpile times
863 // each link causes the bundle to be copied to a new address
864 if ( objectFileImage
->image
->isLinked() ) {
865 // already linked, so clone a new one and link it
867 fprintf(stderr
, "dyld: warning: %s(0x%08X, \"%s\", 0x%08X) called more than once for 0x%08X\n",
868 __func__
, objectFileImage
, moduleName
, options
, objectFileImage
);
870 objectFileImage
->image
= dyld::cloneImage(objectFileImage
->image
);
873 // if this ofi was made with NSCreateObjectFileImageFromFile() then physical path is already set
874 // if this ofi was create with NSCreateObjectFileImageFromMemory() then the phyiscal path should be set if supplied
875 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 ) {
876 if ( objectFileImage
->imageBaseAddress
!= NULL
) {
877 const char* physEnd
= &moduleName
[strlen(moduleName
)+1];
878 objectFileImage
->image
->setPath(physEnd
);
882 // set moduleName as the name anyone calling _dyld_get_image_name() will see
883 objectFileImage
->image
->setLogicalPath(moduleName
);
885 // support private bundles
886 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
887 objectFileImage
->image
->setHideExports();
889 // set up linking options
890 ImageLoader::BindingLaziness bindness
= ImageLoader::kNonLazyOnly
;
891 if ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 )
892 bindness
= ImageLoader::kLazyAndNonLazy
;
893 ImageLoader::InitializerRunning runInitializers
= ImageLoader::kRunInitializers
;
894 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) != 0 )
895 runInitializers
= ImageLoader::kDontRunInitializersButTellObjc
;
897 // load libraries, rebase, bind, to make this image usable
898 dyld::link(objectFileImage
->image
, bindness
, runInitializers
);
900 return ImageLoaderToNSModule(objectFileImage
->image
);
902 catch (const char* msg
) {
903 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
904 dyldAPIhalt(__func__
, msg
);
905 // not halting, so set error state for NSLinkEditError to find
906 dyld::removeImage(objectFileImage
->image
);
907 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
912 #if OLD_LIBSYSTEM_SUPPORT
913 // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
914 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
)
916 if ( dyld::gLogAPIs
)
917 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr
, moduleName
, options
); // note name/args translation
918 ImageLoader
* image
= NULL
;
919 dyld::clearErrorMessage();
921 const char* imageName
= moduleName
;
922 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 )
923 imageName
= &moduleName
[strlen(moduleName
)+1];
925 image
= dyld::loadFromMemory((const uint8_t*)object_addr
, object_size
, imageName
);
927 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 )
928 image
->setLogicalPath(moduleName
);
930 if ( image
!= NULL
) {
931 // support private bundles
932 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
933 image
->setHideExports();
935 // set up linking options
936 ImageLoader::BindingLaziness bindness
= ImageLoader::kNonLazyOnly
;
937 if ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 )
938 bindness
= ImageLoader::kLazyAndNonLazy
;
939 ImageLoader::InitializerRunning runInitializers
= ImageLoader::kRunInitializers
;
940 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) != 0 )
941 runInitializers
= ImageLoader::kDontRunInitializersButTellObjc
;
943 // load libraries, rebase, bind, to make this image usable
944 dyld::link(image
, bindness
, runInitializers
);
947 catch (const char* msg
) {
948 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
949 dyldAPIhalt("NSLinkModule", msg
);
950 // not halting, so set error state for NSLinkEditError to find
951 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
952 // if image was created for this bundle, destroy it
953 if ( image
!= NULL
) {
954 dyld::removeImage(image
);
959 return ImageLoaderToNSModule(image
);
963 NSSymbol
NSLookupSymbolInModule(NSModule
module, const char* symbolName
)
965 if ( dyld::gLogAPIs
)
966 fprintf(stderr
, "%s(%p, \"%s\")\n", __func__
, (void *)module, symbolName
);
967 ImageLoader
* image
= NSModuleToImageLoader(module);
970 return SymbolToNSSymbol(image
->findExportedSymbol(symbolName
, NULL
, false, NULL
));
973 const char* NSNameOfModule(NSModule
module)
975 if ( dyld::gLogAPIs
)
976 fprintf(stderr
, "%s(%p)\n", __func__
, module);
977 ImageLoader
* image
= NSModuleToImageLoader(module);
980 return image
->getPath();
983 const char* NSLibraryNameForModule(NSModule
module)
985 if ( dyld::gLogAPIs
)
986 fprintf(stderr
, "%s(%p)\n", __func__
, module);
987 ImageLoader
* image
= NSModuleToImageLoader(module);
990 return image
->getPath();
993 bool NSUnLinkModule(NSModule
module, uint32_t options
)
995 if ( dyld::gLogAPIs
)
996 fprintf(stderr
, "%s(%p, 0x%08X)\n", __func__
, module, options
);
997 if ( module == NULL
)
999 ImageLoader
* image
= NSModuleToImageLoader(module);
1000 if ( image
== NULL
)
1002 dyld::removeImage(image
);
1004 if ( (options
& NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
) != 0 )
1005 image
->setLeaveMapped();
1007 // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1009 // Only delete image if there is no ofi referencing it
1010 // That means the ofi was destroyed after linking, so no one is left to delete this image
1011 const int ofiCount
= sObjectFileImages
.size();
1013 for (int i
=0; i
< ofiCount
; ++i
) {
1014 NSObjectFileImage ofi
= sObjectFileImages
[i
];
1015 if ( ofi
->image
== image
)
1024 // internal name and parameters do not match public name and parameters...
1025 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
)
1027 if ( dyld::gLogAPIs
)
1028 fprintf(stderr
, "NSLinkEditErrorHandlers()\n");
1030 dyld::registerUndefinedHandler((dyld::UndefinedHandler
)undefined
);
1031 // no support for multiple or linkedit handlers
1034 const struct mach_header
* _dyld_get_image_header_containing_address(const void* address
)
1036 if ( dyld::gLogAPIs
)
1037 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
1038 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1039 if ( image
!= NULL
)
1040 return image
->machHeader();
1045 void _dyld_register_func_for_add_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1047 if ( dyld::gLogAPIs
)
1048 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)func
);
1049 dyld::registerAddCallback(func
);
1052 void _dyld_register_func_for_remove_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1054 if ( dyld::gLogAPIs
)
1055 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)func
);
1056 dyld::registerRemoveCallback(func
);
1059 // called by atexit() function installed by crt
1060 static void _dyld_mod_term_funcs()
1062 if ( dyld::gLogAPIs
)
1063 fprintf(stderr
, "%s()\n", __func__
);
1064 dyld::runTerminators();
1067 // called by crt before main
1068 static void _dyld_make_delayed_module_initializer_calls()
1070 if ( dyld::gLogAPIs
)
1071 fprintf(stderr
, "%s()\n", __func__
);
1072 dyld::initializeMainExecutable();
1076 void NSLinkEditError(NSLinkEditErrors
* c
, int* errorNumber
, const char** fileName
, const char** errorString
)
1079 *c
= sLastErrorFileCode
;
1080 *errorNumber
= sLastErrorNo
;
1081 *fileName
= sLastErrorFilePath
;
1082 *errorString
= dyld::getErrorMessage();
1085 static void _dyld_register_binding_handler(void * (*bindingHandler
)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions
)
1087 if ( dyld::gLogAPIs
)
1088 fprintf(stderr
, "%s()\n", __func__
);
1089 dyld::gLinkContext
.bindingHandler
= bindingHandler
;
1090 dyld::gLinkContext
.bindingOptions
= bindingOptions
;
1093 // Call by fork() in libSystem before the kernel trap is done
1094 static void _dyld_fork_prepare()
1096 if ( dyld::gLogAPIs
)
1097 fprintf(stderr
, "%s()\n", __func__
);
1100 // Call by fork() in libSystem after the kernel trap is done on the parent side
1101 static void _dyld_fork_parent()
1103 if ( dyld::gLogAPIs
)
1104 fprintf(stderr
, "%s()\n", __func__
);
1107 // Call by fork() in libSystem after the kernel trap is done on the child side
1108 static void _dyld_fork_child()
1110 if ( dyld::gLogAPIs
)
1111 fprintf(stderr
, "%s()\n", __func__
);
1112 // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
1113 // in libSystem for the child of a fork. But dyld is built with a static copy
1114 // of libc.a and has its own copy of mach_task_self_ which we reset here.
1116 // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
1117 // in mach_init() mach_task_self_ is initialized to task_self_trap().
1119 extern mach_port_t mach_task_self_
;
1120 mach_task_self_
= task_self_trap();
1123 // Call by fork() in libSystem after the kernel trap is done on the child side after
1124 // other libSystem child side fixups are done
1125 static void _dyld_fork_child_final()
1127 if ( dyld::gLogAPIs
)
1128 fprintf(stderr
, "%s()\n", __func__
);
1132 typedef void (*MonitorProc
)(char *lowpc
, char *highpc
);
1134 static void monInitCallback(ImageLoader
* image
, void* userData
)
1136 MonitorProc proc
= (MonitorProc
)userData
;
1139 if ( image
->getSectionContent("__TEXT", "__text", &start
, &length
) ) {
1140 proc((char*)start
, (char*)start
+length
);
1145 // _dyld_moninit is called from profiling runtime routine moninit().
1146 // dyld calls back with the range of each __TEXT/__text section in every
1149 void _dyld_moninit(MonitorProc proc
)
1151 dyld::forEachImageDo(&monInitCallback
, (void*)proc
);
1154 // returns true if prebinding was used in main executable
1155 bool _dyld_launched_prebound()
1157 if ( dyld::gLogAPIs
)
1158 fprintf(stderr
, "%s()\n", __func__
);
1160 // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
1161 return dyld::mainExecutablePrebound();
1166 // _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
1167 // NSMakePrivateModulePublic() needed for the dlopen() to turn it's
1168 // RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
1169 // flag on the image for this module. If the module was found and it was
1170 // private then everything worked and TRUE is returned else FALSE is returned.
1172 static bool NSMakePrivateModulePublic(NSModule
module)
1174 ImageLoader
* image
= NSModuleToImageLoader(module);
1175 if ( image
!= NULL
) {
1176 if ( image
->hasHiddenExports() ) {
1177 image
->setHideExports(false);
1186 bool lookupDyldFunction(const char* name
, uintptr_t* address
)
1188 for (const dyld_func
* p
= dyld_funcs
; p
->name
!= NULL
; ++p
) {
1189 if ( strcmp(p
->name
, name
) == 0 ) {
1190 if( p
->implementation
== unimplemented
)
1191 fprintf(stderr
, "unimplemented dyld function: %s\n", p
->name
);
1192 *address
= (uintptr_t)p
->implementation
;
1201 static void registerThreadHelpers(const dyld::ThreadingHelpers
* helpers
)
1203 // We need to make sure libSystem's lazy pointer's are bound
1204 // before installing thred helpers.
1205 // The reason for this is that if accessing the lock requires
1206 // a lazy pointer to be bound (and it does when multi-module
1207 // libSystem) is not prebound, the lazy handler will be
1208 // invoked which tries to acquire the lock again...an infinite
1210 ImageLoader
* image
= dyld::findImageContainingAddress(helpers
);
1211 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
1213 dyld::gThreadHelpers
= helpers
;
1217 static void dlerrorClear()
1219 if ( dyld::gThreadHelpers
!= NULL
) {
1220 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(1);
1225 static void dlerrorSet(const char* msg
)
1227 if ( dyld::gThreadHelpers
!= NULL
) {
1228 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(strlen(msg
)+1);
1229 strcpy(buffer
, msg
);
1235 void* dlopen(const char* path
, int mode
)
1237 if ( dyld::gLogAPIs
)
1238 fprintf(stderr
, "%s(%s, 0x%08X)\n", __func__
, path
, mode
);
1242 // passing NULL for path means return magic object
1243 if ( path
== NULL
) {
1244 return RTLD_DEFAULT
;
1248 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1249 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1251 ImageLoader
* image
= NULL
;
1252 dyld::LoadContext context
;
1253 context
.useSearchPaths
= true;
1254 context
.useLdLibraryPath
= (strchr(path
, '/') == NULL
); // a leafname implies should search
1255 context
.matchByInstallName
= true;
1256 context
.dontLoad
= ( (mode
& RTLD_NOLOAD
) != 0 );
1257 context
.mustBeBundle
= false;
1258 context
.mustBeDylib
= false;
1259 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
1260 context
.rpath
= NULL
; // support not yet implemented
1262 image
= load(path
, context
);
1263 if ( image
!= NULL
) {
1264 image
->incrementReferenceCount();
1265 if ( ! image
->isLinked() ) {
1266 ImageLoader::BindingLaziness bindiness
= ImageLoader::kNonLazyOnly
;
1267 if ( (mode
& RTLD_NOW
) != 0 )
1268 bindiness
= ImageLoader::kLazyAndNonLazy
;
1269 dyld::link(image
, bindiness
, ImageLoader::kRunInitializers
);
1270 // only hide exports if image is not already in use
1271 if ( (mode
& RTLD_LOCAL
) != 0 )
1272 image
->setHideExports(true);
1274 // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
1275 // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
1276 // The subtle differences are:
1277 // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
1278 // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
1279 if ( (mode
& RTLD_NODELETE
) != 0 )
1280 image
->setLeaveMapped();
1284 catch (const char* msg
) {
1285 const char* format
= "dlopen(%s, %d): %s";
1286 char temp
[strlen(format
)+strlen(path
)+strlen(msg
)+10];
1287 sprintf(temp
, format
, path
, mode
, msg
);
1293 int dlclose(void* handle
)
1295 if ( dyld::gLogAPIs
)
1296 fprintf(stderr
, "%s(%p)\n", __func__
, handle
);
1298 ImageLoader
* image
= (ImageLoader
*)handle
;
1299 if ( dyld::validImage(image
) ) {
1300 if ( image
->decrementReferenceCount() ) {
1301 // for now, only bundles can be unloaded
1302 // to unload dylibs we would need to track all direct and indirect uses
1303 if ( image
->isBundle() ) {
1304 dyld::removeImage(image
);
1312 dlerrorSet("invalid handle passed to dlclose()");
1319 int dladdr(const void* address
, Dl_info
* info
)
1321 if ( dyld::gLogAPIs
)
1322 fprintf(stderr
, "%s(%p, %p)\n", __func__
, address
, info
);
1324 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1325 if ( image
!= NULL
) {
1326 info
->dli_fname
= image
->getLogicalPath();
1327 info
->dli_fbase
= (void*)image
->machHeader();
1328 // find closest exported symbol in the image
1329 const uint32_t exportCount
= image
->getExportedSymbolCount();
1330 const ImageLoader::Symbol
* bestSym
= NULL
;
1331 const void* bestAddr
= 0;
1332 for(uint32_t i
=0; i
< exportCount
; ++i
) {
1333 const ImageLoader::Symbol
* sym
= image
->getIndexedExportedSymbol(i
);
1334 const void* symAddr
= (void*)image
->getExportedSymbolAddress(sym
);
1335 if ( (symAddr
<= address
) && (bestAddr
< symAddr
) ) {
1340 if ( bestSym
!= NULL
) {
1341 info
->dli_sname
= image
->getExportedSymbolName(bestSym
) + 1; // strip off leading underscore
1342 info
->dli_saddr
= (void*)bestAddr
;
1345 info
->dli_sname
= NULL
;
1346 info
->dli_saddr
= NULL
;
1348 return 1; // success
1350 return 0; // failure
1356 if ( dyld::gLogAPIs
)
1357 fprintf(stderr
, "%s()\n", __func__
);
1359 if ( dyld::gThreadHelpers
!= NULL
) {
1360 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(1);
1361 // if no error set, return NULL
1362 if ( buffer
[0] != '\0' )
1368 void* dlsym(void* handle
, const char* symbolName
)
1370 if ( dyld::gLogAPIs
)
1371 fprintf(stderr
, "%s(%p, %s)\n", __func__
, handle
, symbolName
);
1376 const ImageLoader::Symbol
* sym
;
1378 // dlsym() assumes symbolName passed in is same as in C source code
1379 // dyld assumes all symbol names have an underscore prefix
1380 char underscoredName
[strlen(symbolName
)+2];
1381 underscoredName
[0] = '_';
1382 strcpy(&underscoredName
[1], symbolName
);
1384 // magic "search all" handle
1385 if ( handle
== RTLD_DEFAULT
) {
1386 if ( dyld::flatFindExportedSymbol(underscoredName
, &sym
, &image
) ) {
1387 return (void*)image
->getExportedSymbolAddress(sym
);
1389 const char* format
= "dlsym(RTLD_DEFAULT, %s): symbol not found";
1390 char temp
[strlen(format
)+strlen(symbolName
)+2];
1391 sprintf(temp
, format
, symbolName
);
1396 // magic "search what I would see" handle
1397 if ( handle
== RTLD_NEXT
) {
1398 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1399 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1400 sym
= callerImage
->findExportedSymbolInDependentImages(underscoredName
, &image
); // don't search image, but do search what it links against
1401 if ( sym
!= NULL
) {
1402 return (void*)image
->getExportedSymbolAddress(sym
);
1404 const char* format
= "dlsym(RTLD_NEXT, %s): symbol not found";
1405 char temp
[strlen(format
)+strlen(symbolName
)+2];
1406 sprintf(temp
, format
, symbolName
);
1411 // magic "search me, then what I would see" handle
1412 if ( handle
== RTLD_SELF
) {
1413 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1414 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1415 sym
= callerImage
->findExportedSymbolInImageOrDependentImages(underscoredName
, &image
); // search image and what it links against
1416 if ( sym
!= NULL
) {
1417 return (void*)image
->getExportedSymbolAddress(sym
);
1419 const char* format
= "dlsym(RTLD_SELF, %s): symbol not found";
1420 char temp
[strlen(format
)+strlen(symbolName
)+2];
1421 sprintf(temp
, format
, symbolName
);
1427 image
= (ImageLoader
*)handle
;
1428 if ( dyld::validImage(image
) ) {
1429 sym
= image
->findExportedSymbolInImageOrDependentImages(underscoredName
, &image
); // search image and what it links against
1430 if ( sym
!= NULL
) {
1431 return (void*)image
->getExportedSymbolAddress(sym
);
1433 const char* format
= "dlsym(%p, %s): symbol not found";
1434 char temp
[strlen(format
)+strlen(symbolName
)+20];
1435 sprintf(temp
, format
, handle
, symbolName
);
1439 dlerrorSet("invalid handle passed to dlsym()");
1445 static void commitRepreboundFiles(std::vector
<ImageLoader
*> files
, bool unmapOld
)
1447 // tell file system to flush all dirty buffers to disk
1448 // after this sync, the _redoprebinding files will be on disk
1451 // now commit (swap file) for each re-prebound image
1452 // this only updates directories, since the files have already been flushed by previous sync()
1453 for (std::vector
<ImageLoader
*>::iterator it
=files
.begin(); it
!= files
.end(); it
++) {
1454 (*it
)->reprebindCommit(dyld::gLinkContext
, true, unmapOld
);
1457 // tell file system to flush all dirty buffers to disk
1458 // this should flush out all directory changes caused by the file swapping
1463 #define UPDATE_PREBINDING_DRY_RUN 0x00000001
1464 #define UPDATE_PREBINDING_PROGRESS 0x00000002
1467 // SPI called only by update_prebinding tool to redo prebinding in all prebound files specified
1468 // There must be no dylibs loaded when this fnction is called.
1470 __attribute__((noreturn
))
1471 static void _dyld_update_prebinding(int pathCount
, const char* paths
[], uint32_t flags
)
1473 if ( dyld::gLogAPIs
)
1474 fprintf(stderr
, "%s()\n", __func__
);
1476 // list of requested dylibs actually loaded
1477 std::vector
<ImageLoader
*> preboundImages
;
1480 // verify no dylibs loaded
1481 if ( dyld::getImageCount() != 1 )
1482 throw "_dyld_update_prebinding cannot be called with dylib already loaded";
1484 const uint32_t max_allowed_link_errors
= 10;
1485 uint32_t link_error_count
= 0;
1487 // load and link each dylib
1488 for (int i
=0; i
< pathCount
; ++i
) {
1489 dyld::LoadContext context
;
1490 context
.useSearchPaths
= false;
1491 context
.matchByInstallName
= true;
1492 context
.dontLoad
= false;
1493 context
.mustBeBundle
= false;
1494 context
.mustBeDylib
= true;
1495 context
.origin
= NULL
; // @loader_path not allowed in prebinding list
1496 context
.rpath
= NULL
; // support not yet implemented
1498 ImageLoader
* image
= NULL
;
1500 image
= dyld::load(paths
[i
], context
);
1501 // bind lazy and non-lazy symbols, but don't run initializers
1502 // this may bring in other dylibs later in the list or missing from list, but that is ok
1503 dyld::link(image
, ImageLoader::kLazyAndNonLazy
, ImageLoader::kDontRunInitializers
);
1504 // recored images we successfully loaded
1505 preboundImages
.push_back(image
);
1507 catch (const char* msg
) {
1508 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) ) {
1510 if ( image
== NULL
) // load exception
1512 else // link exception
1514 fprintf(stderr
, "update_prebinding: warning: could not %s %s: %s\n", stage
, paths
[i
], msg
);
1516 if ( image
!= NULL
)
1518 if ( link_error_count
> max_allowed_link_errors
)
1523 // find missing images
1524 uint32_t loadedImageCount
= dyld::getImageCount();
1525 if ( loadedImageCount
> (preboundImages
.size()+1) ) {
1526 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1527 fprintf(stderr
, "update_prebinding: warning: the following dylibs were loaded but will not have their prebinding updated because they are not in the list of paths to reprebind\n");
1528 for (uint32_t i
=1; i
< loadedImageCount
; ++i
) {
1529 ImageLoader
* target
= dyld::getIndexedImage(i
);
1531 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1532 if ( *it
== target
) {
1538 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1539 fprintf(stderr
, " %s\n", target
->getPath());
1543 // warn about unprebound files in the list
1544 bool unpreboundWarned
= false;
1545 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1546 if ( ! (*it
)->isPrebindable() && (*it
!= dyld::mainExecutable()) ) {
1547 if ( ! unpreboundWarned
) {
1548 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1549 fprintf(stderr
, "update_prebinding: warning: the following dylibs were specified but were not built prebound\n");
1550 unpreboundWarned
= true;
1552 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1553 fprintf(stderr
, " %s\n", (*it
)->getPath());
1557 if(UPDATE_PREBINDING_DRY_RUN
& flags
) {
1558 fprintf(stderr
, "update_prebinding: dry-run: no changes were made to the filesystem.\n");
1561 uint32_t imageCount
= preboundImages
.size();
1562 uint32_t imageNumber
= 1;
1564 // on Intel system, update_prebinding is run twice: i386, then emulated ppc
1565 // calculate fudge factors so that progress output represents both runs
1566 int denomFactor
= 1;
1567 int numerAddend
= 0;
1568 if (UPDATE_PREBINDING_PROGRESS
& flags
) {
1570 // i386 half runs first, just double denominator
1574 // if emulated ppc, double denominator and shift numerator
1575 int mib
[] = { CTL_KERN
, KERN_CLASSIC
, getpid() };
1576 int is_emulated
= 0;
1577 size_t len
= sizeof(int);
1578 int ret
= sysctl(mib
, 3, &is_emulated
, &len
, NULL
, 0);
1579 if ((ret
!= -1) && is_emulated
) {
1581 numerAddend
= imageCount
;
1586 // tell each image to write itself out re-prebound
1587 struct timeval currentTime
= { 0 , 0 };
1588 gettimeofday(¤tTime
, NULL
);
1589 time_t timestamp
= currentTime
.tv_sec
;
1590 std::vector
<ImageLoader
*> updatedImages
;
1591 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1592 uint64_t freespace
= (*it
)->reprebind(dyld::gLinkContext
, timestamp
);
1593 updatedImages
.push_back(*it
);
1594 if(UPDATE_PREBINDING_PROGRESS
& flags
) {
1595 fprintf(stdout
, "update_prebinding: progress: %3u/%u\n", imageNumber
+numerAddend
, imageCount
*denomFactor
);
1599 // see if we are running low on disk space (less than 32MB is "low")
1600 const uint64_t kMinFreeSpace
= 32*1024*1024;
1601 if ( freespace
< kMinFreeSpace
) {
1602 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1603 fprintf(stderr
, "update_prebinding: disk space down to %lluMB, committing %lu prebound files\n", freespace
/(1024*1024), updatedImages
.size());
1604 // commit files processed so far, to free up more disk space
1605 commitRepreboundFiles(updatedImages
, true);
1606 // empty list of temp files
1607 updatedImages
.clear();
1611 // commit them, don't need to unmap old, cause we are done
1612 commitRepreboundFiles(updatedImages
, false);
1615 catch (const char* msg
) {
1616 // delete temp files
1618 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1619 (*it
)->reprebindCommit(dyld::gLinkContext
, false, false);
1622 catch (const char* commitMsg
) {
1623 fprintf(stderr
, "update_prebinding: error: %s\n", commitMsg
);
1625 fprintf(stderr
, "update_prebinding: error: %s\n", msg
);
1633 static const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1635 return &dyld_all_image_infos
;