1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
   3  * Copyright (c) 2015 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@ 
  26 #if __arm__ || __arm64__ 
  27   #include <System/sys/mman.h> 
  35 #include <sys/types.h> 
  36 #include <sys/fcntl.h> 
  38 #include <sys/param.h> 
  39 #include <mach/mach.h> 
  40 #include <mach/thread_status.h> 
  41 #include <mach-o/loader.h>  
  42 #include <libkern/OSAtomic.h> 
  44 #include "ImageLoaderMegaDylib.h" 
  45 #include "ImageLoaderMachO.h" 
  46 #include "mach-o/dyld_images.h" 
  47 #include "dyldLibSystemInterface.h" 
  51 extern void addImagesToAllImages(uint32_t infoCount
, const dyld_image_info info
[]); 
  54 #ifndef EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 
  55         #define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE                       0x02 
  58 // relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables 
  61         #define LC_SEGMENT_COMMAND              LC_SEGMENT_64 
  62         #define LC_ROUTINES_COMMAND             LC_ROUTINES_64 
  63         struct macho_segment_command    
: public segment_command_64  
{}; 
  64         struct macho_section                    
: public section_64  
{};         
  65         struct macho_routines_command   
: public routines_command_64  
{};        
  68         #define LC_SEGMENT_COMMAND              LC_SEGMENT 
  69         #define LC_ROUTINES_COMMAND             LC_ROUTINES 
  70         struct macho_segment_command    
: public segment_command 
{}; 
  71         struct macho_section                    
: public section  
{};    
  72         struct macho_routines_command   
: public routines_command  
{};   
  77 #if SUPPORT_ACCELERATE_TABLES 
  80 ImageLoaderMegaDylib
* ImageLoaderMegaDylib::makeImageLoaderMegaDylib(const dyld_cache_header
* header
, long slide
, const LinkContext
& context
) 
  82         return new ImageLoaderMegaDylib(header
, slide
, context
); 
  86         void*                   dyldLazyBinder
;         // filled in at launch by dyld to point into dyld to &stub_binding_helper 
  87         void*                   dyldFuncLookup
;         // filled in at launch by dyld to point into dyld to &_dyld_func_lookup 
  94 ImageLoaderMegaDylib::ImageLoaderMegaDylib(const dyld_cache_header
* header
, long slide
, const LinkContext
& context
) 
  95         : ImageLoader("dyld shared cache", 0), _header(header
), _linkEditBias(NULL
), _slide(slide
), 
  96          _lockArray(NULL
), _lockArrayInUseCount(0) 
  98         pthread_mutex_init(&_lockArrayGuard
, NULL
); 
  99         const dyld_cache_mapping_info
* mappings 
= (const dyld_cache_mapping_info
*)((uint8_t*)_header 
+ _header
->mappingOffset
); 
 100         const dyld_cache_mapping_info
* lastMapping 
= &mappings
[_header
->mappingCount
-1]; 
 101         const dyld_cache_accelerator_info
* accHeader 
= (dyld_cache_accelerator_info
*)(_header
->accelerateInfoAddr 
+ slide
); 
 102         for (const dyld_cache_mapping_info
* m
=mappings
; m 
<= lastMapping
; ++m
) { 
 103                 if ( m
->initProt 
== VM_PROT_READ 
) { 
 104                         _linkEditBias 
= (uint8_t*)(m
->address 
- m
->fileOffset
) + _slide
; 
 108         _endOfCacheInMemory 
= (void*)(lastMapping
->address 
+ lastMapping
->size 
+ slide
); 
 109         _images 
= (const dyld_cache_image_info
*)((uint8_t*)_header 
+ _header
->imagesOffset
); 
 110         _imageExtras 
= (dyld_cache_image_info_extra
*)((char*)accHeader 
+ accHeader
->imagesExtrasOffset
); 
 111         _initializers 
= (dyld_cache_accelerator_initializer
*)((char*)accHeader 
+ accHeader
->initializersOffset
); 
 112         _reExportsArray 
= (uint16_t*)((char*)accHeader 
+ accHeader
->reExportListOffset
); 
 113         _dependenciesArray 
= (uint16_t*)((char*)accHeader 
+ accHeader
->depListOffset
); 
 114         _bottomUpArray 
= (uint16_t*)((char*)accHeader 
+ accHeader
->bottomUpListOffset
); 
 115         _rangeTable 
= (dyld_cache_range_entry
*)((char*)accHeader 
+ accHeader
->rangeTableOffset
); 
 116         _rangeTableCount 
= accHeader
->rangeTableCount
; 
 117         _imageCount 
= accHeader
->imageExtrasCount
; 
 118         _stateFlags 
= (uint8_t*)calloc(_imageCount
, 1); 
 119         _initializerCount 
= accHeader
->initializersCount
; 
 120         _dylibsTrieStart 
= (uint8_t*)accHeader 
+ accHeader
->dylibTrieOffset
; 
 121         _dylibsTrieEnd 
= _dylibsTrieStart 
+ accHeader
->dylibTrieSize
; 
 122         _imageTextInfo 
= (dyld_cache_image_text_info
*)((uint8_t*)_header 
+ _header
->imagesTextOffset
); 
 123         DATAdyld
* dyldSection 
= (DATAdyld
*)(accHeader
->dyldSectionAddr 
+ slide
); 
 124         dyldSection
->dyldLazyBinder 
= NULL
; // not used by libdyld.dylib 
 125         dyldSection
->dyldFuncLookup 
= (void*)&_dyld_func_lookup
; 
 126         dyldSection
->vars
.mh 
= context
.mainExecutable
->machHeader(); 
 127         context
.setNewProgramVars(dyldSection
->vars
); 
 131 void ImageLoaderMegaDylib::unreachable() const 
 136 ImageLoaderMegaDylib::~ImageLoaderMegaDylib() 
 140 const char*     ImageLoaderMegaDylib::getInstallPath() const { 
 144 const macho_header
* ImageLoaderMegaDylib::getIndexedMachHeader(unsigned index
) const 
 146         if ( index 
> _header
->imagesCount 
) 
 147                 dyld::throwf("cache image index out of range (%u), max=%u", index
, _header
->imagesCount 
- 1); 
 148         return (const macho_header
*)(_images
[index
].address 
+ _slide
); 
 151 const char* ImageLoaderMegaDylib::getIndexedPath(unsigned index
) const 
 153         if ( index 
> _header
->imagesCount 
) 
 154                 dyld::throwf("cache image index out of range (%u), max=%u", index
, _header
->imagesCount 
- 1); 
 155         return (char*)_header 
+ _images
[index
].pathFileOffset
; 
 158 const char* ImageLoaderMegaDylib::getIndexedShortName(unsigned index
) const 
 160         const char* path 
= getIndexedPath(index
); 
 161         const char* lastSlash 
= strrchr(path
, '/'); 
 162         if ( lastSlash 
== NULL 
) 
 168 void ImageLoaderMegaDylib::getDylibUUID(unsigned int index
, uuid_t uuid
) const 
 170         if ( index 
> _header
->imagesCount 
) 
 171                 dyld::throwf("cache image index out of range (%u), max=%u", index
, _header
->imagesCount 
- 1); 
 172         memcpy(uuid
, _imageTextInfo
[index
].uuid
, 16); 
 175 void ImageLoaderMegaDylib::printSegments(const macho_header
* mh
) const 
 177         const uint32_t cmd_count 
= mh
->ncmds
; 
 178         const struct load_command
* const cmds 
= (struct load_command
*)((uint8_t*)mh 
+ sizeof(macho_header
)); 
 179         const struct load_command
* cmd 
= cmds
; 
 180         const macho_segment_command
* seg
; 
 181         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 183                         case LC_SEGMENT_COMMAND
: 
 184                                 seg 
= (macho_segment_command
*)cmd
; 
 185                                 dyld::log("%18s at 0x%08lX->0x%08lX\n", seg
->segname
, (long)(seg
->vmaddr 
+ _slide
), (long)(seg
->vmaddr 
+ seg
->vmsize 
+ _slide
)); 
 188                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 192 bool ImageLoaderMegaDylib::hasDylib(const char* path
, unsigned* index
) const 
 194         const uint8_t* imageNode 
= ImageLoader::trieWalk(_dylibsTrieStart
, _dylibsTrieEnd
, path
); 
 195         if ( imageNode 
== NULL 
) { 
 196   #if __MAC_OS_X_VERSION_MIN_REQUIRED 
 197                 // not all symlinks are recorded as aliases in accelerator tables 
 198                 if ( (strncmp(path
, "/usr/lib/", 9) == 0) || (strncmp(path
, "/System/Library/", 16) == 0) ) { 
 199                         char resolvedPath
[PATH_MAX
]; 
 200                         if ( realpath(path
, resolvedPath
) != NULL 
) { 
 201                                 imageNode 
= ImageLoader::trieWalk(_dylibsTrieStart
, _dylibsTrieEnd
, resolvedPath
); 
 204                 if ( imageNode 
== NULL 
) 
 210         *index 
= (unsigned)read_uleb128(imageNode
, _dylibsTrieEnd
); 
 214 bool ImageLoaderMegaDylib::addressInCache(const void* address
, const mach_header
** mh
, const char** path
, unsigned* index
) 
 216         // quick out of bounds check 
 218         if ( (uintptr_t)address 
< 0x7FFF70000000LL 
) 
 221         if ( address 
< (void*)_header 
) 
 224         if ( address 
> _endOfCacheInMemory 
) 
 227         uint64_t unslidAddress 
= (uint64_t)address 
- _slide
; 
 228         // linear search for now 
 229         const dyld_cache_range_entry
* rangeTableEnd 
= &_rangeTable
[_rangeTableCount
]; 
 230         for (const dyld_cache_range_entry
* r 
= _rangeTable
; r 
< rangeTableEnd
; ++r
) { 
 231                 if ( (r
->startAddress 
<= unslidAddress
) && (unslidAddress 
< r
->startAddress
+r
->size
) ) { 
 232                         *index 
= r
->imageIndex
; 
 233                         *mh 
= (mach_header
*)getIndexedMachHeader(r
->imageIndex
); 
 234                         *path 
= getIndexedPath(r
->imageIndex
); 
 243 bool ImageLoaderMegaDylib::findUnwindSections(const void* address
, dyld_unwind_sections
* info
) 
 247         if ( addressInCache(address
, &info
->mh
, &path
, &index
) ) { 
 248                 info
->dwarf_section 
= NULL
; 
 249                 info
->dwarf_section_length 
= 0; 
 250                 ImageLoaderMachO::findSection(info
->mh
, "__TEXT", "__eh_frame", (void**)&info
->dwarf_section
, &info
->dwarf_section_length
); 
 252                 info
->compact_unwind_section 
= NULL
; 
 253                 info
->compact_unwind_section_length 
= 0; 
 254                 ImageLoaderMachO::findSection(info
->mh
, "__TEXT", "__unwind_info", (void**)&info
->compact_unwind_section
, &info
->compact_unwind_section_length
); 
 262 unsigned ImageLoaderMegaDylib::findImageIndex(const LinkContext
& context
, const char* path
) const 
 265         if ( hasDylib(path
, &index
) ) 
 268         // <rdar://problem/26934069> Somehow we found the dylib in the cache, but it is not this literal string, try simple expansions of @rpath 
 269         if ( strncmp(path
, "@rpath/", 7) == 0 ) { 
 270                 std::vector
<const char*> rpathsFromMainExecutable
; 
 271                 context
.mainExecutable
->getRPaths(context
, rpathsFromMainExecutable
); 
 272                 const char* trailingPath 
= &path
[7]; 
 273                 for (const char* anRPath 
: rpathsFromMainExecutable
) { 
 274                         if ( anRPath
[0] != '/' ) 
 276                         char possiblePath
[strlen(anRPath
) + strlen(trailingPath
)+2]; 
 277                         strcpy(possiblePath
, anRPath
); 
 278                         if ( possiblePath
[strlen(possiblePath
)-1] != '/' ) 
 279                                 strcat(possiblePath
, "/"); 
 280                         strcat(possiblePath
, trailingPath
); 
 281                         if ( hasDylib(possiblePath
, &index
) ) { 
 287         // handle symlinks embedded in load commands 
 288         char resolvedPath
[PATH_MAX
]; 
 289         realpath(path
, resolvedPath
); 
 290         int realpathErrno 
= errno
; 
 291         // If realpath() resolves to a path which does not exist on disk, errno is set to ENOENT 
 292         if ( (realpathErrno 
== ENOENT
) || (realpathErrno 
== 0) ) { 
 293                 if ( strcmp(resolvedPath
, path
) != 0 ) 
 294                         return findImageIndex(context
, resolvedPath
); 
 298         dyld::throwf("no cache image with name (%s)", path
); 
 301 void ImageLoaderMegaDylib::initializeCoalIterator(CoalIterator
& it
, unsigned int loadOrder
, unsigned imageIndex
) 
 305         it
.loadOrder 
= loadOrder
; 
 306         it
.weakSymbol 
= false; 
 307         it
.symbolMatches 
= false; 
 310         it
.endIndex 
= _imageExtras
[imageIndex
].weakBindingsSize
; 
 314         it
.imageIndex 
= imageIndex
; 
 317 bool ImageLoaderMegaDylib::incrementCoalIterator(CoalIterator
& it
) 
 322         if ( _imageExtras
[it
.imageIndex
].weakBindingsSize 
== 0 ) { 
 323                 /// hmmm, ld set MH_WEAK_DEFINES or MH_BINDS_TO_WEAK, but there is no weak binding info 
 325                 it
.symbolName 
= "~~~"; 
 328         const uint8_t* start 
= (uint8_t*)(_imageExtras
[it
.imageIndex
].weakBindingsAddr 
+ _slide
); 
 329         const uint8_t* end 
= (uint8_t*)(_imageExtras
[it
.imageIndex
].weakBindingsAddr 
+ _slide 
+ _imageExtras
[it
.imageIndex
].weakBindingsSize
); 
 330         const uint8_t* p 
= start 
+ it
.curIndex
; 
 335         const mach_header
* mh
; 
 337                 uint8_t immediate 
= *p 
& BIND_IMMEDIATE_MASK
; 
 338                 uint8_t opcode 
= *p 
& BIND_OPCODE_MASK
; 
 341                         case BIND_OPCODE_DONE
: 
 343                                 it
.curIndex 
= p 
- start
; 
 344                                 it
.symbolName 
= "~~~"; // sorts to end 
 346                         case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
: 
 347                                 it
.symbolName 
= (char*)p
; 
 348                                 it
.weakSymbol 
= ((immediate 
& BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
) == 0); 
 349                                 it
.symbolMatches 
= false; 
 353                                 it
.curIndex 
= p 
- start
; 
 355                         case BIND_OPCODE_SET_TYPE_IMM
: 
 358                         case BIND_OPCODE_SET_ADDEND_SLEB
: 
 359                                 it
.addend 
= read_sleb128(p
, end
); 
 361                         case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
: 
 362                                 segIndex 
= immediate
; 
 363                                 segOffset 
= read_uleb128(p
, end
); 
 364                                 mh 
= (mach_header
*)getIndexedMachHeader((unsigned)it
.imageIndex
); 
 365                                 if ( uintptr_t segPrefAddress 
= ImageLoaderMachO::segPreferredAddress(mh
, segIndex
) ) 
 366                                         it
.address 
= segPrefAddress 
+ segOffset 
+ _slide
; 
 368                                         dyld::throwf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment %d which is too large", segIndex
); 
 370                         case BIND_OPCODE_ADD_ADDR_ULEB
: 
 371                                 it
.address 
+= read_uleb128(p
, end
); 
 373                         case BIND_OPCODE_DO_BIND
: 
 374                                 it
.address 
+= sizeof(intptr_t); 
 376                         case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
: 
 377                                 it
.address 
+= read_uleb128(p
, end
) + sizeof(intptr_t); 
 379                         case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
: 
 380                                 it
.address 
+= immediate
*sizeof(intptr_t) + sizeof(intptr_t); 
 382                         case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
: 
 383                                 count 
= read_uleb128(p
, end
); 
 384                                 skip 
= read_uleb128(p
, end
); 
 385                                 for (uint32_t i
=0; i 
< count
; ++i
) { 
 386                                         it
.address 
+= skip 
+ sizeof(intptr_t); 
 390                                 dyld::throwf("bad weak bind opcode '%d' found after processing %d bytes in '%s'", *p
, (int)(p
-start
), this->getPath()); 
 393         /// hmmm, BIND_OPCODE_DONE is missing... 
 395         it
.symbolName 
= "~~~"; 
 396         //dyld::log("missing BIND_OPCODE_DONE for image %s\n", this->getPath()); 
 400 uintptr_t ImageLoaderMegaDylib::getAddressCoalIterator(CoalIterator
& it
, const LinkContext
& context
) 
 402         //dyld::log("looking for %s in %s\n", it.symbolName, this->getPath()); 
 404         if ( findInChainedTries(context
, it
.symbolName
, (unsigned)it
.imageIndex
, NULL
, false, &address
) ) { 
 410 void ImageLoaderMegaDylib::updateUsesCoalIterator(CoalIterator
& it
, uintptr_t value
, ImageLoader
* targetImage
, unsigned targetIndex
, const LinkContext
& context
) 
 413         const uint8_t* start 
= (uint8_t*)(_imageExtras
[it
.imageIndex
].weakBindingsAddr 
+ _slide
); 
 414         const uint8_t* end 
= (uint8_t*)(_imageExtras
[it
.imageIndex
].weakBindingsAddr 
+ _slide 
+ _imageExtras
[it
.imageIndex
].weakBindingsSize
); 
 415         const uint8_t* p 
= start 
+ it
.curIndex
; 
 417         uint8_t type 
= it
.type
; 
 418         uintptr_t address 
= it
.address
; 
 419         const char* symbolName 
= it
.symbolName
; 
 420         intptr_t addend 
= it
.addend
; 
 423         const mach_header
* mh
; 
 427         bool boundSomething 
= false; 
 428         const char* targetImagePath 
= targetImage 
? targetImage
->getIndexedPath(targetIndex
) : NULL
; 
 429         while ( !done 
&& (p 
< end
) ) { 
 430                 uint8_t immediate 
= *p 
& BIND_IMMEDIATE_MASK
; 
 431                 uint8_t opcode 
= *p 
& BIND_OPCODE_MASK
; 
 434                         case BIND_OPCODE_DONE
: 
 437                         case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
: 
 440                         case BIND_OPCODE_SET_TYPE_IMM
: 
 443                         case BIND_OPCODE_SET_ADDEND_SLEB
: 
 444                                 addend 
= read_sleb128(p
, end
); 
 446                         case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
: 
 447                                 segIndex 
= immediate
; 
 448                                 segOffset 
= read_uleb128(p
, end
); 
 449                                 mh 
= (mach_header
*)getIndexedMachHeader((unsigned)it
.imageIndex
); 
 450                                 if ( uintptr_t segPrefAddress 
= ImageLoaderMachO::segPreferredAddress(mh
, segIndex
) ) 
 451                                         address 
= segPrefAddress 
+ segOffset 
+ _slide
; 
 453                                         dyld::throwf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment %d which is too large", segIndex
); 
 455                         case BIND_OPCODE_ADD_ADDR_ULEB
: 
 456                                 address 
+= read_uleb128(p
, end
); 
 458                         case BIND_OPCODE_DO_BIND
: 
 459                                 ImageLoaderMachO::bindLocation(context
, address
, value
, type
, symbolName
, addend
, getIndexedPath((unsigned)it
.imageIndex
), targetImagePath
, "weak "); 
 460                                 boundSomething 
= true; 
 461                                 address 
+= sizeof(intptr_t); 
 463                         case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
: 
 464                                 ImageLoaderMachO::bindLocation(context
, address
, value
, type
, symbolName
, addend
, getIndexedPath((unsigned)it
.imageIndex
), targetImagePath
, "weak "); 
 465                                 boundSomething 
= true; 
 466                                 address 
+= read_uleb128(p
, end
) + sizeof(intptr_t); 
 468                         case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
: 
 469                                 ImageLoaderMachO::bindLocation(context
, address
, value
, type
, symbolName
, addend
, getIndexedPath((unsigned)it
.imageIndex
), targetImagePath
, "weak "); 
 470                                 boundSomething 
= true; 
 471                                 address 
+= immediate
*sizeof(intptr_t) + sizeof(intptr_t); 
 473                         case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
: 
 474                                 count 
= read_uleb128(p
, end
); 
 475                                 skip 
= read_uleb128(p
, end
); 
 476                                 for (uint32_t i
=0; i 
< count
; ++i
) { 
 477                                         ImageLoaderMachO::bindLocation(context
, address
, value
, type
, symbolName
, addend
, getIndexedPath((unsigned)it
.imageIndex
), targetImagePath
, "weak "); 
 478                                         boundSomething 
= true; 
 479                                         address 
+= skip 
+ sizeof(intptr_t); 
 483                                 dyld::throwf("bad bind opcode %d in weak binding info", *p
); 
 486         // C++ weak coalescing cannot be tracked by reference counting.  Error on side of never unloading. 
 487         if ( boundSomething 
&& (targetImage 
!= this) ) 
 488                 context
.addDynamicReference(this, targetImage
); 
 492 void ImageLoaderMegaDylib::appendImagesNeedingCoalescing(ImageLoader
* images
[], unsigned imageIndexes
[], unsigned& count
) 
 494         for (unsigned i
=0; i 
< _imageCount
; ++i
) { 
 495                 uint16_t index 
= _bottomUpArray
[i
]; 
 496                 if ( _stateFlags
[index
] == kStateUnused 
) 
 498                 if ( _imageExtras
[index
].weakBindingsSize 
== 0 ) 
 500                 images
[count
] = this; 
 501                 imageIndexes
[count
] = index
; 
 507 bool ImageLoaderMegaDylib::weakSymbolsBound(unsigned index
) 
 509         return ( _stateFlags
[index
] >= kStateFlagWeakBound 
); 
 512 void ImageLoaderMegaDylib::setWeakSymbolsBound(unsigned index
) 
 514         if ( _stateFlags
[index
] == kStateFlagBound 
) 
 515                 _stateFlags
[index
] = kStateFlagWeakBound
; 
 519 void ImageLoaderMegaDylib::recursiveMarkLoaded(const LinkContext
& context
, unsigned imageIndex
) 
 521         if ( _stateFlags
[imageIndex
] != kStateUnused 
) 
 524         const macho_header
* mh 
= getIndexedMachHeader(imageIndex
); 
 525         const char* path 
= getIndexedPath(imageIndex
); 
 527         if ( context
.verboseLoading 
) 
 528                 dyld::log("dyld: loaded: %s\n", path
); 
 529         if ( context
.verboseMapping 
) { 
 530                 dyld::log("dyld: Using shared cached for %s\n", path
); 
 534         // change state to "loaded" before recursing to break cycles 
 535         _stateFlags
[imageIndex
] = kStateLoaded
; 
 536         ++fgImagesUsedFromSharedCache
; 
 538         dyld_image_info debuggerInfo
; 
 539         debuggerInfo
.imageLoadAddress 
= (mach_header
*)mh
; 
 540         debuggerInfo
.imageFilePath 
= path
; 
 541         debuggerInfo
.imageFileModDate 
= 0; 
 542         addImagesToAllImages(1, &debuggerInfo
); 
 544         if ( _imageExtras
[imageIndex
].weakBindingsSize 
!= 0 ) { 
 545                 ++fgImagesRequiringCoalescing
; 
 546                 ++fgImagesHasWeakDefinitions
; 
 549         unsigned startArrayIndex 
= _imageExtras
[imageIndex
].dependentsStartArrayIndex
; 
 550         for (int i
=startArrayIndex
; _dependenciesArray
[i
] != 0xFFFF; ++i
) { 
 551                 unsigned subDep 
= (_dependenciesArray
[i
] & 0x7FFF); // mask off upward bit 
 552                 recursiveMarkLoaded(context
, subDep
); 
 556 void ImageLoaderMegaDylib::recursiveLoadLibraries(const LinkContext
& context
, bool preflightOnly
, const RPathChain
& loaderRPaths
, const char* loadPath
) 
 558         unsigned index 
= findImageIndex(context
, loadPath
); 
 559         recursiveMarkLoaded(context
, index
); 
 562 unsigned int ImageLoaderMegaDylib::recursiveUpdateDepth(unsigned int maxDepth
) 
 569 const ImageLoader::Symbol
* ImageLoaderMegaDylib::findExportedSymbol(const char* name
, bool searchReExports
, const char* thisPath
, const ImageLoader
** foundIn
) const 
 572         if ( !hasDylib(thisPath
, &index
) ) 
 574         const uint8_t* exportNode
; 
 575         const uint8_t* exportTrieEnd
; 
 576         unsigned foundinIndex
; 
 577         // <rdar://problem/22068598> always search re-exports 
 578         // the point of searchReExports was to break cycles in dylibs, we don't have cycles in cache, so ok to search deep 
 579         searchReExports 
= true; 
 580         if ( searchReExports 
) { 
 581                 if ( !exportTrieHasNodeRecursive(name
, index
, &exportNode
, &exportTrieEnd
, &foundinIndex
) ) 
 585                 if ( !exportTrieHasNode(name
, index
, &exportNode
, &exportTrieEnd
) ) 
 589         return (ImageLoader::Symbol
*)exportNode
; 
 592 bool ImageLoaderMegaDylib::exportTrieHasNode(const char* symbolName
, unsigned index
, 
 593                                                                                          const uint8_t** exportNode
, const uint8_t** exportTrieEnd
) const 
 595         const uint8_t* start 
= (uint8_t*)(_imageExtras
[index
].exportsTrieAddr 
+ _slide
); 
 596         const uint32_t size 
= _imageExtras
[index
].exportsTrieSize
; 
 599         const uint8_t* end 
= start 
+ size
; 
 600         const uint8_t* node 
= ImageLoader::trieWalk(start
, end
, symbolName
); 
 604         *exportTrieEnd 
= end
; 
 608 bool ImageLoaderMegaDylib::exportTrieHasNodeRecursive(const char* symbolName
, unsigned index
, 
 609                                                                                                                 const uint8_t** exportNode
, const uint8_t** exportTrieEnd
, 
 610                                                                                                                 unsigned* foundinIndex
) const 
 612         // look in trie for image index 
 613         if ( exportTrieHasNode(symbolName
, index
, exportNode
, exportTrieEnd
) ) { 
 614                 *foundinIndex 
= index
; 
 617         // recursively look in all re-exported tries 
 618         unsigned startArrayIndex 
= _imageExtras
[index
].reExportsStartArrayIndex
; 
 619         for (int i
=startArrayIndex
; _reExportsArray
[i
] != 0xFFFF; ++i
) { 
 620                 unsigned reExIndex 
= _reExportsArray
[i
]; 
 621                 if ( exportTrieHasNodeRecursive(symbolName
, reExIndex
, exportNode
, exportTrieEnd
, foundinIndex
) ) 
 627 bool ImageLoaderMegaDylib::findExportedSymbolAddress(const LinkContext
& context
, const char* symbolName
, 
 628                                                                                                         const ImageLoader
* requestorImage
, int requestorOrdinalOfDef
, 
 629                                                                                                         bool runResolver
, const ImageLoader
** foundIn
, uintptr_t* address
) const 
 631         const char* definedImagePath 
= requestorImage
->libPath(requestorOrdinalOfDef
-1); 
 632         unsigned index 
= findImageIndex(context
, definedImagePath
); 
 634         return findInChainedTries(context
, symbolName
, index
, requestorImage
, runResolver
, address
); 
 637 uintptr_t ImageLoaderMegaDylib::getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
, 
 638                                                                                                                  const ImageLoader
* requestor
, bool runResolver
, const char* symbolName
) const 
 640         // scan for with trie contains this node 
 641         const uint8_t* exportTrieEnd 
= NULL
; 
 642         unsigned imageIndex 
= 0xFFFF; 
 643         const macho_header
* mh 
= NULL
; 
 644         uint64_t unslidTrieNode 
= ((uintptr_t)sym
) - _slide
; 
 645         for (unsigned i
=0; i 
< _imageCount
; ++i
) { 
 646                 uint64_t start 
= _imageExtras
[i
].exportsTrieAddr
; 
 647                 uint64_t end   
= _imageExtras
[i
].exportsTrieAddr 
+  _imageExtras
[i
].exportsTrieSize
; 
 648                 if ( (start 
< unslidTrieNode
) && (unslidTrieNode 
< end
) ) { 
 649                         exportTrieEnd 
= (uint8_t*)(end 
+ _slide
); 
 651                         mh 
= (macho_header
*)(_images
[imageIndex
].address 
+ _slide
); 
 657                 dyld::throwf("getExportedSymbolAddress(Symbol=%p) not in a cache trie", sym
); 
 659         const uint8_t* exportNode 
= (const uint8_t*)sym
; 
 661         processExportNode(context
, symbolName 
? symbolName 
: "unknown", imageIndex
, exportNode
, exportTrieEnd
, requestor
, runResolver
, &address
); 
 665 void ImageLoaderMegaDylib::processExportNode(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
, 
 666                                                                                         const uint8_t* exportNode
, const uint8_t* exportTrieEnd
, 
 667                                                                                           const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const 
 669         const macho_header
* mh 
= getIndexedMachHeader(definedImageIndex
); 
 670         uintptr_t flags 
= read_uleb128(exportNode
, exportTrieEnd
); 
 671         uintptr_t rawAddress
; 
 672         switch ( flags 
& EXPORT_SYMBOL_FLAGS_KIND_MASK 
) { 
 673                 case EXPORT_SYMBOL_FLAGS_KIND_REGULAR
: 
 674                         if ( runResolver 
&& (flags 
& EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
) ) { 
 675                                 // this node has a stub and resolver, run the resolver to get target address 
 676                                 uintptr_t stub 
= read_uleb128(exportNode
, exportTrieEnd
) + (uintptr_t)mh
; // skip over stub 
 677                                 // <rdar://problem/10657737> interposing dylibs have the stub address as their replacee 
 678                                 uintptr_t interposedStub 
= interposedAddress(context
, stub
, requestorImage
); 
 679                                 if ( interposedStub 
!= stub 
) { 
 680                                         *address 
= interposedStub
; 
 683                                 // stub was not interposed, so run resolver 
 684                                 typedef uintptr_t (*ResolverProc
)(void); 
 685                                 ResolverProc resolver 
= (ResolverProc
)(read_uleb128(exportNode
, exportTrieEnd
) + (uintptr_t)mh
); 
 686                                 *address 
= (*resolver
)(); 
 687                                 if ( context
.verboseBind 
) 
 688                                         dyld::log("dyld: resolver at %p returned 0x%08lX\n", resolver
, *address
); 
 691                         if ( flags 
& EXPORT_SYMBOL_FLAGS_REEXPORT 
) { 
 692                                 // re-export from another dylib, lookup there 
 693                                 const uintptr_t ordinal 
= read_uleb128(exportNode
, exportTrieEnd
); 
 694                                 const char* importedName 
= (char*)exportNode
; 
 695                                 if ( importedName
[0] == '\0' ) 
 696                                         importedName 
= symbolName
; 
 697                                 unsigned startArrayIndex 
= _imageExtras
[definedImageIndex
].dependentsStartArrayIndex
; 
 698                                 unsigned reExImageIndex 
= _dependenciesArray
[startArrayIndex 
+ ordinal
-1] & 0x7FFF; 
 699                                 if ( findInChainedTries(context
, importedName
, reExImageIndex
, requestorImage
, runResolver
, address
) ) 
 701                                 dyld::throwf("re-exported symbol '%s' not found for image %s expected re-exported in %s, node=%p", 
 702                                                         symbolName
, getIndexedShortName(definedImageIndex
), getIndexedShortName(reExImageIndex
), exportNode
); 
 704                         rawAddress 
= read_uleb128(exportNode
, exportTrieEnd
) + (uintptr_t)mh
; 
 705                         *address 
= interposedAddress(context
, rawAddress
, requestorImage
); 
 707                 case EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
: 
 708                         if ( flags 
& EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 
) 
 709                                 dyld::throwf("unsupported exported symbol kind. flags=%lu at node=%p", flags
, exportNode
); 
 710                         *address 
= read_uleb128(exportNode
, exportTrieEnd
) + (uintptr_t)mh
; 
 712                 case EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
: 
 713                         if ( flags 
& EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 
) 
 714                                 dyld::throwf("unsupported exported symbol kind. flags=%lu at node=%p", flags
, exportNode
); 
 715                         *address 
= read_uleb128(exportNode
, exportTrieEnd
); 
 718                         dyld::throwf("unsupported exported symbol kind. flags=%lu at node=%p", flags
, exportNode
); 
 720         dyld::throwf("unsupported exported symbol node=%p", exportNode
); 
 723 bool ImageLoaderMegaDylib::findInChainedTries(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
, 
 724                                                                                           const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const 
 726         //dyld::log("findInChainedTries(sym=%s, index=%u, path=%s)\n", symbolName, definedImageIndex, getIndexedPath(definedImageIndex)); 
 727         const uint8_t* exportNode
; 
 728         const uint8_t* exportTrieEnd
; 
 729         unsigned foundinIndex
; 
 730         if ( !exportTrieHasNodeRecursive(symbolName
, definedImageIndex
, &exportNode
, &exportTrieEnd
, &foundinIndex
) ) 
 733         processExportNode(context
, symbolName
, foundinIndex
, exportNode
, exportTrieEnd
, requestorImage
, runResolver
, address
); 
 738 bool ImageLoaderMegaDylib::findInChainedTriesAndDependentsExcept(const LinkContext
& context
, const char* symbolName
, unsigned imageIndex
, 
 739                                                                                                                                 const ImageLoader
* requestorImage
, bool runResolver
, bool alreadyVisited
[], uintptr_t* address
) const 
 741         //dyld::log("findInChainedTriesAndDependentsExcept(sym=%s, index=%u, path=%s)\n", symbolName, imageIndex, getIndexedPath(imageIndex)); 
 742         if ( alreadyVisited
[imageIndex
] ) 
 744         alreadyVisited
[imageIndex
] = true; 
 746         if ( findInChainedTries(context
, symbolName
, imageIndex
, requestorImage
, runResolver
, address
) ) 
 749         unsigned startArrayIndex 
= _imageExtras
[imageIndex
].dependentsStartArrayIndex
; 
 750         for (int i
=startArrayIndex
; _dependenciesArray
[i
] != 0xFFFF; ++i
) { 
 751                 // ignore upward links 
 752                 if ( (_dependenciesArray
[i
] & 0x8000) == 0 ) { 
 753                         unsigned depIndex 
= _dependenciesArray
[i
] & 0x7FFF; 
 754                         if ( _stateFlags
[depIndex
] != kStateFlagInitialized 
) 
 756                         if ( findInChainedTriesAndDependentsExcept(context
, symbolName
, depIndex
, requestorImage
, runResolver
, alreadyVisited
, address
) ) 
 763 bool ImageLoaderMegaDylib::findInChainedTriesAndDependents(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
, 
 764                                                                                                                         const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const 
 766         //dyld::log("findInChainedTriesAndDependents(sym=%s, index=%u, path=%s)\n", symbolName, definedImageIndex, getIndexedPath(definedImageIndex)); 
 767         if ( findInChainedTries(context
, symbolName
, definedImageIndex
, requestorImage
, runResolver
, address
) ) 
 770         bool alreadyVisited
[_header
->imagesCount
]; 
 771         bzero(alreadyVisited
, sizeof(alreadyVisited
)); 
 772         return findInChainedTriesAndDependentsExcept(context
, symbolName
, definedImageIndex
, requestorImage
, runResolver
, alreadyVisited
, address
); 
 776 bool ImageLoaderMegaDylib::flatFindSymbol(const char* name
, bool onlyInCoalesced
, const ImageLoader::Symbol
** sym
, const ImageLoader
** image
) 
 778         // check export trie of all in-use images 
 779         for (unsigned i
=0; i 
< _imageCount 
; ++i
) { 
 780                 uint16_t imageIndex 
= _bottomUpArray
[i
]; 
 781                 if ( _stateFlags
[imageIndex
] == kStateUnused 
) 
 783                 if ( onlyInCoalesced 
&& (_imageExtras
[imageIndex
].weakBindingsSize 
== 0) ) 
 785                 const uint8_t* exportNode
; 
 786                 const uint8_t* exportTrieEnd
; 
 787                 if ( exportTrieHasNode(name
, imageIndex
, &exportNode
, &exportTrieEnd
) ) { 
 788                         *sym 
= (Symbol
*)exportNode
; 
 797 void ImageLoaderMegaDylib::markAllbound(const LinkContext
& context
) 
 799         for (unsigned i
=0; i 
< _imageCount
; ++i
) { 
 800                 uint16_t imageIndex 
= _bottomUpArray
[i
]; 
 801                 if ( _stateFlags
[imageIndex
] == kStateLoaded 
) { 
 802                         _stateFlags
[imageIndex
] = kStateFlagBound
; 
 803                         context
.notifySingleFromCache(dyld_image_state_bound
, (mach_header
*)getIndexedMachHeader(imageIndex
), getIndexedPath(imageIndex
)); 
 809 void ImageLoaderMegaDylib::recursiveSpinLockAcquire(unsigned int imageIndex
, mach_port_t thisThread
) 
 811         pthread_mutex_lock(&_lockArrayGuard
); 
 812         if ( _lockArray 
== NULL 
) 
 813                 _lockArray 
= (recursive_lock
*)calloc(_imageCount
, sizeof(recursive_lock
)); 
 814         _lockArrayInUseCount
++; 
 815         pthread_mutex_unlock(&_lockArrayGuard
); 
 817         recursive_lock
* imagesLock 
= &_lockArray
[imageIndex
]; 
 818         while ( !OSAtomicCompareAndSwap32Barrier(0, thisThread
, (int*)&imagesLock
->thread
) ) { 
 819                 if ( imagesLock
->thread 
== thisThread 
) 
 825 void ImageLoaderMegaDylib::recursiveSpinLockRelease(unsigned int imageIndex
, mach_port_t thisThread
) 
 827         recursive_lock
* imagesLock 
= &_lockArray
[imageIndex
]; 
 828         if ( --imagesLock
->count 
== 0 ) 
 829                 imagesLock
->thread 
= 0; 
 831         pthread_mutex_lock(&_lockArrayGuard
); 
 832         _lockArrayInUseCount
--; 
 833         if ( _lockArrayInUseCount 
== 0 ) { 
 834                 free((void*)_lockArray
); 
 837         pthread_mutex_unlock(&_lockArrayGuard
); 
 841 void ImageLoaderMegaDylib::recursiveInitialization(const LinkContext
& context
, mach_port_t thisThread
, unsigned int imageIndex
, 
 842                                                                                                         InitializerTimingList
& timingInfo
) 
 844         // Don't do any locking until libSystem.dylib is initialized, so we can malloc() the lock array 
 845         bool useLock 
= dyld::gProcessInfo
->libSystemInitialized
; 
 847                 recursiveSpinLockAcquire(imageIndex
, thisThread
); 
 849         // only run initializers if currently in bound state 
 850         if ( (_stateFlags
[imageIndex
] == kStateFlagBound
) || (_stateFlags
[imageIndex
] == kStateFlagWeakBound
) ) { 
 852                 // Each image in cache has its own lock.  We only set the state to Initialized if we hold the lock for the image. 
 853                 _stateFlags
[imageIndex
] = kStateFlagInitialized
; 
 855                 // first recursively init all dependents 
 856                 unsigned startArrayIndex 
= _imageExtras
[imageIndex
].dependentsStartArrayIndex
; 
 857                 for (int i
=startArrayIndex
; _dependenciesArray
[i
] != 0xFFFF; ++i
) { 
 858                         unsigned subDepIndex 
= _dependenciesArray
[i
]; 
 859                         // ignore upward links 
 860                         if ( (subDepIndex 
& 0x8000) == 0 ) 
 861                                 recursiveInitialization(context
, thisThread
, subDepIndex
, timingInfo
); 
 864                 // notify objc about this image 
 865                 context
.notifySingleFromCache(dyld_image_state_dependents_initialized
, (mach_header
*)getIndexedMachHeader(imageIndex
), getIndexedPath(imageIndex
)); 
 867                 // run all initializers for imageIndex 
 868                 const dyld_cache_accelerator_initializer
* pInitStart 
= _initializers
; 
 869                 const dyld_cache_accelerator_initializer
* pInitEnd 
= &pInitStart
[_initializerCount
]; 
 870                 bool ranSomeInitializers 
= false; 
 871                 uint64_t t1 
= mach_absolute_time(); 
 872                 for (const dyld_cache_accelerator_initializer
* p
=pInitStart
; p 
< pInitEnd
; ++p
) { 
 873                         if ( p
->imageIndex 
== imageIndex 
) { 
 874                                 Initializer func 
= (Initializer
)(p
->functionOffset 
+ (uintptr_t)_header
); 
 875                                 if ( context
.verboseInit 
) 
 876                                         dyld::log("dyld: calling initializer function %p in %s\n", func
, getIndexedPath(imageIndex
)); 
 877                                 bool haveLibSystemHelpersBefore 
= (dyld::gLibSystemHelpers 
!= NULL
); 
 878                                 func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
); 
 879                                 bool haveLibSystemHelpersAfter 
= (dyld::gLibSystemHelpers 
!= NULL
); 
 880                                 ranSomeInitializers 
= true; 
 881                                 if ( !haveLibSystemHelpersBefore 
&& haveLibSystemHelpersAfter 
) { 
 882                                         // now safe to use malloc() and other calls in libSystem.dylib 
 883                                         dyld::gProcessInfo
->libSystemInitialized 
= true; 
 887                 if ( ranSomeInitializers 
) { 
 888                         uint64_t t2 
= mach_absolute_time(); 
 889                         const char* shortName 
= strrchr(getIndexedPath(imageIndex
), '/'); 
 890                         if ( shortName 
== NULL 
) 
 891                                 shortName 
= getIndexedPath(imageIndex
); 
 894                         timingInfo
.images
[timingInfo
.count
].shortName 
= shortName
; 
 895                         timingInfo
.images
[timingInfo
.count
].initTime 
= (t2
-t1
); 
 900         // only unlock if this frame locked (note: libSystemInitialized changes after libSystem's initializer is run) 
 902                 recursiveSpinLockRelease(imageIndex
, thisThread
); 
 906 void ImageLoaderMegaDylib::recursiveInitialization(const LinkContext
& context
, mach_port_t thisThread
, const char* pathToInitialize
, 
 907                                                                                                         InitializerTimingList
& timingInfo
, UninitedUpwards
& uninitUps
) 
 910         if ( hasDylib(pathToInitialize
, &imageIndex
) ) { 
 911                 this->recursiveInitialization(context
, thisThread
, imageIndex
, timingInfo
); 
 915 void ImageLoaderMegaDylib::recursiveBind(const LinkContext
& context
, bool forceLazysBound
, bool neverUnload
) 
 917         markAllbound(context
); 
 920 uint8_t ImageLoaderMegaDylib::dyldStateToCacheState(dyld_image_states state
) { 
 922                 case dyld_image_state_mapped
: 
 923                 case dyld_image_state_dependents_mapped
: 
 925                 case dyld_image_state_bound
: 
 926                         return kStateFlagBound
; 
 927                 case dyld_image_state_initialized
: 
 928                         return kStateFlagInitialized
; 
 929                 case dyld_image_state_rebased
: 
 930                 case dyld_image_state_dependents_initialized
: 
 931                 case dyld_image_state_terminated
: 
 937 void ImageLoaderMegaDylib::recursiveApplyInterposing(const LinkContext
& context
) 
 939         if ( context
.verboseInterposing 
) 
 940                 dyld::log("dyld: interposing %lu tuples onto shared cache\n", fgInterposingTuples
.size()); 
 945 unsigned ImageLoaderMegaDylib::appendImagesToNotify(dyld_image_states state
, bool orLater
, dyld_image_info
* infos
) 
 947         uint8_t targetCacheState 
= dyldStateToCacheState(state
); 
 948         if ( targetCacheState 
== kStateUnused 
) 
 951         unsigned usedCount 
= 0; 
 952         for (int i
=_imageCount
-1; i 
> 0; --i
) { 
 953                 uint16_t index 
= _bottomUpArray
[i
]; 
 954                 uint8_t imageState 
= _stateFlags
[index
]; 
 955                 if ( imageState 
== kStateFlagWeakBound 
) 
 956                         imageState 
= kStateFlagBound
; 
 957                 if ( (imageState 
== targetCacheState
) || (orLater 
&& (imageState 
> targetCacheState
)) ) { 
 958                         infos
[usedCount
].imageLoadAddress       
= (mach_header
*)getIndexedMachHeader(index
); 
 959                         infos
[usedCount
].imageFilePath          
= getIndexedPath(index
); 
 960                         infos
[usedCount
].imageFileModDate       
= 0; 
 968 bool ImageLoaderMegaDylib::dlopenFromCache(const LinkContext
& context
, const char* path
, int mode
, void** handle
) 
 971         if ( !hasDylib(path
, &imageIndex
) ) { 
 975         // RTLD_NOLOAD means return handle if already loaded, but don't now load it 
 976         if ( mode 
& RTLD_NOLOAD 
) { 
 977                 dyld::gLibSystemHelpers
->releaseGlobalDyldLock(); 
 978                 if ( _stateFlags
[imageIndex
] == kStateUnused 
) { 
 984                 this->recursiveMarkLoaded(context
, imageIndex
); 
 985                 context
.notifyBatch(dyld_image_state_dependents_mapped
, false); 
 986                 this->markAllbound(context
); 
 987                 context
.notifyBatch(dyld_image_state_bound
, false); 
 989                 this->weakBind(context
); 
 991                 // <rdar://problem/25069046> Release dyld global lock before running initializers in dlopen() with customer cache 
 992                 dyld::gLibSystemHelpers
->releaseGlobalDyldLock(); 
 994                 InitializerTimingList timingInfo
[_initializerCount
]; 
 995                 timingInfo
[0].count 
= 0; 
 996                 mach_port_t thisThread  
= mach_thread_self(); 
 997                 this->recursiveInitialization(context
, thisThread
, imageIndex
, timingInfo
[0]); 
 998                 mach_port_deallocate(mach_task_self(), thisThread
); 
 999                 context
.notifyBatch(dyld_image_state_initialized
, false); 
1002         *handle 
= makeCacheHandle(imageIndex
, mode
); 
1006 bool ImageLoaderMegaDylib::makeCacheHandle(const LinkContext
& context
, unsigned cacheIndex
, int mode
, void** result
) 
1008         if ( cacheIndex 
>= _imageCount 
) 
1011         *result 
= makeCacheHandle(cacheIndex
, mode
); 
1015 void* ImageLoaderMegaDylib::makeCacheHandle(unsigned index
, int mode
) 
1017         uint8_t flags 
= ((mode 
& RTLD_FIRST
) ? 1 : 0); 
1020         return (void*)(uintptr_t)( 0xFFEEDDCC00000000LL 
| (index 
<< 8) | flags
); 
1022         return (void*)(uintptr_t)( 0xF8000000 | (index 
<< 8) | flags
); 
1026 bool ImageLoaderMegaDylib::isCacheHandle(void* handle
, unsigned* index
, uint8_t* flags
) 
1029         if ( (((uintptr_t)handle
) >> 32) == 0xFFEEDDCC ) { 
1031                         *index 
= (((uintptr_t)handle
) >> 8) & 0xFFFF; 
1033                         *flags 
= ((uintptr_t)handle
) & 0xFF; 
1037         if ( (((uintptr_t)handle
) >> 24) == 0xF8 ) { 
1039                         *index 
= (((uintptr_t)handle
) >> 8) & 0xFFFF; 
1041                         *flags 
= ((uintptr_t)handle
) & 0xFF; 
1049 void* ImageLoaderMegaDylib::dlsymFromCache(const LinkContext
& context
, void* handle
, const char* symbolName
, unsigned imageIndex
) 
1051         unsigned indexInHandle
; 
1053         uintptr_t symAddress
; 
1054         if ( handle 
== RTLD_SELF 
) { 
1055                 if ( findInChainedTriesAndDependents(context
, symbolName
, imageIndex
, NULL
, true, &symAddress
) ) 
1056                         return (void*)symAddress
; 
1058         else if ( handle 
== RTLD_NEXT 
) { 
1059                 // FIXME: really need to not look in imageIndex, but look in others. 
1060                 if ( findInChainedTriesAndDependents(context
, symbolName
, imageIndex
, NULL
, true, &symAddress
) ) 
1061                         return (void*)symAddress
; 
1063         else if ( isCacheHandle(handle
, &indexInHandle
, &flags
) ) { 
1064                 bool searchOnlyFirst 
= (flags 
& 1);  // RTLD_FIRST 
1065                 // normal dlsym(handle,) semantics is that the handle is just the first place to search. RTLD_FIRST disables that 
1066                 if ( searchOnlyFirst 
) { 
1067                         if ( findInChainedTries(context
, symbolName
, indexInHandle
, NULL
, true, &symAddress
) ) 
1068                                 return (void*)symAddress
; 
1071                         if ( findInChainedTriesAndDependents(context
, symbolName
, indexInHandle
, NULL
, true, &symAddress
) ) 
1072                                 return (void*)symAddress
; 
1079 bool ImageLoaderMegaDylib::dladdrFromCache(const void* address
, Dl_info
* info
) 
1081         const mach_header
* mh
; 
1083         if ( !addressInCache(address
, &mh
, &info
->dli_fname
, &index
) ) 
1086         info
->dli_fbase 
= (void*)mh
; 
1087         if ( address 
== mh 
) { 
1088                 // special case lookup of header 
1089                 info
->dli_sname 
= "__dso_handle"; 
1090                 info
->dli_saddr 
= info
->dli_fbase
; 
1094         // find closest symbol in the image 
1095         info
->dli_sname 
= ImageLoaderMachO::findClosestSymbol(mh
, address
, (const void**)&info
->dli_saddr
); 
1097         // never return the mach_header symbol 
1098         if ( info
->dli_saddr 
== info
->dli_fbase 
) { 
1099                 info
->dli_sname 
= NULL
; 
1100                 info
->dli_saddr 
= NULL
; 
1104         // strip off leading underscore 
1105         if ( info
->dli_sname 
!= NULL 
) { 
1106                 if ( info
->dli_sname
[0] == '_' ) 
1107                         info
->dli_sname 
= info
->dli_sname 
+1; 
1113 uintptr_t ImageLoaderMegaDylib::bindLazy(uintptr_t lazyBindingInfoOffset
, const LinkContext
& context
, const mach_header
* mh
, unsigned imageIndex
) 
1115         const dyld_info_command
* dyldInfoCmd 
= ImageLoaderMachO::findDyldInfoLoadCommand(mh
); 
1116         if ( dyldInfoCmd 
== NULL 
) 
1119         const uint8_t* const lazyInfoStart 
= &_linkEditBias
[dyldInfoCmd
->lazy_bind_off
]; 
1120         const uint8_t* const lazyInfoEnd 
= &lazyInfoStart
[dyldInfoCmd
->lazy_bind_size
]; 
1121         uint32_t lbOffset 
= (uint32_t)lazyBindingInfoOffset
; 
1123         uintptr_t segOffset
; 
1125         const char* symbolName
; 
1127         if ( ImageLoaderMachO::getLazyBindingInfo(lbOffset
, lazyInfoStart
, lazyInfoEnd
, &segIndex
, &segOffset
, &libraryOrdinal
, &symbolName
, &doneAfterBind
) ) { 
1128                 //const char* thisPath = getIndexedPath(imageIndex); 
1129                 //dyld::log("%s needs symbol '%s' from ordinal=%d\n", thisPath, symbolName, libraryOrdinal); 
1130                 unsigned startDepArrayIndex 
= _imageExtras
[imageIndex
].dependentsStartArrayIndex
; 
1131                 unsigned targetIndex
; 
1132                 if ( libraryOrdinal 
== BIND_SPECIAL_DYLIB_SELF 
) 
1133                         targetIndex 
= imageIndex
; 
1135                         targetIndex 
= _dependenciesArray
[startDepArrayIndex
+libraryOrdinal
-1] & 0x7FFF; 
1136                 //const char* targetPath = getIndexedPath(targetIndex); 
1137                 //dyld::log("%s needs symbol '%s' from %s\n", thisPath, symbolName, targetPath); 
1138                 uintptr_t targetAddress
; 
1139                 if ( findInChainedTries(context
, symbolName
, targetIndex
, this, true, &targetAddress
) ) { 
1140                         if ( uintptr_t segPrefAddress 
= ImageLoaderMachO::segPreferredAddress(mh
, segIndex
) ) { 
1141                                 uintptr_t* lp 
= (uintptr_t*)(segPrefAddress 
+ segOffset 
+ _slide
); 
1142                                 //dyld::log("    storing 0x%0lX to lp %p\n", targetAddress, lp); 
1143                                 *lp 
= targetAddress
; 
1144                                 return targetAddress
; 
1153 #endif // SUPPORT_ACCELERATE_TABLES