1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 // This file implements that API's in <mach-o/dyld.h>
30 #define __STDC_LIMIT_MACROS
34 #include <sys/param.h>
35 #include <sys/mount.h>
36 #include <Availability.h>
43 #include <mach/mach.h>
45 #include <sys/sysctl.h>
46 #include <mach/mach_traps.h> // for task_self_trap()
49 #include "mach-o/dyld_images.h"
50 #include "mach-o/dyld.h"
51 #include "mach-o/dyld_priv.h"
53 #include "ImageLoader.h"
54 #include "ImageLoaderMachO.h"
56 #include "dyldLibSystemInterface.h"
58 #undef _POSIX_C_SOURCE
61 // from dyldExceptions.c
62 extern "C" void __Unwind_SjLj_SetThreadKey(pthread_key_t key
);
65 extern void addImagesToAllImages(uint32_t infoCount
, const dyld_image_info info
[]);
66 extern uint32_t allImagesCount();
67 extern const mach_header
* allImagesIndexedMachHeader(uint32_t index
);
68 extern const char* allImagesIndexedPath(uint32_t index
);
71 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
72 #if __IPHONE_OS_VERSION_MIN_REQUIRED
73 #define DEPRECATED_APIS_SUPPORTED 0
75 #define DEPRECATED_APIS_SUPPORTED 1
78 static bool sDynamicInterposing
= false;
80 #if DEPRECATED_APIS_SUPPORTED
81 static char sLastErrorFilePath
[1024];
82 static NSLinkEditErrors sLastErrorFileCode
;
83 static int sLastErrorNo
;
86 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
87 // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
88 // This conditional keeps support for old libSystem's which needed some help implementing the API's
89 #define OLD_LIBSYSTEM_SUPPORT (__i386__)
91 // The following functions have no prototype in any header. They are special cases
92 // where _dyld_func_lookup() is used directly.
93 static void _dyld_make_delayed_module_initializer_calls();
94 static void registerThreadHelpers(const dyld::LibSystemHelpers
*);
95 #if DEPRECATED_APIS_SUPPORTED
96 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
);
97 #if OLD_LIBSYSTEM_SUPPORT
98 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
);
100 static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions
);
101 static bool NSMakePrivateModulePublic(NSModule
module);
102 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
);
104 // The following functions are dyld API's, but since dyld links with a static copy of libc.a
105 // the public name cannot be used.
106 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module);
107 static bool client_NSIsSymbolNameDefined(const char* symbolName
);
108 #endif // DEPRECATED_APIS_SUPPORTED
109 #if SUPPORT_ZERO_COST_EXCEPTIONS
110 static bool client_dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
);
112 #if DEPRECATED_APIS_SUPPORTED
115 static void unimplemented()
117 dyld::halt("unimplemented dyld function\n");
122 void* implementation
;
125 static struct dyld_func dyld_funcs
[] = {
126 {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image
},
127 {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image
},
128 {"__dyld_dladdr", (void*)dladdr
},
129 {"__dyld_dlclose", (void*)dlclose
},
130 {"__dyld_dlerror", (void*)dlerror
},
131 {"__dyld_dlopen", (void*)dlopen
},
132 {"__dyld_dlsym", (void*)dlsym
},
133 {"__dyld_dlopen_preflight", (void*)dlopen_preflight
},
134 {"__dyld_image_count", (void*)_dyld_image_count
},
135 {"__dyld_get_image_header", (void*)_dyld_get_image_header
},
136 {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide
},
137 {"__dyld_get_image_name", (void*)_dyld_get_image_name
},
138 {"__dyld_get_image_slide", (void*)_dyld_get_image_slide
},
139 {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath
},
142 {"__dyld_register_thread_helpers", (void*)registerThreadHelpers
},
143 {"__dyld_fork_child", (void*)_dyld_fork_child
},
144 {"__dyld_make_delayed_module_initializer_calls", (void*)_dyld_make_delayed_module_initializer_calls
},
145 {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos
},
146 #if SUPPORT_ZERO_COST_EXCEPTIONS
147 {"__dyld_find_unwind_sections", (void*)client_dyld_find_unwind_sections
},
149 #if __i386__ || __x86_64__ || __arm__ || __arm64__
150 {"__dyld_fast_stub_entry", (void*)dyld::fastBindLazySymbol
},
152 {"__dyld_image_path_containing_address", (void*)dyld_image_path_containing_address
},
153 {"__dyld_shared_cache_some_image_overridden", (void*)dyld_shared_cache_some_image_overridden
},
154 {"__dyld_process_is_restricted", (void*)dyld::processIsRestricted
},
155 {"__dyld_dynamic_interpose", (void*)dyld_dynamic_interpose
},
156 #if DYLD_SHARED_CACHE_SUPPORT
157 {"__dyld_shared_cache_file_path", (void*)dyld::getStandardSharedCacheFilePath
},
159 {"__dyld_get_image_header_containing_address", (void*)dyld_image_header_containing_address
},
160 {"__dyld_is_memory_immutable", (void*)_dyld_is_memory_immutable
},
161 {"__dyld_objc_notify_register", (void*)_dyld_objc_notify_register
},
162 {"__dyld_get_shared_cache_uuid", (void*)_dyld_get_shared_cache_uuid
},
166 #if DEPRECATED_APIS_SUPPORTED
167 {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind
},
168 {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint
},
169 {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully
},
170 {"__dyld_install_handlers", (void*)_dyld_install_handlers
},
171 {"__dyld_link_edit_error", (void*)NSLinkEditError
},
172 {"__dyld_unlink_module", (void*)NSUnLinkModule
},
173 {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module
},
174 {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address
},
175 {"__dyld_image_containing_address", (void*)_dyld_image_containing_address
},
176 {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler
},
177 {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol
},
178 {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol
},
179 {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol
},
180 {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol
},
181 {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint
},
182 {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule
},
183 {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage
},
184 {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic
},
185 {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined
},
186 {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint
},
187 {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage
},
188 {"__dyld_NSNameOfModule", (void*)NSNameOfModule
},
189 {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule
},
190 {"__dyld_NSAddLibrary", (void*)NSAddLibrary
},
191 {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching
},
192 {"__dyld_NSAddImage", (void*)NSAddImage
},
193 {"__dyld_launched_prebound", (void*)_dyld_launched_prebound
},
194 {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound
},
195 {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib
},
196 {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile
},
197 {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory
},
198 {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage
},
199 {"__dyld_NSLinkModule", (void*)NSLinkModule
},
200 {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage
},
201 {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage
},
202 {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage
},
203 {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage
},
204 {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage
},
205 {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage
},
206 {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage
},
207 #if OLD_LIBSYSTEM_SUPPORT
208 {"__dyld_link_module", (void*)_dyld_link_module
},
210 #endif //DEPRECATED_APIS_SUPPORTED
217 #if DEPRECATED_APIS_SUPPORTED
219 static void dyldAPIhalt(const char* apiName
, const char* errorMsg
)
221 dyld::log("dyld: %s() error\n", apiName
);
222 dyld::halt(errorMsg
);
225 // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
226 inline NSSymbol
SymbolToNSSymbol(const ImageLoader::Symbol
* sym
)
228 return (NSSymbol
)sym
;
230 inline const ImageLoader::Symbol
* NSSymbolToSymbol(NSSymbol sym
)
232 return (const ImageLoader::Symbol
*)sym
;
235 // dyld's abstract type NSModule is implemented as ImageLoader*
236 inline NSModule
ImageLoaderToNSModule(const ImageLoader
* image
)
238 return (NSModule
)image
;
240 inline ImageLoader
* NSModuleToImageLoader(NSModule
module)
242 ImageLoader
* image
= (ImageLoader
*)module;
243 if ( dyld::validImage(image
) )
248 // actual definition for opaque type
249 struct __NSObjectFileImage
252 const void* imageBaseAddress
; // not used with OFI created from files
253 size_t imageLength
; // not used with OFI created from files
257 VECTOR_NEVER_DESTRUCTED(NSObjectFileImage
);
258 static std::vector
<NSObjectFileImage
> sObjectFileImages
;
263 // __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
264 // The contained image is delete in one of two places:
265 // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
266 // NSDestroyObjectFileImage deletes the image if image is not in list of valid images
271 static void setLastError(NSLinkEditErrors code
, int errnum
, const char* file
, const char* message
)
273 dyld::setErrorMessage(message
);
274 strncpy(sLastErrorFilePath
, file
, 1024);
275 sLastErrorFilePath
[1023] = '\0';
276 sLastErrorFileCode
= code
;
277 sLastErrorNo
= errnum
;
280 #endif // DEPRECATED_APIS_SUPPORTED
283 *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
284 * copies the path of the executable into the buffer and returns 0 if the path
285 * was successfully copied in the provided buffer. If the buffer is not large
286 * enough, -1 is returned and the expected buffer size is copied in *bufsize.
287 * Note that _NSGetExecutablePath will return "a path" to the executable not a
288 * "real path" to the executable. That is the path may be a symbolic link and
289 * not the real file. And with deep directories the total bufsize needed could
290 * be more than MAXPATHLEN.
292 int _NSGetExecutablePath(char* buf
, uint32_t *bufsize
)
294 if ( dyld::gLogAPIs
)
295 dyld::log("%s(...)\n", __func__
);
296 const char* exePath
= dyld::getExecutablePath();
297 if(*bufsize
< strlen(exePath
) + 1){
298 *bufsize
= (uint32_t)(strlen(exePath
) + 1);
301 strcpy(buf
, exePath
);
305 uint32_t _dyld_image_count(void)
307 if ( dyld::gLogAPIs
)
308 dyld::log("%s()\n", __func__
);
309 return allImagesCount();
312 const struct mach_header
* _dyld_get_image_header(uint32_t image_index
)
314 if ( dyld::gLogAPIs
)
315 dyld::log("%s(%u)\n", __func__
, image_index
);
316 return allImagesIndexedMachHeader(image_index
);
319 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index
)
321 if ( dyld::gLogAPIs
)
322 dyld::log("%s(%u)\n", __func__
, image_index
);
323 const struct mach_header
* mh
= allImagesIndexedMachHeader(image_index
);
325 return ImageLoaderMachO::computeSlide(mh
);
330 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
)
332 if ( dyld::gLogAPIs
)
333 dyld::log("%s(%p)\n", __func__
, mh
);
334 return ImageLoaderMachO::computeSlide(mh
);
338 const char* _dyld_get_image_name(uint32_t image_index
)
340 if ( dyld::gLogAPIs
)
341 dyld::log("%s(%u)\n", __func__
, image_index
);
342 return allImagesIndexedPath(image_index
);
345 const struct mach_header
* dyld_image_header_containing_address(const void* address
)
347 if ( dyld::gLogAPIs
)
348 dyld::log("%s(%p)\n", __func__
, address
);
349 #if SUPPORT_ACCELERATE_TABLES
350 const mach_header
* mh
;
352 if ( dyld::addressInCache(address
, &mh
, &path
) )
355 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
357 return image
->machHeader();
362 void _dyld_register_func_for_add_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
364 if ( dyld::gLogAPIs
)
365 dyld::log("%s(%p)\n", __func__
, (void *)func
);
366 dyld::registerAddCallback(func
);
369 void _dyld_register_func_for_remove_image(void (*func
)(const struct mach_header
*mh
, intptr_t vmaddr_slide
))
371 if ( dyld::gLogAPIs
)
372 dyld::log("%s(%p)\n", __func__
, (void *)func
);
373 dyld::registerRemoveCallback(func
);
378 // called by crt before main() by programs linked with 10.4 or earlier crt1.o
379 static void _dyld_make_delayed_module_initializer_calls()
381 if ( dyld::gLogAPIs
)
382 dyld::log("%s()\n", __func__
);
384 #if SUPPORT_OLD_CRT_INITIALIZATION
385 if ( dyld::gRunInitializersOldWay
)
386 dyld::initializeMainExecutable();
392 #if DEPRECATED_APIS_SUPPORTED
395 // _dyld_call_module_initializers_for_dylib() is the dyld side of
396 // __initialize_Cplusplus() which is in dylib1.o.
397 // It is intended to only be called inside -init rouintes.
398 // -init routines are called before module initializers (what C++
399 // initializers use). Calling __initialize_Cplusplus() in a -init
400 // routine causes the module initializers for an image to be called
401 // which then allows C++ to be used inside a -init routine
403 static void _dyld_call_module_initializers_for_dylib(const struct mach_header
* mh_dylib_header
)
405 if ( dyld::gLogAPIs
)
406 dyld::log("__initialize_Cplusplus()\n");
408 // for now, do nothing...
412 void _dyld_lookup_and_bind_fully(const char* symbolName
, void** address
, NSModule
* module)
414 if ( dyld::gLogAPIs
)
415 dyld::log("%s(\"%s\", %p, %p)\n", __func__
, symbolName
, address
, module);
417 const ImageLoader::Symbol
* sym
;
418 dyld::clearErrorMessage();
419 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, (const ImageLoader
**)&image
) ) {
421 image
->bindAllLazyPointers(dyld::gLinkContext
, true);
422 if ( address
!= NULL
)
423 *address
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
);
425 *module = ImageLoaderToNSModule(image
);
427 catch (const char* msg
) {
428 dyldAPIhalt(__func__
, msg
);
432 // on failure to find symbol return NULLs
433 if ( address
!= NULL
)
440 // Note: This cannot have public name because dyld is built with a static copy of libc.a
441 // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
442 static void client_dyld_lookup_and_bind(const char* symbolName
, void** address
, NSModule
* module)
444 if ( dyld::gLogAPIs
)
445 dyld::log("_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName
, address
, module);
446 const ImageLoader
* image
;
447 const ImageLoader::Symbol
* sym
;
448 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
449 if ( address
!= NULL
)
450 *address
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
);
452 *module = ImageLoaderToNSModule(image
);
455 // on failure to find symbol return NULLs
456 if ( address
!= NULL
)
463 void _dyld_lookup_and_bind_with_hint(const char* symbolName
, const char* library_name_hint
, void** address
, NSModule
* module)
465 if ( dyld::gLogAPIs
)
466 dyld::log("%s(\"%s\", \"%s\", %p, %p)\n", __func__
, symbolName
, library_name_hint
, address
, module);
467 const ImageLoader
* image
;
468 const ImageLoader::Symbol
* sym
;
469 // Look for library whose path contains the hint. If that fails search everywhere
470 if ( dyld::flatFindExportedSymbolWithHint(symbolName
, library_name_hint
, &sym
, &image
)
471 || dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
472 if ( address
!= NULL
)
473 *address
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
);
475 *module = ImageLoaderToNSModule(image
);
478 // on failure to find symbol return NULLs
479 if ( address
!= NULL
)
487 NSSymbol
NSLookupAndBindSymbol(const char *symbolName
)
489 if ( dyld::gLogAPIs
)
490 dyld::log("%s(\"%s\")\n", __func__
, symbolName
);
491 const ImageLoader
* image
;
492 const ImageLoader::Symbol
* sym
;
493 if ( dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
) ) {
494 return SymbolToNSSymbol(sym
);
496 // return NULL on failure
500 NSSymbol
NSLookupAndBindSymbolWithHint(const char* symbolName
, const char* libraryNameHint
)
502 if ( dyld::gLogAPIs
)
503 dyld::log("%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
504 const ImageLoader
* image
;
505 const ImageLoader::Symbol
* sym
;
506 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
508 // hint failed, do slow search of all images
509 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
512 return SymbolToNSSymbol(sym
);
514 // return NULL on failure and log
515 if ( dyld::gLogAPIs
)
516 dyld::log("%s(\"%s\", \"%s\") => NULL \n", __func__
, symbolName
, libraryNameHint
);
523 static __attribute__((noinline
))
524 const struct mach_header
* addImage(void* callerAddress
, const char* path
, bool search
, bool dontLoad
, bool matchInstallName
, bool abortOnError
)
526 ImageLoader
* image
= NULL
;
527 std::vector
<const char*> rpathsFromCallerImage
;
529 dyld::clearErrorMessage();
530 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
531 // like dlopen, use rpath from caller image and from main executable
532 if ( callerImage
!= NULL
)
533 callerImage
->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
534 ImageLoader::RPathChain
callersRPaths(NULL
, &rpathsFromCallerImage
);
535 if ( callerImage
!= dyld::mainExecutable() ) {
536 dyld::mainExecutable()->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
538 dyld::LoadContext context
;
539 context
.useSearchPaths
= search
;
540 context
.useFallbackPaths
= search
;
541 context
.useLdLibraryPath
= false;
542 context
.implicitRPath
= false;
543 context
.matchByInstallName
= matchInstallName
;
544 context
.dontLoad
= dontLoad
;
545 context
.mustBeBundle
= false;
546 context
.mustBeDylib
= true;
547 context
.canBePIE
= false;
548 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
549 context
.rpath
= &callersRPaths
; // rpaths from caller and main executable
552 image
= load(path
, context
, cacheIndex
);
553 if ( image
!= NULL
) {
554 if ( context
.matchByInstallName
)
555 image
->setMatchInstallPath(true);
556 dyld::link(image
, false, false, callersRPaths
, cacheIndex
);
557 dyld::runInitializers(image
);
558 // images added with NSAddImage() can never be unloaded
559 image
->setNeverUnload();
562 catch (const char* msg
) {
563 dyld::garbageCollectImages();
565 char pathMsg
[strlen(msg
)+strlen(path
)+4];
566 strcpy(pathMsg
, msg
);
567 strcat(pathMsg
, " ");
568 strcat(pathMsg
, path
);
569 dyldAPIhalt("NSAddImage", pathMsg
);
571 // not halting, so set error state for NSLinkEditError to find
572 setLastError(NSLinkEditOtherError
, 0, path
, msg
);
573 free((void*)msg
); // our free() will do nothing if msg is a string literal
576 // free rpaths (getRPaths() malloc'ed each string)
577 for(std::vector
<const char*>::iterator it
=rpathsFromCallerImage
.begin(); it
!= rpathsFromCallerImage
.end(); ++it
) {
578 const char* str
= *it
;
584 return image
->machHeader();
588 const struct mach_header
* NSAddImage(const char* path
, uint32_t options
)
590 if ( dyld::gLogAPIs
)
591 dyld::log("%s(\"%s\", 0x%08X)\n", __func__
, path
, options
);
592 const bool dontLoad
= ( (options
& NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
) != 0 );
593 const bool search
= ( (options
& NSADDIMAGE_OPTION_WITH_SEARCHING
) != 0 );
594 const bool matchInstallName
= ( (options
& NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
) != 0 );
595 const bool abortOnError
= ( (options
& (NSADDIMAGE_OPTION_RETURN_ON_ERROR
|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
)) == 0 );
596 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
597 return addImage(callerAddress
, path
, search
, dontLoad
, matchInstallName
, abortOnError
);
600 bool NSAddLibrary(const char* path
)
602 if ( dyld::gLogAPIs
)
603 dyld::log("%s(\"%s\")\n", __func__
, path
);
604 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
605 return (addImage(callerAddress
, path
, false, false, false, false) != NULL
);
608 bool NSAddLibraryWithSearching(const char* path
)
610 if ( dyld::gLogAPIs
)
611 dyld::log("%s(\"%s\")\n", __func__
, path
);
612 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
613 return (addImage(callerAddress
, path
, true, false, false, false) != NULL
);
618 //#define NSADDIMAGE_OPTION_NONE 0x0
619 //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
620 //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
622 bool NSIsSymbolNameDefinedInImage(const struct mach_header
* mh
, const char* symbolName
)
624 if ( dyld::gLogAPIs
)
625 dyld::log("%s(%p, \"%s\")\n", __func__
, (void *)mh
, symbolName
);
626 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
627 if ( image
!= NULL
) {
628 if ( image
->findExportedSymbol(symbolName
, true, NULL
) != NULL
)
635 NSSymbol
NSLookupSymbolInImage(const struct mach_header
* mh
, const char* symbolName
, uint32_t options
)
637 if ( dyld::gLogAPIs
)
638 dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__
, mh
, symbolName
, options
);
639 const ImageLoader::Symbol
* symbol
= NULL
;
640 dyld::clearErrorMessage();
641 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
642 if ( image
!= NULL
) {
644 if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
) {
645 image
->bindAllLazyPointers(dyld::gLinkContext
, true);
647 else if ( options
& NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
) {
648 image
->bindAllLazyPointers(dyld::gLinkContext
, false);
651 catch (const char* msg
) {
652 if ( (options
& NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
) == 0 ) {
653 dyldAPIhalt(__func__
, msg
);
656 symbol
= image
->findExportedSymbol(symbolName
, true, NULL
);
658 if ( dyld::gLogAPIs
&& (symbol
== NULL
) )
659 dyld::log("%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__
, mh
, symbolName
, options
);
660 return SymbolToNSSymbol(symbol
);
664 // Note: This cannot have public name because dyld is built with a static copy of libc.a
665 // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
666 static bool client_NSIsSymbolNameDefined(const char* symbolName
)
668 if ( dyld::gLogAPIs
)
669 dyld::log("NSIsSymbolNameDefined(\"%s\")\n", symbolName
);
670 const ImageLoader
* image
;
671 const ImageLoader::Symbol
* sym
;
672 return dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
675 bool NSIsSymbolNameDefinedWithHint(const char* symbolName
, const char* libraryNameHint
)
677 if ( dyld::gLogAPIs
)
678 dyld::log("%s(\"%s\", \"%s\")\n", __func__
, symbolName
, libraryNameHint
);
679 const ImageLoader
* image
;
680 const ImageLoader::Symbol
* sym
;
681 bool found
= dyld::flatFindExportedSymbolWithHint(symbolName
, libraryNameHint
, &sym
, &image
);
683 // hint failed, do slow search of all images
684 found
= dyld::flatFindExportedSymbol(symbolName
, &sym
, &image
);
686 if ( !found
&& dyld::gLogAPIs
)
687 dyld::log("%s(\"%s\", \"%s\") => false \n", __func__
, symbolName
, libraryNameHint
);
691 const char* NSNameOfSymbol(NSSymbol symbol
)
693 if ( dyld::gLogAPIs
)
694 dyld::log("%s(%p)\n", __func__
, (void *)symbol
);
695 const char* result
= NULL
;
696 ImageLoader
* image
= dyld::findImageContainingSymbol(symbol
);
698 result
= image
->getExportedSymbolName(NSSymbolToSymbol(symbol
));
702 void* NSAddressOfSymbol(NSSymbol symbol
)
704 if ( dyld::gLogAPIs
)
705 dyld::log("%s(%p)\n", __func__
, (void *)symbol
);
706 if ( symbol
== NULL
)
709 ImageLoader
* image
= dyld::findImageContainingSymbol(symbol
);
711 result
= (void*)image
->getExportedSymbolAddress(NSSymbolToSymbol(symbol
), dyld::gLinkContext
);
715 NSModule
NSModuleForSymbol(NSSymbol symbol
)
717 if ( dyld::gLogAPIs
)
718 dyld::log("%s(%p)\n", __func__
, (void *)symbol
);
719 NSModule result
= NULL
;
720 ImageLoader
* image
= dyld::findImageContainingSymbol(symbol
);
722 result
= ImageLoaderToNSModule(image
);
729 bool _dyld_all_twolevel_modules_prebound(void)
731 if ( dyld::gLogAPIs
)
732 dyld::log("%s()\n", __func__
);
736 void _dyld_bind_objc_module(const void *objc_module
)
738 if ( dyld::gLogAPIs
)
739 dyld::log("%s(%p)\n", __func__
, objc_module
);
740 // do nothing, with new dyld everything already bound
744 bool _dyld_bind_fully_image_containing_address(const void* address
)
746 if ( dyld::gLogAPIs
)
747 dyld::log("%s(%p)\n", __func__
, address
);
748 dyld::clearErrorMessage();
749 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
750 if ( image
!= NULL
) {
752 image
->bindAllLazyPointers(dyld::gLinkContext
, true);
755 catch (const char* msg
) {
756 dyldAPIhalt(__func__
, msg
);
762 bool _dyld_image_containing_address(const void* address
)
764 if ( dyld::gLogAPIs
)
765 dyld::log("%s(%p)\n", __func__
, address
);
766 ImageLoader
*imageLoader
= dyld::findImageContainingAddress(address
);
767 return (NULL
!= imageLoader
);
770 static NSObjectFileImage
createObjectImageFile(ImageLoader
* image
, const void* address
= NULL
, size_t len
=0)
772 NSObjectFileImage result
= new __NSObjectFileImage();
773 result
->image
= image
;
774 result
->imageBaseAddress
= address
;
775 result
->imageLength
= len
;
776 sObjectFileImages
.push_back(result
);
780 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromFile(const char* pathName
, NSObjectFileImage
*objectFileImage
)
782 if ( dyld::gLogAPIs
)
783 dyld::log("%s(\"%s\", ...)\n", __func__
, pathName
);
785 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
786 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
788 dyld::LoadContext context
;
789 context
.useSearchPaths
= false;
790 context
.useFallbackPaths
= false;
791 context
.useLdLibraryPath
= false;
792 context
.implicitRPath
= false;
793 context
.matchByInstallName
= false;
794 context
.dontLoad
= false;
795 context
.mustBeBundle
= true;
796 context
.mustBeDylib
= false;
797 context
.canBePIE
= false;
798 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
799 context
.rpath
= NULL
; // support not yet implemented
802 ImageLoader
* image
= dyld::load(pathName
, context
, cacheIndex
);
803 // Note: We DO NOT link the image! NSLinkModule will do that
804 if ( image
!= NULL
) {
805 if ( !image
->isBundle() ) {
806 // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
807 return NSObjectFileImageInappropriateFile
;
809 *objectFileImage
= createObjectImageFile(image
);
810 return NSObjectFileImageSuccess
;
813 catch (const char* msg
) {
814 //dyld::log("dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
815 dyld::garbageCollectImages();
817 return NSObjectFileImageInappropriateFile
;
819 return NSObjectFileImageFailure
;
823 NSObjectFileImageReturnCode
NSCreateObjectFileImageFromMemory(const void* address
, size_t size
, NSObjectFileImage
*objectFileImage
)
825 if ( dyld::gLogAPIs
)
826 dyld::log("%s(%p, %lu, %p)\n", __func__
, address
, size
, objectFileImage
);
829 ImageLoader
* image
= dyld::loadFromMemory((const uint8_t*)address
, size
, NULL
);
830 if ( ! image
->isBundle() ) {
831 // this API can only be used with bundles...
832 dyld::garbageCollectImages();
833 return NSObjectFileImageInappropriateFile
;
835 // Note: We DO NOT link the image! NSLinkModule will do that
836 if ( image
!= NULL
) {
837 *objectFileImage
= createObjectImageFile(image
, address
, size
);
838 return NSObjectFileImageSuccess
;
841 catch (const char* msg
) {
843 dyld::garbageCollectImages();
844 //dyld::log("dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg);
846 return NSObjectFileImageFailure
;
849 static bool validOFI(NSObjectFileImage objectFileImage
)
851 const int ofiCount
= sObjectFileImages
.size();
852 for (int i
=0; i
< ofiCount
; ++i
) {
853 if ( sObjectFileImages
[i
] == objectFileImage
)
859 bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage
)
861 if ( dyld::gLogAPIs
)
862 dyld::log("%s(%p)\n", __func__
, objectFileImage
);
864 if ( validOFI(objectFileImage
) ) {
865 // a failure during NSLinkModule will delete the image
866 if ( objectFileImage
->image
!= NULL
) {
867 // if the image has never been linked or has been unlinked, the image is not in the list of valid images
868 // and we should delete it
869 bool linkedImage
= dyld::validImage(objectFileImage
->image
);
870 if ( ! linkedImage
) {
871 ImageLoader::deleteImage(objectFileImage
->image
);
872 objectFileImage
->image
= NULL
;
876 // remove from list of ofi's
877 for (std::vector
<NSObjectFileImage
>::iterator it
=sObjectFileImages
.begin(); it
!= sObjectFileImages
.end(); it
++) {
878 if ( *it
== objectFileImage
) {
879 sObjectFileImages
.erase(it
);
884 // if object was created from a memory, release that memory
885 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
886 if ( objectFileImage
->imageBaseAddress
!= NULL
) {
888 if ( (dyld::gLibSystemHelpers
!= NULL
) && (dyld::gLibSystemHelpers
->version
>= 6) ) {
889 size_t sz
= (*dyld::gLibSystemHelpers
->malloc_size
)(objectFileImage
->imageBaseAddress
);
891 (*dyld::gLibSystemHelpers
->free
)((void*)(objectFileImage
->imageBaseAddress
));
896 vm_deallocate(mach_task_self(), (vm_address_t
)objectFileImage
->imageBaseAddress
, objectFileImage
->imageLength
);
900 delete objectFileImage
;
907 bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage
)
909 if ( dyld::gLogAPIs
)
910 dyld::log("%s(%p)\n", __func__
, objectFileImage
);
911 return objectFileImage
->image
->needsInitialization();
914 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage
)
916 if ( dyld::gLogAPIs
)
917 dyld::log("%s(%p)\n", __func__
, objectFileImage
);
918 return objectFileImage
->image
->getExportedSymbolCount();
921 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
)
923 if ( dyld::gLogAPIs
)
924 dyld::log("%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
925 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedExportedSymbol(ordinal
);
926 return objectFileImage
->image
->getExportedSymbolName(sym
);
929 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage
)
931 if ( dyld::gLogAPIs
)
932 dyld::log("%s(%p)\n", __func__
, objectFileImage
);
933 return objectFileImage
->image
->getImportedSymbolCount();
936 const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage
, uint32_t ordinal
,
937 bool* tentative_definition
)
939 if ( dyld::gLogAPIs
)
940 dyld::log("%s(%p,%d)\n", __func__
, objectFileImage
, ordinal
);
941 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->getIndexedImportedSymbol(ordinal
);
942 if ( tentative_definition
!= NULL
) {
943 ImageLoader::ReferenceFlags flags
= objectFileImage
->image
->getImportedSymbolInfo(sym
);
944 if ( (flags
& ImageLoader::kTentativeDefinition
) != 0 )
945 *tentative_definition
= true;
947 *tentative_definition
= false;
949 return objectFileImage
->image
->getImportedSymbolName(sym
);
952 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage
,
953 const char* segmentName
, const char* sectionName
, unsigned long* size
)
955 if ( dyld::gLogAPIs
)
956 dyld::log("%s(%p,%s, %s)\n", __func__
, objectFileImage
, segmentName
, sectionName
);
960 if ( objectFileImage
->image
->getSectionContent(segmentName
, sectionName
, &start
, &length
) ) {
970 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage
, const char* symbolName
)
972 if ( dyld::gLogAPIs
)
973 dyld::log("%s(%p,%s)\n", __func__
, objectFileImage
, symbolName
);
974 const ImageLoader::Symbol
* sym
= objectFileImage
->image
->findExportedSymbol(symbolName
, true, NULL
);
975 return ( sym
!= NULL
);
980 NSModule
NSLinkModule(NSObjectFileImage objectFileImage
, const char* moduleName
, uint32_t options
)
982 if ( dyld::gLogAPIs
)
983 dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__
, objectFileImage
, moduleName
, options
);
985 dyld::clearErrorMessage();
987 if ( (options
& NSLINKMODULE_OPTION_CAN_UNLOAD
) != 0 )
988 objectFileImage
->image
->setCanUnload();
990 // NSLinkModule allows a bundle to be link multpile times
991 // each link causes the bundle to be copied to a new address
992 if ( objectFileImage
->image
->isLinked() ) {
993 // already linked, so clone a new one and link it
994 objectFileImage
->image
= dyld::cloneImage(objectFileImage
->image
);
997 // for memory based images, set moduleName as the name anyone calling _dyld_get_image_name() will see
998 if ( objectFileImage
->image
->getPath() == NULL
) {
999 objectFileImage
->image
->setPath(moduleName
);
1000 // <rdar://problem/8812589> dyld has NULL paths in image info array
1001 dyld_image_info info
;
1002 info
.imageLoadAddress
= objectFileImage
->image
->machHeader();
1003 info
.imageFilePath
= moduleName
;
1004 info
.imageFileModDate
= 0;
1005 addImagesToAllImages(1, &info
);
1008 // support private bundles
1009 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
1010 objectFileImage
->image
->setHideExports();
1012 // set up linking options
1013 bool forceLazysBound
= ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 );
1015 // load libraries, rebase, bind, to make this image usable
1016 dyld::link(objectFileImage
->image
, forceLazysBound
, false, ImageLoader::RPathChain(NULL
,NULL
), UINT32_MAX
);
1018 // bump reference count to keep this bundle from being garbage collected
1019 objectFileImage
->image
->incrementDlopenReferenceCount();
1021 // run initializers unless magic flag says not to
1022 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) == 0 )
1023 dyld::runInitializers(objectFileImage
->image
);
1025 return ImageLoaderToNSModule(objectFileImage
->image
);
1027 catch (const char* msg
) {
1028 dyld::garbageCollectImages();
1029 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
1030 dyldAPIhalt(__func__
, msg
);
1031 // not halting, so set error state for NSLinkEditError to find
1032 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
1033 // dyld::link() deleted the image so lose our reference
1034 objectFileImage
->image
= NULL
;
1041 #if OLD_LIBSYSTEM_SUPPORT
1042 // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
1043 static NSModule
_dyld_link_module(NSObjectFileImage object_addr
, size_t object_size
, const char* moduleName
, uint32_t options
)
1045 if ( dyld::gLogAPIs
)
1046 dyld::log("%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr
, moduleName
, options
); // note name/args translation
1047 ImageLoader
* image
= NULL
;
1048 dyld::clearErrorMessage();
1050 const char* imageName
= moduleName
;
1051 image
= dyld::loadFromMemory((const uint8_t*)object_addr
, object_size
, imageName
);
1053 if ( image
!= NULL
) {
1054 // support private bundles
1055 if ( (options
& NSLINKMODULE_OPTION_PRIVATE
) != 0 )
1056 image
->setHideExports();
1058 // set up linking options
1059 bool forceLazysBound
= ( (options
& NSLINKMODULE_OPTION_BINDNOW
) != 0 );
1061 // load libraries, rebase, bind, to make this image usable
1062 dyld::link(image
, forceLazysBound
, false, ImageLoader::RPathChain(NULL
,NULL
), UINT32_MAX
);
1064 // run initializers unless magic flag says not to
1065 if ( (options
& NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
) == 0 )
1066 dyld::runInitializers(image
);
1069 catch (const char* msg
) {
1070 if ( (options
& NSLINKMODULE_OPTION_RETURN_ON_ERROR
) == 0 )
1071 dyldAPIhalt("NSLinkModule", msg
);
1072 // not halting, so set error state for NSLinkEditError to find
1073 setLastError(NSLinkEditOtherError
, 0, moduleName
, msg
);
1074 // if image was created for this bundle, destroy it
1075 if ( image
!= NULL
) {
1076 dyld::removeImage(image
);
1077 ImageLoader::deleteImage(image
);
1082 return ImageLoaderToNSModule(image
);
1086 NSSymbol
NSLookupSymbolInModule(NSModule
module, const char* symbolName
)
1088 if ( dyld::gLogAPIs
)
1089 dyld::log("%s(%p, \"%s\")\n", __func__
, (void *)module, symbolName
);
1090 ImageLoader
* image
= NSModuleToImageLoader(module);
1091 if ( image
== NULL
)
1093 return SymbolToNSSymbol(image
->findExportedSymbol(symbolName
, false, NULL
));
1096 const char* NSNameOfModule(NSModule
module)
1098 if ( dyld::gLogAPIs
)
1099 dyld::log("%s(%p)\n", __func__
, module);
1100 ImageLoader
* image
= NSModuleToImageLoader(module);
1101 if ( image
== NULL
)
1103 return image
->getPath();
1106 const char* NSLibraryNameForModule(NSModule
module)
1108 if ( dyld::gLogAPIs
)
1109 dyld::log("%s(%p)\n", __func__
, module);
1110 ImageLoader
* image
= NSModuleToImageLoader(module);
1111 if ( image
== NULL
)
1113 return image
->getPath();
1116 bool NSUnLinkModule(NSModule
module, uint32_t options
)
1118 if ( dyld::gLogAPIs
)
1119 dyld::log("%s(%p, 0x%08X)\n", __func__
, module, options
);
1120 if ( module == NULL
)
1122 ImageLoader
* image
= NSModuleToImageLoader(module);
1123 if ( image
== NULL
)
1125 dyld::runImageStaticTerminators(image
);
1126 if ( (dyld::gLibSystemHelpers
!= NULL
) && (dyld::gLibSystemHelpers
->version
>= 13) ) {
1127 __cxa_range_t ranges
[image
->segmentCount()];
1129 for (unsigned int j
=0; j
< image
->segmentCount(); ++j
) {
1130 if ( !image
->segExecutable(j
) )
1132 ranges
[rangeCount
].addr
= (const void*)image
->segActualLoadAddress(j
);
1133 ranges
[rangeCount
].length
= image
->segSize(j
);
1136 (*dyld::gLibSystemHelpers
->cxa_finalize_ranges
)(ranges
, rangeCount
);
1138 dyld::removeImage(image
);
1140 if ( (options
& NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
) != 0 )
1141 image
->setLeaveMapped();
1143 // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1145 // Only delete image if there is no ofi referencing it
1146 // That means the ofi was destroyed after linking, so no one is left to delete this image
1147 const int ofiCount
= sObjectFileImages
.size();
1149 for (int i
=0; i
< ofiCount
; ++i
) {
1150 NSObjectFileImage ofi
= sObjectFileImages
[i
];
1151 if ( ofi
->image
== image
)
1155 ImageLoader::deleteImage(image
);
1160 // internal name and parameters do not match public name and parameters...
1161 static void _dyld_install_handlers(void* undefined
, void* multiple
, void* linkEdit
)
1163 if ( dyld::gLogAPIs
)
1164 dyld::log("NSLinkEditErrorHandlers()\n");
1166 dyld::registerUndefinedHandler((dyld::UndefinedHandler
)undefined
);
1167 // no support for multiple or linkedit handlers
1173 void NSLinkEditError(NSLinkEditErrors
* c
, int* errorNumber
, const char** fileName
, const char** errorString
)
1176 *c
= sLastErrorFileCode
;
1177 *errorNumber
= sLastErrorNo
;
1178 *fileName
= sLastErrorFilePath
;
1179 *errorString
= dyld::getErrorMessage();
1184 static void _dyld_register_binding_handler(void * (*bindingHandler
)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions
)
1186 if ( dyld::gLogAPIs
)
1187 dyld::log("%s()\n", __func__
);
1188 dyld::gLinkContext
.bindingHandler
= bindingHandler
;
1189 dyld::gLinkContext
.bindingOptions
= bindingOptions
;
1192 #endif //DEPRECATED_APIS_SUPPORTED
1195 // Call by fork() in libSystem after the kernel trap is done on the child side
1196 void _dyld_fork_child()
1198 if ( dyld::gLogAPIs
)
1199 dyld::log("%s()\n", __func__
);
1200 // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
1201 // in libSystem for the child of a fork. But dyld is built with a static copy
1202 // of libc.a and has its own copy of mach_task_self_ which we reset here.
1204 // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
1205 // in mach_init() mach_task_self_ is initialized to task_self_trap().
1207 extern mach_port_t mach_task_self_
;
1208 mach_task_self_
= task_self_trap();
1210 // If dyld is sending load/unload notices to CoreSymbolication, the shared memory
1211 // page is not copied on fork. <rdar://problem/6797342>
1212 // NULL the CoreSymbolication shared memory pointer to prevent a crash.
1213 dyld::gProcessInfo
->coreSymbolicationShmPage
= NULL
;
1214 // for safety, make sure child starts with clean systemOrderFlag
1215 dyld::gProcessInfo
->systemOrderFlag
= 0;
1219 #if DEPRECATED_APIS_SUPPORTED
1220 // returns true if prebinding was used in main executable
1221 bool _dyld_launched_prebound()
1223 if ( dyld::gLogAPIs
)
1224 dyld::log("%s()\n", __func__
);
1226 // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
1227 return dyld::mainExecutablePrebound();
1232 // _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
1233 // NSMakePrivateModulePublic() needed for the dlopen() to turn it's
1234 // RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
1235 // flag on the image for this module. If the module was found and it was
1236 // private then everything worked and TRUE is returned else FALSE is returned.
1238 static bool NSMakePrivateModulePublic(NSModule
module)
1240 ImageLoader
* image
= NSModuleToImageLoader(module);
1241 if ( image
!= NULL
) {
1242 if ( image
->hasHiddenExports() ) {
1243 image
->setHideExports(false);
1250 #endif // DEPRECATED_APIS_SUPPORTED
1252 int _dyld_func_lookup(const char* name
, void** address
)
1254 for (const dyld_func
* p
= dyld_funcs
; p
->name
!= NULL
; ++p
) {
1255 if ( strcmp(p
->name
, name
) == 0 ) {
1256 if( p
->implementation
== unimplemented
)
1257 dyld::log("unimplemented dyld function: %s\n", p
->name
);
1258 *address
= p
->implementation
;
1267 static void registerThreadHelpers(const dyld::LibSystemHelpers
* helpers
)
1269 dyld::gLibSystemHelpers
= helpers
;
1271 #if !SUPPORT_ZERO_COST_EXCEPTIONS
1272 if ( helpers
->version
>= 5 ) {
1273 // create key use by dyld exception handling
1275 int result
= helpers
->pthread_key_create(&key
, NULL
);
1277 __Unwind_SjLj_SetThreadKey(key
);
1283 static void dlerrorClear()
1285 if ( dyld::gLibSystemHelpers
!= NULL
) {
1286 // <rdar://problem/10595338> dlerror buffer leak
1287 // dlerrorClear() should not force allocation, but zero it if already allocated
1288 if ( dyld::gLibSystemHelpers
->version
>= 10 ) {
1289 if ( ! (*dyld::gLibSystemHelpers
->hasPerThreadBufferFor_dlerror
)() )
1293 // first char of buffer is flag whether string (starting at second char) is valid
1294 char* buffer
= (*dyld::gLibSystemHelpers
->getThreadBufferFor_dlerror
)(2);
1300 static void dlerrorSet(const char* msg
)
1302 if ( dyld::gLibSystemHelpers
!= NULL
) {
1303 // first char of buffer is flag whether string (starting at second char) is valid
1304 char* buffer
= (*dyld::gLibSystemHelpers
->getThreadBufferFor_dlerror
)(strlen(msg
)+2);
1306 strcpy(&buffer
[1], msg
);
1311 bool dlopen_preflight(const char* path
)
1313 if ( dyld::gLogAPIs
)
1314 dyld::log("%s(%s)\n", __func__
, path
);
1318 CRSetCrashLogMessage("dyld: in dlopen_preflight()");
1320 const bool leafName
= (strchr(path
, '/') == NULL
);
1321 const bool absolutePath
= (path
[0] == '/');
1322 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1323 char canonicalPath
[PATH_MAX
];
1324 // <rdar://problem/7017050> dlopen() not opening frameworks from shared cache with // or ./ in path
1326 // make path canonical if it contains a // or ./
1327 if ( (strstr(path
, "//") != NULL
) || (strstr(path
, "./") != NULL
) ) {
1328 const char* lastSlash
= strrchr(path
, '/');
1329 char dirPath
[PATH_MAX
];
1330 if ( strlcpy(dirPath
, path
, sizeof(dirPath
)) < sizeof(dirPath
) ) {
1331 dirPath
[lastSlash
-path
] = '\0';
1332 if ( realpath(dirPath
, canonicalPath
) ) {
1333 strlcat(canonicalPath
, "/", sizeof(canonicalPath
));
1334 if ( strlcat(canonicalPath
, lastSlash
+1, sizeof(canonicalPath
)) < sizeof(canonicalPath
) ) {
1335 // if all fit in buffer, use new canonical path
1336 path
= canonicalPath
;
1343 #if SUPPORT_ACCELERATE_TABLES
1344 if ( dyld::isPathInCache(path
) )
1348 #if DYLD_SHARED_CACHE_SUPPORT
1349 // <rdar://problem/5910137> dlopen_preflight() on image in shared cache leaves it loaded but not objc initialized
1350 // if requested path is to something in the dyld shared cache, always succeed
1351 if ( dyld::inSharedCache(path
) )
1355 bool result
= false;
1356 std::vector
<const char*> rpathsFromCallerImage
;
1358 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1359 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1360 // for dlopen, use rpath from caller image and from main executable
1361 if ( callerImage
!= NULL
)
1362 callerImage
->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
1363 ImageLoader::RPathChain
callersRPaths(NULL
, &rpathsFromCallerImage
);
1364 if ( callerImage
!= dyld::mainExecutable() ) {
1365 dyld::mainExecutable()->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
1368 ImageLoader
* image
= NULL
;
1369 dyld::LoadContext context
;
1370 context
.useSearchPaths
= true;
1371 context
.useFallbackPaths
= leafName
; // a partial path implies don't use fallback paths
1372 context
.useLdLibraryPath
= leafName
; // a leafname implies should search
1373 context
.implicitRPath
= !absolutePath
; // a non-absolute path implies try rpath searching
1374 context
.matchByInstallName
= true;
1375 context
.dontLoad
= false;
1376 context
.mustBeBundle
= false;
1377 context
.mustBeDylib
= false;
1378 context
.canBePIE
= true;
1379 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
1380 context
.rpath
= &callersRPaths
; // rpaths from caller and main executable
1382 unsigned cacheIndex
;
1383 image
= load(path
, context
, cacheIndex
);
1384 if ( image
!= NULL
) {
1385 dyld::preflight(image
, callersRPaths
, cacheIndex
); // image object deleted by dyld::preflight()
1389 catch (const char* msg
) {
1390 const char* str
= dyld::mkstringf("dlopen_preflight(%s): %s", path
, msg
);
1393 free((void*)msg
); // our free() will do nothing if msg is a string literal
1395 // free rpaths (getRPaths() malloc'ed each string)
1396 for(std::vector
<const char*>::iterator it
=rpathsFromCallerImage
.begin(); it
!= rpathsFromCallerImage
.end(); ++it
) {
1397 const char* str
= *it
;
1400 CRSetCrashLogMessage(NULL
);
1404 #if SUPPORT_ACCELERATE_TABLES
1405 bool static callerIsNonOSApp(void* callerAddress
, const char** shortName
)
1408 const mach_header
* unusedMh
;
1409 const char* unusedPath
;
1410 unsigned unusedIndex
;
1411 // any address in shared cache is not from app
1412 if ( dyld::addressInCache(callerAddress
, &unusedMh
, &unusedPath
, &unusedIndex
) )
1415 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1416 if ( callerImage
== NULL
)
1419 *shortName
= callerImage
->getShortName();
1420 return ( strncmp(callerImage
->getPath(), "/var/containers/", 16) == 0 );
1424 void* dlopen(const char* path
, int mode
)
1426 if ( dyld::gLogAPIs
)
1427 dyld::log("%s(%s, 0x%08X)\n", __func__
, ((path
==NULL
) ? "NULL" : path
), mode
);
1429 #if SUPPORT_ACCELERATE_TABLES
1430 if ( dyld::gLogAppAPIs
) {
1431 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1432 const char* shortName
;
1433 if ( callerIsNonOSApp(callerAddress
, &shortName
) ) {
1434 dyld::log("%s: %s(%s, 0x%08X)\n", shortName
, __func__
, ((path
==NULL
) ? "NULL" : path
), mode
);
1441 // passing NULL for path means return magic object
1442 if ( path
== NULL
) {
1443 // RTLD_FIRST means any dlsym() calls on the handle should only search that handle and not subsequent images
1444 if ( (mode
& RTLD_FIRST
) != 0 )
1445 return RTLD_MAIN_ONLY
;
1447 return RTLD_DEFAULT
;
1450 // acquire global dyld lock (dlopen is special - libSystem glue does not do locking)
1451 bool lockHeld
= false;
1452 if ( (dyld::gLibSystemHelpers
!= NULL
) && (dyld::gLibSystemHelpers
->version
>= 4) ) {
1453 dyld::gLibSystemHelpers
->acquireGlobalDyldLock();
1454 CRSetCrashLogMessage("dyld: in dlopen()");
1458 void* result
= NULL
;
1459 const bool leafName
= (strchr(path
, '/') == NULL
);
1460 const bool absolutePath
= (path
[0] == '/');
1461 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1462 char canonicalPath
[PATH_MAX
];
1463 // <rdar://problem/7017050> dlopen() not opening frameworks from shared cache with // or ./ in path
1465 // make path canonical if it contains a // or ./
1466 if ( (strstr(path
, "//") != NULL
) || (strstr(path
, "./") != NULL
) ) {
1467 const char* lastSlash
= strrchr(path
, '/');
1468 char dirPath
[PATH_MAX
];
1469 if ( strlcpy(dirPath
, path
, sizeof(dirPath
)) < sizeof(dirPath
) ) {
1470 dirPath
[lastSlash
-path
] = '\0';
1471 if ( realpath(dirPath
, canonicalPath
) ) {
1472 strlcat(canonicalPath
, "/", sizeof(canonicalPath
));
1473 if ( strlcat(canonicalPath
, lastSlash
+1, sizeof(canonicalPath
)) < sizeof(canonicalPath
) ) {
1474 // if all fit in buffer, use new canonical path
1475 path
= canonicalPath
;
1482 #if SUPPORT_ACCELERATE_TABLES
1483 if ( dyld::dlopenFromCache(path
, mode
, &result
) ) {
1484 // Note: dlopenFromCache() releases the lock
1485 if ( dyld::gLogAPIs
)
1486 dyld::log(" %s(%s) ==> %p\n", __func__
, path
, result
);
1491 ImageLoader
* image
= NULL
;
1492 std::vector
<const char*> rpathsFromCallerImage
;
1493 ImageLoader::RPathChain
callersRPaths(NULL
, &rpathsFromCallerImage
);
1495 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1496 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1497 if ( (mode
& RTLD_NOLOAD
) == 0 ) {
1498 // for dlopen, use rpath from caller image and from main executable
1499 if ( callerImage
!= NULL
)
1500 callerImage
->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
1501 if ( callerImage
!= dyld::mainExecutable() )
1502 dyld::mainExecutable()->getRPaths(dyld::gLinkContext
, rpathsFromCallerImage
);
1505 dyld::LoadContext context
;
1506 context
.useSearchPaths
= true;
1507 context
.useFallbackPaths
= leafName
; // a partial path means no fallback paths
1508 context
.useLdLibraryPath
= leafName
; // a leafname implies should search
1509 context
.implicitRPath
= !absolutePath
; // a non-absolute path implies try rpath searching
1510 context
.matchByInstallName
= true;
1511 context
.dontLoad
= ( (mode
& RTLD_NOLOAD
) != 0 );
1512 context
.mustBeBundle
= false;
1513 context
.mustBeDylib
= false;
1514 context
.canBePIE
= true;
1515 context
.origin
= callerImage
!= NULL
? callerImage
->getPath() : NULL
; // caller's image's path
1516 context
.rpath
= &callersRPaths
; // rpaths from caller and main executable
1518 unsigned cacheIndex
;
1519 image
= load(path
, context
, cacheIndex
);
1520 #if SUPPORT_ACCELERATE_TABLES
1521 if ( (image
!= NULL
) && (cacheIndex
!= UINT32_MAX
) ) {
1522 if ( dyld::makeCacheHandle(image
, cacheIndex
, mode
, &result
) ) {
1523 if ( dyld::gLogAPIs
)
1524 dyld::log(" %s(%s) ==> %p\n", __func__
, path
, result
);
1526 dyld::gLibSystemHelpers
->releaseGlobalDyldLock();
1531 if ( image
!= NULL
) {
1532 // bump reference count. Do this before link() so that if an initializer calls dlopen and fails
1533 // this image is not garbage collected
1534 image
->incrementDlopenReferenceCount();
1535 // link in all dependents
1536 if ( (mode
& RTLD_NOLOAD
) == 0 ) {
1537 bool alreadyLinked
= image
->isLinked();
1538 bool forceLazysBound
= ( (mode
& RTLD_NOW
) != 0 );
1539 dyld::link(image
, forceLazysBound
, false, callersRPaths
, cacheIndex
);
1540 if ( ! alreadyLinked
) {
1541 // only hide exports if image is not already in use
1542 if ( (mode
& RTLD_LOCAL
) != 0 )
1543 image
->setHideExports(true);
1547 // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
1548 // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
1549 // The subtle differences are:
1550 // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
1551 // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
1552 if ( (mode
& RTLD_NODELETE
) != 0 )
1553 image
->setLeaveMapped();
1555 // release global dyld lock early, this enables initializers to do threaded operations
1557 CRSetCrashLogMessage(NULL
);
1558 dyld::gLibSystemHelpers
->releaseGlobalDyldLock();
1562 // RTLD_NOLOAD means dlopen should fail unless path is already loaded.
1563 // don't run initializers when RTLD_NOLOAD is set. This only matters if dlopen() is
1564 // called from within an initializer because it can cause initializers to run
1565 // out of order. Most uses of RTLD_NOLOAD are "probes". If they want initialzers
1566 // to run, then don't use RTLD_NOLOAD.
1567 if ( (mode
& RTLD_NOLOAD
) == 0 ) {
1569 dyld::runInitializers(image
);
1572 // RTLD_FIRST means any dlsym() calls on the handle should only search that handle and not subsequent images
1573 // this is tracked by setting the low bit of the handle, which is usually zero by malloc alignment
1574 if ( (mode
& RTLD_FIRST
) != 0 )
1575 result
= (void*)(((uintptr_t)image
)|1);
1580 catch (const char* msg
) {
1581 if ( image
!= NULL
) {
1582 // load() succeeded but, link() failed
1583 // back down reference count and do GC
1584 image
->decrementDlopenReferenceCount();
1585 if ( image
->dlopenCount() == 0 )
1586 dyld::garbageCollectImages();
1588 const char* str
= dyld::mkstringf("dlopen(%s, %d): %s", path
, mode
, msg
);
1589 if ( dyld::gLogAPIs
)
1590 dyld::log(" %s() failed, error: '%s'\n", __func__
, str
);
1593 free((void*)msg
); // our free() will do nothing if msg is a string literal
1596 // free rpaths (getRPaths() malloc'ed each string)
1597 for(std::vector
<const char*>::iterator it
=rpathsFromCallerImage
.begin(); it
!= rpathsFromCallerImage
.end(); ++it
) {
1598 const char* str
= *it
;
1602 // when context.dontLoad is set, load() returns NULL instead of throwing an exception
1603 if ( (mode
& RTLD_NOLOAD
) && (result
== NULL
) ) {
1604 dlerrorSet("image not already loaded");
1608 CRSetCrashLogMessage(NULL
);
1609 dyld::gLibSystemHelpers
->releaseGlobalDyldLock();
1611 if ( dyld::gLogAPIs
&& (result
!= NULL
) )
1612 dyld::log(" %s(%s) ==> %p\n", __func__
, path
, result
);
1618 int dlclose(void* handle
)
1620 if ( dyld::gLogAPIs
)
1621 dyld::log("%s(%p)\n", __func__
, handle
);
1623 // silently accept magic handles for main executable
1624 if ( handle
== RTLD_MAIN_ONLY
)
1626 if ( handle
== RTLD_DEFAULT
)
1629 ImageLoader
* image
= (ImageLoader
*)(((uintptr_t)handle
) & (-4)); // clear mode bits
1630 if ( dyld::validImage(image
) ) {
1632 // decrement use count
1633 if ( image
->decrementDlopenReferenceCount() ) {
1634 dlerrorSet("dlclose() called too many times");
1637 // remove image if reference count went to zero
1638 if ( image
->dlopenCount() == 0 )
1639 dyld::garbageCollectImages();
1643 dlerrorSet("invalid handle passed to dlclose()");
1650 int dladdr(const void* address
, Dl_info
* info
)
1652 if ( dyld::gLogAPIs
)
1653 dyld::log("%s(%p, %p)\n", __func__
, address
, info
);
1655 CRSetCrashLogMessage("dyld: in dladdr()");
1656 #if SUPPORT_ACCELERATE_TABLES
1657 if ( dyld::dladdrFromCache(address
, info
) ) {
1658 CRSetCrashLogMessage(NULL
);
1659 return 1; // success
1663 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1664 if ( image
!= NULL
) {
1665 info
->dli_fname
= image
->getRealPath();
1666 info
->dli_fbase
= (void*)image
->machHeader();
1667 if ( address
== info
->dli_fbase
) {
1668 // special case lookup of header
1669 info
->dli_sname
= "__dso_handle";
1670 info
->dli_saddr
= info
->dli_fbase
;
1671 CRSetCrashLogMessage(NULL
);
1672 return 1; // success
1674 // find closest symbol in the image
1675 info
->dli_sname
= image
->findClosestSymbol(address
, (const void**)&info
->dli_saddr
);
1676 // never return the mach_header symbol
1677 if ( info
->dli_saddr
== info
->dli_fbase
) {
1678 info
->dli_sname
= NULL
;
1679 info
->dli_saddr
= NULL
;
1680 CRSetCrashLogMessage(NULL
);
1681 return 1; // success
1683 if ( info
->dli_sname
!= NULL
) {
1684 if ( info
->dli_sname
[0] == '_' )
1685 info
->dli_sname
= info
->dli_sname
+1; // strip off leading underscore
1686 //dyld::log("dladdr(%p) => %p %s\n", address, info->dli_saddr, info->dli_sname);
1687 CRSetCrashLogMessage(NULL
);
1688 return 1; // success
1690 info
->dli_sname
= NULL
;
1691 info
->dli_saddr
= NULL
;
1692 CRSetCrashLogMessage(NULL
);
1693 return 1; // success
1695 CRSetCrashLogMessage(NULL
);
1696 return 0; // failure
1702 if ( dyld::gLogAPIs
)
1703 dyld::log("%s()\n", __func__
);
1705 if ( dyld::gLibSystemHelpers
!= NULL
) {
1706 // if using newer libdyld.dylib and buffer if buffer not yet allocated, return NULL
1707 if ( dyld::gLibSystemHelpers
->version
>= 10 ) {
1708 if ( ! (*dyld::gLibSystemHelpers
->hasPerThreadBufferFor_dlerror
)() )
1712 // first char of buffer is flag whether string (starting at second char) is valid
1713 char* buffer
= (*dyld::gLibSystemHelpers
->getThreadBufferFor_dlerror
)(2);
1714 if ( buffer
[0] != '\0' ) { // if valid buffer
1715 buffer
[0] = '\0'; // mark invalid, so next call to dlerror returns NULL
1716 return &buffer
[1]; // return message
1722 void* dlsym(void* handle
, const char* symbolName
)
1724 if ( dyld::gLogAPIs
)
1725 dyld::log("%s(%p, %s)\n", __func__
, handle
, symbolName
);
1727 #if SUPPORT_ACCELERATE_TABLES
1728 if ( dyld::gLogAppAPIs
) {
1729 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1730 const char* shortName
;
1731 if ( callerIsNonOSApp(callerAddress
, &shortName
) ) {
1732 dyld::log("%s: %s(%p, %s)\n", shortName
, __func__
, handle
, symbolName
);
1737 CRSetCrashLogMessage("dyld: in dlsym()");
1740 const ImageLoader
* image
;
1741 const ImageLoader::Symbol
* sym
;
1744 // dlsym() assumes symbolName passed in is same as in C source code
1745 // dyld assumes all symbol names have an underscore prefix
1746 char underscoredName
[strlen(symbolName
)+2];
1747 underscoredName
[0] = '_';
1748 strcpy(&underscoredName
[1], symbolName
);
1750 // magic "search all" handle
1751 if ( handle
== RTLD_DEFAULT
) {
1752 if ( dyld::flatFindExportedSymbol(underscoredName
, &sym
, &image
) ) {
1753 CRSetCrashLogMessage(NULL
);
1754 result
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
, NULL
, false, underscoredName
);
1755 if ( dyld::gLogAPIs
)
1756 dyld::log(" %s(RTLD_DEFAULT, %s) ==> %p\n", __func__
, symbolName
, result
);
1759 const char* str
= dyld::mkstringf("dlsym(RTLD_DEFAULT, %s): symbol not found", symbolName
);
1762 CRSetCrashLogMessage(NULL
);
1763 if ( dyld::gLogAPIs
)
1764 dyld::log(" %s(RTLD_DEFAULT, %s) ==> NULL\n", __func__
, symbolName
);
1768 // magic "search only main executable" handle
1769 else if ( handle
== RTLD_MAIN_ONLY
) {
1770 image
= dyld::mainExecutable();
1771 sym
= image
->findExportedSymbol(underscoredName
, true, &image
); // search RTLD_FIRST way
1772 if ( sym
!= NULL
) {
1773 CRSetCrashLogMessage(NULL
);
1774 result
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
, NULL
, false, underscoredName
);
1775 if ( dyld::gLogAPIs
)
1776 dyld::log(" %s(RTLD_MAIN_ONLY, %s) ==> %p\n", __func__
, symbolName
, result
);
1779 const char* str
= dyld::mkstringf("dlsym(RTLD_MAIN_ONLY, %s): symbol not found", symbolName
);
1782 CRSetCrashLogMessage(NULL
);
1783 if ( dyld::gLogAPIs
)
1784 dyld::log(" %s(RTLD_MAIN_ONLY, %s) ==> NULL\n", __func__
, symbolName
);
1788 // magic "search what I would see" handle
1789 else if ( handle
== RTLD_NEXT
) {
1790 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1791 #if SUPPORT_ACCELERATE_TABLES
1792 const mach_header
* mh
;
1795 if ( dyld::addressInCache(callerAddress
, &mh
, &path
, &index
) ) {
1796 // if dylib in cache is calling dlsym(RTLD_NEXT,xxx) handle search differently
1797 result
= dyld::dlsymFromCache(RTLD_NEXT
, underscoredName
, index
);
1798 if ( dyld::gLogAPIs
)
1799 dyld::log(" %s(RTLD_NEXT, %s) ==> %p\n", __func__
, symbolName
, result
);
1803 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1804 sym
= callerImage
->findExportedSymbolInDependentImages(underscoredName
, dyld::gLinkContext
, &image
); // don't search image, but do search what it links against
1805 if ( sym
!= NULL
) {
1806 CRSetCrashLogMessage(NULL
);
1807 result
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
, callerImage
, false, underscoredName
);
1808 if ( dyld::gLogAPIs
)
1809 dyld::log(" %s(RTLD_NEXT, %s) ==> %p\n", __func__
, symbolName
, result
);
1812 const char* str
= dyld::mkstringf("dlsym(RTLD_NEXT, %s): symbol not found", symbolName
);
1815 CRSetCrashLogMessage(NULL
);
1816 if ( dyld::gLogAPIs
)
1817 dyld::log(" %s(RTLD_NEXT, %s) ==> NULL\n", __func__
, symbolName
);
1820 // magic "search me, then what I would see" handle
1821 else if ( handle
== RTLD_SELF
) {
1822 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1823 #if SUPPORT_ACCELERATE_TABLES
1824 const mach_header
* mh
;
1827 if ( dyld::addressInCache(callerAddress
, &mh
, &path
, &index
) ) {
1828 // if dylib in cache is calling dlsym(RTLD_SELF,xxx) handle search differently
1829 result
= dyld::dlsymFromCache(RTLD_SELF
, underscoredName
, index
);
1830 if ( dyld::gLogAPIs
)
1831 dyld::log(" %s(RTLD_SELF, %s) ==> %p\n", __func__
, symbolName
, result
);
1835 ImageLoader
* callerImage
= dyld::findImageContainingAddress(callerAddress
);
1836 sym
= callerImage
->findExportedSymbolInImageOrDependentImages(underscoredName
, dyld::gLinkContext
, &image
); // search image and what it links against
1837 if ( sym
!= NULL
) {
1838 CRSetCrashLogMessage(NULL
);
1839 result
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
, callerImage
, false, underscoredName
);
1840 if ( dyld::gLogAPIs
)
1841 dyld::log(" %s(RTLD_SELF, %s) ==> %p\n", __func__
, symbolName
, result
);
1844 const char* str
= dyld::mkstringf("dlsym(RTLD_SELF, %s): symbol not found", symbolName
);
1847 CRSetCrashLogMessage(NULL
);
1848 if ( dyld::gLogAPIs
)
1849 dyld::log(" %s(RTLD_SELF, %s) ==> NULL\n", __func__
, symbolName
);
1852 #if SUPPORT_ACCELERATE_TABLES
1853 // check for mega dylib handle
1854 else if ( dyld::isCacheHandle(handle
) ) {
1855 result
= dyld::dlsymFromCache(handle
, underscoredName
, 0);
1856 if ( dyld::gLogAPIs
)
1857 dyld::log(" %s(%p, %s) ==> %p\n", __func__
, handle
, symbolName
, result
);
1862 image
= (ImageLoader
*)(((uintptr_t)handle
) & (-4)); // clear mode bits
1863 if ( dyld::validImage(image
) ) {
1864 if ( (((uintptr_t)handle
) & 1) != 0 )
1865 sym
= image
->findExportedSymbol(underscoredName
, true, &image
); // search RTLD_FIRST way
1867 sym
= image
->findExportedSymbolInImageOrDependentImages(underscoredName
, dyld::gLinkContext
, &image
); // search image and what it links against
1869 if ( sym
!= NULL
) {
1870 CRSetCrashLogMessage(NULL
);
1871 ImageLoader
* callerImage
= NULL
;
1872 if ( sDynamicInterposing
) {
1873 // only take time to look up caller, if dynamic interposing in use
1874 void* callerAddress
= __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1875 callerImage
= dyld::findImageContainingAddress(callerAddress
);
1877 result
= (void*)image
->getExportedSymbolAddress(sym
, dyld::gLinkContext
, callerImage
, false, underscoredName
);
1878 if ( dyld::gLogAPIs
)
1879 dyld::log(" %s(%p, %s) ==> %p\n", __func__
, handle
, symbolName
, result
);
1882 const char* str
= dyld::mkstringf("dlsym(%p, %s): symbol not found", handle
, symbolName
);
1887 dlerrorSet("invalid handle passed to dlsym()");
1889 CRSetCrashLogMessage(NULL
);
1890 if ( dyld::gLogAPIs
)
1891 dyld::log(" %s(%p, %s) ==> NULL\n", __func__
, handle
, symbolName
);
1904 const struct dyld_all_image_infos
* _dyld_get_all_image_infos()
1906 return dyld::gProcessInfo
;
1910 #if SUPPORT_ZERO_COST_EXCEPTIONS
1911 static bool client_dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
)
1913 //if ( dyld::gLogAPIs )
1914 // dyld::log("%s(%p, %p)\n", __func__, addr, info);
1916 #if SUPPORT_ACCELERATE_TABLES
1917 if ( dyld::findUnwindSections(addr
, info
) )
1920 ImageLoader
* image
= dyld::findImageContainingAddress(addr
);
1921 if ( image
!= NULL
) {
1922 image
->getUnwindInfo(info
);
1930 const char* dyld_image_path_containing_address(const void* address
)
1932 if ( dyld::gLogAPIs
)
1933 dyld::log("%s(%p)\n", __func__
, address
);
1935 #if SUPPORT_ACCELERATE_TABLES
1936 const mach_header
* mh
;
1938 if ( dyld::addressInCache(address
, &mh
, &path
) )
1942 ImageLoader
* image
= dyld::findImageContainingAddress(address
);
1943 if ( image
!= NULL
)
1944 return image
->getRealPath();
1950 bool dyld_shared_cache_some_image_overridden()
1952 #if DYLD_SHARED_CACHE_SUPPORT
1953 return dyld::gSharedCacheOverridden
;
1960 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
)
1964 if ( array
== NULL
)
1968 ImageLoader
* image
= dyld::findImageByMachHeader(mh
);
1969 if ( image
== NULL
)
1972 // make pass at bound references in this image and update them
1973 dyld::gLinkContext
.dynamicInterposeArray
= array
;
1974 dyld::gLinkContext
.dynamicInterposeCount
= count
;
1975 image
->dynamicInterpose(dyld::gLinkContext
);
1976 dyld::gLinkContext
.dynamicInterposeArray
= NULL
;
1977 dyld::gLinkContext
.dynamicInterposeCount
= 0;
1979 // leave interposing info so any future (lazy) binding will get it too
1980 image
->addDynamicInterposingTuples(array
, count
);
1982 sDynamicInterposing
= true;
1986 bool _dyld_is_memory_immutable(const void* addr
, size_t length
)
1988 if ( dyld::gLogAPIs
)
1989 dyld::log("%s(%p, %ld)\n", __func__
, addr
, length
);
1991 uintptr_t checkStart
= (uintptr_t)addr
;
1992 uintptr_t checkEnd
= checkStart
+ length
;
1994 #if DYLD_SHARED_CACHE_SUPPORT
1995 // quick check to see if in r/o region of shared cache. If so return true.
1996 if ( dyld_shared_cache_ranges
.sharedRegionsCount
> 2 ) {
1997 uintptr_t roStart
= dyld_shared_cache_ranges
.ranges
[0].start
;
1998 uintptr_t roEnd
= roStart
+ dyld_shared_cache_ranges
.ranges
[0].length
;
1999 if ( (roStart
< checkStart
) && (checkEnd
< roEnd
) )
2004 // Otherwise find if addr is in a dyld loaded image
2005 ImageLoader
* image
= dyld::findImageContainingAddress(addr
);
2006 if ( image
!= NULL
) {
2007 // <rdar://problem/24091154> already checked for r/o portion of cache
2008 if ( image
->inSharedCache() )
2010 if ( !image
->neverUnload() )
2012 for (unsigned i
=0, e
=image
->segmentCount(); i
< e
; ++i
) {
2013 if ( (image
->segActualLoadAddress(i
) < checkStart
) && (checkEnd
< image
->segActualEndAddress(i
)) ) {
2014 return !image
->segWriteable(i
);
2023 void _dyld_objc_notify_register(_dyld_objc_notify_mapped mapped
,
2024 _dyld_objc_notify_init init
,
2025 _dyld_objc_notify_unmapped unmapped
)
2027 dyld::registerObjCNotifiers(mapped
, init
, unmapped
);
2031 bool _dyld_get_shared_cache_uuid(uuid_t uuid
)
2033 return dyld::sharedCacheUUID(uuid
);