1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
   3  * Copyright (c) 2004-2012 Apple Inc. All rights reserved. 
   5  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  22  * @APPLE_LICENSE_HEADER_END@ 
  27 #include <malloc/malloc.h> 
  30 #include <crt_externs.h> 
  31 #include <Availability.h> 
  32 #include <vproc_priv.h> 
  37 #include "mach-o/dyld_images.h" 
  38 #include "mach-o/dyld.h" 
  39 #include "mach-o/dyld_priv.h" 
  40 #include "dyld_cache_format.h" 
  42 #include "ImageLoader.h" 
  44 #include "start_glue.h" 
  46 extern "C" int  __cxa_atexit(void (*func
)(void *), void *arg
, void *dso
); 
  47 extern "C" void __cxa_finalize(const void *dso
); 
  48 extern "C" void __cxa_finalize_ranges(const struct __cxa_range_t ranges
[], int count
); 
  51 #ifndef LC_VERSION_MIN_MACOSX 
  52         #define LC_VERSION_MIN_MACOSX 0x24 
  53         struct version_min_command 
{ 
  54                 uint32_t        cmd
;            /* LC_VERSION_MIN_MACOSX or 
  55                                            LC_VERSION_MIN_IPHONEOS  */ 
  56                 uint32_t        cmdsize
;        /* sizeof(struct min_version_command) */ 
  57                 uint32_t        version
;        /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ 
  58                 uint32_t        sdk
;            /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ 
  62 #ifndef LC_VERSION_MIN_IPHONEOS 
  63         #define LC_VERSION_MIN_IPHONEOS 0x25 
  66 #ifndef LC_VERSION_MIN_TVOS 
  67         #define LC_VERSION_MIN_TVOS 0x2F 
  70 #ifndef LC_VERSION_MIN_WATCHOS 
  71         #define LC_VERSION_MIN_WATCHOS 0x30 
  75 #ifndef LC_LOAD_UPWARD_DYLIB 
  76         #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ 
  80 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS 
  81 #if __IPHONE_OS_VERSION_MIN_REQUIRED     
  82         #define DEPRECATED_APIS_SUPPORTED 0 
  84         #define DEPRECATED_APIS_SUPPORTED 1 
  88  * names_match() takes an install_name from an LC_LOAD_DYLIB command and a 
  89  * libraryName (which is -lx or -framework Foo argument passed to the static 
  90  * link editor for the same library) and determines if they match.  This depends 
  91  * on conventional use of names including major versioning. 
  96 const char *install_name
, 
  97 const char* libraryName
) 
 103          * Conventional install names have these forms: 
 104          *      /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit 
 105          *      /Local/Library/Frameworks/AppKit.framework/Appkit 
 106          *      /lib/libsys_s.A.dylib 
 107          *      /usr/lib/libsys_s.dylib 
 109         basename 
= strrchr(install_name
, '/'); 
 111             basename 
= install_name
; 
 116          * By checking the base name matching the library name we take care 
 117          * of the -framework cases. 
 119         if(strcmp(basename
, libraryName
) == 0) 
 123          * Now check the base name for "lib" if so proceed to check for the 
 124          * -lx case dealing with a possible .X.dylib and a .dylib extension. 
 126         if(strncmp(basename
, "lib", 3) ==0){ 
 127             n 
= strlen(libraryName
); 
 128             if(strncmp(basename
+3, libraryName
, n
) == 0){ 
 129                 if(strncmp(basename
+3+n
, ".dylib", 6) == 0) 
 131                 if(basename
[3+n
] == '.' && 
 132                    basename
[3+n
+1] != '\0' && 
 133                    strncmp(basename
+3+n
+2, ".dylib", 6) == 0) 
 140 #if DEPRECATED_APIS_SUPPORTED 
 142 void NSInstallLinkEditErrorHandlers( 
 143 const NSLinkEditErrorHandlers
* handlers
) 
 145         DYLD_LOCK_THIS_BLOCK
; 
 146         typedef void (*ucallback_t
)(const char* symbol_name
); 
 147         typedef NSModule (*mcallback_t
)(NSSymbol s
, NSModule old
, NSModule newhandler
); 
 148         typedef void (*lcallback_t
)(NSLinkEditErrors c
, int errorNumber
, 
 149                                                                 const char* fileName
, const char* errorString
); 
 150         static void (*p
)(ucallback_t undefined
, mcallback_t multiple
, lcallback_t linkEdit
) = NULL
; 
 153             _dyld_func_lookup("__dyld_install_handlers", (void**)&p
); 
 154         mcallback_t m 
= handlers
->multiple
; 
 155         p(handlers
->undefined
, m
, handlers
->linkEdit
); 
 162         DYLD_LOCK_THIS_BLOCK
; 
 163     static const char*  (*p
)(NSModule 
module) = NULL
; 
 166             _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p
); 
 171 NSLibraryNameForModule( 
 174         DYLD_LOCK_THIS_BLOCK
; 
 175     static const char*  (*p
)(NSModule 
module) = NULL
; 
 178             _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p
); 
 183 NSIsSymbolNameDefined( 
 184 const char* symbolName
) 
 186         DYLD_LOCK_THIS_BLOCK
; 
 187     static bool (*p
)(const char* symbolName
) = NULL
; 
 190             _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p
); 
 191         return(p(symbolName
)); 
 195 NSIsSymbolNameDefinedWithHint( 
 196 const char* symbolName
, 
 197 const char* libraryNameHint
) 
 199         DYLD_LOCK_THIS_BLOCK
; 
 200     static bool (*p
)(const char* symbolName
, 
 201                           const char* libraryNameHint
) = NULL
; 
 204             _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p
); 
 205         return(p(symbolName
, libraryNameHint
)); 
 209 NSIsSymbolNameDefinedInImage( 
 210 const struct mach_header 
*image
, 
 211 const char* symbolName
) 
 213         DYLD_LOCK_THIS_BLOCK
; 
 214     static bool (*p
)(const struct mach_header 
*image
, 
 215                           const char* symbolName
) = NULL
; 
 218             _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p
); 
 219         return(p(image
, symbolName
)); 
 223 NSLookupAndBindSymbol( 
 224 const char* symbolName
) 
 226         DYLD_LOCK_THIS_BLOCK
; 
 227     static NSSymbol (*p
)(const char* symbolName
) = NULL
; 
 230             _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p
); 
 231         return(p(symbolName
)); 
 235 NSLookupAndBindSymbolWithHint( 
 236 const char* symbolName
, 
 237 const char* libraryNameHint
) 
 239         DYLD_LOCK_THIS_BLOCK
; 
 240     static NSSymbol (*p
)(const char* symbolName
, 
 241                          const char* libraryNameHint
) = NULL
; 
 244             _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p
); 
 245         return(p(symbolName
, libraryNameHint
)); 
 249 NSLookupSymbolInModule( 
 251 const char* symbolName
) 
 253         DYLD_LOCK_THIS_BLOCK
; 
 254     static NSSymbol (*p
)(NSModule 
module, const char* symbolName
) = NULL
; 
 257             _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p
); 
 258         return(p(module, symbolName
)); 
 262 NSLookupSymbolInImage( 
 263 const struct mach_header 
*image
, 
 264 const char* symbolName
, 
 267         DYLD_LOCK_THIS_BLOCK
; 
 268    static NSSymbol (*p
)(const struct mach_header 
*image
, 
 269                          const char* symbolName
, 
 270                          uint32_t options
) = NULL
; 
 273             _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p
); 
 274         return(p(image
, symbolName
, options
)); 
 281         DYLD_LOCK_THIS_BLOCK
; 
 282     static char * (*p
)(NSSymbol symbol
) = NULL
; 
 285             _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p
); 
 293         DYLD_LOCK_THIS_BLOCK
; 
 294     static void * (*p
)(NSSymbol symbol
) = NULL
; 
 297             _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p
); 
 305         DYLD_LOCK_THIS_BLOCK
; 
 306     static NSModule (*p
)(NSSymbol symbol
) = NULL
; 
 309             _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p
); 
 315 const char* pathName
) 
 317         DYLD_LOCK_THIS_BLOCK
; 
 318     static bool (*p
)(const char* pathName
) = NULL
; 
 321             _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p
); 
 326 NSAddLibraryWithSearching( 
 327 const char* pathName
) 
 329         DYLD_LOCK_THIS_BLOCK
; 
 330     static bool (*p
)(const char* pathName
) = NULL
; 
 333             _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p
); 
 337 const struct mach_header 
* 
 339 const char* image_name
, 
 342         DYLD_LOCK_THIS_BLOCK
; 
 343     static const struct mach_header 
* (*p
)(const char* image_name
, 
 344                                            uint32_t options
) = NULL
; 
 347             _dyld_func_lookup("__dyld_NSAddImage", (void**)&p
); 
 348         return(p(image_name
, options
)); 
 350 #endif // DEPRECATED_APIS_SUPPORTED 
 353  * This routine returns the current version of the named shared library the 
 354  * executable it was built with.  The libraryName parameter is the same as the 
 355  * -lx or -framework Foo argument passed to the static link editor when building 
 356  * the executable (with -lx it would be "x" and with -framework Foo it would be 
 357  * "Foo").  If this the executable was not built against the specified library 
 358  * it returns -1.  It should be noted that if this only returns the value the 
 359  * current version of the named shared library the executable was built with 
 360  * and not a list of current versions that dependent libraries and bundles the 
 361  * program is using were built with. 
 363 int32_t NSVersionOfLinkTimeLibrary(const char* libraryName
) 
 365         // Lazily call _NSGetMachExecuteHeader() and cache result 
 367     static mach_header_64
* mh 
= NULL
; 
 369     static mach_header
* mh 
= NULL
; 
 372             mh 
= _NSGetMachExecuteHeader(); 
 374         const load_command
* lc 
= (load_command
*)((char*)mh 
+ sizeof(mach_header_64
)); 
 376         const load_command
* lc 
= (load_command
*)((char*)mh 
+ sizeof(mach_header
)); 
 378         for(uint32_t i 
= 0; i 
< mh
->ncmds
; i
++){ 
 381                         case LC_LOAD_WEAK_DYLIB
: 
 382                         case LC_LOAD_UPWARD_DYLIB
: 
 383                                 const dylib_command
* dl 
= (dylib_command 
*)lc
; 
 384                                 const char* install_name 
= (char*)dl 
+ dl
->dylib
.name
.offset
; 
 385                                 if ( names_match(install_name
, libraryName
) ) 
 386                                         return dl
->dylib
.current_version
; 
 389             lc 
= (load_command
*)((char*)lc 
+ lc
->cmdsize
); 
 395  * This routine returns the current version of the named shared library the 
 396  * program it is running against.  The libraryName parameter is the same as 
 397  * would be static link editor using the -lx or -framework Foo flags (with -lx 
 398  * it would be "x" and with -framework Foo it would be "Foo").  If the program 
 399  * is not using the specified library it returns -1. 
 401 int32_t NSVersionOfRunTimeLibrary(const char* libraryName
) 
 403         uint32_t n 
= _dyld_image_count(); 
 404         for(uint32_t i 
= 0; i 
< n
; i
++){ 
 405             const mach_header
* mh 
= _dyld_get_image_header(i
); 
 408             if ( mh
->filetype 
!= MH_DYLIB 
) 
 411             const load_command
* lc 
= (load_command
*)((char*)mh 
+ sizeof(mach_header_64
)); 
 413             const load_command
* lc 
= (load_command
*)((char*)mh 
+ sizeof(mach_header
)); 
 415             for(uint32_t j 
= 0; j 
< mh
->ncmds
; j
++){ 
 416                         if ( lc
->cmd 
== LC_ID_DYLIB 
) { 
 417                                 const dylib_command
* dl 
= (dylib_command
*)lc
; 
 418                                 const char* install_name 
= (char *)dl 
+ dl
->dylib
.name
.offset
; 
 419                                 if ( names_match(install_name
, libraryName
) ) 
 420                                         return dl
->dylib
.current_version
; 
 422                         lc 
= (load_command
*)((char*)lc 
+ lc
->cmdsize
); 
 429 #define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff)) 
 432 static bool getVersionLoadCommandInfo(const mach_header
* mh
, uint32_t* loadCommand
, uint32_t* minOS
, uint32_t* sdk
) 
 434         const load_command
* startCmds 
= NULL
; 
 435         if ( mh
->magic 
== MH_MAGIC_64 
) 
 436                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header_64
)); 
 437         else if ( mh
->magic 
== MH_MAGIC 
) 
 438                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header
)); 
 440                 return false;  // not a mach-o file, or wrong endianness 
 442         const load_command
* const cmdsEnd 
= (load_command
*)((char*)startCmds 
+ mh
->sizeofcmds
); 
 443         const load_command
* cmd 
= startCmds
; 
 444         for(uint32_t i 
= 0; i 
< mh
->ncmds
; ++i
) { 
 445             const load_command
* nextCmd 
= (load_command
*)((char *)cmd 
+ cmd
->cmdsize
); 
 446                 if ( (cmd
->cmdsize 
< 8) || (nextCmd 
> cmdsEnd
) || (nextCmd 
< startCmds
)) { 
 449                 const version_min_command
* versCmd
; 
 450                 switch ( cmd
->cmd 
) { 
 451                         case LC_VERSION_MIN_IPHONEOS
: 
 452                         case LC_VERSION_MIN_MACOSX
: 
 453                         case LC_VERSION_MIN_TVOS
: 
 454                         case LC_VERSION_MIN_WATCHOS
: 
 455                                 versCmd 
= (version_min_command
*)cmd
; 
 456                                 *loadCommand 
= versCmd
->cmd
; 
 457                                 *minOS 
= versCmd
->version
; 
 466 #if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED 
 467 static uint32_t deriveSDKVersFromDylibs(const mach_header
* mh
) 
 469         const load_command
* startCmds 
= NULL
; 
 470         if ( mh
->magic 
== MH_MAGIC_64 
) 
 471                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header_64
)); 
 472         else if ( mh
->magic 
== MH_MAGIC 
) 
 473                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header
)); 
 475                 return 0;  // not a mach-o file, or wrong endianness 
 477         const load_command
* const cmdsEnd 
= (load_command
*)((char*)startCmds 
+ mh
->sizeofcmds
); 
 478         const dylib_command
* dylibCmd
; 
 479         const load_command
* cmd 
= startCmds
; 
 480         const char* dylibName
; 
 481   #if __IPHONE_OS_VERSION_MIN_REQUIRED 
 482         uint32_t foundationVers 
= 0; 
 484         uint32_t libSystemVers 
= 0; 
 486         for(uint32_t i 
= 0; i 
< mh
->ncmds
; ++i
) { 
 487             const load_command
* nextCmd 
= (load_command
*)((char *)cmd 
+ cmd
->cmdsize
); 
 488                 // <rdar://problem/14381579&16050962> sanity check size of command 
 489                 if ( (cmd
->cmdsize 
< 8) || (nextCmd 
> cmdsEnd
) || (nextCmd 
< startCmds
)) { 
 492                 switch ( cmd
->cmd 
) { 
 494                         case LC_LOAD_WEAK_DYLIB
: 
 495                         case LC_LOAD_UPWARD_DYLIB
: 
 496                                 dylibCmd 
= (dylib_command
*)cmd
; 
 497                                 // sanity check dylib command layout 
 498                                 if ( dylibCmd
->dylib
.name
.offset 
> cmd
->cmdsize 
) 
 500                                 dylibName 
= (char*)dylibCmd 
+ dylibCmd
->dylib
.name
.offset
; 
 501   #if __IPHONE_OS_VERSION_MIN_REQUIRED 
 502                                 if ( strcmp(dylibName
, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 ) 
 503                                         foundationVers 
= dylibCmd
->dylib
.current_version
; 
 505                                 if ( strcmp(dylibName
, "/usr/lib/libSystem.B.dylib") == 0 ) 
 506                                         libSystemVers 
= dylibCmd
->dylib
.current_version
; 
 513         struct DylibToOSMapping 
{ 
 514                 uint32_t dylibVersion
; 
 518   #if __IPHONE_OS_VERSION_MIN_REQUIRED 
 519         static const DylibToOSMapping foundationMapping
[] = { 
 520                 { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0 
}, 
 521                 { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1 
}, 
 522                 { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2 
}, 
 523                 { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0 
}, 
 524                 { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1 
}, 
 525                 { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2 
}, 
 526                 { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0 
}, 
 527                 { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1 
}, 
 528                 { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2 
}, 
 529                 { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3 
}, 
 530                 { PACKED_VERSION(881,0,0),  DYLD_IOS_VERSION_5_0 
}, 
 531                 { PACKED_VERSION(890,1,0),  DYLD_IOS_VERSION_5_1 
}, 
 532                 { PACKED_VERSION(992,0,0),  DYLD_IOS_VERSION_6_0 
}, 
 533                 { PACKED_VERSION(993,0,0),  DYLD_IOS_VERSION_6_1 
},   
 534                 { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0 
}, 
 535                 { PACKED_VERSION(0,0,0),    DYLD_IOS_VERSION_7_0 
} 
 536                 // We don't need to expand this table because all recent 
 537                 // binaries have LC_VERSION_MIN_ load command. 
 540         if ( foundationVers 
!= 0 ) { 
 541                 uint32_t lastOsVersion 
= 0; 
 542                 for (const DylibToOSMapping
* p
=foundationMapping
; ; ++p
) { 
 543                         if ( p
->dylibVersion 
== 0 ) 
 545                         if ( foundationVers 
< p
->dylibVersion 
) 
 546                                 return lastOsVersion
; 
 547                         lastOsVersion 
= p
->osVersion
; 
 552         // Note: versions are for the GM release.  The last entry should 
 553         // always be zero.  At the start of the next major version, 
 554         // a new last entry needs to be added and the previous zero 
 555         // updated to the GM dylib version. 
 556         static const DylibToOSMapping libSystemMapping
[] = { 
 557                 { PACKED_VERSION(88,1,3),   DYLD_MACOSX_VERSION_10_4 
}, 
 558                 { PACKED_VERSION(111,0,0),  DYLD_MACOSX_VERSION_10_5 
}, 
 559                 { PACKED_VERSION(123,0,0),  DYLD_MACOSX_VERSION_10_6 
}, 
 560                 { PACKED_VERSION(159,0,0),  DYLD_MACOSX_VERSION_10_7 
}, 
 561                 { PACKED_VERSION(169,3,0),  DYLD_MACOSX_VERSION_10_8 
}, 
 562                 { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9 
}, 
 563                 { PACKED_VERSION(0,0,0),    DYLD_MACOSX_VERSION_10_9 
} 
 564                 // We don't need to expand this table because all recent 
 565                 // binaries have LC_VERSION_MIN_ load command. 
 568         if ( libSystemVers 
!= 0 ) { 
 569                 uint32_t lastOsVersion 
= 0; 
 570                 for (const DylibToOSMapping
* p
=libSystemMapping
; ; ++p
) { 
 571                         if ( p
->dylibVersion 
== 0 ) 
 573                         if ( libSystemVers 
< p
->dylibVersion 
) 
 574                                 return lastOsVersion
; 
 575                         lastOsVersion 
= p
->osVersion
; 
 584 #if __WATCH_OS_VERSION_MIN_REQUIRED 
 585 static uint32_t watchVersToIOSVers(uint32_t vers
) 
 587         return vers 
+ 0x00070000; 
 590 uint32_t dyld_get_program_sdk_watch_os_version() 
 592         const mach_header
* mh 
= (mach_header
*)_NSGetMachExecuteHeader(); 
 593         uint32_t loadCommand
; 
 597         if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) { 
 598                 if ( loadCommand 
== LC_VERSION_MIN_WATCHOS 
) 
 604 uint32_t dyld_get_program_min_watch_os_version() 
 606         const mach_header
* mh 
= (mach_header
*)_NSGetMachExecuteHeader(); 
 607         uint32_t loadCommand
; 
 611         if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) { 
 612                 if ( loadCommand 
== LC_VERSION_MIN_WATCHOS 
) 
 613                                 return minOS
;  // return raw minOS (not mapped to iOS version) 
 621  * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the 
 622  * specified binary was built against. 
 624  * First looks for LC_VERSION_MIN_* in binary and if sdk field is  
 625  * not zero, return that value. 
 626  * Otherwise, looks for the libSystem.B.dylib the binary linked 
 627  * against and uses a table to convert that to an sdk version. 
 629 uint32_t dyld_get_sdk_version(const mach_header
* mh
) 
 631         uint32_t loadCommand
; 
 635         if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) { 
 636                 switch (loadCommand
) { 
 637 #if __WATCH_OS_VERSION_MIN_REQUIRED 
 638                         case LC_VERSION_MIN_WATCHOS
: 
 639                                 // new binary. sdk version looks like "2.0" but API wants "9.0" 
 640                                 return watchVersToIOSVers(sdk
); 
 641                         case LC_VERSION_MIN_IPHONEOS
: 
 642                                 // old binary. sdk matches API semantics so can return directly. 
 644 #elif __TV_OS_VERSION_MIN_REQUIRED 
 645                         case LC_VERSION_MIN_TVOS
: 
 646                         case LC_VERSION_MIN_IPHONEOS
: 
 648 #elif __IPHONE_OS_VERSION_MIN_REQUIRED 
 649                         case LC_VERSION_MIN_IPHONEOS
: 
 650                                 if ( sdk 
!= 0 ) // old binaries might not have SDK set 
 654                         case LC_VERSION_MIN_MACOSX
: 
 655                                 if ( sdk 
!= 0 ) // old binaries might not have SDK set 
 662 #if __WATCH_OS_VERSION_MIN_REQUIRED ||__TV_OS_VERSION_MIN_REQUIRED 
 663         // All WatchOS and tv OS binaries should have version load command. 
 666         // MacOSX and iOS have old binaries without version load commmand. 
 667         return deriveSDKVersFromDylibs(mh
); 
 671 uint32_t dyld_get_program_sdk_version() 
 673         return dyld_get_sdk_version((mach_header
*)_NSGetMachExecuteHeader()); 
 676 uint32_t dyld_get_min_os_version(const struct mach_header
* mh
) 
 678         uint32_t loadCommand
; 
 682         if ( getVersionLoadCommandInfo(mh
, &loadCommand
, &minOS
, &sdk
) ) { 
 683                 switch (loadCommand
) { 
 684 #if __WATCH_OS_VERSION_MIN_REQUIRED 
 685                         case LC_VERSION_MIN_WATCHOS
: 
 686                                 // new binary. OS version looks like "2.0" but API wants "9.0" 
 687                                 return watchVersToIOSVers(minOS
); 
 688                         case LC_VERSION_MIN_IPHONEOS
: 
 689                                 // old binary. OS matches API semantics so can return directly. 
 691 #elif __TV_OS_VERSION_MIN_REQUIRED 
 692                         case LC_VERSION_MIN_TVOS
: 
 693                         case LC_VERSION_MIN_IPHONEOS
: 
 695 #elif __IPHONE_OS_VERSION_MIN_REQUIRED 
 696                         case LC_VERSION_MIN_IPHONEOS
: 
 699                         case LC_VERSION_MIN_MACOSX
: 
 708 uint32_t dyld_get_program_min_os_version() 
 710         return dyld_get_min_os_version((mach_header
*)_NSGetMachExecuteHeader()); 
 714 bool _dyld_get_image_uuid(const struct mach_header
* mh
, uuid_t uuid
) 
 716         const load_command
* startCmds 
= NULL
; 
 717         if ( mh
->magic 
== MH_MAGIC_64 
) 
 718                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header_64
)); 
 719         else if ( mh
->magic 
== MH_MAGIC 
) 
 720                 startCmds 
= (load_command
*)((char *)mh 
+ sizeof(mach_header
)); 
 722                 return false;  // not a mach-o file, or wrong endianness 
 724         const load_command
* const cmdsEnd 
= (load_command
*)((char*)startCmds 
+ mh
->sizeofcmds
); 
 725         const load_command
* cmd 
= startCmds
; 
 726         for(uint32_t i 
= 0; i 
< mh
->ncmds
; ++i
) { 
 727             const load_command
* nextCmd 
= (load_command
*)((char *)cmd 
+ cmd
->cmdsize
); 
 728                 if ( (cmd
->cmdsize 
< 8) || (nextCmd 
> cmdsEnd
) || (nextCmd 
< startCmds
)) { 
 731                 if ( cmd
->cmd 
== LC_UUID 
) { 
 732                         const uuid_command
* uuidCmd 
= (uuid_command
*)cmd
; 
 733                         memcpy(uuid
, uuidCmd
->uuid
, 16); 
 744 #if DEPRECATED_APIS_SUPPORTED 
 746  * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the 
 747  * specified file name if the file is a correct Mach-O file that can be loaded 
 748  * with NSloadModule().  For return codes of NSObjectFileImageFailure and 
 749  * NSObjectFileImageFormat an error message is printed to stderr.  All 
 750  * other codes cause no printing.  
 752 NSObjectFileImageReturnCode
 
 753 NSCreateObjectFileImageFromFile( 
 754 const char* pathName
, 
 755 NSObjectFileImage 
*objectFileImage
) 
 757         DYLD_LOCK_THIS_BLOCK
; 
 758     static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
; 
 761             _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p
); 
 762         return p(pathName
, objectFileImage
); 
 767  * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the 
 768  * object file mapped into memory at address of size length if the object file 
 769  * is a correct Mach-O file that can be loaded with NSloadModule().  For return 
 770  * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error 
 771  * message is printed to stderr.  All other codes cause no printing.  
 773 NSObjectFileImageReturnCode
 
 774 NSCreateObjectFileImageFromMemory( 
 777 NSObjectFileImage 
*objectFileImage
) 
 779         DYLD_LOCK_THIS_BLOCK
; 
 780     static NSObjectFileImageReturnCode (*p
)(const void*, size_t, NSObjectFileImage
*) = NULL
; 
 783             _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p
); 
 784         return p(address
, size
, objectFileImage
); 
 787 #if OBSOLETE_DYLD_API 
 789  * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the  
 790  * specified core file name if the file is a correct Mach-O core file. 
 791  * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat 
 792  * an error message is printed to stderr.  All other codes cause no printing.  
 794 NSObjectFileImageReturnCode
 
 795 NSCreateCoreFileImageFromFile( 
 796 const char* pathName
, 
 797 NSObjectFileImage 
*objectFileImage
) 
 799         DYLD_LOCK_THIS_BLOCK
; 
 800     static NSObjectFileImageReturnCode (*p
)(const char*, NSObjectFileImage
*) = NULL
; 
 803             _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p
); 
 804         return p(pathName
, objectFileImage
); 
 809 NSDestroyObjectFileImage( 
 810 NSObjectFileImage objectFileImage
) 
 812         DYLD_LOCK_THIS_BLOCK
; 
 813     static bool (*p
)(NSObjectFileImage
) = NULL
; 
 816             _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p
); 
 817         return p(objectFileImage
); 
 823 NSObjectFileImage objectFileImage
,  
 824 const char* moduleName
, 
 827         DYLD_LOCK_THIS_BLOCK
; 
 828     static NSModule (*p
)(NSObjectFileImage
, const char*, unsigned long) = NULL
; 
 831             _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p
); 
 833         return p(objectFileImage
, moduleName
, options
); 
 840  * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol 
 841  * definitions in the NSObjectFileImage. 
 844 NSSymbolDefinitionCountInObjectFileImage( 
 845 NSObjectFileImage objectFileImage
) 
 847         DYLD_LOCK_THIS_BLOCK
; 
 848     static uint32_t (*p
)(NSObjectFileImage
) = NULL
; 
 851             _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p
); 
 853         return p(objectFileImage
); 
 857  * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th 
 858  * symbol definitions in the NSObjectFileImage.  If the ordinal specified is 
 859  * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will 
 863 NSSymbolDefinitionNameInObjectFileImage( 
 864 NSObjectFileImage objectFileImage
, 
 867         DYLD_LOCK_THIS_BLOCK
; 
 868     static const char*  (*p
)(NSObjectFileImage
, uint32_t) = NULL
; 
 871             _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p
); 
 873         return p(objectFileImage
, ordinal
); 
 877  * NSSymbolReferenceCountInObjectFileImage() returns the number of references 
 878  * to undefined symbols the NSObjectFileImage. 
 881 NSSymbolReferenceCountInObjectFileImage( 
 882 NSObjectFileImage objectFileImage
) 
 884         DYLD_LOCK_THIS_BLOCK
; 
 885     static uint32_t (*p
)(NSObjectFileImage
) = NULL
; 
 888             _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p
); 
 890         return p(objectFileImage
); 
 894  * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th 
 895  * undefined symbol in the NSObjectFileImage. If the ordinal specified is 
 896  * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be 
 900 NSSymbolReferenceNameInObjectFileImage( 
 901 NSObjectFileImage objectFileImage
, 
 903 bool *tentative_definition
) /* can be NULL */ 
 905         DYLD_LOCK_THIS_BLOCK
; 
 906     static const char*  (*p
)(NSObjectFileImage
, uint32_t, bool*) = NULL
; 
 909             _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p
); 
 911         return p(objectFileImage
, ordinal
, tentative_definition
); 
 915  * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol 
 916  * name has a definition in the NSObjectFileImage and FALSE otherwise. 
 919 NSIsSymbolDefinedInObjectFileImage( 
 920 NSObjectFileImage objectFileImage
, 
 921 const char* symbolName
) 
 923         DYLD_LOCK_THIS_BLOCK
; 
 924     static bool (*p
)(NSObjectFileImage
, const char*) = NULL
; 
 927             _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p
); 
 929         return p(objectFileImage
, symbolName
); 
 933  * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents 
 934  * in the NSObjectFileImage for the specified segmentName and sectionName if 
 935  * it exists and it is not a zerofill section.  If not it returns NULL.  If 
 936  * the parameter size is not NULL the size of the section is also returned 
 937  * indirectly through that pointer. 
 940 NSGetSectionDataInObjectFileImage( 
 941 NSObjectFileImage objectFileImage
, 
 942 const char* segmentName
, 
 943 const char* sectionName
, 
 944 unsigned long *size
) /* can be NULL */ 
 946         DYLD_LOCK_THIS_BLOCK
; 
 947     static void* (*p
)(NSObjectFileImage
, const char*, const char*, unsigned long*) = NULL
; 
 950             _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p
); 
 952         return p(objectFileImage
, segmentName
, sectionName
, size
); 
 960 const char* *fileName
, 
 961 const char* *errorString
) 
 963         DYLD_LOCK_THIS_BLOCK
; 
 964     static void (*p
)(NSLinkEditErrors 
*c
, 
 966                      const char* *fileName
, 
 967                      const char* *errorString
) = NULL
; 
 970             _dyld_func_lookup("__dyld_link_edit_error", (void**)&p
); 
 972             p(c
, errorNumber
, fileName
, errorString
); 
 980         DYLD_LOCK_THIS_BLOCK
; 
 981     static bool (*p
)(NSModule 
module, uint32_t options
) = NULL
; 
 984             _dyld_func_lookup("__dyld_unlink_module", (void**)&p
); 
 986         return p(module, options
); 
 989 #if OBSOLETE_DYLD_API 
 992 NSModule moduleToReplace
, 
 993 NSObjectFileImage newObjectFileImage
,  
1001 #endif // DEPRECATED_APIS_SUPPORTED 
1004  *_NSGetExecutablePath copies the path of the executable into the buffer and 
1005  * returns 0 if the path was successfully copied in the provided buffer. If the 
1006  * buffer is not large enough, -1 is returned and the expected buffer size is 
1007  * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to 
1008  * the executable not a "real path" to the executable. That is the path may be 
1009  * a symbolic link and not the real file. And with deep directories the total 
1010  * bufsize needed could be more than MAXPATHLEN. 
1013 _NSGetExecutablePath( 
1017         DYLD_NO_LOCK_THIS_BLOCK
; 
1018     static int (*p
)(char *buf
, uint32_t *bufsize
) = NULL
; 
1021             _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p
); 
1022         return(p(buf
, bufsize
)); 
1025 #if DEPRECATED_APIS_SUPPORTED 
1027 _dyld_lookup_and_bind( 
1028 const char* symbol_name
, 
1032         DYLD_LOCK_THIS_BLOCK
; 
1033     static void (*p
)(const char*, void** , NSModule
*) = NULL
; 
1036             _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p
); 
1037         p(symbol_name
, address
, module); 
1041 _dyld_lookup_and_bind_with_hint( 
1042 const char* symbol_name
, 
1043 const char* library_name_hint
, 
1047         DYLD_LOCK_THIS_BLOCK
; 
1048     static void (*p
)(const char*, const char*, void**, NSModule
*) = NULL
; 
1051             _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p
); 
1052         p(symbol_name
, library_name_hint
, address
, module); 
1055 #if OBSOLETE_DYLD_API 
1057 _dyld_lookup_and_bind_objc( 
1058 const char* symbol_name
, 
1062         DYLD_LOCK_THIS_BLOCK
; 
1063     static void (*p
)(const char* , void**, NSModule
*) = NULL
; 
1066             _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p
); 
1067         p(symbol_name
, address
, module); 
1072 _dyld_lookup_and_bind_fully( 
1073 const char* symbol_name
, 
1077         DYLD_LOCK_THIS_BLOCK
; 
1078     static void (*p
)(const char*, void**, NSModule
*) = NULL
; 
1081             _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p
); 
1082         p(symbol_name
, address
, module); 
1086 _dyld_bind_fully_image_containing_address( 
1087 const void* address
) 
1089         DYLD_LOCK_THIS_BLOCK
; 
1090     static bool (*p
)(const void*) = NULL
; 
1093             _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p
); 
1096 #endif // DEPRECATED_APIS_SUPPORTED 
1100  * _dyld_register_func_for_add_image registers the specified function to be 
1101  * called when a new image is added (a bundle or a dynamic shared library) to 
1102  * the program.  When this function is first registered it is called for once 
1103  * for each image that is currently part of the program. 
1106 _dyld_register_func_for_add_image( 
1107 void (*func
)(const struct mach_header 
*mh
, intptr_t vmaddr_slide
)) 
1109         DYLD_LOCK_THIS_BLOCK
; 
1110         typedef void (*callback_t
)(const struct mach_header 
*mh
, intptr_t vmaddr_slide
); 
1111     static void (*p
)(callback_t func
) = NULL
; 
1114             _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p
); 
1119  * _dyld_register_func_for_remove_image registers the specified function to be 
1120  * called when an image is removed (a bundle or a dynamic shared library) from 
1124 _dyld_register_func_for_remove_image( 
1125 void (*func
)(const struct mach_header 
*mh
, intptr_t vmaddr_slide
)) 
1127         DYLD_LOCK_THIS_BLOCK
; 
1128         typedef void (*callback_t
)(const struct mach_header 
*mh
, intptr_t vmaddr_slide
); 
1129     static void (*p
)(callback_t func
) = NULL
; 
1132             _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p
); 
1136 #if OBSOLETE_DYLD_API 
1138  * _dyld_register_func_for_link_module registers the specified function to be 
1139  * called when a module is bound into the program.  When this function is first 
1140  * registered it is called for once for each module that is currently bound into 
1144 _dyld_register_func_for_link_module( 
1145 void (*func
)(NSModule 
module)) 
1147         DYLD_LOCK_THIS_BLOCK
; 
1148     static void (*p
)(void (*func
)(NSModule 
module)) = NULL
; 
1151             _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p
); 
1156  * _dyld_register_func_for_unlink_module registers the specified function to be 
1157  * called when a module is unbound from the program. 
1160 _dyld_register_func_for_unlink_module( 
1161 void (*func
)(NSModule 
module)) 
1163         DYLD_LOCK_THIS_BLOCK
; 
1164     static void (*p
)(void (*func
)(NSModule 
module)) = NULL
; 
1167             _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p
); 
1172  * _dyld_register_func_for_replace_module registers the specified function to be 
1173  * called when a module is to be replace with another module in the program. 
1176 _dyld_register_func_for_replace_module( 
1177 void (*func
)(NSModule oldmodule
, NSModule newmodule
)) 
1179         DYLD_LOCK_THIS_BLOCK
; 
1180     static void (*p
)(void (*func
)(NSModule oldmodule
, 
1181                                   NSModule newmodule
)) = NULL
; 
1184             _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p
); 
1190  * _dyld_get_objc_module_sect_for_module is passed a module and sets a  
1191  * pointer to the (__OBJC,__module) section and its size for the specified 
1195 _dyld_get_objc_module_sect_for_module( 
1198 unsigned long *size
) 
1200         DYLD_LOCK_THIS_BLOCK
; 
1201     static void (*p
)(NSModule 
module, 
1203                      unsigned long *size
) = NULL
; 
1206             _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p
); 
1207         p(module, objc_module
, size
); 
1211  * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC, 
1212  * __module) section and causes the module that is associated with that address 
1216 _dyld_bind_objc_module(const void* objc_module
) 
1218         DYLD_LOCK_THIS_BLOCK
; 
1219     static void (*p
)(const void *objc_module
) = NULL
; 
1222             _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p
); 
1227 #if DEPRECATED_APIS_SUPPORTED 
1231         // this function exists for compatiblity only 
1237 _dyld_image_count(void) 
1239         DYLD_NO_LOCK_THIS_BLOCK
; 
1240     static uint32_t (*p
)(void) = NULL
; 
1243             _dyld_func_lookup("__dyld_image_count", (void**)&p
); 
1247 const struct mach_header 
* 
1248 _dyld_get_image_header(uint32_t image_index
) 
1250         DYLD_NO_LOCK_THIS_BLOCK
; 
1251     static struct mach_header 
* (*p
)(uint32_t image_index
) = NULL
; 
1254             _dyld_func_lookup("__dyld_get_image_header", (void**)&p
); 
1255         return(p(image_index
)); 
1259 _dyld_get_image_vmaddr_slide(uint32_t image_index
) 
1261         DYLD_NO_LOCK_THIS_BLOCK
; 
1262     static unsigned long (*p
)(uint32_t image_index
) = NULL
; 
1265             _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p
); 
1266         return(p(image_index
)); 
1270 _dyld_get_image_name(uint32_t image_index
) 
1272         DYLD_NO_LOCK_THIS_BLOCK
; 
1273     static const char*  (*p
)(uint32_t image_index
) = NULL
; 
1276             _dyld_func_lookup("__dyld_get_image_name", (void**)&p
); 
1277         return(p(image_index
)); 
1280 // SPI in Mac OS X 10.6 
1281 intptr_t _dyld_get_image_slide(const struct mach_header
* mh
) 
1283         DYLD_NO_LOCK_THIS_BLOCK
; 
1284     static intptr_t (*p
)(const struct mach_header
*) = NULL
; 
1287             _dyld_func_lookup("__dyld_get_image_slide", (void**)&p
); 
1293 _dyld_image_containing_address(const void* address
) 
1295         DYLD_LOCK_THIS_BLOCK
; 
1296     static bool (*p
)(const void*) = NULL
; 
1299             _dyld_func_lookup("__dyld_image_containing_address", (void**)&p
); 
1303 const struct mach_header 
* 
1304 _dyld_get_image_header_containing_address( 
1305 const void* address
) 
1307         DYLD_LOCK_THIS_BLOCK
; 
1308     static const struct mach_header 
* (*p
)(const void*) = NULL
; 
1311             _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
); 
1316 #if DEPRECATED_APIS_SUPPORTED 
1317 bool _dyld_launched_prebound(void) 
1319         DYLD_LOCK_THIS_BLOCK
; 
1320     static bool (*p
)(void) = NULL
; 
1323             _dyld_func_lookup("__dyld_launched_prebound", (void**)&p
); 
1327 bool _dyld_all_twolevel_modules_prebound(void) 
1329         DYLD_LOCK_THIS_BLOCK
; 
1330     static bool (*p
)(void) = NULL
; 
1333             _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p
); 
1336 #endif // DEPRECATED_APIS_SUPPORTED 
1341 #include <pthread.h> 
1343 #include <mach-o/dyld.h> 
1344 #include <servers/bootstrap.h> 
1345 #include "dyldLibSystemInterface.h" 
1348 // pthread key used to access per-thread dlerror message 
1349 static pthread_key_t dlerrorPerThreadKey
; 
1350 static bool dlerrorPerThreadKeyInitialized 
= false; 
1352 // data kept per-thread 
1353 struct dlerrorPerThreadData
 
1355         size_t          sizeAllocated
; 
1359 // function called by dyld to get buffer to store dlerror message 
1360 static char* getPerThreadBufferFor_dlerror(size_t sizeRequired
) 
1362         // ok to create key lazily because this function is called within dyld lock, so there is no race condition 
1363         if (!dlerrorPerThreadKeyInitialized 
) { 
1364                 // create key and tell pthread package to call free() on any data associated with key if thread dies 
1365                 pthread_key_create(&dlerrorPerThreadKey
, &free
); 
1366                 dlerrorPerThreadKeyInitialized 
= true; 
1369         const size_t size 
= (sizeRequired 
< 256) ? 256 : sizeRequired
; 
1370         dlerrorPerThreadData
* data 
= (dlerrorPerThreadData
*)pthread_getspecific(dlerrorPerThreadKey
); 
1371         if ( data 
== NULL 
) { 
1372                 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]); 
1373                 const size_t mallocSize 
= sizeof(dlerrorPerThreadData
)+size
; 
1374                 data 
= (dlerrorPerThreadData
*)malloc(mallocSize
); 
1375                 data
->sizeAllocated 
= size
; 
1376                 pthread_setspecific(dlerrorPerThreadKey
, data
); 
1378         else if ( data
->sizeAllocated 
< sizeRequired 
) { 
1380                 //int mallocSize = offsetof(dlerrorPerThreadData, message[size]); 
1381                 const size_t mallocSize 
= sizeof(dlerrorPerThreadData
)+size
; 
1382                 data 
= (dlerrorPerThreadData
*)malloc(mallocSize
); 
1383                 data
->sizeAllocated 
= size
; 
1384                 pthread_setspecific(dlerrorPerThreadKey
, data
); 
1386         return data
->message
; 
1389 // <rdar://problem/10595338> dlerror buffer leak 
1390 // Only allocate buffer if an actual error message needs to be set 
1391 static bool hasPerThreadBufferFor_dlerror() 
1393         if (!dlerrorPerThreadKeyInitialized 
)  
1396         return (pthread_getspecific(dlerrorPerThreadKey
) != NULL
); 
1399 // use non-lazy pointer to vproc_swap_integer so that lazy binding does not recurse 
1400 typedef vproc_err_t (*vswapproc
)(vproc_t vp
, vproc_gsk_t key
,int64_t *inval
, int64_t *outval
); 
1401 static vswapproc swapProc 
= &vproc_swap_integer
; 
1403 static bool isLaunchdOwned() 
1406         (*swapProc
)(NULL
, VPROC_GSK_IS_MANAGED
, NULL
, &val
); 
1407         return ( val 
!= 0 ); 
1410 #if DYLD_SHARED_CACHE_SUPPORT 
1411 static void shared_cache_missing() 
1413         // leave until dyld's that might call this are rare 
1416 static void shared_cache_out_of_date() 
1418         // leave until dyld's that might call this are rare 
1420 #endif // DYLD_SHARED_CACHE_SUPPORT 
1423 // the table passed to dyld containing thread helpers 
1424 static dyld::LibSystemHelpers sHelpers 
= { 13, &dyldGlobalLockAcquire
, &dyldGlobalLockRelease
, 
1425                                                                         &getPerThreadBufferFor_dlerror
, &malloc
, &free
, &__cxa_atexit
, 
1426                                                 #if DYLD_SHARED_CACHE_SUPPORT 
1427                                                                         &shared_cache_missing
, &shared_cache_out_of_date
, 
1432                                                                         &pthread_key_create
, &pthread_setspecific
, 
1434                                                                         &pthread_getspecific
, 
1437                                                                         &hasPerThreadBufferFor_dlerror
, 
1441                                                                         &__cxa_finalize_ranges
 
1446 // during initialization of libSystem this routine will run 
1447 // and call dyld, registering the helper functions. 
1449 extern "C" void tlv_initializer(); 
1450 extern "C" void _dyld_initializer(); 
1451 void _dyld_initializer() 
1453    void (*p
)(dyld::LibSystemHelpers
*); 
1455         _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p
); 
1465         DYLD_LOCK_THIS_BLOCK
; 
1466     static char* (*p
)() = NULL
; 
1469             _dyld_func_lookup("__dyld_dlerror", (void**)&p
); 
1473 int dladdr(const void* addr
, Dl_info
* info
) 
1475         DYLD_LOCK_THIS_BLOCK
; 
1476     static int (*p
)(const void* , Dl_info
*) = NULL
; 
1479             _dyld_func_lookup("__dyld_dladdr", (void**)&p
); 
1480         return(p(addr
, info
)); 
1483 int dlclose(void* handle
) 
1485         DYLD_LOCK_THIS_BLOCK
; 
1486     static int (*p
)(void* handle
) = NULL
; 
1489             _dyld_func_lookup("__dyld_dlclose", (void**)&p
); 
1493 void* dlopen(const char* path
, int mode
) 
1495         // dlopen is special. locking is done inside dyld to allow initializer to run without lock 
1496         DYLD_NO_LOCK_THIS_BLOCK
; 
1498     static void* (*p
)(const char* path
, int) = NULL
; 
1501             _dyld_func_lookup("__dyld_dlopen", (void**)&p
); 
1502         void* result 
= p(path
, mode
); 
1503         // use asm block to prevent tail call optimization 
1504         // this is needed because dlopen uses __builtin_return_address() and depends on this glue being in the frame chain 
1505         // <rdar://problem/5313172 dlopen() looks too far up stack, can cause crash> 
1506         __asm__ 
volatile("");  
1511 bool dlopen_preflight(const char* path
) 
1513         DYLD_LOCK_THIS_BLOCK
; 
1514     static bool (*p
)(const char* path
) = NULL
; 
1517             _dyld_func_lookup("__dyld_dlopen_preflight", (void**)&p
); 
1521 void* dlsym(void* handle
, const char* symbol
) 
1523         DYLD_LOCK_THIS_BLOCK
; 
1524     static void* (*p
)(void* handle
, const char* symbol
) = NULL
; 
1527             _dyld_func_lookup("__dyld_dlsym", (void**)&p
); 
1528         return(p(handle
, symbol
)); 
1532 const struct dyld_all_image_infos
* _dyld_get_all_image_infos() 
1534         DYLD_NO_LOCK_THIS_BLOCK
; 
1535     static struct dyld_all_image_infos
* (*p
)() = NULL
; 
1538             _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p
); 
1542 #if SUPPORT_ZERO_COST_EXCEPTIONS 
1543 bool _dyld_find_unwind_sections(void* addr
, dyld_unwind_sections
* info
) 
1545         DYLD_NO_LOCK_THIS_BLOCK
; 
1546     static void* (*p
)(void*, dyld_unwind_sections
*) = NULL
; 
1549             _dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p
); 
1550         return p(addr
, info
); 
1555 #if __i386__ || __x86_64__ || __arm__ || __arm64__ 
1556 __attribute__((visibility("hidden")))  
1557 void* _dyld_fast_stub_entry(void* loadercache
, long lazyinfo
) 
1559         DYLD_NO_LOCK_THIS_BLOCK
; 
1560     static void* (*p
)(void*, long) = NULL
; 
1563             _dyld_func_lookup("__dyld_fast_stub_entry", (void**)&p
); 
1564         return p(loadercache
, lazyinfo
); 
1569 const char* dyld_image_path_containing_address(const void* addr
) 
1571         DYLD_NO_LOCK_THIS_BLOCK
; 
1572     static const char* (*p
)(const void*) = NULL
; 
1575             _dyld_func_lookup("__dyld_image_path_containing_address", (void**)&p
); 
1579 const struct mach_header
* dyld_image_header_containing_address(const void* addr
) 
1581         DYLD_NO_LOCK_THIS_BLOCK
; 
1582     static const mach_header
* (*p
)(const void*) = NULL
; 
1585             _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p
); 
1590 bool dyld_shared_cache_some_image_overridden() 
1592         DYLD_NO_LOCK_THIS_BLOCK
; 
1593     static bool (*p
)() = NULL
; 
1596             _dyld_func_lookup("__dyld_shared_cache_some_image_overridden", (void**)&p
); 
1600 bool _dyld_get_shared_cache_uuid(uuid_t uuid
) 
1602         DYLD_NO_LOCK_THIS_BLOCK
; 
1603     static bool (*p
)(uuid_t
) = NULL
; 
1606             _dyld_func_lookup("__dyld_get_shared_cache_uuid", (void**)&p
); 
1611 bool dyld_process_is_restricted() 
1613         DYLD_NO_LOCK_THIS_BLOCK
; 
1614     static bool (*p
)() = NULL
; 
1617             _dyld_func_lookup("__dyld_process_is_restricted", (void**)&p
); 
1621 #if DYLD_SHARED_CACHE_SUPPORT 
1622 const char* dyld_shared_cache_file_path() 
1624         DYLD_NO_LOCK_THIS_BLOCK
; 
1625     static const char* (*p
)() = NULL
; 
1628             _dyld_func_lookup("__dyld_shared_cache_file_path", (void**)&p
); 
1633 void dyld_dynamic_interpose(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) 
1635         DYLD_LOCK_THIS_BLOCK
; 
1636     static void (*p
)(const struct mach_header
* mh
, const struct dyld_interpose_tuple array
[], size_t count
) = NULL
; 
1639             _dyld_func_lookup("__dyld_dynamic_interpose", (void**)&p
); 
1640         p(mh
, array
, count
); 
1644 // SPI called __fork 
1645 void _dyld_fork_child() 
1647         DYLD_NO_LOCK_THIS_BLOCK
; 
1648     static void (*p
)() = NULL
; 
1651             _dyld_func_lookup("__dyld_fork_child", (void**)&p
); 
1657 static void* mapStartOfCache(const char* path
, size_t length
) 
1659         struct stat statbuf
; 
1660         if ( ::stat(path
, &statbuf
) == -1 ) 
1663         if ( statbuf
.st_size 
< length 
) 
1666         int cache_fd 
= ::open(path
, O_RDONLY
); 
1670         void* result 
= ::mmap(NULL
, length
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0); 
1673         if ( result 
== MAP_FAILED 
) 
1680 static const dyld_cache_header
* findCacheInDirAndMap(const uuid_t cacheUuid
, const char* dirPath
) 
1682         DIR* dirp 
= ::opendir(dirPath
); 
1683         if ( dirp 
!= NULL
) { 
1685                 dirent
* entp 
= NULL
; 
1686                 char cachePath
[PATH_MAX
]; 
1687                 while ( ::readdir_r(dirp
, &entry
, &entp
) == 0 ) { 
1690                         if ( entp
->d_type 
!= DT_REG 
)  
1692                         if ( strlcpy(cachePath
, dirPath
, PATH_MAX
) >= PATH_MAX 
) 
1694                         if ( strlcat(cachePath
, "/", PATH_MAX
) >= PATH_MAX 
) 
1696                         if ( strlcat(cachePath
, entp
->d_name
, PATH_MAX
) >= PATH_MAX 
) 
1698                         if ( const dyld_cache_header
* cacheHeader 
= (dyld_cache_header
*)mapStartOfCache(cachePath
, 0x00100000) ) { 
1699                                 if ( ::memcmp(cacheHeader
->uuid
, cacheUuid
, 16) != 0 ) { 
1700                                         // wrong uuid, unmap and keep looking 
1701                                         ::munmap((void*)cacheHeader
, 0x00100000); 
1715 int dyld_shared_cache_find_iterate_text(const uuid_t cacheUuid
, const char* extraSearchDirs
[], void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
)) 
1717         const dyld_cache_header
* cacheHeader 
= NULL
; 
1718         bool needToUnmap 
= true; 
1720         // get info from dyld about this process, to see if requested cache is already mapped into this process 
1721         const dyld_all_image_infos
* allInfo 
= _dyld_get_all_image_infos(); 
1722         if ( (allInfo 
!= NULL
) && (memcmp(allInfo
->sharedCacheUUID
, cacheUuid
, 16) == 0) ) { 
1723                 // requested cache is already mapped, just re-use it 
1724                 cacheHeader 
= (dyld_cache_header
*)(SHARED_REGION_BASE 
+ allInfo
->sharedCacheSlide
); 
1725                 needToUnmap 
= false; 
1728                 // look first is default location for cache files 
1729         #if     __IPHONE_OS_VERSION_MIN_REQUIRED 
1730                 const char* defaultSearchDir 
= IPHONE_DYLD_SHARED_CACHE_DIR
; 
1732                 const char* defaultSearchDir 
= MACOSX_DYLD_SHARED_CACHE_DIR
; 
1734                 cacheHeader 
= findCacheInDirAndMap(cacheUuid
, defaultSearchDir
); 
1735                 // if not there, look in extra search locations 
1736                 if ( cacheHeader 
== NULL 
) { 
1737                         for (const char** p 
= extraSearchDirs
; *p 
!= NULL
; ++p
) { 
1738                                 cacheHeader 
= findCacheInDirAndMap(cacheUuid
, *p
); 
1739                                 if ( cacheHeader 
!= NULL 
) 
1745         if ( cacheHeader 
== NULL 
) 
1748         if ( cacheHeader
->mappingOffset 
< sizeof(dyld_cache_header
) ) { 
1749                 // old cache without imagesText array 
1751                         ::munmap((void*)cacheHeader
, 0x00100000); 
1755         // walk imageText table and call callback for each entry 
1756         const dyld_cache_image_text_info
* imagesText 
= (dyld_cache_image_text_info
*)((char*)cacheHeader 
+ cacheHeader
->imagesTextOffset
); 
1757         const dyld_cache_image_text_info
* imagesTextEnd 
= &imagesText
[cacheHeader
->imagesTextCount
]; 
1758         for (const dyld_cache_image_text_info
* p
=imagesText
; p 
< imagesTextEnd
; ++p
) { 
1759                 dyld_shared_cache_dylib_text_info dylibTextInfo
; 
1760                 dylibTextInfo
.version                   
= 1; 
1761                 dylibTextInfo
.loadAddressUnslid 
= p
->loadAddress
; 
1762                 dylibTextInfo
.textSegmentSize   
= p
->textSegmentSize
; 
1763                 dylibTextInfo
.path                              
= (char*)cacheHeader 
+ p
->pathOffset
; 
1764                 ::memcpy(dylibTextInfo
.dylibUuid
, p
->uuid
, 16); 
1765                 callback(&dylibTextInfo
); 
1769                 ::munmap((void*)cacheHeader
, 0x00100000); 
1774 int dyld_shared_cache_iterate_text(const uuid_t cacheUuid
, void (^callback
)(const dyld_shared_cache_dylib_text_info
* info
)) 
1776         const char* extraSearchDirs
[] = { NULL 
}; 
1777         return dyld_shared_cache_find_iterate_text(cacheUuid
, extraSearchDirs
, callback
); 
1781 bool _dyld_is_memory_immutable(const void* addr
, size_t length
) 
1783         DYLD_NO_LOCK_THIS_BLOCK
; 
1784     static bool (*p
)(const void*, size_t) = NULL
; 
1787             _dyld_func_lookup("__dyld_is_memory_immutable", (void**)&p
); 
1788         return p(addr
, length
); 
1792 void _dyld_objc_notify_register(_dyld_objc_notify_mapped    mapped
, 
1793                                 _dyld_objc_notify_init      init
, 
1794                                 _dyld_objc_notify_unmapped  unmapped
) 
1796         DYLD_LOCK_THIS_BLOCK
; 
1797     static bool (*p
)(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
) = NULL
; 
1800             _dyld_func_lookup("__dyld_objc_notify_register", (void**)&p
); 
1801         p(mapped
, init
, unmapped
);