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