]> git.saurik.com Git - apple/dyld.git/blob - src/dyldAPIs.cpp
dyld-353.2.3.tar.gz
[apple/dyld.git] / src / dyldAPIs.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 //
26 // This file implements that API's in <mach-o/dyld.h>
27 //
28 //
29
30 #define __STDC_LIMIT_MACROS
31 #include <stddef.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <sys/param.h>
35 #include <sys/mount.h>
36 #include <Availability.h>
37
38
39 #include <vector>
40 #include <map>
41 #include <algorithm>
42
43 #include <mach/mach.h>
44 #include <sys/time.h>
45 #include <sys/sysctl.h>
46 #include <mach/mach_traps.h> // for task_self_trap()
47
48
49 #include "mach-o/dyld_images.h"
50 #include "mach-o/dyld.h"
51 #include "mach-o/dyld_priv.h"
52
53 #include "ImageLoader.h"
54 #include "dyld.h"
55 #include "dyldLibSystemInterface.h"
56
57 #undef _POSIX_C_SOURCE
58 #include "dlfcn.h"
59
60 // from dyldExceptions.c
61 extern "C" void __Unwind_SjLj_SetThreadKey(pthread_key_t key);
62
63 // from dyld_gdb.cpp
64 extern void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]);
65
66 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
67 #if __IPHONE_OS_VERSION_MIN_REQUIRED
68 #define DEPRECATED_APIS_SUPPORTED 0
69 #else
70 #define DEPRECATED_APIS_SUPPORTED 1
71 #endif
72
73 static bool sDynamicInterposing = false;
74
75 #if DEPRECATED_APIS_SUPPORTED
76 static char sLastErrorFilePath[1024];
77 static NSLinkEditErrors sLastErrorFileCode;
78 static int sLastErrorNo;
79 #endif
80
81 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
82 // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
83 // This conditional keeps support for old libSystem's which needed some help implementing the API's
84 #define OLD_LIBSYSTEM_SUPPORT (__i386__)
85
86 // The following functions have no prototype in any header. They are special cases
87 // where _dyld_func_lookup() is used directly.
88 static void _dyld_make_delayed_module_initializer_calls();
89 static void registerThreadHelpers(const dyld::LibSystemHelpers*);
90 #if DEPRECATED_APIS_SUPPORTED
91 static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit);
92 #if OLD_LIBSYSTEM_SUPPORT
93 static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options);
94 #endif
95 static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions);
96 static bool NSMakePrivateModulePublic(NSModule module);
97 static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header);
98
99 // The following functions are dyld API's, but since dyld links with a static copy of libc.a
100 // the public name cannot be used.
101 static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module);
102 static bool client_NSIsSymbolNameDefined(const char* symbolName);
103 #endif // DEPRECATED_APIS_SUPPORTED
104 #if SUPPORT_ZERO_COST_EXCEPTIONS
105 static bool client_dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info);
106 #endif
107
108 static void unimplemented()
109 {
110 dyld::halt("unimplemented dyld function\n");
111 }
112
113 struct dyld_func {
114 const char* name;
115 void* implementation;
116 };
117
118 static struct dyld_func dyld_funcs[] = {
119 {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image },
120 {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image },
121 {"__dyld_dladdr", (void*)dladdr },
122 {"__dyld_dlclose", (void*)dlclose },
123 {"__dyld_dlerror", (void*)dlerror },
124 {"__dyld_dlopen", (void*)dlopen },
125 {"__dyld_dlsym", (void*)dlsym },
126 {"__dyld_dlopen_preflight", (void*)dlopen_preflight },
127 {"__dyld_image_count", (void*)_dyld_image_count },
128 {"__dyld_get_image_header", (void*)_dyld_get_image_header },
129 {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide },
130 {"__dyld_get_image_name", (void*)_dyld_get_image_name },
131 {"__dyld_get_image_slide", (void*)_dyld_get_image_slide },
132 {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath },
133
134 // SPIs
135 {"__dyld_dyld_register_image_state_change_handler", (void*)dyld_register_image_state_change_handler },
136 {"__dyld_register_thread_helpers", (void*)registerThreadHelpers },
137 {"__dyld_fork_child", (void*)_dyld_fork_child },
138 {"__dyld_make_delayed_module_initializer_calls", (void*)_dyld_make_delayed_module_initializer_calls },
139 {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos },
140 #if SUPPORT_ZERO_COST_EXCEPTIONS
141 {"__dyld_find_unwind_sections", (void*)client_dyld_find_unwind_sections },
142 #endif
143 #if __i386__ || __x86_64__ || __arm__ || __arm64__
144 {"__dyld_fast_stub_entry", (void*)dyld::fastBindLazySymbol },
145 #endif
146 {"__dyld_image_path_containing_address", (void*)dyld_image_path_containing_address },
147 {"__dyld_shared_cache_some_image_overridden", (void*)dyld_shared_cache_some_image_overridden },
148 {"__dyld_process_is_restricted", (void*)dyld::processIsRestricted },
149 {"__dyld_dynamic_interpose", (void*)dyld_dynamic_interpose },
150
151 // deprecated
152 #if DEPRECATED_APIS_SUPPORTED
153 {"__dyld_get_image_header_containing_address", (void*)_dyld_get_image_header_containing_address },
154 {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind },
155 {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint },
156 {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully },
157 {"__dyld_install_handlers", (void*)_dyld_install_handlers },
158 {"__dyld_link_edit_error", (void*)NSLinkEditError },
159 {"__dyld_unlink_module", (void*)NSUnLinkModule },
160 {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module },
161 {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address },
162 {"__dyld_image_containing_address", (void*)_dyld_image_containing_address },
163 {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler },
164 {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol },
165 {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol },
166 {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol },
167 {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol },
168 {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint },
169 {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule},
170 {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage},
171 {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic},
172 {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined},
173 {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint },
174 {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage},
175 {"__dyld_NSNameOfModule", (void*)NSNameOfModule },
176 {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule },
177 {"__dyld_NSAddLibrary", (void*)NSAddLibrary },
178 {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching },
179 {"__dyld_NSAddImage", (void*)NSAddImage },
180 {"__dyld_launched_prebound", (void*)_dyld_launched_prebound },
181 {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound },
182 {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib },
183 {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile },
184 {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory },
185 {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage },
186 {"__dyld_NSLinkModule", (void*)NSLinkModule },
187 {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage },
188 {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage },
189 {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage },
190 {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage },
191 {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage },
192 {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage },
193 {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage },
194 #if OLD_LIBSYSTEM_SUPPORT
195 {"__dyld_link_module", (void*)_dyld_link_module },
196 #endif
197 #endif //DEPRECATED_APIS_SUPPORTED
198
199 {NULL, 0}
200 };
201
202
203
204 #if DEPRECATED_APIS_SUPPORTED
205
206 static void dyldAPIhalt(const char* apiName, const char* errorMsg)
207 {
208 dyld::log("dyld: %s() error\n", apiName);
209 dyld::halt(errorMsg);
210 }
211
212 // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
213 inline NSSymbol SymbolToNSSymbol(const ImageLoader::Symbol* sym)
214 {
215 return (NSSymbol)sym;
216 }
217 inline const ImageLoader::Symbol* NSSymbolToSymbol(NSSymbol sym)
218 {
219 return (const ImageLoader::Symbol*)sym;
220 }
221
222 // dyld's abstract type NSModule is implemented as ImageLoader*
223 inline NSModule ImageLoaderToNSModule(const ImageLoader* image)
224 {
225 return (NSModule)image;
226 }
227 inline ImageLoader* NSModuleToImageLoader(NSModule module)
228 {
229 ImageLoader* image = (ImageLoader*)module;
230 if ( dyld::validImage(image) )
231 return image;
232 return NULL;
233 }
234
235 // actual definition for opaque type
236 struct __NSObjectFileImage
237 {
238 ImageLoader* image;
239 const void* imageBaseAddress; // not used with OFI created from files
240 size_t imageLength; // not used with OFI created from files
241 };
242
243
244 VECTOR_NEVER_DESTRUCTED(NSObjectFileImage);
245 static std::vector<NSObjectFileImage> sObjectFileImages;
246
247
248
249 //
250 // __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
251 // The contained image is delete in one of two places:
252 // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
253 // NSDestroyObjectFileImage deletes the image if image is not in list of valid images
254 //
255
256
257
258 static void setLastError(NSLinkEditErrors code, int errnum, const char* file, const char* message)
259 {
260 dyld::setErrorMessage(message);
261 strncpy(sLastErrorFilePath, file, 1024);
262 sLastErrorFilePath[1023] = '\0';
263 sLastErrorFileCode = code;
264 sLastErrorNo = errnum;
265 }
266
267 #endif // DEPRECATED_APIS_SUPPORTED
268
269 /*
270 *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
271 * copies the path of the executable into the buffer and returns 0 if the path
272 * was successfully copied in the provided buffer. If the buffer is not large
273 * enough, -1 is returned and the expected buffer size is copied in *bufsize.
274 * Note that _NSGetExecutablePath will return "a path" to the executable not a
275 * "real path" to the executable. That is the path may be a symbolic link and
276 * not the real file. And with deep directories the total bufsize needed could
277 * be more than MAXPATHLEN.
278 */
279 int _NSGetExecutablePath(char* buf, uint32_t *bufsize)
280 {
281 if ( dyld::gLogAPIs )
282 dyld::log("%s(...)\n", __func__);
283 const char* exePath = dyld::getExecutablePath();
284 if(*bufsize < strlen(exePath) + 1){
285 *bufsize = (uint32_t)(strlen(exePath) + 1);
286 return -1;
287 }
288 strcpy(buf, exePath);
289 return 0;
290 }
291
292 uint32_t _dyld_image_count(void)
293 {
294 if ( dyld::gLogAPIs )
295 dyld::log("%s()\n", __func__);
296 return dyld::getImageCount();
297 }
298
299 const struct mach_header* _dyld_get_image_header(uint32_t image_index)
300 {
301 if ( dyld::gLogAPIs )
302 dyld::log("%s(%u)\n", __func__, image_index);
303 ImageLoader* image = dyld::getIndexedImage(image_index);
304 if ( image != NULL )
305 return (struct mach_header*)image->machHeader();
306 else
307 return NULL;
308 }
309
310 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
311 {
312 if ( dyld::gLogAPIs )
313 dyld::log("%s(%u)\n", __func__, image_index);
314 ImageLoader* image = dyld::getIndexedImage(image_index);
315 if ( image != NULL )
316 return image->getSlide();
317 else
318 return 0;
319 }
320
321 intptr_t _dyld_get_image_slide(const struct mach_header* mh)
322 {
323 if ( dyld::gLogAPIs )
324 dyld::log("%s(%p)\n", __func__, mh);
325 ImageLoader* image = dyld::findImageByMachHeader(mh);
326 if ( image != NULL )
327 return image->getSlide();
328 else
329 return 0;
330 }
331
332
333 const char* _dyld_get_image_name(uint32_t image_index)
334 {
335 if ( dyld::gLogAPIs )
336 dyld::log("%s(%u)\n", __func__, image_index);
337 ImageLoader* image = dyld::getIndexedImage(image_index);
338 if ( image != NULL )
339 return image->getRealPath();
340 else
341 return NULL;
342 }
343
344 const struct mach_header * _dyld_get_image_header_containing_address(const void* address)
345 {
346 if ( dyld::gLogAPIs )
347 dyld::log("%s(%p)\n", __func__, address);
348 ImageLoader* image = dyld::findImageContainingAddress(address);
349 if ( image != NULL )
350 return image->machHeader();
351 return NULL;
352 }
353
354
355 void _dyld_register_func_for_add_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
356 {
357 if ( dyld::gLogAPIs )
358 dyld::log("%s(%p)\n", __func__, (void *)func);
359 dyld::registerAddCallback(func);
360 }
361
362 void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
363 {
364 if ( dyld::gLogAPIs )
365 dyld::log("%s(%p)\n", __func__, (void *)func);
366 dyld::registerRemoveCallback(func);
367 }
368
369
370
371 // called by crt before main() by programs linked with 10.4 or earlier crt1.o
372 static void _dyld_make_delayed_module_initializer_calls()
373 {
374 if ( dyld::gLogAPIs )
375 dyld::log("%s()\n", __func__);
376
377 #if SUPPORT_OLD_CRT_INITIALIZATION
378 if ( dyld::gRunInitializersOldWay )
379 dyld::initializeMainExecutable();
380 #endif
381 }
382
383
384
385 #if DEPRECATED_APIS_SUPPORTED
386
387 //
388 // _dyld_call_module_initializers_for_dylib() is the dyld side of
389 // __initialize_Cplusplus() which is in dylib1.o.
390 // It is intended to only be called inside -init rouintes.
391 // -init routines are called before module initializers (what C++
392 // initializers use). Calling __initialize_Cplusplus() in a -init
393 // routine causes the module initializers for an image to be called
394 // which then allows C++ to be used inside a -init routine
395 //
396 static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header)
397 {
398 if ( dyld::gLogAPIs )
399 dyld::log("__initialize_Cplusplus()\n");
400
401 // for now, do nothing...
402 }
403
404
405 void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module)
406 {
407 if ( dyld::gLogAPIs )
408 dyld::log("%s(\"%s\", %p, %p)\n", __func__, symbolName, address, module);
409 ImageLoader* image;
410 const ImageLoader::Symbol* sym;
411 dyld::clearErrorMessage();
412 if ( dyld::flatFindExportedSymbol(symbolName, &sym, (const ImageLoader**)&image) ) {
413 try {
414 image->bindAllLazyPointers(dyld::gLinkContext, true);
415 if ( address != NULL)
416 *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
417 if ( module != NULL)
418 *module = ImageLoaderToNSModule(image);
419 }
420 catch (const char* msg) {
421 dyldAPIhalt(__func__, msg);
422 }
423 }
424 else {
425 // on failure to find symbol return NULLs
426 if ( address != NULL)
427 *address = NULL;
428 if ( module != NULL)
429 *module = NULL;
430 }
431 }
432
433 // Note: This cannot have public name because dyld is built with a static copy of libc.a
434 // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
435 static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module)
436 {
437 if ( dyld::gLogAPIs )
438 dyld::log("_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName, address, module);
439 const ImageLoader* image;
440 const ImageLoader::Symbol* sym;
441 if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
442 if ( address != NULL)
443 *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
444 if ( module != NULL)
445 *module = ImageLoaderToNSModule(image);
446 }
447 else {
448 // on failure to find symbol return NULLs
449 if ( address != NULL)
450 *address = NULL;
451 if ( module != NULL)
452 *module = NULL;
453 }
454 }
455
456 void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* library_name_hint, void** address, NSModule* module)
457 {
458 if ( dyld::gLogAPIs )
459 dyld::log("%s(\"%s\", \"%s\", %p, %p)\n", __func__, symbolName, library_name_hint, address, module);
460 const ImageLoader* image;
461 const ImageLoader::Symbol* sym;
462 // Look for library whose path contains the hint. If that fails search everywhere
463 if ( dyld::flatFindExportedSymbolWithHint(symbolName, library_name_hint, &sym, &image)
464 || dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
465 if ( address != NULL)
466 *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
467 if ( module != NULL)
468 *module = ImageLoaderToNSModule(image);
469 }
470 else {
471 // on failure to find symbol return NULLs
472 if ( address != NULL)
473 *address = NULL;
474 if ( module != NULL)
475 *module = NULL;
476 }
477 }
478
479
480 NSSymbol NSLookupAndBindSymbol(const char *symbolName)
481 {
482 if ( dyld::gLogAPIs )
483 dyld::log("%s(\"%s\")\n", __func__, symbolName);
484 const ImageLoader* image;
485 const ImageLoader::Symbol* sym;
486 if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
487 return SymbolToNSSymbol(sym);
488 }
489 // return NULL on failure
490 return NULL;
491 }
492
493 NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint)
494 {
495 if ( dyld::gLogAPIs )
496 dyld::log("%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
497 const ImageLoader* image;
498 const ImageLoader::Symbol* sym;
499 bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
500 if ( ! found ) {
501 // hint failed, do slow search of all images
502 found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
503 }
504 if ( found )
505 return SymbolToNSSymbol(sym);
506
507 // return NULL on failure and log
508 if ( dyld::gLogAPIs )
509 dyld::log("%s(\"%s\", \"%s\") => NULL \n", __func__, symbolName, libraryNameHint);
510 return NULL;
511 }
512
513
514
515
516 static __attribute__((noinline))
517 const struct mach_header* addImage(void* callerAddress, const char* path, bool search, bool dontLoad, bool matchInstallName, bool abortOnError)
518 {
519 ImageLoader* image = NULL;
520 std::vector<const char*> rpathsFromCallerImage;
521 try {
522 dyld::clearErrorMessage();
523 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
524 // like dlopen, use rpath from caller image and from main executable
525 if ( callerImage != NULL )
526 callerImage->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
527 ImageLoader::RPathChain callersRPaths(NULL, &rpathsFromCallerImage);
528 if ( callerImage != dyld::mainExecutable() ) {
529 dyld::mainExecutable()->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
530 }
531 dyld::LoadContext context;
532 context.useSearchPaths = search;
533 context.useFallbackPaths = search;
534 context.useLdLibraryPath = false;
535 context.implicitRPath = false;
536 context.matchByInstallName = matchInstallName;
537 context.dontLoad = dontLoad;
538 context.mustBeBundle = false;
539 context.mustBeDylib = true;
540 context.canBePIE = false;
541 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
542 context.rpath = &callersRPaths; // rpaths from caller and main executable
543
544 image = load(path, context);
545 if ( image != NULL ) {
546 if ( context.matchByInstallName )
547 image->setMatchInstallPath(true);
548 dyld::link(image, false, false, callersRPaths);
549 dyld::runInitializers(image);
550 // images added with NSAddImage() can never be unloaded
551 image->setNeverUnload();
552 }
553 }
554 catch (const char* msg) {
555 dyld::garbageCollectImages();
556 if ( abortOnError) {
557 char pathMsg[strlen(msg)+strlen(path)+4];
558 strcpy(pathMsg, msg);
559 strcat(pathMsg, " ");
560 strcat(pathMsg, path);
561 dyldAPIhalt("NSAddImage", pathMsg);
562 }
563 // not halting, so set error state for NSLinkEditError to find
564 setLastError(NSLinkEditOtherError, 0, path, msg);
565 free((void*)msg); // our free() will do nothing if msg is a string literal
566 image = NULL;
567 }
568 // free rpaths (getRPaths() malloc'ed each string)
569 for(std::vector<const char*>::iterator it=rpathsFromCallerImage.begin(); it != rpathsFromCallerImage.end(); ++it) {
570 const char* str = *it;
571 free((void*)str);
572 }
573 if ( image == NULL )
574 return NULL;
575 else
576 return image->machHeader();
577 }
578
579
580 const struct mach_header* NSAddImage(const char* path, uint32_t options)
581 {
582 if ( dyld::gLogAPIs )
583 dyld::log("%s(\"%s\", 0x%08X)\n", __func__, path, options);
584 const bool dontLoad = ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 );
585 const bool search = ( (options & NSADDIMAGE_OPTION_WITH_SEARCHING) != 0 );
586 const bool matchInstallName = ( (options & NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME) != 0 );
587 const bool abortOnError = ( (options & (NSADDIMAGE_OPTION_RETURN_ON_ERROR|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)) == 0 );
588 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
589 return addImage(callerAddress, path, search, dontLoad, matchInstallName, abortOnError);
590 }
591
592 bool NSAddLibrary(const char* path)
593 {
594 if ( dyld::gLogAPIs )
595 dyld::log("%s(\"%s\")\n", __func__, path);
596 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
597 return (addImage(callerAddress, path, false, false, false, false) != NULL);
598 }
599
600 bool NSAddLibraryWithSearching(const char* path)
601 {
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, true, false, false, false) != NULL);
606 }
607
608
609
610 //#define NSADDIMAGE_OPTION_NONE 0x0
611 //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
612 //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
613
614 bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName)
615 {
616 if ( dyld::gLogAPIs )
617 dyld::log("%s(%p, \"%s\")\n", __func__, (void *)mh, symbolName);
618 ImageLoader* image = dyld::findImageByMachHeader(mh);
619 if ( image != NULL ) {
620 if ( image->findExportedSymbol(symbolName, true, NULL) != NULL)
621 return true;
622 }
623 return false;
624 }
625
626
627 NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolName, uint32_t options)
628 {
629 if ( dyld::gLogAPIs )
630 dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__, mh, symbolName, options);
631 const ImageLoader::Symbol* symbol = NULL;
632 dyld::clearErrorMessage();
633 ImageLoader* image = dyld::findImageByMachHeader(mh);
634 if ( image != NULL ) {
635 try {
636 if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) {
637 image->bindAllLazyPointers(dyld::gLinkContext, true);
638 }
639 else if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW ) {
640 image->bindAllLazyPointers(dyld::gLinkContext, false);
641 }
642 }
643 catch (const char* msg) {
644 if ( (options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) == 0 ) {
645 dyldAPIhalt(__func__, msg);
646 }
647 }
648 symbol = image->findExportedSymbol(symbolName, true, NULL);
649 }
650 if ( dyld::gLogAPIs && (symbol == NULL) )
651 dyld::log("%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options);
652 return SymbolToNSSymbol(symbol);
653 }
654
655
656 // Note: This cannot have public name because dyld is built with a static copy of libc.a
657 // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
658 static bool client_NSIsSymbolNameDefined(const char* symbolName)
659 {
660 if ( dyld::gLogAPIs )
661 dyld::log("NSIsSymbolNameDefined(\"%s\")\n", symbolName);
662 const ImageLoader* image;
663 const ImageLoader::Symbol* sym;
664 return dyld::flatFindExportedSymbol(symbolName, &sym, &image);
665 }
666
667 bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint)
668 {
669 if ( dyld::gLogAPIs )
670 dyld::log("%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
671 const ImageLoader* image;
672 const ImageLoader::Symbol* sym;
673 bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
674 if ( ! found ) {
675 // hint failed, do slow search of all images
676 found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
677 }
678 if ( !found && dyld::gLogAPIs )
679 dyld::log("%s(\"%s\", \"%s\") => false \n", __func__, symbolName, libraryNameHint);
680 return found;
681 }
682
683 const char* NSNameOfSymbol(NSSymbol symbol)
684 {
685 if ( dyld::gLogAPIs )
686 dyld::log("%s(%p)\n", __func__, (void *)symbol);
687 const char* result = NULL;
688 ImageLoader* image = dyld::findImageContainingSymbol(symbol);
689 if ( image != NULL )
690 result = image->getExportedSymbolName(NSSymbolToSymbol(symbol));
691 return result;
692 }
693
694 void* NSAddressOfSymbol(NSSymbol symbol)
695 {
696 if ( dyld::gLogAPIs )
697 dyld::log("%s(%p)\n", __func__, (void *)symbol);
698 if ( symbol == NULL )
699 return NULL;
700 void* result = NULL;
701 ImageLoader* image = dyld::findImageContainingSymbol(symbol);
702 if ( image != NULL )
703 result = (void*)image->getExportedSymbolAddress(NSSymbolToSymbol(symbol), dyld::gLinkContext);
704 return result;
705 }
706
707 NSModule NSModuleForSymbol(NSSymbol symbol)
708 {
709 if ( dyld::gLogAPIs )
710 dyld::log("%s(%p)\n", __func__, (void *)symbol);
711 NSModule result = NULL;
712 ImageLoader* image = dyld::findImageContainingSymbol(symbol);
713 if ( image != NULL )
714 result = ImageLoaderToNSModule(image);
715 return result;
716 }
717
718
719
720
721 bool _dyld_all_twolevel_modules_prebound(void)
722 {
723 if ( dyld::gLogAPIs )
724 dyld::log("%s()\n", __func__);
725 return FALSE;
726 }
727
728 void _dyld_bind_objc_module(const void *objc_module)
729 {
730 if ( dyld::gLogAPIs )
731 dyld::log("%s(%p)\n", __func__, objc_module);
732 // do nothing, with new dyld everything already bound
733 }
734
735
736 bool _dyld_bind_fully_image_containing_address(const void* address)
737 {
738 if ( dyld::gLogAPIs )
739 dyld::log("%s(%p)\n", __func__, address);
740 dyld::clearErrorMessage();
741 ImageLoader* image = dyld::findImageContainingAddress(address);
742 if ( image != NULL ) {
743 try {
744 image->bindAllLazyPointers(dyld::gLinkContext, true);
745 return true;
746 }
747 catch (const char* msg) {
748 dyldAPIhalt(__func__, msg);
749 }
750 }
751 return false;
752 }
753
754 bool _dyld_image_containing_address(const void* address)
755 {
756 if ( dyld::gLogAPIs )
757 dyld::log("%s(%p)\n", __func__, address);
758 ImageLoader *imageLoader = dyld::findImageContainingAddress(address);
759 return (NULL != imageLoader);
760 }
761
762 static NSObjectFileImage createObjectImageFile(ImageLoader* image, const void* address = NULL, size_t len=0)
763 {
764 NSObjectFileImage result = new __NSObjectFileImage();
765 result->image = image;
766 result->imageBaseAddress = address;
767 result->imageLength = len;
768 sObjectFileImages.push_back(result);
769 return result;
770 }
771
772 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage)
773 {
774 if ( dyld::gLogAPIs )
775 dyld::log("%s(\"%s\", ...)\n", __func__, pathName);
776 try {
777 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
778 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
779
780 dyld::LoadContext context;
781 context.useSearchPaths = false;
782 context.useFallbackPaths = false;
783 context.useLdLibraryPath = false;
784 context.implicitRPath = false;
785 context.matchByInstallName = false;
786 context.dontLoad = false;
787 context.mustBeBundle = true;
788 context.mustBeDylib = false;
789 context.canBePIE = false;
790 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
791 context.rpath = NULL; // support not yet implemented
792
793 ImageLoader* image = dyld::load(pathName, context);
794 // Note: We DO NOT link the image! NSLinkModule will do that
795 if ( image != NULL ) {
796 if ( !image->isBundle() ) {
797 // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
798 return NSObjectFileImageInappropriateFile;
799 }
800 *objectFileImage = createObjectImageFile(image);
801 return NSObjectFileImageSuccess;
802 }
803 }
804 catch (const char* msg) {
805 //dyld::log("dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
806 dyld::garbageCollectImages();
807 free((void*)msg);
808 return NSObjectFileImageInappropriateFile;
809 }
810 return NSObjectFileImageFailure;
811 }
812
813
814 NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage *objectFileImage)
815 {
816 if ( dyld::gLogAPIs )
817 dyld::log("%s(%p, %lu, %p)\n", __func__, address, size, objectFileImage);
818
819 try {
820 ImageLoader* image = dyld::loadFromMemory((const uint8_t*)address, size, NULL);
821 if ( ! image->isBundle() ) {
822 // this API can only be used with bundles...
823 dyld::garbageCollectImages();
824 return NSObjectFileImageInappropriateFile;
825 }
826 // Note: We DO NOT link the image! NSLinkModule will do that
827 if ( image != NULL ) {
828 *objectFileImage = createObjectImageFile(image, address, size);
829 return NSObjectFileImageSuccess;
830 }
831 }
832 catch (const char* msg) {
833 free((void*)msg);
834 dyld::garbageCollectImages();
835 //dyld::log("dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg);
836 }
837 return NSObjectFileImageFailure;
838 }
839
840 static bool validOFI(NSObjectFileImage objectFileImage)
841 {
842 const int ofiCount = sObjectFileImages.size();
843 for (int i=0; i < ofiCount; ++i) {
844 if ( sObjectFileImages[i] == objectFileImage )
845 return true;
846 }
847 return false;
848 }
849
850 bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage)
851 {
852 if ( dyld::gLogAPIs )
853 dyld::log("%s(%p)\n", __func__, objectFileImage);
854
855 if ( validOFI(objectFileImage) ) {
856 // a failure during NSLinkModule will delete the image
857 if ( objectFileImage->image != NULL ) {
858 // if the image has never been linked or has been unlinked, the image is not in the list of valid images
859 // and we should delete it
860 bool linkedImage = dyld::validImage(objectFileImage->image);
861 if ( ! linkedImage ) {
862 ImageLoader::deleteImage(objectFileImage->image);
863 objectFileImage->image = NULL;
864 }
865 }
866
867 // remove from list of ofi's
868 for (std::vector<NSObjectFileImage>::iterator it=sObjectFileImages.begin(); it != sObjectFileImages.end(); it++) {
869 if ( *it == objectFileImage ) {
870 sObjectFileImages.erase(it);
871 break;
872 }
873 }
874
875 // if object was created from a memory, release that memory
876 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
877 if ( objectFileImage->imageBaseAddress != NULL ) {
878 bool freed = false;
879 if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 6) ) {
880 size_t sz = (*dyld::gLibSystemHelpers->malloc_size)(objectFileImage->imageBaseAddress);
881 if ( sz != 0 ) {
882 (*dyld::gLibSystemHelpers->free)((void*)(objectFileImage->imageBaseAddress));
883 freed = true;
884 }
885 }
886 if ( ! freed )
887 vm_deallocate(mach_task_self(), (vm_address_t)objectFileImage->imageBaseAddress, objectFileImage->imageLength);
888 }
889
890 // free ofi object
891 delete objectFileImage;
892
893 return true;
894 }
895 return false;
896 }
897
898 bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage)
899 {
900 if ( dyld::gLogAPIs )
901 dyld::log("%s(%p)\n", __func__, objectFileImage);
902 return objectFileImage->image->needsInitialization();
903 }
904
905 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage)
906 {
907 if ( dyld::gLogAPIs )
908 dyld::log("%s(%p)\n", __func__, objectFileImage);
909 return objectFileImage->image->getExportedSymbolCount();
910 }
911
912 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal)
913 {
914 if ( dyld::gLogAPIs )
915 dyld::log("%s(%p,%d)\n", __func__, objectFileImage, ordinal);
916 const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedExportedSymbol(ordinal);
917 return objectFileImage->image->getExportedSymbolName(sym);
918 }
919
920 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage)
921 {
922 if ( dyld::gLogAPIs )
923 dyld::log("%s(%p)\n", __func__, objectFileImage);
924 return objectFileImage->image->getImportedSymbolCount();
925 }
926
927 const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal,
928 bool* tentative_definition)
929 {
930 if ( dyld::gLogAPIs )
931 dyld::log("%s(%p,%d)\n", __func__, objectFileImage, ordinal);
932 const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedImportedSymbol(ordinal);
933 if ( tentative_definition != NULL ) {
934 ImageLoader::ReferenceFlags flags = objectFileImage->image->getImportedSymbolInfo(sym);
935 if ( (flags & ImageLoader::kTentativeDefinition) != 0 )
936 *tentative_definition = true;
937 else
938 *tentative_definition = false;
939 }
940 return objectFileImage->image->getImportedSymbolName(sym);
941 }
942
943 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage,
944 const char* segmentName, const char* sectionName, unsigned long* size)
945 {
946 if ( dyld::gLogAPIs )
947 dyld::log("%s(%p,%s, %s)\n", __func__, objectFileImage, segmentName, sectionName);
948
949 void* start;
950 size_t length;
951 if ( objectFileImage->image->getSectionContent(segmentName, sectionName, &start, &length) ) {
952 if ( size != NULL )
953 *size = length;
954 return start;
955 }
956 return NULL;
957 }
958
959
960
961 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName)
962 {
963 if ( dyld::gLogAPIs )
964 dyld::log("%s(%p,%s)\n", __func__, objectFileImage, symbolName);
965 const ImageLoader::Symbol* sym = objectFileImage->image->findExportedSymbol(symbolName, true, NULL);
966 return ( sym != NULL );
967 }
968
969
970
971 NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options)
972 {
973 if ( dyld::gLogAPIs )
974 dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__, objectFileImage, moduleName, options);
975
976 dyld::clearErrorMessage();
977 try {
978 if ( (options & NSLINKMODULE_OPTION_CAN_UNLOAD) != 0 )
979 objectFileImage->image->setCanUnload();
980
981 // NSLinkModule allows a bundle to be link multpile times
982 // each link causes the bundle to be copied to a new address
983 if ( objectFileImage->image->isLinked() ) {
984 // already linked, so clone a new one and link it
985 objectFileImage->image = dyld::cloneImage(objectFileImage->image);
986 }
987
988 // for memory based images, set moduleName as the name anyone calling _dyld_get_image_name() will see
989 if ( objectFileImage->image->getPath() == NULL ) {
990 objectFileImage->image->setPath(moduleName);
991 // <rdar://problem/8812589> dyld has NULL paths in image info array
992 dyld_image_info info;
993 info.imageLoadAddress = objectFileImage->image->machHeader();
994 info.imageFilePath = moduleName;
995 info.imageFileModDate = 0;
996 addImagesToAllImages(1, &info);
997 }
998
999 // support private bundles
1000 if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
1001 objectFileImage->image->setHideExports();
1002
1003 // set up linking options
1004 bool forceLazysBound = ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 );
1005
1006 // load libraries, rebase, bind, to make this image usable
1007 dyld::link(objectFileImage->image, forceLazysBound, false, ImageLoader::RPathChain(NULL,NULL));
1008
1009 // bump reference count to keep this bundle from being garbage collected
1010 objectFileImage->image->incrementDlopenReferenceCount();
1011
1012 // run initializers unless magic flag says not to
1013 if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) == 0 )
1014 dyld::runInitializers(objectFileImage->image);
1015
1016 return ImageLoaderToNSModule(objectFileImage->image);
1017 }
1018 catch (const char* msg) {
1019 dyld::garbageCollectImages();
1020 if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
1021 dyldAPIhalt(__func__, msg);
1022 // not halting, so set error state for NSLinkEditError to find
1023 setLastError(NSLinkEditOtherError, 0, moduleName, msg);
1024 // dyld::link() deleted the image so lose our reference
1025 objectFileImage->image = NULL;
1026 free((void*)msg);
1027 return NULL;
1028 }
1029 }
1030
1031
1032 #if OLD_LIBSYSTEM_SUPPORT
1033 // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
1034 static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options)
1035 {
1036 if ( dyld::gLogAPIs )
1037 dyld::log("%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr, moduleName, options); // note name/args translation
1038 ImageLoader* image = NULL;
1039 dyld::clearErrorMessage();
1040 try {
1041 const char* imageName = moduleName;
1042 image = dyld::loadFromMemory((const uint8_t*)object_addr, object_size, imageName);
1043
1044 if ( image != NULL ) {
1045 // support private bundles
1046 if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
1047 image->setHideExports();
1048
1049 // set up linking options
1050 bool forceLazysBound = ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 );
1051
1052 // load libraries, rebase, bind, to make this image usable
1053 dyld::link(image, forceLazysBound, false, ImageLoader::RPathChain(NULL,NULL));
1054
1055 // run initializers unless magic flag says not to
1056 if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) == 0 )
1057 dyld::runInitializers(image);
1058 }
1059 }
1060 catch (const char* msg) {
1061 if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
1062 dyldAPIhalt("NSLinkModule", msg);
1063 // not halting, so set error state for NSLinkEditError to find
1064 setLastError(NSLinkEditOtherError, 0, moduleName, msg);
1065 // if image was created for this bundle, destroy it
1066 if ( image != NULL ) {
1067 dyld::removeImage(image);
1068 ImageLoader::deleteImage(image);
1069 }
1070 image = NULL;
1071 free((void*)msg);
1072 }
1073 return ImageLoaderToNSModule(image);
1074 }
1075 #endif
1076
1077 NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
1078 {
1079 if ( dyld::gLogAPIs )
1080 dyld::log("%s(%p, \"%s\")\n", __func__, (void *)module, symbolName);
1081 ImageLoader* image = NSModuleToImageLoader(module);
1082 if ( image == NULL )
1083 return NULL;
1084 return SymbolToNSSymbol(image->findExportedSymbol(symbolName, false, NULL));
1085 }
1086
1087 const char* NSNameOfModule(NSModule module)
1088 {
1089 if ( dyld::gLogAPIs )
1090 dyld::log("%s(%p)\n", __func__, module);
1091 ImageLoader* image = NSModuleToImageLoader(module);
1092 if ( image == NULL )
1093 return NULL;
1094 return image->getPath();
1095 }
1096
1097 const char* NSLibraryNameForModule(NSModule module)
1098 {
1099 if ( dyld::gLogAPIs )
1100 dyld::log("%s(%p)\n", __func__, module);
1101 ImageLoader* image = NSModuleToImageLoader(module);
1102 if ( image == NULL )
1103 return NULL;
1104 return image->getPath();
1105 }
1106
1107 bool NSUnLinkModule(NSModule module, uint32_t options)
1108 {
1109 if ( dyld::gLogAPIs )
1110 dyld::log("%s(%p, 0x%08X)\n", __func__, module, options);
1111 if ( module == NULL )
1112 return false;
1113 ImageLoader* image = NSModuleToImageLoader(module);
1114 if ( image == NULL )
1115 return false;
1116 dyld::runImageStaticTerminators(image);
1117 if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 13) ) {
1118 __cxa_range_t ranges[3];
1119 int rangeCount = 0;
1120 for (unsigned int j=0; j < image->segmentCount(); ++j) {
1121 if ( !image->segExecutable(j) )
1122 continue;
1123 ranges[rangeCount].addr = (const void*)image->segActualLoadAddress(j);
1124 ranges[rangeCount].length = image->segSize(j);
1125 ++rangeCount;
1126 }
1127 (*dyld::gLibSystemHelpers->cxa_finalize_ranges)(ranges, rangeCount);
1128 }
1129 dyld::removeImage(image);
1130
1131 if ( (options & NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) != 0 )
1132 image->setLeaveMapped();
1133
1134 // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1135
1136 // Only delete image if there is no ofi referencing it
1137 // That means the ofi was destroyed after linking, so no one is left to delete this image
1138 const int ofiCount = sObjectFileImages.size();
1139 bool found = false;
1140 for (int i=0; i < ofiCount; ++i) {
1141 NSObjectFileImage ofi = sObjectFileImages[i];
1142 if ( ofi->image == image )
1143 found = true;
1144 }
1145 if ( !found )
1146 ImageLoader::deleteImage(image);
1147
1148 return true;
1149 }
1150
1151 // internal name and parameters do not match public name and parameters...
1152 static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit)
1153 {
1154 if ( dyld::gLogAPIs )
1155 dyld::log("NSLinkEditErrorHandlers()\n");
1156
1157 dyld::registerUndefinedHandler((dyld::UndefinedHandler)undefined);
1158 // no support for multiple or linkedit handlers
1159 }
1160
1161
1162
1163
1164 void NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString)
1165 {
1166 // FIXME FIXME
1167 *c = sLastErrorFileCode;
1168 *errorNumber = sLastErrorNo;
1169 *fileName = sLastErrorFilePath;
1170 *errorString = dyld::getErrorMessage();
1171 }
1172
1173
1174
1175 static void _dyld_register_binding_handler(void * (*bindingHandler)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions)
1176 {
1177 if ( dyld::gLogAPIs )
1178 dyld::log("%s()\n", __func__);
1179 dyld::gLinkContext.bindingHandler = bindingHandler;
1180 dyld::gLinkContext.bindingOptions = bindingOptions;
1181 }
1182
1183 #endif //DEPRECATED_APIS_SUPPORTED
1184
1185
1186 // Call by fork() in libSystem after the kernel trap is done on the child side
1187 void _dyld_fork_child()
1188 {
1189 if ( dyld::gLogAPIs )
1190 dyld::log("%s()\n", __func__);
1191 // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
1192 // in libSystem for the child of a fork. But dyld is built with a static copy
1193 // of libc.a and has its own copy of mach_task_self_ which we reset here.
1194 //
1195 // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
1196 // in mach_init() mach_task_self_ is initialized to task_self_trap().
1197 //
1198 extern mach_port_t mach_task_self_;
1199 mach_task_self_ = task_self_trap();
1200
1201 // If dyld is sending load/unload notices to CoreSymbolication, the shared memory
1202 // page is not copied on fork. <rdar://problem/6797342>
1203 // NULL the CoreSymbolication shared memory pointer to prevent a crash.
1204 dyld::gProcessInfo->coreSymbolicationShmPage = NULL;
1205 // for safety, make sure child starts with clean systemOrderFlag
1206 dyld::gProcessInfo->systemOrderFlag = 0;
1207 }
1208
1209
1210 #if DEPRECATED_APIS_SUPPORTED
1211 // returns true if prebinding was used in main executable
1212 bool _dyld_launched_prebound()
1213 {
1214 if ( dyld::gLogAPIs )
1215 dyld::log("%s()\n", __func__);
1216
1217 // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
1218 return dyld::mainExecutablePrebound();
1219 }
1220
1221
1222 //
1223 // _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
1224 // NSMakePrivateModulePublic() needed for the dlopen() to turn it's
1225 // RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
1226 // flag on the image for this module. If the module was found and it was
1227 // private then everything worked and TRUE is returned else FALSE is returned.
1228 //
1229 static bool NSMakePrivateModulePublic(NSModule module)
1230 {
1231 ImageLoader* image = NSModuleToImageLoader(module);
1232 if ( image != NULL ) {
1233 if ( image->hasHiddenExports() ) {
1234 image->setHideExports(false);
1235 return true;
1236 }
1237 }
1238 return false;
1239 }
1240
1241 #endif // DEPRECATED_APIS_SUPPORTED
1242
1243 int _dyld_func_lookup(const char* name, void** address)
1244 {
1245 for (const dyld_func* p = dyld_funcs; p->name != NULL; ++p) {
1246 if ( strcmp(p->name, name) == 0 ) {
1247 if( p->implementation == unimplemented )
1248 dyld::log("unimplemented dyld function: %s\n", p->name);
1249 *address = p->implementation;
1250 return true;
1251 }
1252 }
1253 *address = 0;
1254 return false;
1255 }
1256
1257
1258 static void registerThreadHelpers(const dyld::LibSystemHelpers* helpers)
1259 {
1260 dyld::gLibSystemHelpers = helpers;
1261
1262 // let gdb know it is safe to run code in inferior that might call malloc()
1263 dyld::gProcessInfo->libSystemInitialized = true;
1264
1265 #if !SUPPORT_ZERO_COST_EXCEPTIONS
1266 if ( helpers->version >= 5 ) {
1267 // create key use by dyld exception handling
1268 pthread_key_t key;
1269 int result = helpers->pthread_key_create(&key, NULL);
1270 if ( result == 0 )
1271 __Unwind_SjLj_SetThreadKey(key);
1272 }
1273 #endif
1274 }
1275
1276
1277 static void dlerrorClear()
1278 {
1279 if ( dyld::gLibSystemHelpers != NULL ) {
1280 // <rdar://problem/10595338> dlerror buffer leak
1281 // dlerrorClear() should not force allocation, but zero it if already allocated
1282 if ( dyld::gLibSystemHelpers->version >= 10 ) {
1283 if ( ! (*dyld::gLibSystemHelpers->hasPerThreadBufferFor_dlerror)() )
1284 return;
1285 }
1286
1287 // first char of buffer is flag whether string (starting at second char) is valid
1288 char* buffer = (*dyld::gLibSystemHelpers->getThreadBufferFor_dlerror)(2);
1289 buffer[0] = '\0';
1290 buffer[1] = '\0';
1291 }
1292 }
1293
1294 static void dlerrorSet(const char* msg)
1295 {
1296 if ( dyld::gLibSystemHelpers != NULL ) {
1297 // first char of buffer is flag whether string (starting at second char) is valid
1298 char* buffer = (*dyld::gLibSystemHelpers->getThreadBufferFor_dlerror)(strlen(msg)+2);
1299 buffer[0] = '\1';
1300 strcpy(&buffer[1], msg);
1301 }
1302 }
1303
1304
1305 bool dlopen_preflight(const char* path)
1306 {
1307 if ( dyld::gLogAPIs )
1308 dyld::log("%s(%s)\n", __func__, path);
1309
1310 dlerrorClear();
1311
1312 #if DYLD_SHARED_CACHE_SUPPORT
1313 // <rdar://problem/5910137> dlopen_preflight() on image in shared cache leaves it loaded but not objc initialized
1314 // if requested path is to something in the dyld shared cache, always succeed
1315 if ( dyld::inSharedCache(path) )
1316 return true;
1317 #endif
1318
1319 CRSetCrashLogMessage("dyld: in dlopen_preflight()");
1320
1321 bool result = false;
1322 std::vector<const char*> rpathsFromCallerImage;
1323 try {
1324 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1325 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1326 // for dlopen, use rpath from caller image and from main executable
1327 if ( callerImage != NULL )
1328 callerImage->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
1329 ImageLoader::RPathChain callersRPaths(NULL, &rpathsFromCallerImage);
1330 if ( callerImage != dyld::mainExecutable() ) {
1331 dyld::mainExecutable()->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
1332 }
1333
1334 ImageLoader* image = NULL;
1335 const bool leafName = (strchr(path, '/') == NULL);
1336 const bool absolutePath = (path[0] == '/');
1337 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1338 char canonicalPath[PATH_MAX];
1339 // <rdar://problem/7017050> dlopen() not opening frameworks from shared cache with // or ./ in path
1340 if ( !leafName ) {
1341 // make path canonical if it contains a // or ./
1342 if ( (strstr(path, "//") != NULL) || (strstr(path, "./") != NULL) ) {
1343 const char* lastSlash = strrchr(path, '/');
1344 char dirPath[PATH_MAX];
1345 if ( strlcpy(dirPath, path, sizeof(dirPath)) < sizeof(dirPath) ) {
1346 dirPath[lastSlash-path] = '\0';
1347 if ( realpath(dirPath, canonicalPath) ) {
1348 strlcat(canonicalPath, "/", sizeof(canonicalPath));
1349 if ( strlcat(canonicalPath, lastSlash+1, sizeof(canonicalPath)) < sizeof(canonicalPath) ) {
1350 // if all fit in buffer, use new canonical path
1351 path = canonicalPath;
1352 }
1353 }
1354 }
1355 }
1356 }
1357 #endif
1358 dyld::LoadContext context;
1359 context.useSearchPaths = true;
1360 context.useFallbackPaths= leafName; // a partial path implies don't use fallback paths
1361 context.useLdLibraryPath= leafName; // a leafname implies should search
1362 context.implicitRPath = !absolutePath; // a non-absolute path implies try rpath searching
1363 context.matchByInstallName = true;
1364 context.dontLoad = false;
1365 context.mustBeBundle = false;
1366 context.mustBeDylib = false;
1367 context.canBePIE = true;
1368 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
1369 context.rpath = &callersRPaths; // rpaths from caller and main executable
1370
1371 image = load(path, context);
1372 if ( image != NULL ) {
1373 dyld::preflight(image, callersRPaths); // image object deleted by dyld::preflight()
1374 result = true;
1375 }
1376 }
1377 catch (const char* msg) {
1378 const char* str = dyld::mkstringf("dlopen_preflight(%s): %s", path, msg);
1379 dlerrorSet(str);
1380 free((void*)str);
1381 free((void*)msg); // our free() will do nothing if msg is a string literal
1382 }
1383 // free rpaths (getRPaths() malloc'ed each string)
1384 for(std::vector<const char*>::iterator it=rpathsFromCallerImage.begin(); it != rpathsFromCallerImage.end(); ++it) {
1385 const char* str = *it;
1386 free((void*)str);
1387 }
1388 CRSetCrashLogMessage(NULL);
1389 return result;
1390 }
1391
1392
1393 void* dlopen(const char* path, int mode)
1394 {
1395 if ( dyld::gLogAPIs )
1396 dyld::log("%s(%s, 0x%08X)\n", __func__, ((path==NULL) ? "NULL" : path), mode);
1397
1398 dlerrorClear();
1399
1400 // passing NULL for path means return magic object
1401 if ( path == NULL ) {
1402 // RTLD_FIRST means any dlsym() calls on the handle should only search that handle and not subsequent images
1403 if ( (mode & RTLD_FIRST) != 0 )
1404 return RTLD_MAIN_ONLY;
1405 else
1406 return RTLD_DEFAULT;
1407 }
1408
1409 // acquire global dyld lock (dlopen is special - libSystem glue does not do locking)
1410 bool lockHeld = false;
1411 if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 4) ) {
1412 dyld::gLibSystemHelpers->acquireGlobalDyldLock();
1413 CRSetCrashLogMessage("dyld: in dlopen()");
1414 lockHeld = true;
1415 }
1416
1417 void* result = NULL;
1418 ImageLoader* image = NULL;
1419 std::vector<const char*> rpathsFromCallerImage;
1420 try {
1421 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1422 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1423 // for dlopen, use rpath from caller image and from main executable
1424 if ( callerImage != NULL )
1425 callerImage->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
1426 ImageLoader::RPathChain callersRPaths(NULL, &rpathsFromCallerImage);
1427 if ( callerImage != dyld::mainExecutable() ) {
1428 dyld::mainExecutable()->getRPaths(dyld::gLinkContext, rpathsFromCallerImage);
1429 }
1430
1431 const bool leafName = (strchr(path, '/') == NULL);
1432 const bool absolutePath = (path[0] == '/');
1433 #if __IPHONE_OS_VERSION_MIN_REQUIRED
1434 char canonicalPath[PATH_MAX];
1435 // <rdar://problem/7017050> dlopen() not opening frameworks from shared cache with // or ./ in path
1436 if ( !leafName ) {
1437 // make path canonical if it contains a // or ./
1438 if ( (strstr(path, "//") != NULL) || (strstr(path, "./") != NULL) ) {
1439 const char* lastSlash = strrchr(path, '/');
1440 char dirPath[PATH_MAX];
1441 if ( strlcpy(dirPath, path, sizeof(dirPath)) < sizeof(dirPath) ) {
1442 dirPath[lastSlash-path] = '\0';
1443 if ( realpath(dirPath, canonicalPath) ) {
1444 strlcat(canonicalPath, "/", sizeof(canonicalPath));
1445 if ( strlcat(canonicalPath, lastSlash+1, sizeof(canonicalPath)) < sizeof(canonicalPath) ) {
1446 // if all fit in buffer, use new canonical path
1447 path = canonicalPath;
1448 }
1449 }
1450 }
1451 }
1452 }
1453 #endif
1454 dyld::LoadContext context;
1455 context.useSearchPaths = true;
1456 context.useFallbackPaths= leafName; // a partial path means no fallback paths
1457 context.useLdLibraryPath= leafName; // a leafname implies should search
1458 context.implicitRPath = !absolutePath; // a non-absolute path implies try rpath searching
1459 context.matchByInstallName = true;
1460 context.dontLoad = ( (mode & RTLD_NOLOAD) != 0 );
1461 context.mustBeBundle = false;
1462 context.mustBeDylib = false;
1463 context.canBePIE = true;
1464 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
1465 context.rpath = &callersRPaths; // rpaths from caller and main executable
1466
1467 image = load(path, context);
1468 if ( image != NULL ) {
1469 // bump reference count. Do this before link() so that if an initializer calls dlopen and fails
1470 // this image is not garbage collected
1471 image->incrementDlopenReferenceCount();
1472 // link in all dependents
1473 if ( (mode & RTLD_NOLOAD) == 0 ) {
1474 bool alreadyLinked = image->isLinked();
1475 bool forceLazysBound = ( (mode & RTLD_NOW) != 0 );
1476 dyld::link(image, forceLazysBound, false, callersRPaths);
1477 if ( ! alreadyLinked ) {
1478 // only hide exports if image is not already in use
1479 if ( (mode & RTLD_LOCAL) != 0 )
1480 image->setHideExports(true);
1481 }
1482 }
1483
1484 // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
1485 // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
1486 // The subtle differences are:
1487 // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
1488 // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
1489 if ( (mode & RTLD_NODELETE) != 0 )
1490 image->setLeaveMapped();
1491
1492 // release global dyld lock early, this enables initializers to do threaded operations
1493 if ( lockHeld ) {
1494 CRSetCrashLogMessage(NULL);
1495 dyld::gLibSystemHelpers->releaseGlobalDyldLock();
1496 lockHeld = false;
1497 }
1498
1499 // RTLD_NOLOAD means dlopen should fail unless path is already loaded.
1500 // don't run initializers when RTLD_NOLOAD is set. This only matters if dlopen() is
1501 // called from within an initializer because it can cause initializers to run
1502 // out of order. Most uses of RTLD_NOLOAD are "probes". If they want initialzers
1503 // to run, then don't use RTLD_NOLOAD.
1504 if ( (mode & RTLD_NOLOAD) == 0 ) {
1505 // run initializers
1506 dyld::runInitializers(image);
1507 }
1508
1509 // RTLD_FIRST means any dlsym() calls on the handle should only search that handle and not subsequent images
1510 // this is tracked by setting the low bit of the handle, which is usually zero by malloc alignment
1511 if ( (mode & RTLD_FIRST) != 0 )
1512 result = (void*)(((uintptr_t)image)|1);
1513 else
1514 result = image;
1515 }
1516 }
1517 catch (const char* msg) {
1518 if ( image != NULL ) {
1519 // load() succeeded but, link() failed
1520 // back down reference count and do GC
1521 image->decrementDlopenReferenceCount();
1522 if ( image->dlopenCount() == 0 )
1523 dyld::garbageCollectImages();
1524 }
1525 const char* str = dyld::mkstringf("dlopen(%s, %d): %s", path, mode, msg);
1526 if ( dyld::gLogAPIs )
1527 dyld::log(" %s() failed, error: '%s'\n", __func__, str);
1528 dlerrorSet(str);
1529 free((void*)str);
1530 free((void*)msg); // our free() will do nothing if msg is a string literal
1531 result = NULL;
1532 }
1533 // free rpaths (getRPaths() malloc'ed each string)
1534 for(std::vector<const char*>::iterator it=rpathsFromCallerImage.begin(); it != rpathsFromCallerImage.end(); ++it) {
1535 const char* str = *it;
1536 free((void*)str);
1537 }
1538
1539 // when context.dontLoad is set, load() returns NULL instead of throwing an exception
1540 if ( (mode & RTLD_NOLOAD) && (result == NULL) ) {
1541 dlerrorSet("image not already loaded");
1542 }
1543
1544 if ( lockHeld ) {
1545 CRSetCrashLogMessage(NULL);
1546 dyld::gLibSystemHelpers->releaseGlobalDyldLock();
1547 }
1548 if ( dyld::gLogAPIs && (result != NULL) )
1549 dyld::log(" %s(%s) ==> %p\n", __func__, path, result);
1550 return result;
1551 }
1552
1553
1554
1555 int dlclose(void* handle)
1556 {
1557 if ( dyld::gLogAPIs )
1558 dyld::log("%s(%p)\n", __func__, handle);
1559
1560 // silently accept magic handles for main executable
1561 if ( handle == RTLD_MAIN_ONLY )
1562 return 0;
1563 if ( handle == RTLD_DEFAULT )
1564 return 0;
1565
1566 ImageLoader* image = (ImageLoader*)(((uintptr_t)handle) & (-4)); // clear mode bits
1567 if ( dyld::validImage(image) ) {
1568 dlerrorClear();
1569 // decrement use count
1570 if ( image->decrementDlopenReferenceCount() ) {
1571 dlerrorSet("dlclose() called too many times");
1572 return -1;
1573 }
1574 // remove image if reference count went to zero
1575 if ( image->dlopenCount() == 0 )
1576 dyld::garbageCollectImages();
1577 return 0;
1578 }
1579 else {
1580 dlerrorSet("invalid handle passed to dlclose()");
1581 return -1;
1582 }
1583 }
1584
1585
1586
1587 int dladdr(const void* address, Dl_info* info)
1588 {
1589 if ( dyld::gLogAPIs )
1590 dyld::log("%s(%p, %p)\n", __func__, address, info);
1591
1592 CRSetCrashLogMessage("dyld: in dladdr()");
1593 ImageLoader* image = dyld::findImageContainingAddress(address);
1594 if ( image != NULL ) {
1595 info->dli_fname = image->getRealPath();
1596 info->dli_fbase = (void*)image->machHeader();
1597 if ( address == info->dli_fbase ) {
1598 // special case lookup of header
1599 info->dli_sname = "__dso_handle";
1600 info->dli_saddr = info->dli_fbase;
1601 CRSetCrashLogMessage(NULL);
1602 return 1; // success
1603 }
1604 // find closest symbol in the image
1605 info->dli_sname = image->findClosestSymbol(address, (const void**)&info->dli_saddr);
1606 // never return the mach_header symbol
1607 if ( info->dli_saddr == info->dli_fbase ) {
1608 info->dli_sname = NULL;
1609 info->dli_saddr = NULL;
1610 CRSetCrashLogMessage(NULL);
1611 return 1; // success
1612 }
1613 if ( info->dli_sname != NULL ) {
1614 if ( info->dli_sname[0] == '_' )
1615 info->dli_sname = info->dli_sname +1; // strip off leading underscore
1616 //dyld::log("dladdr(%p) => %p %s\n", address, info->dli_saddr, info->dli_sname);
1617 CRSetCrashLogMessage(NULL);
1618 return 1; // success
1619 }
1620 info->dli_sname = NULL;
1621 info->dli_saddr = NULL;
1622 CRSetCrashLogMessage(NULL);
1623 return 1; // success
1624 }
1625 CRSetCrashLogMessage(NULL);
1626 return 0; // failure
1627 }
1628
1629
1630 char* dlerror()
1631 {
1632 if ( dyld::gLogAPIs )
1633 dyld::log("%s()\n", __func__);
1634
1635 if ( dyld::gLibSystemHelpers != NULL ) {
1636 // if using newer libdyld.dylib and buffer if buffer not yet allocated, return NULL
1637 if ( dyld::gLibSystemHelpers->version >= 10 ) {
1638 if ( ! (*dyld::gLibSystemHelpers->hasPerThreadBufferFor_dlerror)() )
1639 return NULL;
1640 }
1641
1642 // first char of buffer is flag whether string (starting at second char) is valid
1643 char* buffer = (*dyld::gLibSystemHelpers->getThreadBufferFor_dlerror)(2);
1644 if ( buffer[0] != '\0' ) { // if valid buffer
1645 buffer[0] = '\0'; // mark invalid, so next call to dlerror returns NULL
1646 return &buffer[1]; // return message
1647 }
1648 }
1649 return NULL;
1650 }
1651
1652 void* dlsym(void* handle, const char* symbolName)
1653 {
1654 if ( dyld::gLogAPIs )
1655 dyld::log("%s(%p, %s)\n", __func__, handle, symbolName);
1656
1657 CRSetCrashLogMessage("dyld: in dlsym()");
1658 dlerrorClear();
1659
1660 const ImageLoader* image;
1661 const ImageLoader::Symbol* sym;
1662
1663 // dlsym() assumes symbolName passed in is same as in C source code
1664 // dyld assumes all symbol names have an underscore prefix
1665 char underscoredName[strlen(symbolName)+2];
1666 underscoredName[0] = '_';
1667 strcpy(&underscoredName[1], symbolName);
1668
1669 // magic "search all" handle
1670 if ( handle == RTLD_DEFAULT ) {
1671 if ( dyld::flatFindExportedSymbol(underscoredName, &sym, &image) ) {
1672 CRSetCrashLogMessage(NULL);
1673 return (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
1674 }
1675 const char* str = dyld::mkstringf("dlsym(RTLD_DEFAULT, %s): symbol not found", symbolName);
1676 dlerrorSet(str);
1677 free((void*)str);
1678 CRSetCrashLogMessage(NULL);
1679 return NULL;
1680 }
1681
1682 // magic "search only main executable" handle
1683 if ( handle == RTLD_MAIN_ONLY ) {
1684 image = dyld::mainExecutable();
1685 sym = image->findExportedSymbol(underscoredName, true, &image); // search RTLD_FIRST way
1686 if ( sym != NULL ) {
1687 CRSetCrashLogMessage(NULL);
1688 return (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
1689 }
1690 const char* str = dyld::mkstringf("dlsym(RTLD_MAIN_ONLY, %s): symbol not found", symbolName);
1691 dlerrorSet(str);
1692 free((void*)str);
1693 CRSetCrashLogMessage(NULL);
1694 return NULL;
1695 }
1696
1697 // magic "search what I would see" handle
1698 if ( handle == RTLD_NEXT ) {
1699 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1700 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1701 sym = callerImage->findExportedSymbolInDependentImages(underscoredName, dyld::gLinkContext, &image); // don't search image, but do search what it links against
1702 if ( sym != NULL ) {
1703 CRSetCrashLogMessage(NULL);
1704 return (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
1705 }
1706 const char* str = dyld::mkstringf("dlsym(RTLD_NEXT, %s): symbol not found", symbolName);
1707 dlerrorSet(str);
1708 free((void*)str);
1709 CRSetCrashLogMessage(NULL);
1710 return NULL;
1711 }
1712 // magic "search me, then what I would see" handle
1713 if ( handle == RTLD_SELF ) {
1714 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1715 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1716 sym = callerImage->findExportedSymbolInImageOrDependentImages(underscoredName, dyld::gLinkContext, &image); // search image and what it links against
1717 if ( sym != NULL ) {
1718 CRSetCrashLogMessage(NULL);
1719 return (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext);
1720 }
1721 const char* str = dyld::mkstringf("dlsym(RTLD_SELF, %s): symbol not found", symbolName);
1722 dlerrorSet(str);
1723 free((void*)str);
1724 CRSetCrashLogMessage(NULL);
1725 return NULL;
1726 }
1727 // real handle
1728 image = (ImageLoader*)(((uintptr_t)handle) & (-4)); // clear mode bits
1729 if ( dyld::validImage(image) ) {
1730 if ( (((uintptr_t)handle) & 1) != 0 )
1731 sym = image->findExportedSymbol(underscoredName, true, &image); // search RTLD_FIRST way
1732 else
1733 sym = image->findExportedSymbolInImageOrDependentImages(underscoredName, dyld::gLinkContext, &image); // search image and what it links against
1734
1735 if ( sym != NULL ) {
1736 CRSetCrashLogMessage(NULL);
1737 ImageLoader* callerImage = NULL;
1738 if ( sDynamicInterposing ) {
1739 // only take time to look up caller, if dynamic interposing in use
1740 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1741 callerImage = dyld::findImageContainingAddress(callerAddress);
1742 }
1743 return (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext, callerImage);
1744 }
1745 const char* str = dyld::mkstringf("dlsym(%p, %s): symbol not found", handle, symbolName);
1746 dlerrorSet(str);
1747 free((void*)str);
1748 }
1749 else {
1750 dlerrorSet("invalid handle passed to dlsym()");
1751 }
1752 CRSetCrashLogMessage(NULL);
1753 return NULL;
1754 }
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765 const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1766 {
1767 return dyld::gProcessInfo;
1768 }
1769
1770 #if SUPPORT_ZERO_COST_EXCEPTIONS
1771 static bool client_dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
1772 {
1773 //if ( dyld::gLogAPIs )
1774 // dyld::log("%s(%p, %p)\n", __func__, addr, info);
1775
1776 ImageLoader* image = dyld::findImageContainingAddress(addr);
1777 if ( image != NULL ) {
1778 image->getUnwindInfo(info);
1779 return true;
1780 }
1781 return false;
1782 }
1783 #endif
1784
1785
1786 void dyld_register_image_state_change_handler(dyld_image_states state, bool batch,
1787 dyld_image_state_change_handler handler)
1788 {
1789 if ( dyld::gLogAPIs )
1790 dyld::log("%s(%d, %d, %p)\n", __func__, state, batch, handler);
1791 if ( batch )
1792 dyld::registerImageStateBatchChangeHandler(state, handler);
1793 else
1794 dyld::registerImageStateSingleChangeHandler(state, handler);
1795 }
1796
1797 const char* dyld_image_path_containing_address(const void* address)
1798 {
1799 if ( dyld::gLogAPIs )
1800 dyld::log("%s(%p)\n", __func__, address);
1801
1802 ImageLoader* image = dyld::findImageContainingAddress(address);
1803 if ( image != NULL )
1804 return image->getRealPath();
1805 return NULL;
1806 }
1807
1808
1809
1810 bool dyld_shared_cache_some_image_overridden()
1811 {
1812 #if DYLD_SHARED_CACHE_SUPPORT
1813 return dyld::gSharedCacheOverridden;
1814 #else
1815 return true;
1816 #endif
1817 }
1818
1819
1820 void dyld_dynamic_interpose(const struct mach_header* mh, const struct dyld_interpose_tuple array[], size_t count)
1821 {
1822 if ( mh == NULL )
1823 return;
1824 if ( array == NULL )
1825 return;
1826 if ( count == 0 )
1827 return;
1828 ImageLoader* image = dyld::findImageByMachHeader(mh);
1829 if ( image == NULL )
1830 return;
1831
1832 // make pass at bound references in this image and update them
1833 dyld::gLinkContext.dynamicInterposeArray = array;
1834 dyld::gLinkContext.dynamicInterposeCount = count;
1835 image->dynamicInterpose(dyld::gLinkContext);
1836 dyld::gLinkContext.dynamicInterposeArray = NULL;
1837 dyld::gLinkContext.dynamicInterposeCount = 0;
1838
1839 // leave interposing info so any future (lazy) binding will get it too
1840 image->addDynamicInterposingTuples(array, count);
1841
1842 sDynamicInterposing = true;
1843 }
1844
1845
1846