]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
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 |