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