dyld-43.1.tar.gz
[apple/dyld.git] / src / dyldAPIs.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2005 Apple Computer, 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
31 #include <stddef.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <mach/mach.h>
35 #include <sys/time.h>
36
37 extern "C" mach_port_name_t task_self_trap(void); // can't include <System/mach/mach_traps.h> because it is missing extern C
38
39 #include "mach-o/dyld_gdb.h"
40 #include "mach-o/dyld.h"
41 #include "mach-o/dyld_priv.h"
42 #include "dlfcn.h"
43
44 #include "ImageLoader.h"
45 #include "dyld.h"
46 #include "dyldLibSystemThreadHelpers.h"
47
48 static char sLastErrorFilePath[1024];
49 static NSLinkEditErrors sLastErrorFileCode;
50 static int sLastErrorNo;
51
52
53 // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
54 // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
55 // This conditional keeps support for old libSystem's which needed some help implementing the API's
56 #define OLD_LIBSYSTEM_SUPPORT 1
57
58
59 // The following functions have no prototype in any header. They are special cases
60 // where _dyld_func_lookup() is used directly.
61 static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit);
62 static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options);
63 static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions);
64 static void _dyld_fork_prepare();
65 static void _dyld_fork_parent();
66 static void _dyld_fork_child();
67 static void _dyld_fork_child_final();
68 static void _dyld_make_delayed_module_initializer_calls();
69 static void _dyld_mod_term_funcs();
70 static bool NSMakePrivateModulePublic(NSModule module);
71 static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header);
72 static void registerThreadHelpers(const dyld::ThreadingHelpers*);
73 static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags);
74 static const struct dyld_all_image_infos* _dyld_get_all_image_infos();
75
76 // The following functions are dyld API's, but since dyld links with a static copy of libc.a
77 // the public name cannot be used.
78 static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module);
79 static bool client_NSIsSymbolNameDefined(const char* symbolName);
80
81
82 static void unimplemented()
83 {
84 dyld::halt("unimplemented dyld function\n");
85 }
86
87 struct dyld_func {
88 const char* name;
89 void* implementation;
90 };
91
92 static struct dyld_func dyld_funcs[] = {
93 {"__dyld_image_count", (void*)_dyld_image_count },
94 {"__dyld_get_image_header", (void*)_dyld_get_image_header },
95 {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide },
96 {"__dyld_get_image_name", (void*)_dyld_get_image_name },
97 {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind },
98 {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint },
99 {"__dyld_lookup_and_bind_objc", (void*)unimplemented },
100 {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully },
101 {"__dyld_install_handlers", (void*)_dyld_install_handlers },
102 {"__dyld_link_edit_error", (void*)NSLinkEditError },
103 #if OLD_LIBSYSTEM_SUPPORT
104 {"__dyld_link_module", (void*)_dyld_link_module },
105 #endif
106 {"__dyld_unlink_module", (void*)NSUnLinkModule },
107 {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image },
108 {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image },
109 {"__dyld_register_func_for_link_module", (void*)unimplemented },
110 {"__dyld_register_func_for_unlink_module", (void*)unimplemented },
111 {"__dyld_register_func_for_replace_module", (void*)unimplemented },
112 {"__dyld_get_objc_module_sect_for_module", (void*)unimplemented },
113 {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module },
114 {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address },
115 {"__dyld_image_containing_address", (void*)_dyld_image_containing_address },
116 {"__dyld_get_image_header_containing_address", (void*)_dyld_get_image_header_containing_address },
117 {"__dyld_moninit", (void*)_dyld_moninit },
118 {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler },
119 {"__dyld_fork_prepare", (void*)_dyld_fork_prepare },
120 {"__dyld_fork_parent", (void*)_dyld_fork_parent },
121 {"__dyld_fork_child", (void*)_dyld_fork_child },
122 {"__dyld_fork_child_final", (void*)_dyld_fork_child_final },
123 {"__dyld_fork_mach_init", (void*)unimplemented },
124 {"__dyld_make_delayed_module_initializer_calls",(void*)_dyld_make_delayed_module_initializer_calls },
125 {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol },
126 {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol },
127 {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol },
128 {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol },
129 {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint },
130 {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule},
131 {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage},
132 {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic},
133 {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined},
134 {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint },
135 {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage},
136 {"__dyld_NSNameOfModule", (void*)NSNameOfModule },
137 {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule },
138 {"__dyld_NSAddLibrary", (void*)NSAddLibrary },
139 {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching },
140 {"__dyld_NSAddImage", (void*)NSAddImage },
141 {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath },
142 {"__dyld_launched_prebound", (void*)_dyld_launched_prebound },
143 {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound },
144 {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib },
145 {"__dyld_mod_term_funcs", (void*)_dyld_mod_term_funcs },
146 {"__dyld_install_link_edit_symbol_handlers", (void*)dyld::registerZeroLinkHandlers },
147 {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile },
148 {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory },
149 {"__dyld_NSCreateCoreFileImageFromFile", (void*)unimplemented },
150 {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage },
151 {"__dyld_NSLinkModule", (void*)NSLinkModule },
152 {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage },
153 {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage },
154 {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage },
155 {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage },
156 {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage },
157 {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage },
158 {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage },
159 {"__dyld_NSFindSectionAndOffsetInObjectFileImage", (void*)NSFindSectionAndOffsetInObjectFileImage },
160 {"__dyld_register_thread_helpers", (void*)registerThreadHelpers },
161 {"__dyld_dladdr", (void*)dladdr },
162 {"__dyld_dlclose", (void*)dlclose },
163 {"__dyld_dlerror", (void*)dlerror },
164 {"__dyld_dlopen", (void*)dlopen },
165 {"__dyld_dlsym", (void*)dlsym },
166 {"__dyld_update_prebinding", (void*)_dyld_update_prebinding },
167 {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos },
168 {NULL, 0}
169 };
170
171
172
173 // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
174 inline NSSymbol SymbolToNSSymbol(const ImageLoader::Symbol* sym)
175 {
176 return (NSSymbol)sym;
177 }
178 inline const ImageLoader::Symbol* NSSymbolToSymbol(NSSymbol sym)
179 {
180 return (const ImageLoader::Symbol*)sym;
181 }
182
183 // dyld's abstract type NSModule is implemented as ImageLoader*
184 inline NSModule ImageLoaderToNSModule(ImageLoader* image)
185 {
186 return (NSModule)image;
187 }
188 inline ImageLoader* NSModuleToImageLoader(NSModule module)
189 {
190 ImageLoader* image = (ImageLoader*)module;
191 if ( dyld::validImage(image) )
192 return image;
193 return NULL;
194 }
195
196 // actual definition for opaque type
197 struct __NSObjectFileImage
198 {
199 ImageLoader* image;
200 const void* imageBaseAddress; // not used with OFI created from files
201 size_t imageLength; // not used with OFI created from files
202 };
203 static std::vector<NSObjectFileImage> sObjectFileImages;
204
205
206
207 //
208 // __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
209 // The contained image is delete in one of two places:
210 // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
211 // NSDestroyObjectFileImage deletes the image if image is not in list of valid images
212 //
213
214
215 static void dyldAPIhalt(const char* apiName, const char* errorMsg)
216 {
217 fprintf(stderr, "dyld: %s() error\n", apiName);
218 dyld::halt(errorMsg);
219 }
220
221
222
223 static void setLastError(NSLinkEditErrors code, int errnum, const char* file, const char* message)
224 {
225 dyld::setErrorMessage(message);
226 strncpy(sLastErrorFilePath, file, 1024);
227 sLastErrorFilePath[1023] = '\0';
228 sLastErrorFileCode = code;
229 sLastErrorNo = errnum;
230 }
231
232
233 /*
234 *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
235 * copies the path of the executable into the buffer and returns 0 if the path
236 * was successfully copied in the provided buffer. If the buffer is not large
237 * enough, -1 is returned and the expected buffer size is copied in *bufsize.
238 * Note that _NSGetExecutablePath will return "a path" to the executable not a
239 * "real path" to the executable. That is the path may be a symbolic link and
240 * not the real file. And with deep directories the total bufsize needed could
241 * be more than MAXPATHLEN.
242 */
243 int _NSGetExecutablePath(char* buf, uint32_t *bufsize)
244 {
245 if ( dyld::gLogAPIs )
246 fprintf(stderr, "%s(...)\n", __func__);
247 const char* exePath = dyld::getExecutablePath();
248 if(*bufsize < strlen(exePath) + 1){
249 *bufsize = strlen(exePath) + 1;
250 return -1;
251 }
252 strcpy(buf, exePath);
253 return 0;
254 }
255
256
257 //
258 // _dyld_call_module_initializers_for_dylib() is the dyld side of
259 // __initialize_Cplusplus() which is in dylib1.o.
260 // It is intended to only be called inside -init rouintes.
261 // -init routines are called before module initializers (what C++
262 // initializers use). Calling __initialize_Cplusplus() in a -init
263 // routine causes the module initializers for an image to be called
264 // which then allows C++ to be used inside a -init routine
265 //
266 static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header)
267 {
268 if ( dyld::gLogAPIs )
269 fprintf(stderr, "__initialize_Cplusplus()\n");
270
271 // for now, do nothing...
272 }
273
274
275 void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module)
276 {
277 if ( dyld::gLogAPIs )
278 fprintf(stderr, "%s(\"%s\", %p, %p)\n", __func__, symbolName, address, module);
279 ImageLoader* image;
280 const ImageLoader::Symbol* sym;
281 dyld::clearErrorMessage();
282 if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
283 try {
284 dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
285 if ( address != NULL)
286 *address = (void*)image->getExportedSymbolAddress(sym);
287 if ( module != NULL)
288 *module = ImageLoaderToNSModule(image);
289 }
290 catch (const char* msg) {
291 dyldAPIhalt(__func__, msg);
292 }
293 }
294 else {
295 // on failure to find symbol return NULLs
296 if ( address != NULL)
297 *address = NULL;
298 if ( module != NULL)
299 *module = NULL;
300 }
301 }
302
303 // Note: This cannot have public name because dyld is built with a static copy of libc.a
304 // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
305 static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module)
306 {
307 if ( dyld::gLogAPIs )
308 fprintf(stderr, "_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName, address, module);
309 ImageLoader* image;
310 const ImageLoader::Symbol* sym;
311 if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
312 if ( address != NULL)
313 *address = (void*)image->getExportedSymbolAddress(sym);
314 if ( module != NULL)
315 *module = ImageLoaderToNSModule(image);
316 }
317 else {
318 // on failure to find symbol return NULLs
319 if ( address != NULL)
320 *address = NULL;
321 if ( module != NULL)
322 *module = NULL;
323 }
324 }
325
326 void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* library_name_hint, void** address, NSModule* module)
327 {
328 if ( dyld::gLogAPIs )
329 fprintf(stderr, "%s(\"%s\", \"%s\", %p, %p)\n", __func__, symbolName, library_name_hint, address, module);
330 ImageLoader* image;
331 const ImageLoader::Symbol* sym;
332 // Look for library whose path contains the hint. If that fails search everywhere
333 if ( dyld::flatFindExportedSymbolWithHint(symbolName, library_name_hint, &sym, &image)
334 || dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
335 if ( address != NULL)
336 *address = (void*)image->getExportedSymbolAddress(sym);
337 if ( module != NULL)
338 *module = ImageLoaderToNSModule(image);
339 }
340 else {
341 // on failure to find symbol return NULLs
342 if ( address != NULL)
343 *address = NULL;
344 if ( module != NULL)
345 *module = NULL;
346 }
347 }
348
349
350 NSSymbol NSLookupAndBindSymbol(const char *symbolName)
351 {
352 if ( dyld::gLogAPIs )
353 fprintf(stderr, "%s(\"%s\")\n", __func__, symbolName);
354 ImageLoader* image;
355 const ImageLoader::Symbol* sym;
356 if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
357 return SymbolToNSSymbol(sym);
358 }
359 // return NULL on failure
360 return NULL;
361 }
362
363 NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint)
364 {
365 if ( dyld::gLogAPIs )
366 fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
367 ImageLoader* image;
368 const ImageLoader::Symbol* sym;
369 bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
370 if ( ! found ) {
371 // hint failed, do slow search of all images
372 found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
373 }
374 if ( found )
375 return SymbolToNSSymbol(sym);
376
377 // return NULL on failure and log
378 if ( dyld::gLogAPIs )
379 fprintf(stderr, "%s(\"%s\", \"%s\") => NULL \n", __func__, symbolName, libraryNameHint);
380 return NULL;
381 }
382
383 uint32_t _dyld_image_count(void)
384 {
385 if ( dyld::gLogAPIs )
386 fprintf(stderr, "%s()\n", __func__);
387 return dyld::getImageCount();
388 }
389
390 const struct mach_header* _dyld_get_image_header(uint32_t image_index)
391 {
392 if ( dyld::gLogAPIs )
393 fprintf(stderr, "%s(%u)\n", __func__, image_index);
394 ImageLoader* image = dyld::getIndexedImage(image_index);
395 if ( image != NULL )
396 return (struct mach_header*)image->machHeader();
397 else
398 return NULL;
399 }
400
401
402 static __attribute__((noinline))
403 const struct mach_header* addImage(const char* path, bool search, bool dontLoad, bool matchInstallName, bool abortOnError)
404 {
405 ImageLoader* image = NULL;
406 try {
407 dyld::clearErrorMessage();
408 void* callerAddress = __builtin_return_address(2); // note layers: 2: real client, 1: libSystem glue, 0: dyld API
409 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
410 dyld::LoadContext context;
411 context.useSearchPaths = search;
412 context.useLdLibraryPath = false;
413 context.matchByInstallName = matchInstallName;
414 context.dontLoad = dontLoad;
415 context.mustBeBundle = false;
416 context.mustBeDylib = true;
417 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
418 context.rpath = NULL; // support not yet implemented
419
420 image = load(path, context);
421 if ( image != NULL ) {
422 if ( context.matchByInstallName )
423 image->setMatchInstallPath(true);
424 dyld::link(image, ImageLoader::kNonLazyOnly, ImageLoader::kRunInitializers);
425 return image->machHeader();
426 }
427 }
428 catch (const char* msg) {
429 if ( abortOnError) {
430 char pathMsg[strlen(msg)+strlen(path)+4];
431 strcpy(pathMsg, msg);
432 strcat(pathMsg, " ");
433 strcat(pathMsg, path);
434 dyldAPIhalt("NSAddImage", pathMsg);
435 }
436 // not halting, so set error state for NSLinkEditError to find
437 setLastError(NSLinkEditOtherError, 0, path, msg);
438 }
439 return NULL;
440 }
441
442 const struct mach_header* NSAddImage(const char* path, uint32_t options)
443 {
444 if ( dyld::gLogAPIs )
445 fprintf(stderr, "%s(\"%s\", 0x%08X)\n", __func__, path, options);
446 const bool dontLoad = ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 );
447 const bool search = ( (options & NSADDIMAGE_OPTION_WITH_SEARCHING) != 0 );
448 const bool matchInstallName = ( (options & NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME) != 0 );
449 const bool abortOnError = ( (options & NSADDIMAGE_OPTION_RETURN_ON_ERROR) == 0 );
450 return addImage(path, search, dontLoad, matchInstallName, abortOnError);
451 }
452
453 bool NSAddLibrary(const char* path)
454 {
455 if ( dyld::gLogAPIs )
456 fprintf(stderr, "%s(\"%s\")\n", __func__, path);
457 return (addImage(path, false, false, false, false) != NULL);
458 }
459
460 bool NSAddLibraryWithSearching(const char* path)
461 {
462 if ( dyld::gLogAPIs )
463 fprintf(stderr, "%s(\"%s\")\n", __func__, path);
464 return (addImage(path, true, false, false, false) != NULL);
465 }
466
467
468
469 //#define NSADDIMAGE_OPTION_NONE 0x0
470 //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
471 //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
472
473 bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName)
474 {
475 if ( dyld::gLogAPIs )
476 fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)mh, symbolName);
477 ImageLoader* image = dyld::findImageByMachHeader(mh);
478 if ( image != NULL ) {
479 if ( image->findExportedSymbol(symbolName, NULL, true, NULL) != NULL)
480 return true;
481 }
482 return false;
483 }
484
485 NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolName, uint32_t options)
486 {
487 if ( dyld::gLogAPIs )
488 fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, mh, symbolName, options);
489 const ImageLoader::Symbol* symbol = NULL;
490 dyld::clearErrorMessage();
491 ImageLoader* image = dyld::findImageByMachHeader(mh);
492 if ( image != NULL ) {
493 try {
494 if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) {
495 dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
496 }
497 else if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW ) {
498 dyld::link(image, ImageLoader::kLazyOnlyNoDependents, ImageLoader::kDontRunInitializers);
499 }
500 }
501 catch (const char* msg) {
502 if ( (options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) == 0 ) {
503 dyldAPIhalt(__func__, msg);
504 }
505 }
506 symbol = image->findExportedSymbol(symbolName, NULL, true, NULL);
507 }
508 if ( dyld::gLogAPIs && (symbol == NULL) )
509 fprintf(stderr, "%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options);
510 return SymbolToNSSymbol(symbol);
511 }
512
513
514 // Note: This cannot have public name because dyld is built with a static copy of libc.a
515 // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
516 static bool client_NSIsSymbolNameDefined(const char* symbolName)
517 {
518 if ( dyld::gLogAPIs )
519 fprintf(stderr, "NSIsSymbolNameDefined(\"%s\")\n", symbolName);
520 ImageLoader* image;
521 const ImageLoader::Symbol* sym;
522 return dyld::flatFindExportedSymbol(symbolName, &sym, &image);
523 }
524
525 bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint)
526 {
527 if ( dyld::gLogAPIs )
528 fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
529 ImageLoader* image;
530 const ImageLoader::Symbol* sym;
531 bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
532 if ( ! found ) {
533 // hint failed, do slow search of all images
534 found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
535 }
536 if ( !found && dyld::gLogAPIs )
537 fprintf(stderr, "%s(\"%s\", \"%s\") => false \n", __func__, symbolName, libraryNameHint);
538 return found;
539 }
540
541 const char* NSNameOfSymbol(NSSymbol symbol)
542 {
543 if ( dyld::gLogAPIs )
544 fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
545 const char* result = NULL;
546 ImageLoader* image = dyld::findImageContainingAddress(symbol);
547 if ( image != NULL )
548 result = image->getExportedSymbolName(NSSymbolToSymbol(symbol));
549 return result;
550 }
551
552 void* NSAddressOfSymbol(NSSymbol symbol)
553 {
554 if ( dyld::gLogAPIs )
555 fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
556 void* result = NULL;
557 ImageLoader* image = dyld::findImageContainingAddress(symbol);
558 if ( image != NULL )
559 result = (void*)image->getExportedSymbolAddress(NSSymbolToSymbol(symbol));
560 return result;
561 }
562
563 NSModule NSModuleForSymbol(NSSymbol symbol)
564 {
565 if ( dyld::gLogAPIs )
566 fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
567 NSModule result = NULL;
568 ImageLoader* image = dyld::findImageContainingAddress(symbol);
569 if ( image != NULL )
570 result = ImageLoaderToNSModule(image);
571 return result;
572 }
573
574
575 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
576 {
577 if ( dyld::gLogAPIs )
578 fprintf(stderr, "%s(%u)\n", __func__, image_index);
579 ImageLoader* image = dyld::getIndexedImage(image_index);
580 if ( image != NULL )
581 return image->getSlide();
582 else
583 return 0;
584 }
585
586 const char* _dyld_get_image_name(uint32_t image_index)
587 {
588 if ( dyld::gLogAPIs )
589 fprintf(stderr, "%s(%u)\n", __func__, image_index);
590 ImageLoader* image = dyld::getIndexedImage(image_index);
591 if ( image != NULL )
592 return image->getLogicalPath();
593 else
594 return NULL;
595 }
596
597
598
599 bool _dyld_all_twolevel_modules_prebound(void)
600 {
601 if ( dyld::gLogAPIs )
602 fprintf(stderr, "%s()\n", __func__);
603 return FALSE; // fixme
604 }
605
606 void _dyld_bind_objc_module(const void *objc_module)
607 {
608 if ( dyld::gLogAPIs )
609 fprintf(stderr, "%s(%p)\n", __func__, objc_module);
610 // do nothing, with new dyld everything already bound
611 }
612
613
614 bool _dyld_bind_fully_image_containing_address(const void* address)
615 {
616 if ( dyld::gLogAPIs )
617 fprintf(stderr, "%s(%p)\n", __func__, address);
618 dyld::clearErrorMessage();
619 ImageLoader* image = dyld::findImageContainingAddress(address);
620 if ( image != NULL ) {
621 try {
622 dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
623 return true;
624 }
625 catch (const char* msg) {
626 dyldAPIhalt(__func__, msg);
627 }
628 }
629 return false;
630 }
631
632 bool _dyld_image_containing_address(const void* address)
633 {
634 if ( dyld::gLogAPIs )
635 fprintf(stderr, "%s(%p)\n", __func__, address);
636 ImageLoader *imageLoader = dyld::findImageContainingAddress(address);
637 return (NULL != imageLoader);
638 }
639
640 static NSObjectFileImage createObjectImageFile(ImageLoader* image, const void* address = NULL, size_t len=0)
641 {
642 NSObjectFileImage result = new __NSObjectFileImage();
643 result->image = image;
644 result->imageBaseAddress = address;
645 result->imageLength = len;
646 sObjectFileImages.push_back(result);
647 return result;
648 }
649
650 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage)
651 {
652 if ( dyld::gLogAPIs )
653 fprintf(stderr, "%s(\"%s\", ...)\n", __func__, pathName);
654 try {
655 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
656 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
657
658 dyld::LoadContext context;
659 context.useSearchPaths = false;
660 context.useLdLibraryPath = false;
661 context.matchByInstallName = false;
662 context.dontLoad = false;
663 context.mustBeBundle = true;
664 context.mustBeDylib = false;
665 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
666 context.rpath = NULL; // support not yet implemented
667
668 ImageLoader* image = dyld::load(pathName, context);
669 // Note: We DO NOT link the image! NSLinkModule will do that
670 if ( image != NULL ) {
671 if ( !image->isBundle() ) {
672 // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
673 return NSObjectFileImageInappropriateFile;
674 }
675 *objectFileImage = createObjectImageFile(image);
676 return NSObjectFileImageSuccess;
677 }
678 }
679 catch (const char* msg) {
680 //fprintf(stderr, "dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
681 return NSObjectFileImageInappropriateFile;
682 }
683 return NSObjectFileImageFailure;
684 }
685
686
687 NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage *objectFileImage)
688 {
689 if ( dyld::gLogAPIs )
690 fprintf(stderr, "%s(%p, %lu, %p)\n", __func__, address, size, objectFileImage);
691
692 try {
693 ImageLoader* image = dyld::loadFromMemory((const uint8_t*)address, size, NULL);
694 if ( ! image->isBundle() ) {
695 // this API can only be used with bundles...
696 delete image;
697 return NSObjectFileImageInappropriateFile;
698 }
699 // Note: We DO NOT link the image! NSLinkModule will do that
700 if ( image != NULL ) {
701 *objectFileImage = createObjectImageFile(image, address, size);
702 return NSObjectFileImageSuccess;
703 }
704 }
705 catch (const char* msg) {
706 fprintf(stderr, "dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg);
707 }
708 return NSObjectFileImageFailure;
709 }
710
711 static bool validOFI(NSObjectFileImage objectFileImage)
712 {
713 const int ofiCount = sObjectFileImages.size();
714 for (int i=0; i < ofiCount; ++i) {
715 if ( sObjectFileImages[i] == objectFileImage )
716 return true;
717 }
718 return false;
719 }
720
721 bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage)
722 {
723 if ( dyld::gLogAPIs )
724 fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
725
726 if ( validOFI(objectFileImage) ) {
727 // if the image has never been linked or has been unlinked, the image is not in the list of valid images
728 // and we should delete it
729 bool linkedImage = dyld::validImage(objectFileImage->image);
730 if ( ! linkedImage )
731 delete objectFileImage->image;
732
733 // remove from list of ofi's
734 for (std::vector<NSObjectFileImage>::iterator it=sObjectFileImages.begin(); it != sObjectFileImages.end(); it++) {
735 if ( *it == objectFileImage ) {
736 sObjectFileImages.erase(it);
737 break;
738 }
739 }
740
741 // if object was created from a memory, release that memory
742 // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
743 if ( objectFileImage->imageBaseAddress != NULL ) {
744 vm_deallocate(mach_task_self(), (vm_address_t)objectFileImage->imageBaseAddress, objectFileImage->imageLength);
745 }
746
747 // free ofi object
748 delete objectFileImage;
749
750 return true;
751 }
752 return false;
753 }
754
755 bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage)
756 {
757 if ( dyld::gLogAPIs )
758 fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
759 return objectFileImage->image->needsInitialization();
760 }
761
762 uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage)
763 {
764 if ( dyld::gLogAPIs )
765 fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
766 return objectFileImage->image->getExportedSymbolCount();
767 }
768
769 const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal)
770 {
771 if ( dyld::gLogAPIs )
772 fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
773 const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedExportedSymbol(ordinal);
774 return objectFileImage->image->getExportedSymbolName(sym);
775 }
776
777 uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage)
778 {
779 if ( dyld::gLogAPIs )
780 fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
781 return objectFileImage->image->getImportedSymbolCount();
782 }
783
784 const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal,
785 bool* tentative_definition)
786 {
787 if ( dyld::gLogAPIs )
788 fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
789 const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedImportedSymbol(ordinal);
790 if ( tentative_definition != NULL ) {
791 ImageLoader::ReferenceFlags flags = objectFileImage->image->geImportedSymbolInfo(sym);
792 if ( (flags & ImageLoader::kTentativeDefinition) != 0 )
793 *tentative_definition = true;
794 else
795 *tentative_definition = false;
796 }
797 return objectFileImage->image->getImportedSymbolName(sym);
798 }
799
800 void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage,
801 const char* segmentName, const char* sectionName, unsigned long* size)
802 {
803 if ( dyld::gLogAPIs )
804 fprintf(stderr, "%s(%p,%s, %s)\n", __func__, objectFileImage, segmentName, sectionName);
805
806 void* start;
807 size_t length;
808 if ( objectFileImage->image->getSectionContent(segmentName, sectionName, &start, &length) ) {
809 if ( size != NULL )
810 *size = length;
811 return start;
812 }
813 return NULL;
814 }
815
816
817
818 bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName)
819 {
820 if ( dyld::gLogAPIs )
821 fprintf(stderr, "%s(%p,%s)\n", __func__, objectFileImage, symbolName);
822 const ImageLoader::Symbol* sym = objectFileImage->image->findExportedSymbol(symbolName, NULL, true, NULL);
823 return ( sym != NULL );
824 }
825
826 /*
827 * Given an imageOffset into an ObjectFileImage, returns
828 * the segment/section name and offset into that section of
829 * that imageOffset. Returns FALSE if the imageOffset is not
830 * in any section. You can used the resulting sectionOffset to
831 * index into the data returned by NSGetSectionDataInObjectFileImage.
832 *
833 * First appeared in Mac OS X 10.3
834 *
835 * SPI: currently only used by ZeroLink to detect +load methods
836 */
837 bool
838 NSFindSectionAndOffsetInObjectFileImage(NSObjectFileImage objectFileImage,
839 unsigned long imageOffset,
840 const char** segmentName, /* can be NULL */
841 const char** sectionName, /* can be NULL */
842 unsigned long* sectionOffset) /* can be NULL */
843 {
844 if ( dyld::gLogAPIs )
845 fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
846
847 return objectFileImage->image->findSection((char*)(objectFileImage->image->getBaseAddress())+imageOffset, segmentName, sectionName, sectionOffset);
848 }
849
850
851
852 NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options)
853 {
854 if ( dyld::gLogAPIs )
855 fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, objectFileImage, moduleName, options);
856
857 dyld::clearErrorMessage();
858 try {
859 // NSLinkModule allows a bundle to be link multpile times
860 // each link causes the bundle to be copied to a new address
861 if ( objectFileImage->image->isLinked() ) {
862 // already linked, so clone a new one and link it
863 #if 0
864 fprintf(stderr, "dyld: warning: %s(0x%08X, \"%s\", 0x%08X) called more than once for 0x%08X\n",
865 __func__, objectFileImage, moduleName, options, objectFileImage);
866 #endif
867 objectFileImage->image = dyld::cloneImage(objectFileImage->image);
868 }
869
870 // if this ofi was made with NSCreateObjectFileImageFromFile() then physical path is already set
871 // if this ofi was create with NSCreateObjectFileImageFromMemory() then the phyiscal path should be set if supplied
872 if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 ) {
873 if ( objectFileImage->imageBaseAddress != NULL ) {
874 const char* physEnd = &moduleName[strlen(moduleName)+1];
875 objectFileImage->image->setPath(physEnd);
876 }
877 }
878
879 // set moduleName as the name anyone calling _dyld_get_image_name() will see
880 objectFileImage->image->setLogicalPath(moduleName);
881
882 // support private bundles
883 if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
884 objectFileImage->image->setHideExports();
885
886 // set up linking options
887 ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
888 if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
889 bindness = ImageLoader::kLazyAndNonLazy;
890 ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
891 if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
892 runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
893
894 // load libraries, rebase, bind, to make this image usable
895 dyld::link(objectFileImage->image, bindness, runInitializers);
896
897 return ImageLoaderToNSModule(objectFileImage->image);
898 }
899 catch (const char* msg) {
900 if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
901 dyldAPIhalt(__func__, msg);
902 // not halting, so set error state for NSLinkEditError to find
903 dyld::removeImage(objectFileImage->image);
904 setLastError(NSLinkEditOtherError, 0, moduleName, msg);
905 return NULL;
906 }
907 }
908
909 #if OLD_LIBSYSTEM_SUPPORT
910 // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
911 static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options)
912 {
913 if ( dyld::gLogAPIs )
914 fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr, moduleName, options); // note name/args translation
915 ImageLoader* image = NULL;
916 dyld::clearErrorMessage();
917 try {
918 const char* imageName = moduleName;
919 if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
920 imageName = &moduleName[strlen(moduleName)+1];
921
922 image = dyld::loadFromMemory((const uint8_t*)object_addr, object_size, imageName);
923
924 if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
925 image->setLogicalPath(moduleName);
926
927 if ( image != NULL ) {
928 // support private bundles
929 if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
930 image->setHideExports();
931
932 // set up linking options
933 ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
934 if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
935 bindness = ImageLoader::kLazyAndNonLazy;
936 ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
937 if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
938 runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
939
940 // load libraries, rebase, bind, to make this image usable
941 dyld::link(image, bindness, runInitializers);
942 }
943 }
944 catch (const char* msg) {
945 if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
946 dyldAPIhalt("NSLinkModule", msg);
947 // not halting, so set error state for NSLinkEditError to find
948 setLastError(NSLinkEditOtherError, 0, moduleName, msg);
949 // if image was created for this bundle, destroy it
950 if ( image != NULL ) {
951 dyld::removeImage(image);
952 delete image;
953 }
954 image = NULL;
955 }
956 return ImageLoaderToNSModule(image);
957 }
958 #endif
959
960 NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
961 {
962 if ( dyld::gLogAPIs )
963 fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)module, symbolName);
964 ImageLoader* image = NSModuleToImageLoader(module);
965 if ( image == NULL )
966 return NULL;
967 return SymbolToNSSymbol(image->findExportedSymbol(symbolName, NULL, false, NULL));
968 }
969
970 const char* NSNameOfModule(NSModule module)
971 {
972 if ( dyld::gLogAPIs )
973 fprintf(stderr, "%s(%p)\n", __func__, module);
974 ImageLoader* image = NSModuleToImageLoader(module);
975 if ( image == NULL )
976 return NULL;
977 return image->getPath();
978 }
979
980 const char* NSLibraryNameForModule(NSModule module)
981 {
982 if ( dyld::gLogAPIs )
983 fprintf(stderr, "%s(%p)\n", __func__, module);
984 ImageLoader* image = NSModuleToImageLoader(module);
985 if ( image == NULL )
986 return NULL;
987 return image->getPath();
988 }
989
990 bool NSUnLinkModule(NSModule module, uint32_t options)
991 {
992 if ( dyld::gLogAPIs )
993 fprintf(stderr, "%s(%p, 0x%08X)\n", __func__, module, options);
994 if ( module == NULL )
995 return false;
996 ImageLoader* image = NSModuleToImageLoader(module);
997 if ( image == NULL )
998 return false;
999 dyld::removeImage(image);
1000
1001 if ( (options & NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) != 0 )
1002 image->setLeaveMapped();
1003
1004 // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1005
1006 // Only delete image if there is no ofi referencing it
1007 // That means the ofi was destroyed after linking, so no one is left to delete this image
1008 const int ofiCount = sObjectFileImages.size();
1009 bool found = false;
1010 for (int i=0; i < ofiCount; ++i) {
1011 NSObjectFileImage ofi = sObjectFileImages[i];
1012 if ( ofi->image == image )
1013 found = true;
1014 }
1015 if ( !found )
1016 delete image;
1017
1018 return true;
1019 }
1020
1021 // internal name and parameters do not match public name and parameters...
1022 static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit)
1023 {
1024 if ( dyld::gLogAPIs )
1025 fprintf(stderr, "NSLinkEditErrorHandlers()\n");
1026
1027 dyld::registerUndefinedHandler((dyld::UndefinedHandler)undefined);
1028 // no support for multiple or linkedit handlers
1029 }
1030
1031 const struct mach_header * _dyld_get_image_header_containing_address(const void* address)
1032 {
1033 if ( dyld::gLogAPIs )
1034 fprintf(stderr, "%s(%p)\n", __func__, address);
1035 ImageLoader* image = dyld::findImageContainingAddress(address);
1036 if ( image != NULL )
1037 return image->machHeader();
1038 return NULL;
1039 }
1040
1041
1042 void _dyld_register_func_for_add_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1043 {
1044 if ( dyld::gLogAPIs )
1045 fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
1046 dyld::registerAddCallback(func);
1047 }
1048
1049 void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
1050 {
1051 if ( dyld::gLogAPIs )
1052 fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
1053 dyld::registerRemoveCallback(func);
1054 }
1055
1056 // called by atexit() function installed by crt
1057 static void _dyld_mod_term_funcs()
1058 {
1059 if ( dyld::gLogAPIs )
1060 fprintf(stderr, "%s()\n", __func__);
1061 dyld::runTerminators();
1062 }
1063
1064 // called by crt before main
1065 static void _dyld_make_delayed_module_initializer_calls()
1066 {
1067 if ( dyld::gLogAPIs )
1068 fprintf(stderr, "%s()\n", __func__);
1069 dyld::initializeMainExecutable();
1070 }
1071
1072
1073 void NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString)
1074 {
1075 // FIXME FIXME
1076 *c = sLastErrorFileCode;
1077 *errorNumber = sLastErrorNo;
1078 *fileName = sLastErrorFilePath;
1079 *errorString = dyld::getErrorMessage();
1080 }
1081
1082 static void _dyld_register_binding_handler(void * (*bindingHandler)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions)
1083 {
1084 if ( dyld::gLogAPIs )
1085 fprintf(stderr, "%s()\n", __func__);
1086 dyld::gLinkContext.bindingHandler = bindingHandler;
1087 dyld::gLinkContext.bindingOptions = bindingOptions;
1088 }
1089
1090 // Call by fork() in libSystem before the kernel trap is done
1091 static void _dyld_fork_prepare()
1092 {
1093 if ( dyld::gLogAPIs )
1094 fprintf(stderr, "%s()\n", __func__);
1095 }
1096
1097 // Call by fork() in libSystem after the kernel trap is done on the parent side
1098 static void _dyld_fork_parent()
1099 {
1100 if ( dyld::gLogAPIs )
1101 fprintf(stderr, "%s()\n", __func__);
1102 }
1103
1104 // Call by fork() in libSystem after the kernel trap is done on the child side
1105 static void _dyld_fork_child()
1106 {
1107 if ( dyld::gLogAPIs )
1108 fprintf(stderr, "%s()\n", __func__);
1109 // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
1110 // in libSystem for the child of a fork. But dyld is built with a static copy
1111 // of libc.a and has its own copy of mach_task_self_ which we reset here.
1112 //
1113 // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
1114 // in mach_init() mach_task_self_ is initialized to task_self_trap().
1115 //
1116 extern mach_port_t mach_task_self_;
1117 mach_task_self_ = task_self_trap();
1118 }
1119
1120 // Call by fork() in libSystem after the kernel trap is done on the child side after
1121 // other libSystem child side fixups are done
1122 static void _dyld_fork_child_final()
1123 {
1124 if ( dyld::gLogAPIs )
1125 fprintf(stderr, "%s()\n", __func__);
1126 }
1127
1128
1129 typedef void (*MonitorProc)(char *lowpc, char *highpc);
1130
1131 static void monInitCallback(ImageLoader* image, void* userData)
1132 {
1133 MonitorProc proc = (MonitorProc)userData;
1134 void* start;
1135 size_t length;
1136 if ( image->getSectionContent("__TEXT", "__text", &start, &length) ) {
1137 proc((char*)start, (char*)start+length);
1138 }
1139 }
1140
1141 //
1142 // _dyld_moninit is called from profiling runtime routine moninit().
1143 // dyld calls back with the range of each __TEXT/__text section in every
1144 // linked image.
1145 //
1146 void _dyld_moninit(MonitorProc proc)
1147 {
1148 dyld::forEachImageDo(&monInitCallback, (void*)proc);
1149 }
1150
1151 // returns true if prebinding was used in main executable
1152 bool _dyld_launched_prebound()
1153 {
1154 if ( dyld::gLogAPIs )
1155 fprintf(stderr, "%s()\n", __func__);
1156
1157 // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
1158 return dyld::mainExecutablePrebound();
1159 }
1160
1161
1162 //
1163 // _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
1164 // NSMakePrivateModulePublic() needed for the dlopen() to turn it's
1165 // RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
1166 // flag on the image for this module. If the module was found and it was
1167 // private then everything worked and TRUE is returned else FALSE is returned.
1168 //
1169 static bool NSMakePrivateModulePublic(NSModule module)
1170 {
1171 ImageLoader* image = NSModuleToImageLoader(module);
1172 if ( image != NULL ) {
1173 if ( image->hasHiddenExports() ) {
1174 image->setHideExports(false);
1175 return true;
1176 }
1177 }
1178 return false;
1179 }
1180
1181
1182
1183 bool lookupDyldFunction(const char* name, uintptr_t* address)
1184 {
1185 for (const dyld_func* p = dyld_funcs; p->name != NULL; ++p) {
1186 if ( strcmp(p->name, name) == 0 ) {
1187 if( p->implementation == unimplemented )
1188 fprintf(stderr, "unimplemented dyld function: %s\n", p->name);
1189 *address = (uintptr_t)p->implementation;
1190 return true;
1191 }
1192 }
1193 *address = 0;
1194 return false;
1195 }
1196
1197
1198 static void registerThreadHelpers(const dyld::ThreadingHelpers* helpers)
1199 {
1200 // We need to make sure libSystem's lazy pointer's are bound
1201 // before installing thred helpers.
1202 // The reason for this is that if accessing the lock requires
1203 // a lazy pointer to be bound (and it does when multi-module
1204 // libSystem) is not prebound, the lazy handler will be
1205 // invoked which tries to acquire the lock again...an infinite
1206 // loop.
1207 ImageLoader* image = dyld::findImageContainingAddress(helpers);
1208 dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
1209
1210 dyld::gThreadHelpers = helpers;
1211 }
1212
1213
1214 static void dlerrorClear()
1215 {
1216 if ( dyld::gThreadHelpers != NULL ) {
1217 char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
1218 buffer[0] = '\0';
1219 }
1220 }
1221
1222 static void dlerrorSet(const char* msg)
1223 {
1224 if ( dyld::gThreadHelpers != NULL ) {
1225 char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(strlen(msg)+1);
1226 strcpy(buffer, msg);
1227 }
1228 }
1229
1230
1231
1232 void* dlopen(const char* path, int mode)
1233 {
1234 if ( dyld::gLogAPIs )
1235 fprintf(stderr, "%s(%s, 0x%08X)\n", __func__, path, mode);
1236
1237 dlerrorClear();
1238
1239 // passing NULL for path means return magic object
1240 if ( path == NULL ) {
1241 return RTLD_DEFAULT;
1242 }
1243
1244 try {
1245 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1246 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1247
1248 ImageLoader* image = NULL;
1249 dyld::LoadContext context;
1250 context.useSearchPaths = true;
1251 context.useLdLibraryPath= (strchr(path, '/') == NULL); // a leafname implies should search
1252 context.matchByInstallName = true;
1253 context.dontLoad = ( (mode & RTLD_NOLOAD) != 0 );
1254 context.mustBeBundle = false;
1255 context.mustBeDylib = false;
1256 context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
1257 context.rpath = NULL; // support not yet implemented
1258
1259 image = load(path, context);
1260 if ( image != NULL ) {
1261 image->incrementReferenceCount();
1262 if ( ! image->isLinked() ) {
1263 ImageLoader::BindingLaziness bindiness = ImageLoader::kNonLazyOnly;
1264 if ( (mode & RTLD_NOW) != 0 )
1265 bindiness = ImageLoader::kLazyAndNonLazy;
1266 dyld::link(image, bindiness, ImageLoader::kRunInitializers);
1267 // only hide exports if image is not already in use
1268 if ( (mode & RTLD_LOCAL) != 0 )
1269 image->setHideExports(true);
1270 }
1271 // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
1272 // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
1273 // The subtle differences are:
1274 // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
1275 // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
1276 if ( (mode & RTLD_NODELETE) != 0 )
1277 image->setLeaveMapped();
1278 return image;
1279 }
1280 }
1281 catch (const char* msg) {
1282 const char* format = "dlopen(%s, %d): %s";
1283 char temp[strlen(format)+strlen(path)+strlen(msg)+10];
1284 sprintf(temp, format, path, mode, msg);
1285 dlerrorSet(temp);
1286 }
1287 return NULL;
1288 }
1289
1290 int dlclose(void* handle)
1291 {
1292 if ( dyld::gLogAPIs )
1293 fprintf(stderr, "%s(%p)\n", __func__, handle);
1294
1295 ImageLoader* image = (ImageLoader*)handle;
1296 if ( dyld::validImage(image) ) {
1297 if ( image->decrementReferenceCount() ) {
1298 // for now, only bundles can be unloaded
1299 // to unload dylibs we would need to track all direct and indirect uses
1300 if ( image->isBundle() ) {
1301 dyld::removeImage(image);
1302 delete image;
1303 }
1304 }
1305 dlerrorClear();
1306 return 0;
1307 }
1308 else {
1309 dlerrorSet("invalid handle passed to dlclose()");
1310 return -1;
1311 }
1312 }
1313
1314
1315
1316 int dladdr(const void* address, Dl_info* info)
1317 {
1318 if ( dyld::gLogAPIs )
1319 fprintf(stderr, "%s(%p, %p)\n", __func__, address, info);
1320
1321 ImageLoader* image = dyld::findImageContainingAddress(address);
1322 if ( image != NULL ) {
1323 info->dli_fname = image->getLogicalPath();
1324 info->dli_fbase = (void*)image->machHeader();
1325 // find closest exported symbol in the image
1326 const uint32_t exportCount = image->getExportedSymbolCount();
1327 const ImageLoader::Symbol* bestSym = NULL;
1328 const void* bestAddr = 0;
1329 for(uint32_t i=0; i < exportCount; ++i) {
1330 const ImageLoader::Symbol* sym = image->getIndexedExportedSymbol(i);
1331 const void* symAddr = (void*)image->getExportedSymbolAddress(sym);
1332 if ( (symAddr <= address) && (bestAddr < symAddr) ) {
1333 bestSym = sym;
1334 bestAddr = symAddr;
1335 }
1336 }
1337 if ( bestSym != NULL ) {
1338 info->dli_sname = image->getExportedSymbolName(bestSym) + 1; // strip off leading underscore
1339 info->dli_saddr = (void*)bestAddr;
1340 }
1341 else {
1342 info->dli_sname = NULL;
1343 info->dli_saddr = NULL;
1344 }
1345 return 1; // success
1346 }
1347 return 0; // failure
1348 }
1349
1350
1351 char* dlerror()
1352 {
1353 if ( dyld::gLogAPIs )
1354 fprintf(stderr, "%s()\n", __func__);
1355
1356 if ( dyld::gThreadHelpers != NULL ) {
1357 char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
1358 // if no error set, return NULL
1359 if ( buffer[0] != '\0' )
1360 return buffer;
1361 }
1362 return NULL;
1363 }
1364
1365 void* dlsym(void* handle, const char* symbolName)
1366 {
1367 if ( dyld::gLogAPIs )
1368 fprintf(stderr, "%s(%p, %s)\n", __func__, handle, symbolName);
1369
1370 dlerrorClear();
1371
1372 ImageLoader* image;
1373 const ImageLoader::Symbol* sym;
1374
1375 // dlsym() assumes symbolName passed in is same as in C source code
1376 // dyld assumes all symbol names have an underscore prefix
1377 char underscoredName[strlen(symbolName)+2];
1378 underscoredName[0] = '_';
1379 strcpy(&underscoredName[1], symbolName);
1380
1381 // magic "search all" handle
1382 if ( handle == RTLD_DEFAULT ) {
1383 if ( dyld::flatFindExportedSymbol(underscoredName, &sym, &image) ) {
1384 return (void*)image->getExportedSymbolAddress(sym);
1385 }
1386 const char* format = "dlsym(RTLD_DEFAULT, %s): symbol not found";
1387 char temp[strlen(format)+strlen(symbolName)+2];
1388 sprintf(temp, format, symbolName);
1389 dlerrorSet(temp);
1390 return NULL;
1391 }
1392
1393 // magic "search what I would see" handle
1394 if ( handle == RTLD_NEXT ) {
1395 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1396 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1397 sym = callerImage->findExportedSymbolInDependentImages(underscoredName, &image); // don't search image, but do search what it links against
1398 if ( sym != NULL ) {
1399 return (void*)image->getExportedSymbolAddress(sym);
1400 }
1401 const char* format = "dlsym(RTLD_NEXT, %s): symbol not found";
1402 char temp[strlen(format)+strlen(symbolName)+2];
1403 sprintf(temp, format, symbolName);
1404 dlerrorSet(temp);
1405 return NULL;
1406 }
1407 #ifdef RTLD_SELF
1408 // magic "search me, then what I would see" handle
1409 if ( handle == RTLD_SELF ) {
1410 void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
1411 ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
1412 sym = callerImage->findExportedSymbolInImageOrDependentImages(underscoredName, &image); // search image and what it links against
1413 if ( sym != NULL ) {
1414 return (void*)image->getExportedSymbolAddress(sym);
1415 }
1416 const char* format = "dlsym(RTLD_SELF, %s): symbol not found";
1417 char temp[strlen(format)+strlen(symbolName)+2];
1418 sprintf(temp, format, symbolName);
1419 dlerrorSet(temp);
1420 return NULL;
1421 }
1422 #endif
1423 // real handle
1424 image = (ImageLoader*)handle;
1425 if ( dyld::validImage(image) ) {
1426 sym = image->findExportedSymbolInImageOrDependentImages(underscoredName, &image); // search image and what it links against
1427 if ( sym != NULL ) {
1428 return (void*)image->getExportedSymbolAddress(sym);
1429 }
1430 const char* format = "dlsym(%p, %s): symbol not found";
1431 char temp[strlen(format)+strlen(symbolName)+20];
1432 sprintf(temp, format, handle, symbolName);
1433 dlerrorSet(temp);
1434 }
1435 else {
1436 dlerrorSet("invalid handle passed to dlsym()");
1437 }
1438 return NULL;
1439 }
1440
1441
1442 static void commitRepreboundFiles(std::vector<ImageLoader*> files, bool unmapOld)
1443 {
1444 // tell file system to flush all dirty buffers to disk
1445 // after this sync, the _redoprebinding files will be on disk
1446 sync();
1447
1448 // now commit (swap file) for each re-prebound image
1449 // this only updates directories, since the files have already been flushed by previous sync()
1450 for (std::vector<ImageLoader*>::iterator it=files.begin(); it != files.end(); it++) {
1451 (*it)->reprebindCommit(dyld::gLinkContext, true, unmapOld);
1452 }
1453
1454 // tell file system to flush all dirty buffers to disk
1455 // this should flush out all directory changes caused by the file swapping
1456 sync();
1457 }
1458
1459
1460 #define UPDATE_PREBINDING_DRY_RUN 0x00000001
1461 #define UPDATE_PREBINDING_PROGRESS 0x00000002
1462
1463 //
1464 // SPI called only by update_prebinding tool to redo prebinding in all prebound files specified
1465 // There must be no dylibs loaded when this fnction is called.
1466 //
1467 __attribute__((noreturn))
1468 static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags)
1469 {
1470 if ( dyld::gLogAPIs )
1471 fprintf(stderr, "%s()\n", __func__);
1472
1473 // list of requested dylibs actually loaded
1474 std::vector<ImageLoader*> preboundImages;
1475
1476 try {
1477 // verify no dylibs loaded
1478 if ( dyld::getImageCount() != 1 )
1479 throw "_dyld_update_prebinding cannot be called with dylib already loaded";
1480
1481 const uint32_t max_allowed_link_errors = 10;
1482 uint32_t link_error_count = 0;
1483
1484 // load and link each dylib
1485 for (int i=0; i < pathCount; ++i) {
1486 dyld::LoadContext context;
1487 context.useSearchPaths = false;
1488 context.matchByInstallName = true;
1489 context.dontLoad = false;
1490 context.mustBeBundle = false;
1491 context.mustBeDylib = true;
1492 context.origin = NULL; // @loader_path not allowed in prebinding list
1493 context.rpath = NULL; // support not yet implemented
1494
1495 ImageLoader* image = NULL;
1496 try {
1497 image = dyld::load(paths[i], context);
1498 // bind lazy and non-lazy symbols, but don't run initializers
1499 // this may bring in other dylibs later in the list or missing from list, but that is ok
1500 dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
1501 // recored images we successfully loaded
1502 preboundImages.push_back(image);
1503 }
1504 catch (const char* msg) {
1505 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) ) {
1506 const char *stage;
1507 if ( image == NULL ) // load exception
1508 stage = "load";
1509 else // link exception
1510 stage = "link";
1511 fprintf(stderr, "update_prebinding: warning: could not %s %s: %s\n", stage, paths[i], msg);
1512 }
1513 if ( image != NULL )
1514 link_error_count++;
1515 if ( link_error_count > max_allowed_link_errors )
1516 throw;
1517 }
1518 }
1519
1520 // find missing images
1521 uint32_t loadedImageCount = dyld::getImageCount();
1522 if ( loadedImageCount > (preboundImages.size()+1) ) {
1523 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
1524 fprintf(stderr, "update_prebinding: warning: the following dylibs were loaded but will not have their prebinding updated because they are not in the list of paths to reprebind\n");
1525 for (uint32_t i=1; i < loadedImageCount; ++i) {
1526 ImageLoader* target = dyld::getIndexedImage(i);
1527 bool found = false;
1528 for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
1529 if ( *it == target ) {
1530 found = true;
1531 break;
1532 }
1533 }
1534 if ( !found )
1535 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
1536 fprintf(stderr, " %s\n", target->getPath());
1537 }
1538 }
1539
1540 // warn about unprebound files in the list
1541 bool unpreboundWarned = false;
1542 for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
1543 if ( ! (*it)->isPrebindable() && (*it != dyld::mainExecutable()) ) {
1544 if ( ! unpreboundWarned ) {
1545 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
1546 fprintf(stderr, "update_prebinding: warning: the following dylibs were specified but were not built prebound\n");
1547 unpreboundWarned = true;
1548 }
1549 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
1550 fprintf(stderr, " %s\n", (*it)->getPath());
1551 }
1552 }
1553
1554 if(UPDATE_PREBINDING_DRY_RUN & flags) {
1555 fprintf(stderr, "update_prebinding: dry-run: no changes were made to the filesystem.\n");
1556 }
1557 else {
1558 uint32_t imageCount = preboundImages.size();
1559 uint32_t imageNumber = 1;
1560 // tell each image to write itself out re-prebound
1561 struct timeval currentTime = { 0 , 0 };
1562 gettimeofday(&currentTime, NULL);
1563 time_t timestamp = currentTime.tv_sec;
1564 std::vector<ImageLoader*> updatedImages;
1565 for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
1566 uint64_t freespace = (*it)->reprebind(dyld::gLinkContext, timestamp);
1567 updatedImages.push_back(*it);
1568 if(UPDATE_PREBINDING_PROGRESS & flags) {
1569 fprintf(stdout, "update_prebinding: progress: %3u/%u\n", imageNumber, imageCount);
1570 fflush(stdout);
1571 imageNumber++;
1572 }
1573 // see if we are running low on disk space (less than 32MB is "low")
1574 const uint64_t kMinFreeSpace = 32*1024*1024;
1575 if ( freespace < kMinFreeSpace ) {
1576 if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
1577 fprintf(stderr, "update_prebinding: disk space down to %lluMB, committing %lu prebound files\n", freespace/(1024*1024), updatedImages.size());
1578 // commit files processed so far, to free up more disk space
1579 commitRepreboundFiles(updatedImages, true);
1580 // empty list of temp files
1581 updatedImages.clear();
1582 }
1583 }
1584
1585 // commit them, don't need to unmap old, cause we are done
1586 commitRepreboundFiles(updatedImages, false);
1587 }
1588 }
1589 catch (const char* msg) {
1590 // delete temp files
1591 try {
1592 for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
1593 (*it)->reprebindCommit(dyld::gLinkContext, false, false);
1594 }
1595 }
1596 catch (const char* commitMsg) {
1597 fprintf(stderr, "update_prebinding: error: %s\n", commitMsg);
1598 }
1599 fprintf(stderr, "update_prebinding: error: %s\n", msg);
1600 exit(1);
1601 }
1602 exit(0);
1603 }
1604
1605
1606
1607 static const struct dyld_all_image_infos* _dyld_get_all_image_infos()
1608 {
1609 return &dyld_all_image_infos;
1610 }
1611
1612
1613
1614
1615
1616
1617
1618