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