]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
39a8cd10 | 3 | * Copyright (c) 2004-2009 Apple Inc. All rights reserved. |
0959b6d4 A |
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 | ||
bac542e6 | 30 | #define __STDC_LIMIT_MACROS |
0959b6d4 | 31 | #include <stddef.h> |
bac542e6 | 32 | #include <stdint.h> |
0959b6d4 | 33 | #include <string.h> |
bac542e6 A |
34 | #include <sys/param.h> |
35 | #include <sys/mount.h> | |
39a8cd10 | 36 | #include <Availability.h> |
bac542e6 A |
37 | |
38 | ||
39 | #include <vector> | |
40 | #include <map> | |
41 | #include <algorithm> | |
42 | ||
0959b6d4 A |
43 | #include <mach/mach.h> |
44 | #include <sys/time.h> | |
a3afc008 | 45 | #include <sys/sysctl.h> |
39a8cd10 | 46 | #include <mach/mach_traps.h> // for task_self_trap() |
0959b6d4 | 47 | |
0959b6d4 | 48 | |
bac542e6 | 49 | #include "mach-o/dyld_images.h" |
0959b6d4 A |
50 | #include "mach-o/dyld.h" |
51 | #include "mach-o/dyld_priv.h" | |
0959b6d4 A |
52 | |
53 | #include "ImageLoader.h" | |
54 | #include "dyld.h" | |
bac542e6 A |
55 | #include "dyldLibSystemInterface.h" |
56 | ||
57 | #undef _POSIX_C_SOURCE | |
58 | #include "dlfcn.h" | |
59 | ||
412ebb8e A |
60 | // from dyldExceptions.c |
61 | extern "C" void __Unwind_SjLj_SetThreadKey(pthread_key_t key); | |
62 | ||
63 | // from dyld_gdb.cpp | |
64 | extern void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]); | |
bac542e6 | 65 | |
39a8cd10 A |
66 | // deprecated APIs are still availble on Mac OS X, but not on iPhone OS |
67 | #if __IPHONE_OS_VERSION_MIN_REQUIRED | |
68 | #define DEPRECATED_APIS_SUPPORTED 0 | |
69 | #else | |
70 | #define DEPRECATED_APIS_SUPPORTED 1 | |
bac542e6 | 71 | #endif |
0959b6d4 | 72 | |
19894a12 | 73 | static bool sDynamicInterposing = false; |
39a8cd10 A |
74 | |
75 | #if DEPRECATED_APIS_SUPPORTED | |
0959b6d4 A |
76 | static char sLastErrorFilePath[1024]; |
77 | static NSLinkEditErrors sLastErrorFileCode; | |
78 | static int sLastErrorNo; | |
39a8cd10 | 79 | #endif |
0959b6d4 A |
80 | |
81 | // In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib | |
82 | // Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards | |
83 | // This conditional keeps support for old libSystem's which needed some help implementing the API's | |
832b6fce | 84 | #define OLD_LIBSYSTEM_SUPPORT (__i386__) |
0959b6d4 A |
85 | |
86 | // The following functions have no prototype in any header. They are special cases | |
87 | // where _dyld_func_lookup() is used directly. | |
39a8cd10 A |
88 | static void _dyld_make_delayed_module_initializer_calls(); |
89 | static void registerThreadHelpers(const dyld::LibSystemHelpers*); | |
90 | #if DEPRECATED_APIS_SUPPORTED | |
0959b6d4 | 91 | static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit); |
bac542e6 | 92 | #if OLD_LIBSYSTEM_SUPPORT |
0959b6d4 | 93 | static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options); |
bac542e6 | 94 | #endif |
0959b6d4 | 95 | static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions); |
0959b6d4 A |
96 | static bool NSMakePrivateModulePublic(NSModule module); |
97 | static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header); | |
0959b6d4 A |
98 | |
99 | // The following functions are dyld API's, but since dyld links with a static copy of libc.a | |
100 | // the public name cannot be used. | |
101 | static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module); | |
102 | static bool client_NSIsSymbolNameDefined(const char* symbolName); | |
39a8cd10 | 103 | #endif // DEPRECATED_APIS_SUPPORTED |
19894a12 | 104 | #if SUPPORT_ZERO_COST_EXCEPTIONS |
39a8cd10 | 105 | static bool client_dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info); |
412ebb8e | 106 | #endif |
0959b6d4 A |
107 | |
108 | static void unimplemented() | |
109 | { | |
110 | dyld::halt("unimplemented dyld function\n"); | |
111 | } | |
112 | ||
113 | struct dyld_func { | |
114 | const char* name; | |
115 | void* implementation; | |
116 | }; | |
117 | ||
118 | static struct dyld_func dyld_funcs[] = { | |
bac542e6 A |
119 | {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image }, |
120 | {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image }, | |
bac542e6 A |
121 | {"__dyld_dladdr", (void*)dladdr }, |
122 | {"__dyld_dlclose", (void*)dlclose }, | |
123 | {"__dyld_dlerror", (void*)dlerror }, | |
124 | {"__dyld_dlopen", (void*)dlopen }, | |
125 | {"__dyld_dlsym", (void*)dlsym }, | |
126 | {"__dyld_dlopen_preflight", (void*)dlopen_preflight }, | |
bac542e6 A |
127 | {"__dyld_image_count", (void*)_dyld_image_count }, |
128 | {"__dyld_get_image_header", (void*)_dyld_get_image_header }, | |
129 | {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide }, | |
130 | {"__dyld_get_image_name", (void*)_dyld_get_image_name }, | |
39a8cd10 | 131 | {"__dyld_get_image_slide", (void*)_dyld_get_image_slide }, |
bac542e6 | 132 | {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath }, |
39a8cd10 A |
133 | |
134 | // SPIs | |
135 | {"__dyld_dyld_register_image_state_change_handler", (void*)dyld_register_image_state_change_handler }, | |
136 | {"__dyld_register_thread_helpers", (void*)registerThreadHelpers }, | |
137 | {"__dyld_fork_child", (void*)_dyld_fork_child }, | |
39a8cd10 A |
138 | {"__dyld_make_delayed_module_initializer_calls", (void*)_dyld_make_delayed_module_initializer_calls }, |
139 | {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos }, | |
19894a12 | 140 | #if SUPPORT_ZERO_COST_EXCEPTIONS |
39a8cd10 A |
141 | {"__dyld_find_unwind_sections", (void*)client_dyld_find_unwind_sections }, |
142 | #endif | |
19894a12 | 143 | #if __i386__ || __x86_64__ || __arm__ || __arm64__ |
39a8cd10 A |
144 | {"__dyld_fast_stub_entry", (void*)dyld::fastBindLazySymbol }, |
145 | #endif | |
146 | {"__dyld_image_path_containing_address", (void*)dyld_image_path_containing_address }, | |
412ebb8e | 147 | {"__dyld_shared_cache_some_image_overridden", (void*)dyld_shared_cache_some_image_overridden }, |
2fd3f4e8 | 148 | {"__dyld_process_is_restricted", (void*)dyld::processIsRestricted }, |
19894a12 | 149 | {"__dyld_dynamic_interpose", (void*)dyld_dynamic_interpose }, |
df9d6cf7 A |
150 | #if DYLD_SHARED_CACHE_SUPPORT |
151 | {"__dyld_shared_cache_file_path", (void*)dyld::getStandardSharedCacheFilePath }, | |
152 | #endif | |
153 | {"__dyld_get_image_header_containing_address", (void*)dyld_image_header_containing_address }, | |
39a8cd10 A |
154 | |
155 | // deprecated | |
156 | #if DEPRECATED_APIS_SUPPORTED | |
0959b6d4 A |
157 | {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind }, |
158 | {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint }, | |
0959b6d4 A |
159 | {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully }, |
160 | {"__dyld_install_handlers", (void*)_dyld_install_handlers }, | |
161 | {"__dyld_link_edit_error", (void*)NSLinkEditError }, | |
0959b6d4 | 162 | {"__dyld_unlink_module", (void*)NSUnLinkModule }, |
0959b6d4 A |
163 | {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module }, |
164 | {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address }, | |
165 | {"__dyld_image_containing_address", (void*)_dyld_image_containing_address }, | |
bac542e6 | 166 | {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler }, |
0959b6d4 A |
167 | {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol }, |
168 | {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol }, | |
169 | {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol }, | |
170 | {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol }, | |
171 | {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint }, | |
172 | {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule}, | |
173 | {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage}, | |
174 | {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic}, | |
175 | {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined}, | |
176 | {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint }, | |
177 | {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage}, | |
178 | {"__dyld_NSNameOfModule", (void*)NSNameOfModule }, | |
179 | {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule }, | |
180 | {"__dyld_NSAddLibrary", (void*)NSAddLibrary }, | |
181 | {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching }, | |
182 | {"__dyld_NSAddImage", (void*)NSAddImage }, | |
0959b6d4 A |
183 | {"__dyld_launched_prebound", (void*)_dyld_launched_prebound }, |
184 | {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound }, | |
185 | {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib }, | |
0959b6d4 A |
186 | {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile }, |
187 | {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory }, | |
0959b6d4 A |
188 | {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage }, |
189 | {"__dyld_NSLinkModule", (void*)NSLinkModule }, | |
190 | {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage }, | |
191 | {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage }, | |
192 | {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage }, | |
193 | {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage }, | |
194 | {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage }, | |
195 | {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage }, | |
196 | {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage }, | |
bac542e6 A |
197 | #if OLD_LIBSYSTEM_SUPPORT |
198 | {"__dyld_link_module", (void*)_dyld_link_module }, | |
199 | #endif | |
39a8cd10 A |
200 | #endif //DEPRECATED_APIS_SUPPORTED |
201 | ||
0959b6d4 A |
202 | {NULL, 0} |
203 | }; | |
204 | ||
205 | ||
206 | ||
39a8cd10 A |
207 | #if DEPRECATED_APIS_SUPPORTED |
208 | ||
209 | static void dyldAPIhalt(const char* apiName, const char* errorMsg) | |
210 | { | |
211 | dyld::log("dyld: %s() error\n", apiName); | |
212 | dyld::halt(errorMsg); | |
213 | } | |
214 | ||
0959b6d4 A |
215 | // dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol* |
216 | inline NSSymbol SymbolToNSSymbol(const ImageLoader::Symbol* sym) | |
217 | { | |
218 | return (NSSymbol)sym; | |
219 | } | |
220 | inline const ImageLoader::Symbol* NSSymbolToSymbol(NSSymbol sym) | |
221 | { | |
222 | return (const ImageLoader::Symbol*)sym; | |
223 | } | |
224 | ||
225 | // dyld's abstract type NSModule is implemented as ImageLoader* | |
bac542e6 | 226 | inline NSModule ImageLoaderToNSModule(const ImageLoader* image) |
0959b6d4 A |
227 | { |
228 | return (NSModule)image; | |
229 | } | |
230 | inline ImageLoader* NSModuleToImageLoader(NSModule module) | |
231 | { | |
232 | ImageLoader* image = (ImageLoader*)module; | |
233 | if ( dyld::validImage(image) ) | |
234 | return image; | |
235 | return NULL; | |
236 | } | |
237 | ||
238 | // actual definition for opaque type | |
239 | struct __NSObjectFileImage | |
240 | { | |
241 | ImageLoader* image; | |
242 | const void* imageBaseAddress; // not used with OFI created from files | |
243 | size_t imageLength; // not used with OFI created from files | |
244 | }; | |
2fd3f4e8 A |
245 | |
246 | ||
247 | VECTOR_NEVER_DESTRUCTED(NSObjectFileImage); | |
0959b6d4 A |
248 | static std::vector<NSObjectFileImage> sObjectFileImages; |
249 | ||
250 | ||
251 | ||
252 | // | |
253 | // __NSObjectFileImage are deleted in NSDestroyObjectFileImage() | |
254 | // The contained image is delete in one of two places: | |
255 | // NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it | |
256 | // NSDestroyObjectFileImage deletes the image if image is not in list of valid images | |
257 | // | |
258 | ||
259 | ||
0959b6d4 A |
260 | |
261 | static void setLastError(NSLinkEditErrors code, int errnum, const char* file, const char* message) | |
262 | { | |
263 | dyld::setErrorMessage(message); | |
264 | strncpy(sLastErrorFilePath, file, 1024); | |
265 | sLastErrorFilePath[1023] = '\0'; | |
266 | sLastErrorFileCode = code; | |
267 | sLastErrorNo = errnum; | |
268 | } | |
269 | ||
39a8cd10 | 270 | #endif // DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
271 | |
272 | /* | |
273 | *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which | |
274 | * copies the path of the executable into the buffer and returns 0 if the path | |
275 | * was successfully copied in the provided buffer. If the buffer is not large | |
276 | * enough, -1 is returned and the expected buffer size is copied in *bufsize. | |
277 | * Note that _NSGetExecutablePath will return "a path" to the executable not a | |
278 | * "real path" to the executable. That is the path may be a symbolic link and | |
279 | * not the real file. And with deep directories the total bufsize needed could | |
280 | * be more than MAXPATHLEN. | |
281 | */ | |
282 | int _NSGetExecutablePath(char* buf, uint32_t *bufsize) | |
283 | { | |
284 | if ( dyld::gLogAPIs ) | |
bac542e6 | 285 | dyld::log("%s(...)\n", __func__); |
0959b6d4 A |
286 | const char* exePath = dyld::getExecutablePath(); |
287 | if(*bufsize < strlen(exePath) + 1){ | |
19894a12 | 288 | *bufsize = (uint32_t)(strlen(exePath) + 1); |
0959b6d4 A |
289 | return -1; |
290 | } | |
291 | strcpy(buf, exePath); | |
292 | return 0; | |
293 | } | |
294 | ||
39a8cd10 A |
295 | uint32_t _dyld_image_count(void) |
296 | { | |
297 | if ( dyld::gLogAPIs ) | |
298 | dyld::log("%s()\n", __func__); | |
299 | return dyld::getImageCount(); | |
300 | } | |
301 | ||
302 | const struct mach_header* _dyld_get_image_header(uint32_t image_index) | |
303 | { | |
304 | if ( dyld::gLogAPIs ) | |
305 | dyld::log("%s(%u)\n", __func__, image_index); | |
306 | ImageLoader* image = dyld::getIndexedImage(image_index); | |
307 | if ( image != NULL ) | |
308 | return (struct mach_header*)image->machHeader(); | |
309 | else | |
310 | return NULL; | |
311 | } | |
312 | ||
313 | intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index) | |
314 | { | |
315 | if ( dyld::gLogAPIs ) | |
316 | dyld::log("%s(%u)\n", __func__, image_index); | |
317 | ImageLoader* image = dyld::getIndexedImage(image_index); | |
318 | if ( image != NULL ) | |
319 | return image->getSlide(); | |
320 | else | |
321 | return 0; | |
322 | } | |
323 | ||
324 | intptr_t _dyld_get_image_slide(const struct mach_header* mh) | |
325 | { | |
326 | if ( dyld::gLogAPIs ) | |
327 | dyld::log("%s(%p)\n", __func__, mh); | |
328 | ImageLoader* image = dyld::findImageByMachHeader(mh); | |
329 | if ( image != NULL ) | |
330 | return image->getSlide(); | |
331 | else | |
332 | return 0; | |
333 | } | |
334 | ||
335 | ||
336 | const char* _dyld_get_image_name(uint32_t image_index) | |
337 | { | |
338 | if ( dyld::gLogAPIs ) | |
339 | dyld::log("%s(%u)\n", __func__, image_index); | |
340 | ImageLoader* image = dyld::getIndexedImage(image_index); | |
341 | if ( image != NULL ) | |
832b6fce | 342 | return image->getRealPath(); |
39a8cd10 A |
343 | else |
344 | return NULL; | |
345 | } | |
346 | ||
df9d6cf7 | 347 | const struct mach_header * dyld_image_header_containing_address(const void* address) |
39a8cd10 A |
348 | { |
349 | if ( dyld::gLogAPIs ) | |
350 | dyld::log("%s(%p)\n", __func__, address); | |
351 | ImageLoader* image = dyld::findImageContainingAddress(address); | |
352 | if ( image != NULL ) | |
353 | return image->machHeader(); | |
354 | return NULL; | |
355 | } | |
356 | ||
357 | ||
358 | void _dyld_register_func_for_add_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) | |
359 | { | |
360 | if ( dyld::gLogAPIs ) | |
361 | dyld::log("%s(%p)\n", __func__, (void *)func); | |
362 | dyld::registerAddCallback(func); | |
363 | } | |
364 | ||
365 | void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) | |
366 | { | |
367 | if ( dyld::gLogAPIs ) | |
368 | dyld::log("%s(%p)\n", __func__, (void *)func); | |
369 | dyld::registerRemoveCallback(func); | |
370 | } | |
371 | ||
372 | ||
373 | ||
374 | // called by crt before main() by programs linked with 10.4 or earlier crt1.o | |
375 | static void _dyld_make_delayed_module_initializer_calls() | |
376 | { | |
377 | if ( dyld::gLogAPIs ) | |
378 | dyld::log("%s()\n", __func__); | |
379 | ||
380 | #if SUPPORT_OLD_CRT_INITIALIZATION | |
381 | if ( dyld::gRunInitializersOldWay ) | |
382 | dyld::initializeMainExecutable(); | |
383 | #endif | |
384 | } | |
385 | ||
386 | ||
387 | ||
388 | #if DEPRECATED_APIS_SUPPORTED | |
0959b6d4 A |
389 | |
390 | // | |
391 | // _dyld_call_module_initializers_for_dylib() is the dyld side of | |
392 | // __initialize_Cplusplus() which is in dylib1.o. | |
393 | // It is intended to only be called inside -init rouintes. | |
394 | // -init routines are called before module initializers (what C++ | |
395 | // initializers use). Calling __initialize_Cplusplus() in a -init | |
396 | // routine causes the module initializers for an image to be called | |
397 | // which then allows C++ to be used inside a -init routine | |
398 | // | |
399 | static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header) | |
400 | { | |
401 | if ( dyld::gLogAPIs ) | |
bac542e6 | 402 | dyld::log("__initialize_Cplusplus()\n"); |
0959b6d4 A |
403 | |
404 | // for now, do nothing... | |
405 | } | |
406 | ||
407 | ||
408 | void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module) | |
409 | { | |
410 | if ( dyld::gLogAPIs ) | |
bac542e6 | 411 | dyld::log("%s(\"%s\", %p, %p)\n", __func__, symbolName, address, module); |
0959b6d4 A |
412 | ImageLoader* image; |
413 | const ImageLoader::Symbol* sym; | |
414 | dyld::clearErrorMessage(); | |
bac542e6 | 415 | if ( dyld::flatFindExportedSymbol(symbolName, &sym, (const ImageLoader**)&image) ) { |
0959b6d4 | 416 | try { |
bac542e6 | 417 | image->bindAllLazyPointers(dyld::gLinkContext, true); |
0959b6d4 | 418 | if ( address != NULL) |
bac542e6 | 419 | *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext); |
0959b6d4 A |
420 | if ( module != NULL) |
421 | *module = ImageLoaderToNSModule(image); | |
422 | } | |
423 | catch (const char* msg) { | |
424 | dyldAPIhalt(__func__, msg); | |
425 | } | |
426 | } | |
427 | else { | |
428 | // on failure to find symbol return NULLs | |
429 | if ( address != NULL) | |
430 | *address = NULL; | |
431 | if ( module != NULL) | |
432 | *module = NULL; | |
433 | } | |
434 | } | |
435 | ||
436 | // Note: This cannot have public name because dyld is built with a static copy of libc.a | |
437 | // which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process | |
438 | static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module) | |
439 | { | |
440 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
441 | dyld::log("_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName, address, module); |
442 | const ImageLoader* image; | |
0959b6d4 A |
443 | const ImageLoader::Symbol* sym; |
444 | if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) { | |
445 | if ( address != NULL) | |
bac542e6 | 446 | *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext); |
0959b6d4 A |
447 | if ( module != NULL) |
448 | *module = ImageLoaderToNSModule(image); | |
449 | } | |
450 | else { | |
451 | // on failure to find symbol return NULLs | |
452 | if ( address != NULL) | |
453 | *address = NULL; | |
454 | if ( module != NULL) | |
455 | *module = NULL; | |
456 | } | |
457 | } | |
458 | ||
459 | void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* library_name_hint, void** address, NSModule* module) | |
460 | { | |
461 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
462 | dyld::log("%s(\"%s\", \"%s\", %p, %p)\n", __func__, symbolName, library_name_hint, address, module); |
463 | const ImageLoader* image; | |
0959b6d4 A |
464 | const ImageLoader::Symbol* sym; |
465 | // Look for library whose path contains the hint. If that fails search everywhere | |
466 | if ( dyld::flatFindExportedSymbolWithHint(symbolName, library_name_hint, &sym, &image) | |
467 | || dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) { | |
468 | if ( address != NULL) | |
bac542e6 | 469 | *address = (void*)image->getExportedSymbolAddress(sym, dyld::gLinkContext); |
0959b6d4 A |
470 | if ( module != NULL) |
471 | *module = ImageLoaderToNSModule(image); | |
472 | } | |
473 | else { | |
474 | // on failure to find symbol return NULLs | |
475 | if ( address != NULL) | |
476 | *address = NULL; | |
477 | if ( module != NULL) | |
478 | *module = NULL; | |
479 | } | |
480 | } | |
481 | ||
482 | ||
483 | NSSymbol NSLookupAndBindSymbol(const char *symbolName) | |
484 | { | |
485 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
486 | dyld::log("%s(\"%s\")\n", __func__, symbolName); |
487 | const ImageLoader* image; | |
0959b6d4 A |
488 | const ImageLoader::Symbol* sym; |
489 | if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) { | |
490 | return SymbolToNSSymbol(sym); | |
491 | } | |
492 | // return NULL on failure | |
493 | return NULL; | |
494 | } | |
495 | ||
496 | NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint) | |
497 | { | |
498 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
499 | dyld::log("%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint); |
500 | const ImageLoader* image; | |
0959b6d4 A |
501 | const ImageLoader::Symbol* sym; |
502 | bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image); | |
503 | if ( ! found ) { | |
504 | // hint failed, do slow search of all images | |
505 | found = dyld::flatFindExportedSymbol(symbolName, &sym, &image); | |
506 | } | |
507 | if ( found ) | |
508 | return SymbolToNSSymbol(sym); | |
509 | ||
510 | // return NULL on failure and log | |
511 | if ( dyld::gLogAPIs ) | |
bac542e6 | 512 | dyld::log("%s(\"%s\", \"%s\") => NULL \n", __func__, symbolName, libraryNameHint); |
0959b6d4 A |
513 | return NULL; |
514 | } | |
515 | ||
0959b6d4 | 516 | |
0959b6d4 A |
517 | |
518 | ||
519 | static __attribute__((noinline)) | |
8bc9f0af | 520 | const struct mach_header* addImage(void* callerAddress, const char* path, bool search, bool dontLoad, bool matchInstallName, bool abortOnError) |
0959b6d4 A |
521 | { |
522 | ImageLoader* image = NULL; | |
bac542e6 | 523 | std::vector<const char*> rpathsFromCallerImage; |
0959b6d4 A |
524 | try { |
525 | dyld::clearErrorMessage(); | |
0959b6d4 | 526 | ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress); |
bac542e6 A |
527 | // like dlopen, use rpath from caller image and from main executable |
528 | if ( callerImage != NULL ) | |
529 | callerImage->getRPaths(dyld::gLinkContext, rpathsFromCallerImage); | |
530 | ImageLoader::RPathChain callersRPaths(NULL, &rpathsFromCallerImage); | |
531 | if ( callerImage != dyld::mainExecutable() ) { | |
532 | dyld::mainExecutable()->getRPaths(dyld::gLinkContext, rpathsFromCallerImage); | |
533 | } | |
0959b6d4 A |
534 | dyld::LoadContext context; |
535 | context.useSearchPaths = search; | |
39a8cd10 | 536 | context.useFallbackPaths = search; |
0959b6d4 | 537 | context.useLdLibraryPath = false; |
bac542e6 | 538 | context.implicitRPath = false; |
0959b6d4 A |
539 | context.matchByInstallName = matchInstallName; |
540 | context.dontLoad = dontLoad; | |
541 | context.mustBeBundle = false; | |
542 | context.mustBeDylib = true; | |
39a8cd10 | 543 | context.canBePIE = false; |
0959b6d4 | 544 | context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path |
bac542e6 | 545 | context.rpath = &callersRPaths; // rpaths from caller and main executable |
0959b6d4 A |
546 | |
547 | image = load(path, context); | |
548 | if ( image != NULL ) { | |
549 | if ( context.matchByInstallName ) | |
550 | image->setMatchInstallPath(true); | |
2fd3f4e8 | 551 | dyld::link(image, false, false, callersRPaths); |
bac542e6 A |
552 | dyld::runInitializers(image); |
553 | // images added with NSAddImage() can never be unloaded | |
554 | image->setNeverUnload(); | |
0959b6d4 A |
555 | } |
556 | } | |
557 | catch (const char* msg) { | |
bac542e6 | 558 | dyld::garbageCollectImages(); |
0959b6d4 A |
559 | if ( abortOnError) { |
560 | char pathMsg[strlen(msg)+strlen(path)+4]; | |
561 | strcpy(pathMsg, msg); | |
562 | strcat(pathMsg, " "); | |
563 | strcat(pathMsg, path); | |
564 | dyldAPIhalt("NSAddImage", pathMsg); | |
565 | } | |
566 | // not halting, so set error state for NSLinkEditError to find | |
567 | setLastError(NSLinkEditOtherError, 0, path, msg); | |
2028a915 | 568 | free((void*)msg); // our free() will do nothing if msg is a string literal |
bac542e6 | 569 | image = NULL; |
0959b6d4 | 570 | } |
bac542e6 A |
571 | // free rpaths (getRPaths() malloc'ed each string) |
572 | for(std::vector<const char*>::iterator it=rpathsFromCallerImage.begin(); it != rpathsFromCallerImage.end(); ++it) { | |
573 | const char* str = *it; | |
574 | free((void*)str); | |
575 | } | |
576 | if ( image == NULL ) | |
577 | return NULL; | |
578 | else | |
579 | return image->machHeader(); | |
0959b6d4 A |
580 | } |
581 | ||
bac542e6 | 582 | |
0959b6d4 A |
583 | const struct mach_header* NSAddImage(const char* path, uint32_t options) |
584 | { | |
585 | if ( dyld::gLogAPIs ) | |
bac542e6 | 586 | dyld::log("%s(\"%s\", 0x%08X)\n", __func__, path, options); |
0959b6d4 A |
587 | const bool dontLoad = ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 ); |
588 | const bool search = ( (options & NSADDIMAGE_OPTION_WITH_SEARCHING) != 0 ); | |
589 | const bool matchInstallName = ( (options & NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME) != 0 ); | |
832b6fce | 590 | const bool abortOnError = ( (options & (NSADDIMAGE_OPTION_RETURN_ON_ERROR|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)) == 0 ); |
8bc9f0af A |
591 | void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue |
592 | return addImage(callerAddress, path, search, dontLoad, matchInstallName, abortOnError); | |
0959b6d4 A |
593 | } |
594 | ||
595 | bool NSAddLibrary(const char* path) | |
596 | { | |
597 | if ( dyld::gLogAPIs ) | |
bac542e6 | 598 | dyld::log("%s(\"%s\")\n", __func__, path); |
8bc9f0af A |
599 | void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue |
600 | return (addImage(callerAddress, path, false, false, false, false) != NULL); | |
0959b6d4 A |
601 | } |
602 | ||
603 | bool NSAddLibraryWithSearching(const char* path) | |
604 | { | |
605 | if ( dyld::gLogAPIs ) | |
bac542e6 | 606 | dyld::log("%s(\"%s\")\n", __func__, path); |
8bc9f0af A |
607 | void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue |
608 | return (addImage(callerAddress, path, true, false, false, false) != NULL); | |
0959b6d4 A |
609 | } |
610 | ||
611 | ||
612 | ||
613 | //#define NSADDIMAGE_OPTION_NONE 0x0 | |
614 | //#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 | |
615 | //#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8 | |
616 | ||
617 | bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName) | |
618 | { | |
619 | if ( dyld::gLogAPIs ) | |
bac542e6 | 620 | dyld::log("%s(%p, \"%s\")\n", __func__, (void *)mh, symbolName); |
0959b6d4 A |
621 | ImageLoader* image = dyld::findImageByMachHeader(mh); |
622 | if ( image != NULL ) { | |
39a8cd10 | 623 | if ( image->findExportedSymbol(symbolName, true, NULL) != NULL) |
0959b6d4 A |
624 | return true; |
625 | } | |
626 | return false; | |
627 | } | |
628 | ||
39a8cd10 | 629 | |
0959b6d4 A |
630 | NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolName, uint32_t options) |
631 | { | |
632 | if ( dyld::gLogAPIs ) | |
bac542e6 | 633 | dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__, mh, symbolName, options); |
0959b6d4 A |
634 | const ImageLoader::Symbol* symbol = NULL; |
635 | dyld::clearErrorMessage(); | |
636 | ImageLoader* image = dyld::findImageByMachHeader(mh); | |
637 | if ( image != NULL ) { | |
638 | try { | |
639 | if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) { | |
bac542e6 | 640 | image->bindAllLazyPointers(dyld::gLinkContext, true); |
0959b6d4 A |
641 | } |
642 | else if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW ) { | |
bac542e6 | 643 | image->bindAllLazyPointers(dyld::gLinkContext, false); |
0959b6d4 A |
644 | } |
645 | } | |
646 | catch (const char* msg) { | |
647 | if ( (options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) == 0 ) { | |
648 | dyldAPIhalt(__func__, msg); | |
649 | } | |
650 | } | |
39a8cd10 | 651 | symbol = image->findExportedSymbol(symbolName, true, NULL); |
0959b6d4 A |
652 | } |
653 | if ( dyld::gLogAPIs && (symbol == NULL) ) | |
bac542e6 | 654 | dyld::log("%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options); |
0959b6d4 A |
655 | return SymbolToNSSymbol(symbol); |
656 | } | |
657 | ||
658 | ||
659 | // Note: This cannot have public name because dyld is built with a static copy of libc.a | |
660 | // which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process | |
661 | static bool client_NSIsSymbolNameDefined(const char* symbolName) | |
662 | { | |
663 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
664 | dyld::log("NSIsSymbolNameDefined(\"%s\")\n", symbolName); |
665 | const ImageLoader* image; | |
0959b6d4 A |
666 | const ImageLoader::Symbol* sym; |
667 | return dyld::flatFindExportedSymbol(symbolName, &sym, &image); | |
668 | } | |
669 | ||
670 | bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint) | |
671 | { | |
672 | if ( dyld::gLogAPIs ) | |
bac542e6 A |
673 | dyld::log("%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint); |
674 | const ImageLoader* image; | |
0959b6d4 A |
675 | const ImageLoader::Symbol* sym; |
676 | bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image); | |
677 | if ( ! found ) { | |
678 | // hint failed, do slow search of all images | |
679 | found = dyld::flatFindExportedSymbol(symbolName, &sym, &image); | |
680 | } | |
681 | if ( !found && dyld::gLogAPIs ) | |
bac542e6 | 682 | dyld::log("%s(\"%s\", \"%s\") => false \n", __func__, symbolName, libraryNameHint); |
0959b6d4 A |
683 | return found; |
684 | } | |
685 | ||
686 | const char* NSNameOfSymbol(NSSymbol symbol) | |
687 | { | |
688 | if ( dyld::gLogAPIs ) | |
bac542e6 | 689 | dyld::log("%s(%p)\n", __func__, (void *)symbol); |
0959b6d4 | 690 | const char* result = NULL; |
39a8cd10 | 691 | ImageLoader* image = dyld::findImageContainingSymbol(symbol); |
0959b6d4 A |
692 | if ( image != NULL ) |
693 | result = image->getExportedSymbolName(NSSymbolToSymbol(symbol)); | |
694 | return result; | |
695 | } | |
696 | ||
697 | void* NSAddressOfSymbol(NSSymbol symbol) | |
698 | { | |
699 | if ( dyld::gLogAPIs ) | |
bac542e6 | 700 | dyld::log("%s(%p)\n", __func__, (void *)symbol); |
39a8cd10 A |
701 | if ( symbol == NULL ) |
702 | return NULL; | |
0959b6d4 | 703 | void* result = NULL; |
39a8cd10 | 704 | ImageLoader* image = dyld::findImageContainingSymbol(symbol); |
0959b6d4 | 705 | if ( image != NULL ) |
bac542e6 | 706 | result = (void*)image->getExportedSymbolAddress(NSSymbolToSymbol(symbol), dyld::gLinkContext); |
0959b6d4 A |
707 | return result; |
708 | } | |
709 | ||
710 | NSModule NSModuleForSymbol(NSSymbol symbol) | |
711 | { | |
712 | if ( dyld::gLogAPIs ) | |
bac542e6 | 713 | dyld::log("%s(%p)\n", __func__, (void *)symbol); |
0959b6d4 | 714 | NSModule result = NULL; |
39a8cd10 | 715 | ImageLoader* image = dyld::findImageContainingSymbol(symbol); |
0959b6d4 A |
716 | if ( image != NULL ) |
717 | result = ImageLoaderToNSModule(image); | |
718 | return result; | |
719 | } | |
720 | ||
721 | ||
0959b6d4 A |
722 | |
723 | ||
724 | bool _dyld_all_twolevel_modules_prebound(void) | |
725 | { | |
726 | if ( dyld::gLogAPIs ) | |
bac542e6 | 727 | dyld::log("%s()\n", __func__); |
39a8cd10 | 728 | return FALSE; |
0959b6d4 A |
729 | } |
730 | ||
731 | void _dyld_bind_objc_module(const void *objc_module) | |
732 | { | |
733 | if ( dyld::gLogAPIs ) | |
bac542e6 | 734 | dyld::log("%s(%p)\n", __func__, objc_module); |
0959b6d4 A |
735 | // do nothing, with new dyld everything already bound |
736 | } | |
737 | ||
738 | ||
739 | bool _dyld_bind_fully_image_containing_address(const void* address) | |
740 | { | |
741 | if ( dyld::gLogAPIs ) | |
bac542e6 | 742 | dyld::log("%s(%p)\n", __func__, address); |
0959b6d4 A |
743 | dyld::clearErrorMessage(); |
744 | ImageLoader* image = dyld::findImageContainingAddress(address); | |
745 | if ( image != NULL ) { | |
746 | try { | |
bac542e6 | 747 | image->bindAllLazyPointers(dyld::gLinkContext, true); |
0959b6d4 A |
748 | return true; |
749 | } | |
750 | catch (const char* msg) { | |
751 | dyldAPIhalt(__func__, msg); | |
752 | } | |
753 | } | |
754 | return false; | |
755 | } | |
756 | ||
757 | bool _dyld_image_containing_address(const void* address) | |
758 | { | |
759 | if ( dyld::gLogAPIs ) | |
bac542e6 | 760 | dyld::log("%s(%p)\n", __func__, address); |
0959b6d4 A |
761 | ImageLoader *imageLoader = dyld::findImageContainingAddress(address); |
762 | return (NULL != imageLoader); | |
763 | } | |
764 | ||
765 | static NSObjectFileImage createObjectImageFile(ImageLoader* image, const void* address = NULL, size_t len=0) | |
766 | { | |
767 | NSObjectFileImage result = new __NSObjectFileImage(); | |
768 | result->image = image; | |
769 | result->imageBaseAddress = address; | |
770 | result->imageLength = len; | |
771 | sObjectFileImages.push_back(result); | |
772 | return result; | |
773 | } | |
774 | ||
775 | NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage) | |
776 | { | |
777 | if ( dyld::gLogAPIs ) | |
bac542e6 | 778 | dyld::log("%s(\"%s\", ...)\n", __func__, pathName); |
0959b6d4 A |
779 | try { |
780 | void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue | |
781 | ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress); | |
782 | ||
783 | dyld::LoadContext context; | |
784 | context.useSearchPaths = false; | |
39a8cd10 | 785 | context.useFallbackPaths = false; |
0959b6d4 | 786 | context.useLdLibraryPath = false; |
bac542e6 | 787 | context.implicitRPath = false; |
0959b6d4 A |
788 | context.matchByInstallName = false; |
789 | context.dontLoad = false; | |
790 | context.mustBeBundle = true; | |
791 | context.mustBeDylib = false; | |
39a8cd10 | 792 | context.canBePIE = false; |
0959b6d4 A |
793 | context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path |
794 | context.rpath = NULL; // support not yet implemented | |
795 | ||
796 | ImageLoader* image = dyld::load(pathName, context); | |
797 | // Note: We DO NOT link the image! NSLinkModule will do that | |
798 | if ( image != NULL ) { | |
799 | if ( !image->isBundle() ) { | |
800 | // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded) | |
801 | return NSObjectFileImageInappropriateFile; | |
802 | } | |
803 | *objectFileImage = createObjectImageFile(image); | |
804 | return NSObjectFileImageSuccess; | |
805 | } | |
806 | } | |
807 | catch (const char* msg) { | |
bac542e6 A |
808 | //dyld::log("dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg); |
809 | dyld::garbageCollectImages(); | |
810 | free((void*)msg); | |
0959b6d4 A |
811 | return NSObjectFileImageInappropriateFile; |
812 | } | |
813 | return NSObjectFileImageFailure; | |
814 | } | |
815 | ||
816 | ||
817 | NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage *objectFileImage) | |
818 | { | |
819 | if ( dyld::gLogAPIs ) | |
bac542e6 | 820 | dyld::log("%s(%p, %lu, %p)\n", __func__, address, size, objectFileImage); |
0959b6d4 A |
821 | |
822 | try { | |
823 | ImageLoader* image = dyld::loadFromMemory((const uint8_t*)address, size, NULL); | |
824 | if ( ! image->isBundle() ) { | |
825 | // this API can only be used with bundles... | |
bac542e6 | 826 | dyld::garbageCollectImages(); |
0959b6d4 A |
827 | return NSObjectFileImageInappropriateFile; |
828 | } | |
829 | // Note: We DO NOT link the image! NSLinkModule will do that | |
830 | if ( image != NULL ) { | |
831 | *objectFileImage = createObjectImageFile(image, address, size); | |
832 | return NSObjectFileImageSuccess; | |
833 | } | |
834 | } | |
835 | catch (const char* msg) { | |
bac542e6 A |
836 | free((void*)msg); |
837 | dyld::garbageCollectImages(); | |
838 | //dyld::log("dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg); | |
0959b6d4 A |
839 | } |
840 | return NSObjectFileImageFailure; | |
841 | } | |
842 | ||
843 | static bool validOFI(NSObjectFileImage objectFileImage) | |
844 | { | |
845 | const int ofiCount = sObjectFileImages.size(); | |
846 | for (int i=0; i < ofiCount; ++i) { | |
847 | if ( sObjectFileImages[i] == objectFileImage ) | |
848 | return true; | |
849 | } | |
850 | return false; | |
851 | } | |
852 | ||
853 | bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage) | |
854 | { | |
855 | if ( dyld::gLogAPIs ) | |
bac542e6 | 856 | dyld::log("%s(%p)\n", __func__, objectFileImage); |
0959b6d4 A |
857 | |
858 | if ( validOFI(objectFileImage) ) { | |
bac542e6 A |
859 | // a failure during NSLinkModule will delete the image |
860 | if ( objectFileImage->image != NULL ) { | |
861 | // if the image has never been linked or has been unlinked, the image is not in the list of valid images | |
862 | // and we should delete it | |
863 | bool linkedImage = dyld::validImage(objectFileImage->image); | |
864 | if ( ! linkedImage ) { | |
39a8cd10 | 865 | ImageLoader::deleteImage(objectFileImage->image); |
bac542e6 A |
866 | objectFileImage->image = NULL; |
867 | } | |
868 | } | |
0959b6d4 A |
869 | |
870 | // remove from list of ofi's | |
871 | for (std::vector<NSObjectFileImage>::iterator it=sObjectFileImages.begin(); it != sObjectFileImages.end(); it++) { | |
872 | if ( *it == objectFileImage ) { | |
873 | sObjectFileImages.erase(it); | |
874 | break; | |
875 | } | |
876 | } | |
877 | ||
878 | // if object was created from a memory, release that memory | |
879 | // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld | |
880 | if ( objectFileImage->imageBaseAddress != NULL ) { | |
39a8cd10 A |
881 | bool freed = false; |
882 | if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 6) ) { | |
883 | size_t sz = (*dyld::gLibSystemHelpers->malloc_size)(objectFileImage->imageBaseAddress); | |
884 | if ( sz != 0 ) { | |
885 | (*dyld::gLibSystemHelpers->free)((void*)(objectFileImage->imageBaseAddress)); | |
886 | freed = true; | |
887 | } | |
888 | } | |
889 | if ( ! freed ) | |
890 | vm_deallocate(mach_task_self(), (vm_address_t)objectFileImage->imageBaseAddress, objectFileImage->imageLength); | |
0959b6d4 A |
891 | } |
892 | ||
893 | // free ofi object | |
894 | delete objectFileImage; | |
895 | ||
896 | return true; | |
897 | } | |
898 | return false; | |
899 | } | |
900 | ||
901 | bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage) | |
902 | { | |
903 | if ( dyld::gLogAPIs ) | |
bac542e6 | 904 | dyld::log("%s(%p)\n", __func__, objectFileImage); |
0959b6d4 A |
905 | return objectFileImage->image->needsInitialization(); |
906 | } | |
907 | ||
908 | uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage) | |
909 | { | |
910 | if ( dyld::gLogAPIs ) | |
bac542e6 | 911 | dyld::log("%s(%p)\n", __func__, objectFileImage); |
0959b6d4 A |
912 | return objectFileImage->image->getExportedSymbolCount(); |
913 | } | |
914 | ||
915 | const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal) | |
916 | { | |
917 | if ( dyld::gLogAPIs ) | |
bac542e6 | 918 | dyld::log("%s(%p,%d)\n", __func__, objectFileImage, ordinal); |
0959b6d4 A |
919 | const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedExportedSymbol(ordinal); |
920 | return objectFileImage->image->getExportedSymbolName(sym); | |
921 | } | |
922 | ||
923 | uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage) | |
924 | { | |
925 | if ( dyld::gLogAPIs ) | |
bac542e6 | 926 | dyld::log("%s(%p)\n", __func__, objectFileImage); |
0959b6d4 A |
927 | return objectFileImage->image->getImportedSymbolCount(); |
928 | } | |
929 | ||
930 | const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal, | |
931 | bool* tentative_definition) | |
932 | { | |
933 | if ( dyld::gLogAPIs ) | |
bac542e6 | 934 | dyld::log("%s(%p,%d)\n", __func__, objectFileImage, ordinal); |
0959b6d4 A |
935 | const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedImportedSymbol(ordinal); |
936 | if ( tentative_definition != NULL ) { | |
39a8cd10 | 937 | ImageLoader::ReferenceFlags flags = objectFileImage->image->getImportedSymbolInfo(sym); |
0959b6d4 A |
938 | if ( (flags & ImageLoader::kTentativeDefinition) != 0 ) |
939 | *tentative_definition = true; | |
940 | else | |
941 | *tentative_definition = false; | |
942 | } | |
943 | return objectFileImage->image->getImportedSymbolName(sym); | |
944 | } | |
945 | ||
946 | void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage, | |
947 | const char* segmentName, const char* sectionName, unsigned long* size) | |
948 | { | |
949 | if ( dyld::gLogAPIs ) | |
bac542e6 | 950 | dyld::log("%s(%p,%s, %s)\n", __func__, objectFileImage, segmentName, sectionName); |
0959b6d4 A |
951 | |
952 | void* start; | |
953 | size_t length; | |
954 | if ( objectFileImage->image->getSectionContent(segmentName, sectionName, &start, &length) ) { | |
955 | if ( size != NULL ) | |
956 | *size = length; | |
957 | return start; | |
958 | } | |
959 | return NULL; | |
960 | } | |
961 | ||
962 | ||
963 | ||
964 | bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName) | |
965 | { | |
966 | if ( dyld::gLogAPIs ) | |
bac542e6 | 967 | dyld::log("%s(%p,%s)\n", __func__, objectFileImage, symbolName); |
39a8cd10 | 968 | const ImageLoader::Symbol* sym = objectFileImage->image->findExportedSymbol(symbolName, true, NULL); |
0959b6d4 A |
969 | return ( sym != NULL ); |
970 | } | |
971 | ||
0959b6d4 A |
972 | |
973 | ||
974 | NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options) | |
975 | { | |
976 | if ( dyld::gLogAPIs ) | |
bac542e6 | 977 | dyld::log("%s(%p, \"%s\", 0x%08X)\n", __func__, objectFileImage, moduleName, options); |
0959b6d4 A |
978 | |
979 | dyld::clearErrorMessage(); | |
980 | try { | |
2fd3f4e8 A |
981 | if ( (options & NSLINKMODULE_OPTION_CAN_UNLOAD) != 0 ) |
982 | objectFileImage->image->setCanUnload(); | |
983 | ||
0959b6d4 A |
984 | // NSLinkModule allows a bundle to be link multpile times |
985 | // each link causes the bundle to be copied to a new address | |
986 | if ( objectFileImage->image->isLinked() ) { | |
987 | // already linked, so clone a new one and link it | |
0959b6d4 A |
988 | objectFileImage->image = dyld::cloneImage(objectFileImage->image); |
989 | } | |
412ebb8e | 990 | |
39a8cd10 | 991 | // for memory based images, set moduleName as the name anyone calling _dyld_get_image_name() will see |
412ebb8e | 992 | if ( objectFileImage->image->getPath() == NULL ) { |
39a8cd10 | 993 | objectFileImage->image->setPath(moduleName); |
412ebb8e A |
994 | // <rdar://problem/8812589> dyld has NULL paths in image info array |
995 | dyld_image_info info; | |
996 | info.imageLoadAddress = objectFileImage->image->machHeader(); | |
997 | info.imageFilePath = moduleName; | |
998 | info.imageFileModDate = 0; | |
999 | addImagesToAllImages(1, &info); | |
1000 | } | |
0959b6d4 A |
1001 | |
1002 | // support private bundles | |
1003 | if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 ) | |
1004 | objectFileImage->image->setHideExports(); | |
1005 | ||
1006 | // set up linking options | |
bac542e6 | 1007 | bool forceLazysBound = ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 ); |
0959b6d4 A |
1008 | |
1009 | // load libraries, rebase, bind, to make this image usable | |
2fd3f4e8 | 1010 | dyld::link(objectFileImage->image, forceLazysBound, false, ImageLoader::RPathChain(NULL,NULL)); |
0959b6d4 | 1011 | |
39a8cd10 A |
1012 | // bump reference count to keep this bundle from being garbage collected |
1013 | objectFileImage->image->incrementDlopenReferenceCount(); | |
1014 | ||
bac542e6 A |
1015 | // run initializers unless magic flag says not to |
1016 | if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) == 0 ) | |
1017 | dyld::runInitializers(objectFileImage->image); | |
1018 | ||
0959b6d4 A |
1019 | return ImageLoaderToNSModule(objectFileImage->image); |
1020 | } | |
1021 | catch (const char* msg) { | |
bac542e6 | 1022 | dyld::garbageCollectImages(); |
0959b6d4 A |
1023 | if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 ) |
1024 | dyldAPIhalt(__func__, msg); | |
1025 | // not halting, so set error state for NSLinkEditError to find | |
0959b6d4 | 1026 | setLastError(NSLinkEditOtherError, 0, moduleName, msg); |
bac542e6 A |
1027 | // dyld::link() deleted the image so lose our reference |
1028 | objectFileImage->image = NULL; | |
1029 | free((void*)msg); | |
0959b6d4 A |
1030 | return NULL; |
1031 | } | |
1032 | } | |
1033 | ||
bac542e6 | 1034 | |
0959b6d4 A |
1035 | #if OLD_LIBSYSTEM_SUPPORT |
1036 | // This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld | |
1037 | static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options) | |
1038 | { | |
1039 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1040 | dyld::log("%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr, moduleName, options); // note name/args translation |
0959b6d4 A |
1041 | ImageLoader* image = NULL; |
1042 | dyld::clearErrorMessage(); | |
1043 | try { | |
39a8cd10 | 1044 | const char* imageName = moduleName; |
0959b6d4 A |
1045 | image = dyld::loadFromMemory((const uint8_t*)object_addr, object_size, imageName); |
1046 | ||
0959b6d4 A |
1047 | if ( image != NULL ) { |
1048 | // support private bundles | |
1049 | if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 ) | |
1050 | image->setHideExports(); | |
1051 | ||
1052 | // set up linking options | |
bac542e6 | 1053 | bool forceLazysBound = ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 ); |
0959b6d4 A |
1054 | |
1055 | // load libraries, rebase, bind, to make this image usable | |
2fd3f4e8 | 1056 | dyld::link(image, forceLazysBound, false, ImageLoader::RPathChain(NULL,NULL)); |
bac542e6 A |
1057 | |
1058 | // run initializers unless magic flag says not to | |
1059 | if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) == 0 ) | |
1060 | dyld::runInitializers(image); | |
0959b6d4 A |
1061 | } |
1062 | } | |
1063 | catch (const char* msg) { | |
1064 | if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 ) | |
1065 | dyldAPIhalt("NSLinkModule", msg); | |
1066 | // not halting, so set error state for NSLinkEditError to find | |
1067 | setLastError(NSLinkEditOtherError, 0, moduleName, msg); | |
1068 | // if image was created for this bundle, destroy it | |
1069 | if ( image != NULL ) { | |
1070 | dyld::removeImage(image); | |
39a8cd10 | 1071 | ImageLoader::deleteImage(image); |
0959b6d4 A |
1072 | } |
1073 | image = NULL; | |
bac542e6 | 1074 | free((void*)msg); |
0959b6d4 A |
1075 | } |
1076 | return ImageLoaderToNSModule(image); | |
1077 | } | |
1078 | #endif | |
1079 | ||
1080 | NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName) | |
1081 | { | |
1082 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1083 | dyld::log("%s(%p, \"%s\")\n", __func__, (void *)module, symbolName); |
0959b6d4 A |
1084 | ImageLoader* image = NSModuleToImageLoader(module); |
1085 | if ( image == NULL ) | |
1086 | return NULL; | |
39a8cd10 | 1087 | return SymbolToNSSymbol(image->findExportedSymbol(symbolName, false, NULL)); |
0959b6d4 A |
1088 | } |
1089 | ||
1090 | const char* NSNameOfModule(NSModule module) | |
1091 | { | |
1092 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1093 | dyld::log("%s(%p)\n", __func__, module); |
0959b6d4 A |
1094 | ImageLoader* image = NSModuleToImageLoader(module); |
1095 | if ( image == NULL ) | |
1096 | return NULL; | |
1097 | return image->getPath(); | |
1098 | } | |
1099 | ||
1100 | const char* NSLibraryNameForModule(NSModule module) | |
1101 | { | |
1102 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1103 | dyld::log("%s(%p)\n", __func__, module); |
0959b6d4 A |
1104 | ImageLoader* image = NSModuleToImageLoader(module); |
1105 | if ( image == NULL ) | |
1106 | return NULL; | |
1107 | return image->getPath(); | |
1108 | } | |
1109 | ||
1110 | bool NSUnLinkModule(NSModule module, uint32_t options) | |
1111 | { | |
1112 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1113 | dyld::log("%s(%p, 0x%08X)\n", __func__, module, options); |
0959b6d4 A |
1114 | if ( module == NULL ) |
1115 | return false; | |
1116 | ImageLoader* image = NSModuleToImageLoader(module); | |
1117 | if ( image == NULL ) | |
1118 | return false; | |
19894a12 A |
1119 | dyld::runImageStaticTerminators(image); |
1120 | if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 13) ) { | |
df9d6cf7 | 1121 | __cxa_range_t ranges[image->segmentCount()]; |
19894a12 A |
1122 | int rangeCount = 0; |
1123 | for (unsigned int j=0; j < image->segmentCount(); ++j) { | |
1124 | if ( !image->segExecutable(j) ) | |
1125 | continue; | |
1126 | ranges[rangeCount].addr = (const void*)image->segActualLoadAddress(j); | |
1127 | ranges[rangeCount].length = image->segSize(j); | |
1128 | ++rangeCount; | |
1129 | } | |
1130 | (*dyld::gLibSystemHelpers->cxa_finalize_ranges)(ranges, rangeCount); | |
1131 | } | |
0959b6d4 A |
1132 | dyld::removeImage(image); |
1133 | ||
1134 | if ( (options & NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) != 0 ) | |
1135 | image->setLeaveMapped(); | |
1136 | ||
1137 | // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES | |
1138 | ||
1139 | // Only delete image if there is no ofi referencing it | |
1140 | // That means the ofi was destroyed after linking, so no one is left to delete this image | |
1141 | const int ofiCount = sObjectFileImages.size(); | |
1142 | bool found = false; | |
1143 | for (int i=0; i < ofiCount; ++i) { | |
1144 | NSObjectFileImage ofi = sObjectFileImages[i]; | |
1145 | if ( ofi->image == image ) | |
1146 | found = true; | |
1147 | } | |
1148 | if ( !found ) | |
39a8cd10 | 1149 | ImageLoader::deleteImage(image); |
0959b6d4 A |
1150 | |
1151 | return true; | |
1152 | } | |
1153 | ||
1154 | // internal name and parameters do not match public name and parameters... | |
1155 | static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit) | |
1156 | { | |
1157 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1158 | dyld::log("NSLinkEditErrorHandlers()\n"); |
0959b6d4 A |
1159 | |
1160 | dyld::registerUndefinedHandler((dyld::UndefinedHandler)undefined); | |
1161 | // no support for multiple or linkedit handlers | |
1162 | } | |
1163 | ||
0959b6d4 | 1164 | |
0959b6d4 A |
1165 | |
1166 | ||
1167 | void NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString) | |
1168 | { | |
1169 | // FIXME FIXME | |
1170 | *c = sLastErrorFileCode; | |
1171 | *errorNumber = sLastErrorNo; | |
1172 | *fileName = sLastErrorFilePath; | |
1173 | *errorString = dyld::getErrorMessage(); | |
1174 | } | |
1175 | ||
39a8cd10 A |
1176 | |
1177 | ||
0959b6d4 A |
1178 | static void _dyld_register_binding_handler(void * (*bindingHandler)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions) |
1179 | { | |
1180 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1181 | dyld::log("%s()\n", __func__); |
0959b6d4 A |
1182 | dyld::gLinkContext.bindingHandler = bindingHandler; |
1183 | dyld::gLinkContext.bindingOptions = bindingOptions; | |
1184 | } | |
1185 | ||
39a8cd10 A |
1186 | #endif //DEPRECATED_APIS_SUPPORTED |
1187 | ||
0959b6d4 A |
1188 | |
1189 | // Call by fork() in libSystem after the kernel trap is done on the child side | |
412ebb8e | 1190 | void _dyld_fork_child() |
0959b6d4 A |
1191 | { |
1192 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1193 | dyld::log("%s()\n", __func__); |
0959b6d4 A |
1194 | // The implementation of fork() in libSystem knows to reset the variable mach_task_self_ |
1195 | // in libSystem for the child of a fork. But dyld is built with a static copy | |
1196 | // of libc.a and has its own copy of mach_task_self_ which we reset here. | |
1197 | // | |
1198 | // In mach_init.h mach_task_self() is #defined to mach_task_self_ and | |
1199 | // in mach_init() mach_task_self_ is initialized to task_self_trap(). | |
1200 | // | |
1201 | extern mach_port_t mach_task_self_; | |
1202 | mach_task_self_ = task_self_trap(); | |
39a8cd10 A |
1203 | |
1204 | // If dyld is sending load/unload notices to CoreSymbolication, the shared memory | |
1205 | // page is not copied on fork. <rdar://problem/6797342> | |
1206 | // NULL the CoreSymbolication shared memory pointer to prevent a crash. | |
2fd3f4e8 | 1207 | dyld::gProcessInfo->coreSymbolicationShmPage = NULL; |
39a8cd10 | 1208 | // for safety, make sure child starts with clean systemOrderFlag |
2fd3f4e8 | 1209 | dyld::gProcessInfo->systemOrderFlag = 0; |
0959b6d4 A |
1210 | } |
1211 | ||
0959b6d4 | 1212 | |
39a8cd10 | 1213 | #if DEPRECATED_APIS_SUPPORTED |
0959b6d4 A |
1214 | // returns true if prebinding was used in main executable |
1215 | bool _dyld_launched_prebound() | |
1216 | { | |
1217 | if ( dyld::gLogAPIs ) | |
bac542e6 | 1218 | dyld::log("%s()\n", __func__); |
0959b6d4 A |
1219 | |
1220 |