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>
37 extern "C" mach_port_name_t
task_self_trap(void); // can't include <System/mach/mach_traps.h> because it is missing extern C
39 #include "mach-o/dyld_gdb.h"
40 #include "mach-o/dyld.h"
41 #include "mach-o/dyld_priv.h"
44 #include "ImageLoader.h"
46 #include "dyldLibSystemThreadHelpers.h"
48 static char sLastErrorFilePath
[1024];
49 static NSLinkEditErrors sLastErrorFileCode
;
50 static int sLastErrorNo
;
53 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
54 // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
55 // This conditional keeps support for old libSystem's which needed some help implementing the API's
56 #define OLD_LIBSYSTEM_SUPPORT 1
59 // The following functions have no prototype in any header. They are special cases
60 // where _dyld_func_lookup() is used directly.
61 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
);
62 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
);
63 static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions
);
64 static void _dyld_fork_prepare();
65 static void _dyld_fork_parent();
66 static void _dyld_fork_child();
67 static void _dyld_fork_child_final();
68 static void _dyld_make_delayed_module_initializer_calls();
69 static void _dyld_mod_term_funcs();
70 static bool NSMakePrivateModulePublic(NSModule
module);
71 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
);
72 static void registerThreadHelpers(const dyld::ThreadingHelpers
*);
73 static void _dyld_update_prebinding(int pathCount
, const char* paths
[], uint32_t flags
);
74 static const struct dyld_all_image_infos
* _dyld_get_all_image_infos();
76 // The following functions are dyld API's, but since dyld links with a static copy of libc.a
77 // the public name cannot be used.
78 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module);
79 static bool client_NSIsSymbolNameDefined(const char* symbolName
);
82 static void unimplemented()
84 dyld::halt("unimplemented dyld function\n");
92 static struct dyld_func dyld_funcs
[] = {
93 {"__dyld_image_count", (void*)_dyld_image_count
},
94 {"__dyld_get_image_header", (void*)_dyld_get_image_header
},
95 {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide
},
96 {"__dyld_get_image_name", (void*)_dyld_get_image_name
},
97 {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind
},
98 {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint
},
99 {"__dyld_lookup_and_bind_objc", (void*)unimplemented
},
100 {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully
},
101 {"__dyld_install_handlers", (void*)_dyld_install_handlers
},
102 {"__dyld_link_edit_error", (void*)NSLinkEditError
},
103 #if OLD_LIBSYSTEM_SUPPORT
104 {"__dyld_link_module", (void*)_dyld_link_module
},
106 {"__dyld_unlink_module", (void*)NSUnLinkModule
},
107 {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image
},
108 {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image
},
109 {"__dyld_register_func_for_link_module", (void*)unimplemented
},
110 {"__dyld_register_func_for_unlink_module", (void*)unimplemented
},
111 {"__dyld_register_func_for_replace_module", (void*)unimplemented
},
112 {"__dyld_get_objc_module_sect_for_module", (void*)unimplemented
},
113 {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module
},
114 {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address
},
115 {"__dyld_image_containing_address", (void*)_dyld_image_containing_address
},
116 {"__dyld_get_image_header_containing_address", (void*)_dyld_get_image_header_containing_address
},
117 {"__dyld_moninit", (void*)_dyld_moninit
},
118 {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler
},
119 {"__dyld_fork_prepare", (void*)_dyld_fork_prepare
},
120 {"__dyld_fork_parent", (void*)_dyld_fork_parent
},
121 {"__dyld_fork_child", (void*)_dyld_fork_child
},
122 {"__dyld_fork_child_final", (void*)_dyld_fork_child_final
},
123 {"__dyld_fork_mach_init", (void*)unimplemented
},
124 {"__dyld_make_delayed_module_initializer_calls",(void*)_dyld_make_delayed_module_initializer_calls
},
125 {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol
},
126 {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol
},
127 {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol
},
128 {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol
},
129 {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint
},
130 {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule
},
131 {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage
},
132 {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic
},
133 {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined
},
134 {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint
},
135 {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage
},
136 {"__dyld_NSNameOfModule", (void*)NSNameOfModule
},
137 {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule
},
138 {"__dyld_NSAddLibrary", (void*)NSAddLibrary
},
139 {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching
},
140 {"__dyld_NSAddImage", (void*)NSAddImage
},
141 {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath
},
142 {"__dyld_launched_prebound", (void*)_dyld_launched_prebound
},
143 {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound
},
144 {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib
},
145 {"__dyld_mod_term_funcs", (void*)_dyld_mod_term_funcs
},
146 {"__dyld_install_link_edit_symbol_handlers", (void*)dyld::registerZeroLinkHandlers
},
147 {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile
},
148 {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory
},
149 {"__dyld_NSCreateCoreFileImageFromFile", (void*)unimplemented
},
150 {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage
},
151 {"__dyld_NSLinkModule", (void*)NSLinkModule
},
152 {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage
},
153 {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage
},
154 {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage
},
155 {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage
},
156 {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage
},
157 {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage
},
158 {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage
},
159 {"__dyld_NSFindSectionAndOffsetInObjectFileImage", (void*)NSFindSectionAndOffsetInObjectFileImage
},
160 {"__dyld_register_thread_helpers", (void*)registerThreadHelpers
},
161 {"__dyld_dladdr", (void*)dladdr
},
162 {"__dyld_dlclose", (void*)dlclose
},
163 {"__dyld_dlerror", (void*)dlerror
},
164 {"__dyld_dlopen", (void*)dlopen
},
165 {"__dyld_dlsym", (void*)dlsym
},
166 {"__dyld_update_prebinding", (void*)_dyld_update_prebinding
},
167 {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos
},
173 // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
174 inline NSSymbol
SymbolToNSSymbol(const ImageLoader::Symbol
* sym
)
176 return (NSSymbol
)sym
;
178 inline const ImageLoader::Symbol
* NSSymbolToSymbol(NSSymbol sym
)
180 return (const ImageLoader::Symbol
*)sym
;
183 // dyld's abstract type NSModule is implemented as ImageLoader*
184 inline NSModule
ImageLoaderToNSModule(ImageLoader
* image
)
186 return (NSModule
)image
;
188 inline ImageLoader
* NSModuleToImageLoader(NSModule
module)
190 ImageLoader
* image
= (ImageLoader
*)module;
191 if ( dyld::validImage(image
) )
196 // actual definition for opaque type
197 struct __NSObjectFileImage
200 const void* imageBaseAddress
; // not used with OFI created from files
201 size_t imageLength
; // not used with OFI created from files
203 static std::vector
<NSObjectFileImage
> sObjectFileImages
;
208 // __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
209 // The contained image is delete in one of two places:
210 // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
211 // NSDestroyObjectFileImage deletes the image if image is not in list of valid images
215 static void dyldAPIhalt(const char* apiName
, const char* errorMsg
)
217 fprintf(stderr
, "dyld: %s() error\n", apiName
);
218 dyld::halt(errorMsg
);
223 static void setLastError(NSLinkEditErrors code
, int errnum
, const char* file
, const char* message
)
225 dyld::setErrorMessage(message
);
226 strncpy(sLastErrorFilePath
, file
, 1024);
227 sLastErrorFilePath
[1023] = '\0';
228 sLastErrorFileCode
= code
;
229 sLastErrorNo
= errnum
;
234 *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
235 * copies the path of the executable into the buffer and returns 0 if the path
236 * was successfully copied in the provided buffer. If the buffer is not large
237 * enough, -1 is returned and the expected buffer size is copied in *bufsize.
238 * Note that _NSGetExecutablePath will return "a path" to the executable not a
239 * "real path" to the executable. That is the path may be a symbolic link and
240 * not the real file. And with deep directories the total bufsize needed could
241 * be more than MAXPATHLEN.
243 int _NSGetExecutablePath(char* buf
, uint32_t *bufsize
)
245 if ( dyld::gLogAPIs
)
246 fprintf(stderr
, "%s(...)\n", __func__
);
247 const char* exePath
= dyld::getExecutablePath();
248 if(*bufsize
< strlen(exePath
) + 1){
249 *bufsize
= strlen(exePath
) + 1;
252 strcpy(buf
, exePath
);
258 // _dyld_call_module_initializers_for_dylib() is the dyld side of
259 // __initialize_Cplusplus() which is in dylib1.o.
260 // It is intended to only be called inside -init rouintes.
261 // -init routines are called before module initializers (what C++
262 // initializers use). Calling __initialize_Cplusplus() in a -init
263 // routine causes the module initializers for an image to be called
264 // which then allows C++ to be used inside a -init routine
266 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
)
268 if ( dyld::gLogAPIs
)
269 fprintf(stderr
, "__initialize_Cplusplus()\n");
271 // for now, do nothing...
275 void _dyld_lookup_and_bind_fully(const char* symbolName
, void** address
, NSModule
* module)
277 if ( dyld::gLogAPIs
)
278 fprintf(stderr
, "%s(\"%s\", %p, %p)\n", __func__
, symbolName
, address
, module);
280 const ImageLoader::Symbol
* sym
;
281 dyld::clearErrorMessage();
282 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
284 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
285 if ( address
!= NULL
)
286 *address
= (void*)image
->getExportedSymbolAddress(sym
);
288 *module = ImageLoaderToNSModule(image
);
290 catch (const char* msg
) {
291 dyldAPIhalt(__func__
, msg
);
295 // on failure to find symbol return NULLs
296 if ( address
!= NULL
)
303 // Note: This cannot have public name because dyld is built with a static copy of libc.a
304 // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
305 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module)
307 if ( dyld::gLogAPIs
)
308 fprintf(stderr
, "_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName
, address
, module);
310 const ImageLoader::Symbol
* sym
;
311 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
312 if ( address
!= NULL
)
313 *address
= (void*)image
->getExportedSymbolAddress(sym
);
315 *module = ImageLoaderToNSModule(image
);
318 // on failure to find symbol return NULLs
319 if ( address
!= NULL
)
326 void _dyld_lookup_and_bind_with_hint(const char* symbolName
, const char* library_name_hint
, void** address
, NSModule
* module)
328 if ( dyld::gLogAPIs
)
329 fprintf(stderr
, "%s(\"%s\", \"%s\", %p, %p)\n", __func__
, symbolName
, library_name_hint
, address
, module);
331 const ImageLoader::Symbol
* sym
;
332 // Look for library whose path contains the hint. If that fails search everywhere
333 if ( dyld::flatFindExportedSymbolWithHint(symbolName
, library_name_hint
, &sym
, &image
)
334 || dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
335 if ( address
!= NULL
)
336 *address
= (void*)image
->getExportedSymbolAddress(sym
);
338 *module = ImageLoaderToNSModule(image
);
341 // on failure to find symbol return NULLs
342 if ( address
!= NULL
)
350 NSSymbol
NSLookupAndBindSymbol(const char *symbolName
)
352 if ( dyld::gLogAPIs
)
353 fprintf(stderr
, "%s(\"%s\")\n", __func__
, symbolName
);
355 const ImageLoader::Symbol
* sym
;
356 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
357 return SymbolToNSSymbol(sym
);
359 // return NULL on failure
363 NSSymbol
NSLookupAndBindSymbolWithHint(const char* symbolName
, const char* libraryNameHint
)
365 if ( dyld::gLogAPIs
)
366 fprintf(stderr
, "%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
368 const ImageLoader::Symbol
* sym
;
369 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
371 // hint failed, do slow search of all images
372 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
375 return SymbolToNSSymbol(sym
);
377 // return NULL on failure and log
378 if ( dyld::gLogAPIs
)
379 fprintf(stderr
, "%s(\"%s\", \"%s\") => NULL \n", __func__
, symbolName
, libraryNameHint
);
383 uint32_t _dyld_image_count(void)
385 if ( dyld::gLogAPIs
)
386 fprintf(stderr
, "%s()\n", __func__
);
387 return dyld::getImageCount();
390 const struct mach_header
* _dyld_get_image_header(uint32_t image_index
)
392 if ( dyld::gLogAPIs
)
393 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
394 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
396 return (struct mach_header
*)image
->machHeader();
402 static __attribute__((noinline
))
403 const struct mach_header
* addImage(const char* path
, bool search
, bool dontLoad
, bool matchInstallName
, bool abortOnError
)
405 ImageLoader
* image
= NULL
;
407 dyld::clearErrorMessage();
408 void* callerAddress
= __builtin_return_address(2); // note layers: 2: real client, 1: libSystem glue, 0: dyld API
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 return addImage(path
, search
, dontLoad
, matchInstallName
, abortOnError
);
453 bool NSAddLibrary(const char* path
)
455 if ( dyld::gLogAPIs
)
456 fprintf(stderr
, "%s(\"%s\")\n", __func__
, path
);
457 return (addImage(path
, false, false, false, false) != NULL
);
460 bool NSAddLibraryWithSearching(const char* path
)
462 if ( dyld::gLogAPIs
)
463 fprintf(stderr
, "%s(\"%s\")\n", __func__
, path
);
464 return (addImage(path
, true, false, false, false) != NULL
);
469 //#define NSADDIMAGE_OPTION_NONE 0x0
470 //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
471 //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
473 bool NSIsSymbolNameDefinedInImage(const struct mach_header
* mh
, const char* symbolName
)
475 if ( dyld::gLogAPIs
)
476 fprintf(stderr
, "%s(%p, \"%s\")\n", __func__
, (void *)mh
, symbolName
);
477 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
478 if ( image
!= NULL
) {
479 if ( image
->findExportedSymbol(symbolName
, NULL
, true, NULL
) != NULL
)
485 NSSymbol
NSLookupSymbolInImage(const struct mach_header
* mh
, const char* symbolName
, uint32_t options
)
487 if ( dyld::gLogAPIs
)
488 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", __func__
, mh
, symbolName
, options
);
489 const ImageLoader::Symbol
* symbol
= NULL
;
490 dyld::clearErrorMessage();
491 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
492 if ( image
!= NULL
) {
494 if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
) {
495 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
497 else if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
) {
498 dyld::link(image
, ImageLoader::kLazyOnlyNoDependents
, ImageLoader::kDontRunInitializers
);
501 catch (const char* msg
) {
502 if ( (options
& NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
) == 0 ) {
503 dyldAPIhalt(__func__
, msg
);
506 symbol
= image
->findExportedSymbol(symbolName
, NULL
, true, NULL
);
508 if ( dyld::gLogAPIs
&& (symbol
== NULL
) )
509 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__
, mh
, symbolName
, options
);
510 return SymbolToNSSymbol(symbol
);
514 // Note: This cannot have public name because dyld is built with a static copy of libc.a
515 // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
516 static bool client_NSIsSymbolNameDefined(const char* symbolName
)
518 if ( dyld::gLogAPIs
)
519 fprintf(stderr
, "NSIsSymbolNameDefined(\"%s\")\n", symbolName
);
521 const ImageLoader::Symbol
* sym
;
522 return dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
525 bool NSIsSymbolNameDefinedWithHint(const char* symbolName
, const char* libraryNameHint
)
527 if ( dyld::gLogAPIs
)
528 fprintf(stderr
, "%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
530 const ImageLoader::Symbol
* sym
;
531 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
533 // hint failed, do slow search of all images
534 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
536 if ( !found
&& dyld::gLogAPIs
)
537 fprintf(stderr
, "%s(\"%s\", \"%s\") => false \n", __func__
, symbolName
, libraryNameHint
);
541 const char* NSNameOfSymbol(NSSymbol symbol
)
543 if ( dyld::gLogAPIs
)
544 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
545 const char* result
= NULL
;
546 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
548 result
= image
->getExportedSymbolName(NSSymbolToSymbol(symbol
));
552 void* NSAddressOfSymbol(NSSymbol symbol
)
554 if ( dyld::gLogAPIs
)
555 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
557 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
559 result
= (void*)image
->getExportedSymbolAddress(NSSymbolToSymbol(symbol
));
563 NSModule
NSModuleForSymbol(NSSymbol symbol
)
565 if ( dyld::gLogAPIs
)
566 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)symbol
);
567 NSModule result
= NULL
;
568 ImageLoader
* image
= dyld::findImageContainingAddress(symbol
);
570 result
= ImageLoaderToNSModule(image
);
575 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index
)
577 if ( dyld::gLogAPIs
)
578 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
579 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
581 return image
->getSlide();
586 const char* _dyld_get_image_name(uint32_t image_index
)
588 if ( dyld::gLogAPIs
)
589 fprintf(stderr
, "%s(%u)\n", __func__
, image_index
);
590 ImageLoader
* image
= dyld::getIndexedImage(image_index
);
592 return image
->getLogicalPath();
599 bool _dyld_all_twolevel_modules_prebound(void)
601 if ( dyld::gLogAPIs
)
602 fprintf(stderr
, "%s()\n", __func__
);
603 return FALSE
; // fixme
606 void _dyld_bind_objc_module(const void *objc_module
)
608 if ( dyld::gLogAPIs
)
609 fprintf(stderr
, "%s(%p)\n", __func__
, objc_module
);
610 // do nothing, with new dyld everything already bound
614 bool _dyld_bind_fully_image_containing_address(const void* address
)
616 if ( dyld::gLogAPIs
)
617 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
618 dyld::clearErrorMessage();
619 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
620 if ( image
!= NULL
) {
622 dyld::link(image
, ImageLoader::kLazyAndNonLazy
, ImageLoader::kDontRunInitializers
);
625 catch (const char* msg
) {
626 dyldAPIhalt(__func__
, msg
);
632 bool _dyld_image_containing_address(const void* address
)
634 if ( dyld::gLogAPIs
)
635 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
636 ImageLoader
*imageLoader
= dyld::findImageContainingAddress(address
);
637 return (NULL
!= imageLoader
);
640 static NSObjectFileImage
createObjectImageFile(ImageLoader
* image
, const void* address
= NULL
, size_t len
=0)
642 NSObjectFileImage result
= new __NSObjectFileImage();
643 result
->image
= image
;
644 result
->imageBaseAddress
= address
;
645 result
->imageLength
= len
;
646 sObjectFileImages
.push_back(result
);
650 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromFile(const char* pathName
, NSObjectFileImage
*objectFileImage
)
652 if ( dyld::gLogAPIs
)
653 fprintf(stderr
, "%s(\"%s\", ...)\n", __func__
, pathName
);
655 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
656 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
658 dyld::LoadContext context
;
659 context
.useSearchPaths
= false;
660 context
.useLdLibraryPath
= false;
661 context
.matchByInstallName
= false;
662 context
.dontLoad
= false;
663 context
.mustBeBundle
= true;
664 context
.mustBeDylib
= false;
665 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
666 context
.rpath
= NULL
; // support not yet implemented
668 ImageLoader
* image
= dyld::load(pathName
, context
);
669 // Note: We DO NOT link the image! NSLinkModule will do that
670 if ( image
!= NULL
) {
671 if ( !image
->isBundle() ) {
672 // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
673 return NSObjectFileImageInappropriateFile
;
675 *objectFileImage
= createObjectImageFile(image
);
676 return NSObjectFileImageSuccess
;
679 catch (const char* msg
) {
680 //fprintf(stderr, "dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
681 return NSObjectFileImageInappropriateFile
;
683 return NSObjectFileImageFailure
;
687 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromMemory(const void* address
, size_t size
, NSObjectFileImage
*objectFileImage
)
689 if ( dyld::gLogAPIs
)
690 fprintf(stderr
, "%s(%p, %lu, %p)\n", __func__
, address
, size
, objectFileImage
);
693 ImageLoader
* image
= dyld::loadFromMemory((const uint8_t*)address
, size
, NULL
);
694 if ( ! image
->isBundle() ) {
695 // this API can only be used with bundles...
697 return NSObjectFileImageInappropriateFile
;
699 // Note: We DO NOT link the image! NSLinkModule will do that
700 if ( image
!= NULL
) {
701 *objectFileImage
= createObjectImageFile(image
, address
, size
);
702 return NSObjectFileImageSuccess
;
705 catch (const char* msg
) {
706 fprintf(stderr
, "dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg
);
708 return NSObjectFileImageFailure
;
711 static bool validOFI(NSObjectFileImage objectFileImage
)
713 const int ofiCount
= sObjectFileImages
.size();
714 for (int i
=0; i
< ofiCount
; ++i
) {
715 if ( sObjectFileImages
[i
] == objectFileImage
)
721 bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage
)
723 if ( dyld::gLogAPIs
)
724 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
726 if ( validOFI(objectFileImage
) ) {
727 // if the image has never been linked or has been unlinked, the image is not in the list of valid images
728 // and we should delete it
729 bool linkedImage
= dyld::validImage(objectFileImage
->image
);
731 delete objectFileImage
->image
;
733 // remove from list of ofi's
734 for (std::vector
<NSObjectFileImage
>::iterator it
=sObjectFileImages
.begin(); it
!= sObjectFileImages
.end(); it
++) {
735 if ( *it
== objectFileImage
) {
736 sObjectFileImages
.erase(it
);
741 // if object was created from a memory, release that memory
742 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
743 if ( objectFileImage
->imageBaseAddress
!= NULL
) {
744 vm_deallocate(mach_task_self(), (vm_address_t
)objectFileImage
->imageBaseAddress
, objectFileImage
->imageLength
);
748 delete objectFileImage
;
755 bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage
)
757 if ( dyld::gLogAPIs
)
758 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
759 return objectFileImage
->image
->needsInitialization();
762 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage
)
764 if ( dyld::gLogAPIs
)
765 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
766 return objectFileImage
->image
->getExportedSymbolCount();
769 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
)
771 if ( dyld::gLogAPIs
)
772 fprintf(stderr
, "%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
773 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedExportedSymbol(ordinal
);
774 return objectFileImage
->image
->getExportedSymbolName(sym
);
777 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage
)
779 if ( dyld::gLogAPIs
)
780 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
781 return objectFileImage
->image
->getImportedSymbolCount();
784 const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
,
785 bool* tentative_definition
)
787 if ( dyld::gLogAPIs
)
788 fprintf(stderr
, "%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
789 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedImportedSymbol(ordinal
);
790 if ( tentative_definition
!= NULL
) {
791 ImageLoader::ReferenceFlags flags
= objectFileImage
->image
->geImportedSymbolInfo(sym
);
792 if ( (flags
& ImageLoader::kTentativeDefinition
) != 0 )
793 *tentative_definition
= true;
795 *tentative_definition
= false;
797 return objectFileImage
->image
->getImportedSymbolName(sym
);
800 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage
,
801 const char* segmentName
, const char* sectionName
, unsigned long* size
)
803 if ( dyld::gLogAPIs
)
804 fprintf(stderr
, "%s(%p,%s, %s)\n", __func__
, objectFileImage
, segmentName
, sectionName
);
808 if ( objectFileImage
->image
->getSectionContent(segmentName
, sectionName
, &start
, &length
) ) {
818 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage
, const char* symbolName
)
820 if ( dyld::gLogAPIs
)
821 fprintf(stderr
, "%s(%p,%s)\n", __func__
, objectFileImage
, symbolName
);
822 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->findExportedSymbol(symbolName
, NULL
, true, NULL
);
823 return ( sym
!= NULL
);
827 * Given an imageOffset into an ObjectFileImage, returns
828 * the segment/section name and offset into that section of
829 * that imageOffset. Returns FALSE if the imageOffset is not
830 * in any section. You can used the resulting sectionOffset to
831 * index into the data returned by NSGetSectionDataInObjectFileImage.
833 * First appeared in Mac OS X 10.3
835 * SPI: currently only used by ZeroLink to detect +load methods
838 NSFindSectionAndOffsetInObjectFileImage(NSObjectFileImage objectFileImage
,
839 unsigned long imageOffset
,
840 const char** segmentName
, /* can be NULL */
841 const char** sectionName
, /* can be NULL */
842 unsigned long* sectionOffset
) /* can be NULL */
844 if ( dyld::gLogAPIs
)
845 fprintf(stderr
, "%s(%p)\n", __func__
, objectFileImage
);
847 return objectFileImage
->image
->findSection((char*)(objectFileImage
->image
->getBaseAddress())+imageOffset
, segmentName
, sectionName
, sectionOffset
);
852 NSModule
NSLinkModule(NSObjectFileImage objectFileImage
, const char* moduleName
, uint32_t options
)
854 if ( dyld::gLogAPIs
)
855 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", __func__
, objectFileImage
, moduleName
, options
);
857 dyld::clearErrorMessage();
859 // NSLinkModule allows a bundle to be link multpile times
860 // each link causes the bundle to be copied to a new address
861 if ( objectFileImage
->image
->isLinked() ) {
862 // already linked, so clone a new one and link it
864 fprintf(stderr
, "dyld: warning: %s(0x%08X, \"%s\", 0x%08X) called more than once for 0x%08X\n",
865 __func__
, objectFileImage
, moduleName
, options
, objectFileImage
);
867 objectFileImage
->image
= dyld::cloneImage(objectFileImage
->image
);
870 // if this ofi was made with NSCreateObjectFileImageFromFile() then physical path is already set
871 // if this ofi was create with NSCreateObjectFileImageFromMemory() then the phyiscal path should be set if supplied
872 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 ) {
873 if ( objectFileImage
->imageBaseAddress
!= NULL
) {
874 const char* physEnd
= &moduleName
[strlen(moduleName
)+1];
875 objectFileImage
->image
->setPath(physEnd
);
879 // set moduleName as the name anyone calling _dyld_get_image_name() will see
880 objectFileImage
->image
->setLogicalPath(moduleName
);
882 // support private bundles
883 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
884 objectFileImage
->image
->setHideExports();
886 // set up linking options
887 ImageLoader::BindingLaziness bindness
= ImageLoader::kNonLazyOnly
;
888 if ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 )
889 bindness
= ImageLoader::kLazyAndNonLazy
;
890 ImageLoader::InitializerRunning runInitializers
= ImageLoader::kRunInitializers
;
891 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) != 0 )
892 runInitializers
= ImageLoader::kDontRunInitializersButTellObjc
;
894 // load libraries, rebase, bind, to make this image usable
895 dyld::link(objectFileImage
->image
, bindness
, runInitializers
);
897 return ImageLoaderToNSModule(objectFileImage
->image
);
899 catch (const char* msg
) {
900 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
901 dyldAPIhalt(__func__
, msg
);
902 // not halting, so set error state for NSLinkEditError to find
903 dyld::removeImage(objectFileImage
->image
);
904 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
909 #if OLD_LIBSYSTEM_SUPPORT
910 // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
911 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
)
913 if ( dyld::gLogAPIs
)
914 fprintf(stderr
, "%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr
, moduleName
, options
); // note name/args translation
915 ImageLoader
* image
= NULL
;
916 dyld::clearErrorMessage();
918 const char* imageName
= moduleName
;
919 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 )
920 imageName
= &moduleName
[strlen(moduleName
)+1];
922 image
= dyld::loadFromMemory((const uint8_t*)object_addr
, object_size
, imageName
);
924 if ( (options
& NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
) != 0 )
925 image
->setLogicalPath(moduleName
);
927 if ( image
!= NULL
) {
928 // support private bundles
929 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
930 image
->setHideExports();
932 // set up linking options
933 ImageLoader::BindingLaziness bindness
= ImageLoader::kNonLazyOnly
;
934 if ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 )
935 bindness
= ImageLoader::kLazyAndNonLazy
;
936 ImageLoader::InitializerRunning runInitializers
= ImageLoader::kRunInitializers
;
937 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) != 0 )
938 runInitializers
= ImageLoader::kDontRunInitializersButTellObjc
;
940 // load libraries, rebase, bind, to make this image usable
941 dyld::link(image
, bindness
, runInitializers
);
944 catch (const char* msg
) {
945 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
946 dyldAPIhalt("NSLinkModule", msg
);
947 // not halting, so set error state for NSLinkEditError to find
948 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
949 // if image was created for this bundle, destroy it
950 if ( image
!= NULL
) {
951 dyld::removeImage(image
);
956 return ImageLoaderToNSModule(image
);
960 NSSymbol
NSLookupSymbolInModule(NSModule
module, const char* symbolName
)
962 if ( dyld::gLogAPIs
)
963 fprintf(stderr
, "%s(%p, \"%s\")\n", __func__
, (void *)module, symbolName
);
964 ImageLoader
* image
= NSModuleToImageLoader(module);
967 return SymbolToNSSymbol(image
->findExportedSymbol(symbolName
, NULL
, false, NULL
));
970 const char* NSNameOfModule(NSModule
module)
972 if ( dyld::gLogAPIs
)
973 fprintf(stderr
, "%s(%p)\n", __func__
, module);
974 ImageLoader
* image
= NSModuleToImageLoader(module);
977 return image
->getPath();
980 const char* NSLibraryNameForModule(NSModule
module)
982 if ( dyld::gLogAPIs
)
983 fprintf(stderr
, "%s(%p)\n", __func__
, module);
984 ImageLoader
* image
= NSModuleToImageLoader(module);
987 return image
->getPath();
990 bool NSUnLinkModule(NSModule
module, uint32_t options
)
992 if ( dyld::gLogAPIs
)
993 fprintf(stderr
, "%s(%p, 0x%08X)\n", __func__
, module, options
);
994 if ( module == NULL
)
996 ImageLoader
* image
= NSModuleToImageLoader(module);
999 dyld::removeImage(image
);
1001 if ( (options
& NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
) != 0 )
1002 image
->setLeaveMapped();
1004 // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1006 // Only delete image if there is no ofi referencing it
1007 // That means the ofi was destroyed after linking, so no one is left to delete this image
1008 const int ofiCount
= sObjectFileImages
.size();
1010 for (int i
=0; i
< ofiCount
; ++i
) {
1011 NSObjectFileImage ofi
= sObjectFileImages
[i
];
1012 if ( ofi
->image
== image
)
1021 // internal name and parameters do not match public name and parameters...
1022 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
)
1024 if ( dyld::gLogAPIs
)
1025 fprintf(stderr
, "NSLinkEditErrorHandlers()\n");
1027 dyld::registerUndefinedHandler((dyld::UndefinedHandler
)undefined
);
1028 // no support for multiple or linkedit handlers
1031 const struct mach_header
* _dyld_get_image_header_containing_address(const void* address
)
1033 if ( dyld::gLogAPIs
)
1034 fprintf(stderr
, "%s(%p)\n", __func__
, address
);
1035 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1036 if ( image
!= NULL
)
1037 return image
->machHeader();
1042 void _dyld_register_func_for_add_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1044 if ( dyld::gLogAPIs
)
1045 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)func
);
1046 dyld::registerAddCallback(func
);
1049 void _dyld_register_func_for_remove_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
1051 if ( dyld::gLogAPIs
)
1052 fprintf(stderr
, "%s(%p)\n", __func__
, (void *)func
);
1053 dyld::registerRemoveCallback(func
);
1056 // called by atexit() function installed by crt
1057 static void _dyld_mod_term_funcs()
1059 if ( dyld::gLogAPIs
)
1060 fprintf(stderr
, "%s()\n", __func__
);
1061 dyld::runTerminators();
1064 // called by crt before main
1065 static void _dyld_make_delayed_module_initializer_calls()
1067 if ( dyld::gLogAPIs
)
1068 fprintf(stderr
, "%s()\n", __func__
);
1069 dyld::initializeMainExecutable();
1073 void NSLinkEditError(NSLinkEditErrors
* c
, int* errorNumber
, const char** fileName
, const char** errorString
)
1076 *c
= sLastErrorFileCode
;
1077 *errorNumber
= sLastErrorNo
;
1078 *fileName
= sLastErrorFilePath
;
1079 *errorString
= dyld::getErrorMessage();
1082 static void _dyld_register_binding_handler(void * (*bindingHandler
)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions
)
1084 if ( dyld::gLogAPIs
)
1085 fprintf(stderr
, "%s()\n", __func__
);
1086 dyld::gLinkContext
.bindingHandler
= bindingHandler
;
1087 dyld::gLinkContext
.bindingOptions
= bindingOptions
;
1090 // Call by fork() in libSystem before the kernel trap is done
1091 static void _dyld_fork_prepare()
1093 if ( dyld::gLogAPIs
)
1094 fprintf(stderr
, "%s()\n", __func__
);
1097 // Call by fork() in libSystem after the kernel trap is done on the parent side
1098 static void _dyld_fork_parent()
1100 if ( dyld::gLogAPIs
)
1101 fprintf(stderr
, "%s()\n", __func__
);
1104 // Call by fork() in libSystem after the kernel trap is done on the child side
1105 static void _dyld_fork_child()
1107 if ( dyld::gLogAPIs
)
1108 fprintf(stderr
, "%s()\n", __func__
);
1109 // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
1110 // in libSystem for the child of a fork. But dyld is built with a static copy
1111 // of libc.a and has its own copy of mach_task_self_ which we reset here.
1113 // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
1114 // in mach_init() mach_task_self_ is initialized to task_self_trap().
1116 extern mach_port_t mach_task_self_
;
1117 mach_task_self_
= task_self_trap();
1120 // Call by fork() in libSystem after the kernel trap is done on the child side after
1121 // other libSystem child side fixups are done
1122 static void _dyld_fork_child_final()
1124 if ( dyld::gLogAPIs
)
1125 fprintf(stderr
, "%s()\n", __func__
);
1129 typedef void (*MonitorProc
)(char *lowpc
, char *highpc
);
1131 static void monInitCallback(ImageLoader
* image
, void* userData
)
1133 MonitorProc proc
= (MonitorProc
)userData
;
1136 if ( image
->getSectionContent("__TEXT", "__text", &start
, &length
) ) {
1137 proc((char*)start
, (char*)start
+length
);
1142 // _dyld_moninit is called from profiling runtime routine moninit().
1143 // dyld calls back with the range of each __TEXT/__text section in every
1146 void _dyld_moninit(MonitorProc proc
)
1148 dyld::forEachImageDo(&monInitCallback
, (void*)proc
);
1151 // returns true if prebinding was used in main executable
1152 bool _dyld_launched_prebound()
1154 if ( dyld::gLogAPIs
)
1155 fprintf(stderr
, "%s()\n", __func__
);
1157 // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
1158 return dyld::mainExecutablePrebound();
1163 // _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
1164 // NSMakePrivateModulePublic() needed for the dlopen() to turn it's
1165 // RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
1166 // flag on the image for this module. If the module was found and it was
1167 // private then everything worked and TRUE is returned else FALSE is returned.
1169 static bool NSMakePrivateModulePublic(NSModule
module)
1171 ImageLoader
* image
= NSModuleToImageLoader(module);
1172 if ( image
!= NULL
) {
1173 if ( image
->hasHiddenExports() ) {
1174 image
->setHideExports(false);
1183 bool lookupDyldFunction(const char* name
, uintptr_t* address
)
1185 for (const dyld_func
* p
= dyld_funcs
; p
->name
!= NULL
; ++p
) {
1186 if ( strcmp(p
->name
, name
) == 0 ) {
1187 if( p
->implementation
== unimplemented
)
1188 fprintf(stderr
, "unimplemented dyld function: %s\n", p
->name
);
1189 *address
= (uintptr_t)p
->implementation
;
1198 static void registerThreadHelpers(const dyld::ThreadingHelpers
* helpers
)
1200 // We need to make sure libSystem's lazy pointer's are bound
1201 // before installing thred helpers.
1202 // The reason for this is that if accessing the lock requires
1203 // a lazy pointer to be bound (and it does when multi-module
1204 // libSystem) is not prebound, the lazy handler will be
1205 // invoked which tries to acquire the lock again...an infinite
1207 ImageLoader
* image
= dyld::findImageContainingAddress(helpers
);
1208 dyld::link(image
, ImageLoader::kLazyOnly
, ImageLoader::kDontRunInitializers
);
1210 dyld::gThreadHelpers
= helpers
;
1214 static void dlerrorClear()
1216 if ( dyld::gThreadHelpers
!= NULL
) {
1217 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(1);
1222 static void dlerrorSet(const char* msg
)
1224 if ( dyld::gThreadHelpers
!= NULL
) {
1225 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(strlen(msg
)+1);
1226 strcpy(buffer
, msg
);
1232 void* dlopen(const char* path
, int mode
)
1234 if ( dyld::gLogAPIs
)
1235 fprintf(stderr
, "%s(%s, 0x%08X)\n", __func__
, path
, mode
);
1239 // passing NULL for path means return magic object
1240 if ( path
== NULL
) {
1241 return RTLD_DEFAULT
;
1245 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1246 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1248 ImageLoader
* image
= NULL
;
1249 dyld::LoadContext context
;
1250 context
.useSearchPaths
= true;
1251 context
.useLdLibraryPath
= (strchr(path
, '/') == NULL
); // a leafname implies should search
1252 context
.matchByInstallName
= true;
1253 context
.dontLoad
= ( (mode
& RTLD_NOLOAD
) != 0 );
1254 context
.mustBeBundle
= false;
1255 context
.mustBeDylib
= false;
1256 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
1257 context
.rpath
= NULL
; // support not yet implemented
1259 image
= load(path
, context
);
1260 if ( image
!= NULL
) {
1261 image
->incrementReferenceCount();
1262 if ( ! image
->isLinked() ) {
1263 ImageLoader::BindingLaziness bindiness
= ImageLoader::kNonLazyOnly
;
1264 if ( (mode
& RTLD_NOW
) != 0 )
1265 bindiness
= ImageLoader::kLazyAndNonLazy
;
1266 dyld::link(image
, bindiness
, ImageLoader::kRunInitializers
);
1267 // only hide exports if image is not already in use
1268 if ( (mode
& RTLD_LOCAL
) != 0 )
1269 image
->setHideExports(true);
1271 // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
1272 // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
1273 // The subtle differences are:
1274 // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
1275 // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
1276 if ( (mode
& RTLD_NODELETE
) != 0 )
1277 image
->setLeaveMapped();
1281 catch (const char* msg
) {
1282 const char* format
= "dlopen(%s, %d): %s";
1283 char temp
[strlen(format
)+strlen(path
)+strlen(msg
)+10];
1284 sprintf(temp
, format
, path
, mode
, msg
);
1290 int dlclose(void* handle
)
1292 if ( dyld::gLogAPIs
)
1293 fprintf(stderr
, "%s(%p)\n", __func__
, handle
);
1295 ImageLoader
* image
= (ImageLoader
*)handle
;
1296 if ( dyld::validImage(image
) ) {
1297 if ( image
->decrementReferenceCount() ) {
1298 // for now, only bundles can be unloaded
1299 // to unload dylibs we would need to track all direct and indirect uses
1300 if ( image
->isBundle() ) {
1301 dyld::removeImage(image
);
1309 dlerrorSet("invalid handle passed to dlclose()");
1316 int dladdr(const void* address
, Dl_info
* info
)
1318 if ( dyld::gLogAPIs
)
1319 fprintf(stderr
, "%s(%p, %p)\n", __func__
, address
, info
);
1321 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1322 if ( image
!= NULL
) {
1323 info
->dli_fname
= image
->getLogicalPath();
1324 info
->dli_fbase
= (void*)image
->machHeader();
1325 // find closest exported symbol in the image
1326 const uint32_t exportCount
= image
->getExportedSymbolCount();
1327 const ImageLoader::Symbol
* bestSym
= NULL
;
1328 const void* bestAddr
= 0;
1329 for(uint32_t i
=0; i
< exportCount
; ++i
) {
1330 const ImageLoader::Symbol
* sym
= image
->getIndexedExportedSymbol(i
);
1331 const void* symAddr
= (void*)image
->getExportedSymbolAddress(sym
);
1332 if ( (symAddr
<= address
) && (bestAddr
< symAddr
) ) {
1337 if ( bestSym
!= NULL
) {
1338 info
->dli_sname
= image
->getExportedSymbolName(bestSym
) + 1; // strip off leading underscore
1339 info
->dli_saddr
= (void*)bestAddr
;
1342 info
->dli_sname
= NULL
;
1343 info
->dli_saddr
= NULL
;
1345 return 1; // success
1347 return 0; // failure
1353 if ( dyld::gLogAPIs
)
1354 fprintf(stderr
, "%s()\n", __func__
);
1356 if ( dyld::gThreadHelpers
!= NULL
) {
1357 char* buffer
= (*dyld::gThreadHelpers
->getThreadBufferFor_dlerror
)(1);
1358 // if no error set, return NULL
1359 if ( buffer
[0] != '\0' )
1365 void* dlsym(void* handle
, const char* symbolName
)
1367 if ( dyld::gLogAPIs
)
1368 fprintf(stderr
, "%s(%p, %s)\n", __func__
, handle
, symbolName
);
1373 const ImageLoader::Symbol
* sym
;
1375 // dlsym() assumes symbolName passed in is same as in C source code
1376 // dyld assumes all symbol names have an underscore prefix
1377 char underscoredName
[strlen(symbolName
)+2];
1378 underscoredName
[0] = '_';
1379 strcpy(&underscoredName
[1], symbolName
);
1381 // magic "search all" handle
1382 if ( handle
== RTLD_DEFAULT
) {
1383 if ( dyld::flatFindExportedSymbol(underscoredName
, &sym
, &image
) ) {
1384 return (void*)image
->getExportedSymbolAddress(sym
);
1386 const char* format
= "dlsym(RTLD_DEFAULT, %s): symbol not found";
1387 char temp
[strlen(format
)+strlen(symbolName
)+2];
1388 sprintf(temp
, format
, symbolName
);
1393 // magic "search what I would see" handle
1394 if ( handle
== RTLD_NEXT
) {
1395 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1396 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1397 sym
= callerImage
->resolveSymbol(underscoredName
, false, &image
);
1398 if ( sym
!= NULL
) {
1399 return (void*)image
->getExportedSymbolAddress(sym
);
1401 const char* format
= "dlsym(RTLD_NEXT, %s): symbol not found";
1402 char temp
[strlen(format
)+strlen(symbolName
)+2];
1403 sprintf(temp
, format
, symbolName
);
1408 // magic "search me, then what I would see" handle
1409 if ( handle
== RTLD_SELF
) {
1410 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1411 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1412 sym
= callerImage
->findExportedSymbol(underscoredName
, NULL
, false, &image
); // search first in calling image
1413 if ( sym
!= NULL
) {
1414 return (void*)image
->getExportedSymbolAddress(sym
);
1416 sym
= callerImage
->resolveSymbol(underscoredName
, false, &image
); // search what calling image links against
1417 if ( sym
!= NULL
) {
1418 return (void*)image
->getExportedSymbolAddress(sym
);
1420 const char* format
= "dlsym(RTLD_SELF, %s): symbol not found";
1421 char temp
[strlen(format
)+strlen(symbolName
)+2];
1422 sprintf(temp
, format
, symbolName
);
1428 image
= (ImageLoader
*)handle
;
1429 if ( dyld::validImage(image
) ) {
1430 ImageLoader
* foundIn
;
1431 sym
= image
->findExportedSymbol(underscoredName
, NULL
, true, &foundIn
);
1432 if ( sym
!= NULL
) {
1433 return (void*)(foundIn
->getExportedSymbolAddress(sym
));
1435 sym
= image
->resolveSymbol(underscoredName
, false, &image
);// search what image links against
1436 if ( sym
!= NULL
) {
1437 return (void*)image
->getExportedSymbolAddress(sym
);
1439 const char* format
= "dlsym(%p, %s): symbol not found";
1440 char temp
[strlen(format
)+strlen(symbolName
)+20];
1441 sprintf(temp
, format
, handle
, symbolName
);
1445 dlerrorSet("invalid handle passed to dlsym()");
1451 #define UPDATE_PREBINDING_DRY_RUN 0x00000001
1452 #define UPDATE_PREBINDING_PROGRESS 0x00000002
1455 // SPI called only by update_prebinding tool to redo prebinding in all prebound files specified
1456 // There must be no dylibs loaded when this fnction is called.
1458 __attribute__((noreturn
))
1459 static void _dyld_update_prebinding(int pathCount
, const char* paths
[], uint32_t flags
)
1461 if ( dyld::gLogAPIs
)
1462 fprintf(stderr
, "%s()\n", __func__
);
1464 // list of requested dylibs actually loaded
1465 std::vector
<ImageLoader
*> preboundImages
;
1468 // verify no dylibs loaded
1469 if ( dyld::getImageCount() != 1 )
1470 throw "_dyld_update_prebinding cannot be called with dylib already loaded";
1472 const uint32_t max_allowed_link_errors
= 10;
1473 uint32_t link_error_count
= 0;
1475 // load and link each dylib
1476 for (int i
=0; i
< pathCount
; ++i
) {
1477 dyld::LoadContext context
;
1478 context
.useSearchPaths
= false;
1479 context
.matchByInstallName
= true;
1480 context
.dontLoad
= false;
1481 context
.mustBeBundle
= false;
1482 context
.mustBeDylib
= true;
1483 context
.origin
= NULL
; // @loader_path not allowed in prebinding list
1484 context
.rpath
= NULL
; // support not yet implemented
1486 ImageLoader
* image
= NULL
;
1488 image
= dyld::load(paths
[i
], context
);
1489 // bind lazy and non-lazy symbols, but don't run initializers
1490 // this may bring in other dylibs later in the list or missing from list, but that is ok
1491 dyld::link(image
, ImageLoader::kLazyAndNonLazy
, ImageLoader::kDontRunInitializers
);
1492 // recored images we successfully loaded
1493 preboundImages
.push_back(image
);
1495 catch (const char* msg
) {
1496 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) ) {
1498 if ( image
== NULL
) // load exception
1500 else // link exception
1502 fprintf(stderr
, "update_prebinding: warning: could not %s %s: %s\n", stage
, paths
[i
], msg
);
1504 if ( image
!= NULL
)
1506 if ( link_error_count
> max_allowed_link_errors
)
1511 // find missing images
1512 uint32_t loadedImageCount
= dyld::getImageCount();
1513 if ( loadedImageCount
> (preboundImages
.size()+1) ) {
1514 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1515 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");
1516 for (uint32_t i
=1; i
< loadedImageCount
; ++i
) {
1517 ImageLoader
* target
= dyld::getIndexedImage(i
);
1519 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1520 if ( *it
== target
) {
1526 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1527 fprintf(stderr
, " %s\n", target
->getPath());
1531 // warn about unprebound files in the list
1532 bool unpreboundWarned
= false;
1533 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1534 if ( ! (*it
)->isPrebindable() && (*it
!= dyld::mainExecutable()) ) {
1535 if ( ! unpreboundWarned
) {
1536 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1537 fprintf(stderr
, "update_prebinding: warning: the following dylibs were specified but were not built prebound\n");
1538 unpreboundWarned
= true;
1540 if ( dyld::gLinkContext
.verbosePrebinding
|| (UPDATE_PREBINDING_DRY_RUN
& flags
) )
1541 fprintf(stderr
, " %s\n", (*it
)->getPath());
1545 if(UPDATE_PREBINDING_DRY_RUN
& flags
) {
1546 fprintf(stderr
, "update_prebinding: dry-run: no changes were made to the filesystem.\n");
1549 uint32_t imageCount
= preboundImages
.size();
1550 uint32_t imageNumber
= 1;
1551 // tell each image to write itself out re-prebound
1552 struct timeval currentTime
= { 0 , 0 };
1553 gettimeofday(¤tTime
, NULL
);
1554 time_t timestamp
= currentTime
.tv_sec
;
1555 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1556 (*it
)->reprebind(dyld::gLinkContext
, timestamp
);
1557 if(UPDATE_PREBINDING_PROGRESS
& flags
) {
1558 fprintf(stdout
, "update_prebinding: progress: %3u/%u\n", imageNumber
, imageCount
);
1564 // tell file system to flush all dirty buffers to disk
1565 // after this sync, all the _redoprebinding files will be on disk
1568 // now commit (swap file) for each re-prebound image
1569 // this only updates directories, since the files have already been flushed by previous sync()
1570 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1571 (*it
)->reprebindCommit(dyld::gLinkContext
, true);
1574 // tell file system to flush all dirty buffers to disk
1575 // this should flush out all directory changes caused by the file swapping
1579 catch (const char* msg
) {
1580 // delete temp files
1582 for (std::vector
<ImageLoader
*>::iterator it
=preboundImages
.begin(); it
!= preboundImages
.end(); it
++) {
1583 (*it
)->reprebindCommit(dyld::gLinkContext
, false);
1586 catch (const char* commitMsg
) {
1587 fprintf(stderr
, "update_prebinding: error: %s\n", commitMsg
);
1589 fprintf(stderr
, "update_prebinding: error: %s\n", msg
);
1597 static const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1599 return &dyld_all_image_infos
;