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