1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
   3  * Copyright (c) 2004-2010 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@ 
  25 // work around until conformance work is complete rdar://problem/4508801 
  30 #define __STDC_LIMIT_MACROS 
  34 #include <sys/types.h> 
  35 #include <sys/fcntl.h> 
  38 #include <mach/mach.h> 
  39 #include <mach/thread_status.h> 
  40 #include <mach-o/loader.h>  
  41 #include <mach-o/nlist.h>  
  42 #include <sys/sysctl.h> 
  43 #include <sys/syscall.h> 
  44 #include <libkern/OSAtomic.h> 
  45 #include <libkern/OSCacheControl.h> 
  47 #include <System/sys/codesign.h> 
  49 #include "ImageLoaderMachO.h" 
  50 #include "ImageLoaderMachOCompressed.h" 
  51 #if SUPPORT_CLASSIC_MACHO 
  52 #include "ImageLoaderMachOClassic.h" 
  54 #include "mach-o/dyld_images.h" 
  56 // <rdar://problem/8718137> use stack guard random value to add padding between dylibs 
  57 extern "C" long __stack_chk_guard
; 
  59 #ifndef LC_LOAD_UPWARD_DYLIB 
  60         #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ 
  63 // relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables 
  65         #define LC_SEGMENT_COMMAND              LC_SEGMENT_64 
  66         #define LC_ROUTINES_COMMAND             LC_ROUTINES_64 
  67         #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT 
  68         struct macho_segment_command    
: public segment_command_64  
{}; 
  69         struct macho_section                    
: public section_64  
{};         
  70         struct macho_routines_command   
: public routines_command_64  
{};        
  72         #define LC_SEGMENT_COMMAND              LC_SEGMENT 
  73         #define LC_ROUTINES_COMMAND             LC_ROUTINES 
  74         #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT_64 
  75         struct macho_segment_command    
: public segment_command 
{}; 
  76         struct macho_section                    
: public section  
{};    
  77         struct macho_routines_command   
: public routines_command  
{};   
  80 uint32_t ImageLoaderMachO::fgSymbolTableBinarySearchs 
= 0; 
  81 uint32_t ImageLoaderMachO::fgSymbolTrieSearchs 
= 0; 
  84 ImageLoaderMachO::ImageLoaderMachO(const macho_header
* mh
, const char* path
, unsigned int segCount
,  
  85                                                                                                                                 uint32_t segOffsets
[], unsigned int libCount
) 
  86  : ImageLoader(path
, libCount
), fMachOData((uint8_t*)mh
), fLinkEditBase(NULL
), fSlide(0),  
  87         fEHFrameSectionOffset(0), fUnwindInfoSectionOffset(0), fDylibIDOffset(0),  
  88         fSegmentsCount(segCount
), fIsSplitSeg(false), fInSharedCache(false),   
  89 #if TEXT_RELOC_SUPPORT 
  90         fTextSegmentRebases(false), 
  91         fTextSegmentBinds(false), 
  94         fReadOnlyImportSegment(false), 
  96         fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false), 
  97         fHasInitializers(false), fHasTerminators(false), fRegisteredAsRequiresCoalescing(false) 
  99         fIsSplitSeg 
= ((mh
->flags 
& MH_SPLIT_SEGS
) != 0);         
 101         // construct SegmentMachO object for each LC_SEGMENT cmd using "placement new" to put  
 102         // each SegmentMachO object in array at end of ImageLoaderMachO object 
 103         const uint32_t cmd_count 
= mh
->ncmds
; 
 104         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 105         const struct load_command
* cmd 
= cmds
; 
 106         for (uint32_t i 
= 0, segIndex
=0; i 
< cmd_count
; ++i
) { 
 107                 if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
 108                         const struct macho_segment_command
* segCmd 
= (struct macho_segment_command
*)cmd
; 
 109                         // ignore zero-sized segments 
 110                         if ( segCmd
->vmsize 
!= 0 ) { 
 111                                 // record offset of load command 
 112                                 segOffsets
[segIndex
++] = (uint32_t)((uint8_t*)segCmd 
- fMachOData
); 
 115                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 121 // determine if this mach-o file has classic or compressed LINKEDIT and number of segments it has 
 122 void ImageLoaderMachO::sniffLoadCommands(const macho_header
* mh
, const char* path
, bool* compressed
,  
 123                                                                                         unsigned int* segCount
, unsigned int* libCount
, const LinkContext
& context
, 
 124                                                                                         const linkedit_data_command
** codeSigCmd
) 
 130         struct macho_segment_command
* segCmd
; 
 131         bool foundLoadCommandSegment 
= false; 
 132         uint32_t loadCommandSegmentIndex 
= 0xFFFFFFFF; 
 133         uintptr_t loadCommandSegmentVMStart 
= 0; 
 134         uintptr_t loadCommandSegmentVMEnd 
= 0; 
 136         const uint32_t cmd_count 
= mh
->ncmds
; 
 137         const struct load_command
* const startCmds    
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
)); 
 138         const struct load_command
* const endCmds 
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
) + mh
->sizeofcmds
); 
 139         const struct load_command
* cmd 
= startCmds
; 
 140         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 141                 uint32_t cmdLength 
= cmd
->cmdsize
; 
 142                 if ( cmdLength 
< 8 ) { 
 143                         dyld::throwf("malformed mach-o image: load command #%d length (%u) too small in %s", 
 146                 const struct load_command
* const nextCmd 
= (const struct load_command
*)(((char*)cmd
)+cmdLength
); 
 147                 if ( (nextCmd 
> endCmds
) || (nextCmd 
< cmd
) ) { 
 148                         dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s", 
 149                                                                                            i
, cmdLength
, mh
->sizeofcmds
, path
); 
 153                         case LC_DYLD_INFO_ONLY
: 
 156                         case LC_SEGMENT_COMMAND
: 
 157                                 segCmd 
= (struct macho_segment_command
*)cmd
; 
 158                                 // ignore zero-sized segments 
 159                                 if ( segCmd
->vmsize 
!= 0 ) 
 161                                 // <rdar://problem/7942521> all load commands must be in an executable segment 
 162                                 if ( context
.codeSigningEnforced 
&& (segCmd
->fileoff 
< mh
->sizeofcmds
) && (segCmd
->filesize 
!= 0) ) { 
 163                                         if ( (segCmd
->fileoff 
!= 0) || (segCmd
->filesize 
< (mh
->sizeofcmds
+sizeof(macho_header
))) )  
 164                                                 dyld::throwf("malformed mach-o image: segment %s does not span all load commands", segCmd
->segname
);  
 165                                         if ( segCmd
->initprot 
!= (VM_PROT_READ 
| VM_PROT_EXECUTE
) )  
 166                                                 dyld::throwf("malformed mach-o image: load commands found in segment %s with wrong permissions", segCmd
->segname
);  
 167                                         if ( foundLoadCommandSegment 
) 
 168                                                 throw "load commands in multiple segments"; 
 169                                         foundLoadCommandSegment 
= true; 
 170                                         loadCommandSegmentIndex 
= i
; 
 171                                         loadCommandSegmentVMStart 
= segCmd
->vmaddr
; 
 172                                         loadCommandSegmentVMEnd   
= segCmd
->vmaddr 
+ segCmd
->vmsize
; 
 173                                         if ( (intptr_t)(segCmd
->vmsize
) < 0) 
 174                                                 dyld::throwf("malformed mach-o image: segment load command %s size too large", segCmd
->segname
); 
 175                                         if ( loadCommandSegmentVMEnd 
< loadCommandSegmentVMStart 
) 
 176                                                 dyld::throwf("malformed mach-o image: segment load command %s wraps around address space", segCmd
->segname
); 
 179                         case LC_SEGMENT_COMMAND_WRONG
: 
 180                                 dyld::throwf("malformed mach-o image: wrong LC_SEGMENT[_64] for architecture");  
 183                         case LC_LOAD_WEAK_DYLIB
: 
 184                         case LC_REEXPORT_DYLIB
: 
 185                         case LC_LOAD_UPWARD_DYLIB
: 
 188                         case LC_CODE_SIGNATURE
: 
 189                                 *codeSigCmd 
= (struct linkedit_data_command
*)cmd
; // only support one LC_CODE_SIGNATURE per image 
 195         if ( context
.codeSigningEnforced 
&& !foundLoadCommandSegment 
) 
 196                 throw "load commands not in a segment"; 
 197         // <rdar://problem/13145644> verify another segment does not over-map load commands 
 199         if ( context
.codeSigningEnforced 
) { 
 200                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 202                                 case LC_SEGMENT_COMMAND
: 
 203                                         if ( i 
!= loadCommandSegmentIndex 
) { 
 204                                                 segCmd 
= (struct macho_segment_command
*)cmd
; 
 205                                                 uintptr_t start 
= segCmd
->vmaddr
; 
 206                                                 uintptr_t end 
= segCmd
->vmaddr 
+ segCmd
->vmsize
; 
 207                                                 if ( ((start 
<= loadCommandSegmentVMStart
) && (end 
> loadCommandSegmentVMStart
))  
 208                                                    || ((start 
>= loadCommandSegmentVMStart
) && (start 
< loadCommandSegmentVMEnd
)) ) 
 209                                                         dyld::throwf("malformed mach-o image: segment %s overlaps load commands", segCmd
->segname
);  
 213                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 217         // fSegmentsArrayCount is only 8-bits 
 218         if ( *segCount 
> 255 ) 
 219                 dyld::throwf("malformed mach-o image: more than 255 segments in %s", path
); 
 221         // fSegmentsArrayCount is only 8-bits 
 222         if ( *libCount 
> 4095 ) 
 223                 dyld::throwf("malformed mach-o image: more than 4095 dependent libraries in %s", path
); 
 225         if ( needsAddedLibSystemDepency(*libCount
, mh
) ) 
 231 // create image for main executable 
 232 ImageLoader
* ImageLoaderMachO::instantiateMainExecutable(const macho_header
* mh
, uintptr_t slide
, const char* path
, const LinkContext
& context
) 
 234         //dyld::log("ImageLoader=%ld, ImageLoaderMachO=%ld, ImageLoaderMachOClassic=%ld, ImageLoaderMachOCompressed=%ld\n", 
 235         //      sizeof(ImageLoader), sizeof(ImageLoaderMachO), sizeof(ImageLoaderMachOClassic), sizeof(ImageLoaderMachOCompressed)); 
 237         unsigned int segCount
; 
 238         unsigned int libCount
; 
 239         const linkedit_data_command
* codeSigCmd
; 
 240         sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
, context
, &codeSigCmd
); 
 241         // instantiate concrete class based on content of load commands 
 243                 return ImageLoaderMachOCompressed::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
); 
 245 #if SUPPORT_CLASSIC_MACHO 
 246                 return ImageLoaderMachOClassic::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
); 
 248                 throw "missing LC_DYLD_INFO load command"; 
 253 // create image by mapping in a mach-o file 
 254 ImageLoader
* ImageLoaderMachO::instantiateFromFile(const char* path
, int fd
, const uint8_t firstPage
[4096], uint64_t offsetInFat
,  
 255                                                                         uint64_t lenInFat
, const struct stat
& info
, const LinkContext
& context
) 
 258         const unsigned int dataSize 
= sizeof(macho_header
) + ((macho_header
*)firstPage
)->sizeofcmds
; 
 259         uint8_t buffer
[dataSize
]; 
 260         const uint8_t* fileData 
= firstPage
; 
 261         if ( dataSize 
> 4096 ) { 
 262                 // only read more if cmds take up more space than first page 
 264                 memcpy(buffer
, firstPage
, 4096); 
 265                 pread(fd
, &buffer
[4096], dataSize
-4096, offsetInFat
+4096); 
 269         unsigned int segCount
; 
 270         unsigned int libCount
; 
 271         const linkedit_data_command
* codeSigCmd
; 
 272         sniffLoadCommands((const macho_header
*)fileData
, path
, &compressed
, &segCount
, &libCount
, context
, &codeSigCmd
); 
 273         // instantiate concrete class based on content of load commands 
 275                 return ImageLoaderMachOCompressed::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, codeSigCmd
, context
); 
 277 #if SUPPORT_CLASSIC_MACHO 
 278                 return ImageLoaderMachOClassic::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, codeSigCmd
, context
); 
 280                 throw "missing LC_DYLD_INFO load command"; 
 284 // create image by using cached mach-o file 
 285 ImageLoader
* ImageLoaderMachO::instantiateFromCache(const macho_header
* mh
, const char* path
, long slide
, const struct stat
& info
, const LinkContext
& context
) 
 287         // instantiate right concrete class 
 289         unsigned int segCount
; 
 290         unsigned int libCount
; 
 291         const linkedit_data_command
* codeSigCmd
; 
 292         sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
, context
, &codeSigCmd
); 
 293         // instantiate concrete class based on content of load commands 
 295                 return ImageLoaderMachOCompressed::instantiateFromCache(mh
, path
, slide
, info
, segCount
, libCount
, context
); 
 297 #if SUPPORT_CLASSIC_MACHO 
 298                 return ImageLoaderMachOClassic::instantiateFromCache(mh
, path
, slide
, info
, segCount
, libCount
, context
); 
 300                 throw "missing LC_DYLD_INFO load command"; 
 304 // create image by copying an in-memory mach-o file 
 305 ImageLoader
* ImageLoaderMachO::instantiateFromMemory(const char* moduleName
, const macho_header
* mh
, uint64_t len
, const LinkContext
& context
) 
 308         unsigned int segCount
; 
 309         unsigned int libCount
; 
 310         const linkedit_data_command
* sigcmd
; 
 311         sniffLoadCommands(mh
, moduleName
, &compressed
, &segCount
, &libCount
, context
, &sigcmd
); 
 312         // instantiate concrete class based on content of load commands 
 314                 return ImageLoaderMachOCompressed::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
); 
 316 #if SUPPORT_CLASSIC_MACHO 
 317                 return ImageLoaderMachOClassic::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
); 
 319                 throw "missing LC_DYLD_INFO load command"; 
 324 int ImageLoaderMachO::crashIfInvalidCodeSignature() 
 326         // Now that segments are mapped in, try reading from first executable segment. 
 327         // If code signing is enabled the kernel will validate the code signature 
 328         // when paging in, and kill the process if invalid. 
 329         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
 330                 if ( (segFileOffset(i
) == 0) && (segFileSize(i
) != 0) ) { 
 331                         // return read value to ensure compiler does not optimize away load 
 332                         int* p 
= (int*)segActualLoadAddress(i
); 
 340 void ImageLoaderMachO::parseLoadCmds() 
 342         // now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide 
 343         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
 344                 // set up pointer to __LINKEDIT segment 
 345                 if ( strcmp(segName(i
),"__LINKEDIT") == 0 )  
 346                         fLinkEditBase 
= (uint8_t*)(segActualLoadAddress(i
) - segFileOffset(i
)); 
 347 #if TEXT_RELOC_SUPPORT 
 348                 // __TEXT segment always starts at beginning of file and contains mach_header and load commands 
 349                 if ( segExecutable(i
) ) { 
 350                         if ( segHasRebaseFixUps(i
) && (fSlide 
!= 0) ) 
 351                                 fTextSegmentRebases 
= true; 
 352                         if ( segHasBindFixUps(i
) ) 
 353                                 fTextSegmentBinds 
= true; 
 357                 if ( segIsReadOnlyImport(i
) ) 
 358                         fReadOnlyImportSegment 
= true; 
 360                 // some segment always starts at beginning of file and contains mach_header and load commands 
 361                 if ( (segFileOffset(i
) == 0) && (segFileSize(i
) != 0) ) { 
 362                         fMachOData 
= (uint8_t*)(segActualLoadAddress(i
)); 
 366         // keep count of prebound images with weak exports 
 367         if ( this->participatesInCoalescing() ) { 
 368                 ++fgImagesRequiringCoalescing
; 
 369                 fRegisteredAsRequiresCoalescing 
= true; 
 370                 if ( this->hasCoalescedExports() )  
 371                         ++fgImagesHasWeakDefinitions
; 
 374         // keep count of images used in shared cache 
 375         if ( fInSharedCache 
) 
 376                 ++fgImagesUsedFromSharedCache
; 
 378         // walk load commands (mapped in at start of __TEXT segment) 
 379         const dyld_info_command
* dyldInfo 
= NULL
; 
 380         const macho_nlist
* symbolTable 
= NULL
; 
 381         const char* symbolTableStrings 
= NULL
; 
 382         const struct load_command
* firstUnknownCmd 
= NULL
; 
 383         const struct version_min_command
* minOSVersionCmd 
= NULL
; 
 384         const dysymtab_command
* dynSymbolTable 
= NULL
; 
 385         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 386         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 387         const struct load_command
* cmd 
= cmds
; 
 388         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 392                                         const struct symtab_command
* symtab 
= (struct symtab_command
*)cmd
; 
 393                                         symbolTableStrings 
= (const char*)&fLinkEditBase
[symtab
->stroff
]; 
 394                                         symbolTable 
= (macho_nlist
*)(&fLinkEditBase
[symtab
->symoff
]); 
 398                                 dynSymbolTable 
= (struct dysymtab_command
*)cmd
; 
 400                         case LC_SUB_UMBRELLA
: 
 401                                 fHasSubUmbrella 
= true; 
 403                         case LC_SUB_FRAMEWORK
: 
 407                                 fHasSubLibraries 
= true; 
 409                         case LC_ROUTINES_COMMAND
: 
 413                         case LC_DYLD_INFO_ONLY
: 
 414                                 dyldInfo 
= (struct dyld_info_command
*)cmd
; 
 416                         case LC_SEGMENT_COMMAND
: 
 418                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
 419                                         const bool isTextSeg 
= (strcmp(seg
->segname
, "__TEXT") == 0); 
 420                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
 421                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
 422                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 423                                                 const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
 424                                                 if ( type 
== S_MOD_INIT_FUNC_POINTERS 
) 
 425                                                         fHasInitializers 
= true; 
 426                                                 else if ( type 
== S_MOD_TERM_FUNC_POINTERS 
) 
 427                                                         fHasTerminators 
= true; 
 428                                                 else if ( type 
== S_DTRACE_DOF 
) 
 429                                                         fHasDOFSections 
= true; 
 430                                                 else if ( isTextSeg 
&& (strcmp(sect
->sectname
, "__eh_frame") == 0) ) 
 431                                                         fEHFrameSectionOffset 
= (uint32_t)((uint8_t*)sect 
- fMachOData
); 
 432                                                 else if ( isTextSeg 
&& (strcmp(sect
->sectname
, "__unwind_info") == 0) ) 
 433                                                         fUnwindInfoSectionOffset 
= (uint32_t)((uint8_t*)sect 
- fMachOData
); 
 437                         case LC_TWOLEVEL_HINTS
: 
 438                                 // no longer supported 
 442                                         fDylibIDOffset 
= (uint32_t)((uint8_t*)cmd 
- fMachOData
); 
 446                         case LC_LOAD_WEAK_DYLIB
: 
 447                     case LC_REEXPORT_DYLIB
: 
 448                         case LC_LOAD_UPWARD_DYLIB
: 
 450                                 // do nothing, just prevent LC_REQ_DYLD exception from occuring 
 452                         case LC_VERSION_MIN_MACOSX
: 
 453                         case LC_VERSION_MIN_IPHONEOS
: 
 454                                 minOSVersionCmd 
= (version_min_command
*)cmd
; 
 457                                 if ( (cmd
->cmd 
& LC_REQ_DYLD
) != 0 ) { 
 458                                         if ( firstUnknownCmd 
== NULL 
) 
 459                                                 firstUnknownCmd 
= cmd
; 
 463                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 465         if ( firstUnknownCmd 
!= NULL 
) { 
 466                 if ( minOSVersionCmd 
!= NULL 
)  { 
 467                         dyld::throwf("cannot load '%s' because it was built for OS version %u.%u (load command 0x%08X is unknown)",  
 468                                                  this->getShortName(), 
 469                                                  minOSVersionCmd
->version 
>> 16, ((minOSVersionCmd
->version 
>> 8) & 0xff),  
 470                                                  firstUnknownCmd
->cmd
); 
 473                         dyld::throwf("cannot load '%s' (load command 0x%08X is unknown)", this->getShortName(), firstUnknownCmd
->cmd
); 
 478         if ( dyldInfo 
!= NULL 
) 
 479                 this->setDyldInfo(dyldInfo
); 
 480         if ( symbolTable 
!= NULL
) 
 481                 this->setSymbolTableInfo(symbolTable
, symbolTableStrings
, dynSymbolTable
); 
 485 // don't do this work in destructor because we need object to be full subclass 
 486 // for UnmapSegments() to work 
 487 void ImageLoaderMachO::destroy() 
 489         // update count of images with weak exports 
 490         if ( fRegisteredAsRequiresCoalescing 
) { 
 491                 --fgImagesRequiringCoalescing
; 
 492                 if ( this->hasCoalescedExports() )  
 493                         --fgImagesHasWeakDefinitions
; 
 496         // keep count of images used in shared cache 
 497         if ( fInSharedCache 
) 
 498                 --fgImagesUsedFromSharedCache
; 
 500         // unmap image when done 
 505 unsigned int ImageLoaderMachO::segmentCount() const 
 507         return fSegmentsCount
; 
 511 const macho_segment_command
* ImageLoaderMachO::segLoadCommand(unsigned int segIndex
) const 
 513         uint32_t* lcOffsets 
= this->segmentCommandOffsets(); 
 514         uint32_t lcOffset 
=     lcOffsets
[segIndex
]; 
 515         return (macho_segment_command
*)(&fMachOData
[lcOffset
]); 
 518 const char*     ImageLoaderMachO::segName(unsigned int segIndex
) const 
 520         return segLoadCommand(segIndex
)->segname
; 
 524 uintptr_t ImageLoaderMachO::segSize(unsigned int segIndex
) const 
 526         return segLoadCommand(segIndex
)->vmsize
; 
 530 uintptr_t ImageLoaderMachO::segFileSize(unsigned int segIndex
) const 
 532         return segLoadCommand(segIndex
)->filesize
; 
 536 bool ImageLoaderMachO::segHasTrailingZeroFill(unsigned int segIndex
) 
 538         return ( segWriteable(segIndex
) && (segSize(segIndex
) > segFileSize(segIndex
)) ); 
 542 uintptr_t ImageLoaderMachO::segFileOffset(unsigned int segIndex
) const 
 544         return segLoadCommand(segIndex
)->fileoff
; 
 548 bool ImageLoaderMachO::segReadable(unsigned int segIndex
) const 
 550         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_READ
) != 0); 
 554 bool ImageLoaderMachO::segWriteable(unsigned int segIndex
) const 
 556         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_WRITE
) != 0); 
 560 bool ImageLoaderMachO::segExecutable(unsigned int segIndex
) const 
 562         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_EXECUTE
) != 0); 
 566 bool ImageLoaderMachO::segUnaccessible(unsigned int segIndex
) const 
 568         return (segLoadCommand(segIndex
)->initprot 
== 0); 
 571 bool ImageLoaderMachO::segHasPreferredLoadAddress(unsigned int segIndex
) const 
 573         return (segLoadCommand(segIndex
)->vmaddr 
!= 0); 
 576 uintptr_t ImageLoaderMachO::segPreferredLoadAddress(unsigned int segIndex
) const 
 578         return segLoadCommand(segIndex
)->vmaddr
; 
 581 uintptr_t ImageLoaderMachO::segActualLoadAddress(unsigned int segIndex
) const 
 583         return segLoadCommand(segIndex
)->vmaddr 
+ fSlide
; 
 587 uintptr_t ImageLoaderMachO::segActualEndAddress(unsigned int segIndex
) const 
 589         return segActualLoadAddress(segIndex
) + segSize(segIndex
); 
 592 bool ImageLoaderMachO::segHasRebaseFixUps(unsigned int segIndex
) const 
 594 #if TEXT_RELOC_SUPPORT 
 595         // scan sections for fix-up bit 
 596         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 597         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)segCmd 
+ sizeof(struct macho_segment_command
)); 
 598         const struct macho_section
* const sectionsEnd 
= §ionsStart
[segCmd
->nsects
]; 
 599         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 600                 if ( (sect
->flags 
& S_ATTR_LOC_RELOC
) != 0 ) 
 607 bool ImageLoaderMachO::segHasBindFixUps(unsigned int segIndex
) const 
 609 #if TEXT_RELOC_SUPPORT 
 610         // scan sections for fix-up bit 
 611         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 612         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)segCmd 
+ sizeof(struct macho_segment_command
)); 
 613         const struct macho_section
* const sectionsEnd 
= §ionsStart
[segCmd
->nsects
]; 
 614         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 615                 if ( (sect
->flags 
& S_ATTR_EXT_RELOC
) != 0 ) 
 623 bool ImageLoaderMachO::segIsReadOnlyImport(unsigned int segIndex
) const 
 625         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 626         return (    (segCmd
->initprot 
& VM_PROT_EXECUTE
)  
 627                         && ((segCmd
->initprot 
& VM_PROT_WRITE
) == 0)  
 628                         && (strcmp(segCmd
->segname
, "__IMPORT") == 0) ); 
 633 void ImageLoaderMachO::UnmapSegments() 
 635         // usually unmap image when done 
 636         if ( ! this->leaveMapped() && (this->getState() >= dyld_image_state_mapped
) ) { 
 637                 // unmap TEXT segment last because it contains load command being inspected 
 638                 unsigned int textSegmentIndex 
= 0; 
 639                 for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
 640                         //dyld::log("unmap %s at 0x%08lX\n", seg->getName(), seg->getActualLoadAddress(this)); 
 641                         if ( strcmp(segName(i
), "__TEXT") == 0 ) { 
 642                                 textSegmentIndex 
= i
; 
 646                                 --ImageLoader::fgTotalSegmentsMapped
; 
 647                                 ImageLoader::fgTotalBytesMapped 
-= segSize(i
); 
 648                                 munmap((void*)segActualLoadAddress(i
), segSize(i
)); 
 652                 --ImageLoader::fgTotalSegmentsMapped
; 
 653                 ImageLoader::fgTotalBytesMapped 
-= segSize(textSegmentIndex
); 
 654                 munmap((void*)segActualLoadAddress(textSegmentIndex
), segSize(textSegmentIndex
)); 
 659 // prefetch __DATA/__OBJC pages during launch, but not for dynamically loaded code 
 660 void ImageLoaderMachO::preFetchDATA(int fd
, uint64_t offsetInFat
, const LinkContext
& context
) 
 662         if ( context
.linkingMainExecutable 
) { 
 663                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
 664                         if ( segWriteable(i
) && (segFileSize(i
) > 0) ) { 
 665                                 // prefetch writable segment that have mmap'ed regions 
 667                                 advice
.ra_offset 
= offsetInFat 
+ segFileOffset(i
); 
 668                                 advice
.ra_count 
= (int)segFileSize(i
); 
 669                                 // limit prefetch to 1MB (256 pages) 
 670                                 if ( advice
.ra_count 
> 1024*1024 ) 
 671                                         advice
.ra_count 
= 1024*1024; 
 672                                 // don't prefetch single pages, let them fault in 
 673                                 fgTotalBytesPreFetched 
+= advice
.ra_count
; 
 674                                 fcntl(fd
, F_RDADVISE
, &advice
); 
 675                                 if ( context
.verboseMapping 
) { 
 676                                         dyld::log("%18s prefetching 0x%0lX -> 0x%0lX\n",  
 677                                                 segName(i
), segActualLoadAddress(i
), segActualLoadAddress(i
)+advice
.ra_count
-1); 
 685 bool ImageLoaderMachO::segmentsMustSlideTogether() const  
 690 bool ImageLoaderMachO::segmentsCanSlide() const  
 692         return (this->isDylib() || this->isBundle() || this->isPositionIndependentExecutable()); 
 695 bool ImageLoaderMachO::isBundle() const  
 697         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 698         return ( mh
->filetype 
== MH_BUNDLE 
); 
 701 bool ImageLoaderMachO::isDylib() const  
 703         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 704         return ( mh
->filetype 
== MH_DYLIB 
); 
 707 bool ImageLoaderMachO::isExecutable() const  
 709         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 710         return ( mh
->filetype 
== MH_EXECUTE 
); 
 713 bool ImageLoaderMachO::isPositionIndependentExecutable() const  
 715         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 716         return ( (mh
->filetype 
== MH_EXECUTE
) && ((mh
->flags 
& MH_PIE
) != 0) ); 
 720 bool ImageLoaderMachO::forceFlat() const  
 722         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 723         return ( (mh
->flags 
& MH_FORCE_FLAT
) != 0 ); 
 726 bool ImageLoaderMachO::usesTwoLevelNameSpace() const 
 728         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 729         return ( (mh
->flags 
& MH_TWOLEVEL
) != 0 ); 
 732 bool ImageLoaderMachO::isPrebindable() const  
 734         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 735         return ( (mh
->flags 
& MH_PREBOUND
) != 0 ); 
 738 bool ImageLoaderMachO::hasCoalescedExports() const  
 740         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 741         return ( (mh
->flags 
& MH_WEAK_DEFINES
) != 0 ); 
 744 bool ImageLoaderMachO::hasReferencesToWeakSymbols() const  
 746         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 747         return ( (mh
->flags 
& MH_BINDS_TO_WEAK
) != 0 ); 
 750 bool ImageLoaderMachO::participatesInCoalescing() const  
 752         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 753         // if image is loaded with RTLD_LOCAL, then its symbols' visibility 
 754         // is reduced and it can't coalesce with other images 
 755         if ( this->hasHiddenExports() ) 
 757         return ( (mh
->flags 
& (MH_WEAK_DEFINES
|MH_BINDS_TO_WEAK
)) != 0 ); 
 762 void ImageLoaderMachO::setSlide(intptr_t slide
) 
 767 void ImageLoaderMachO::loadCodeSignature(const struct linkedit_data_command
* codeSigCmd
, int fd
,  uint64_t offsetInFatFile
, const LinkContext
& context
) 
 769         // if dylib being loaded has no code signature load command 
 770         if ( codeSigCmd 
== NULL 
) { 
 771 #if __MAC_OS_X_VERSION_MIN_REQUIRED 
 772                 bool codeSigningEnforced 
= context
.codeSigningEnforced
; 
 773                 if ( context
.mainExecutableCodeSigned 
&& !codeSigningEnforced 
) { 
 774                         static bool codeSignEnforcementDynamicallyEnabled 
= false; 
 775                         if ( !codeSignEnforcementDynamicallyEnabled 
) { 
 777                                 if ( csops(0, CS_OPS_STATUS
, &flags
, sizeof(flags
)) != -1 ) { 
 778                                         if ( flags 
& CS_ENFORCEMENT 
) { 
 779                                                 codeSignEnforcementDynamicallyEnabled 
= true; 
 783                         codeSigningEnforced 
= codeSignEnforcementDynamicallyEnabled
; 
 785                 // if we require dylibs to be code signed 
 786                 if ( codeSigningEnforced  
) { 
 787                         // if there is a non-load command based code signature, use it 
 788                         off_t offset 
= (off_t
)offsetInFatFile
; 
 789                         if ( fcntl(fd
, F_FINDSIGS
, &offset
, sizeof(offset
)) != -1 ) 
 791                         // otherwise gracefully return from dlopen() 
 792                         dyld::throwf("required code signature missing for '%s'\n", this->getPath()); 
 797 #if __MAC_OS_X_VERSION_MIN_REQUIRED 
 798                 // <rdar://problem/13622786> ignore code signatures in binaries built with pre-10.9 tools 
 799                 if ( this->sdkVersion() < DYLD_MACOSX_VERSION_10_9 
) { 
 803                 fsignatures_t siginfo
; 
 804                 siginfo
.fs_file_start
=offsetInFatFile
;                          // start of mach-o slice in fat file  
 805                 siginfo
.fs_blob_start
=(void*)(long)(codeSigCmd
->dataoff
);       // start of CD in mach-o file 
 806                 siginfo
.fs_blob_size
=codeSigCmd
->datasize
;                      // size of CD 
 807                 int result 
= fcntl(fd
, F_ADDFILESIGS
, &siginfo
); 
 808                 if ( result 
== -1 ) { 
 809                         if ( (errno 
== EPERM
) || (errno 
== EBADEXEC
) ) 
 810                                 dyld::throwf("code signature invalid for '%s'\n", this->getPath()); 
 811                         if ( context
.verboseCodeSignatures 
)  
 812                                 dyld::log("dyld: Failed registering code signature for %s, errno=%d\n", this->getPath(), errno
); 
 814                                 dyld::log("dyld: Registered code signature for %s\n", this->getPath()); 
 820 const char* ImageLoaderMachO::getInstallPath() const 
 822         if ( fDylibIDOffset 
!= 0 ) { 
 823                 const dylib_command
* dylibID 
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]); 
 824                 return (char*)dylibID 
+ dylibID
->dylib
.name
.offset
; 
 829 void ImageLoaderMachO::registerInterposing() 
 831         // mach-o files advertise interposing by having a __DATA __interpose section 
 832         struct InterposeData 
{ uintptr_t replacement
; uintptr_t replacee
; }; 
 833         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 834         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 835         const struct load_command
* cmd 
= cmds
; 
 836         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 838                         case LC_SEGMENT_COMMAND
: 
 840                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
 841                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
 842                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
 843                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 844                                                 if ( ((sect
->flags 
& SECTION_TYPE
) == S_INTERPOSING
) || ((strcmp(sect
->sectname
, "__interpose") == 0) && (strcmp(seg
->segname
, "__DATA") == 0)) ) { 
 845                                                         const InterposeData
* interposeArray 
= (InterposeData
*)(sect
->addr 
+ fSlide
); 
 846                                                         const size_t count 
= sect
->size 
/ sizeof(InterposeData
); 
 847                                                         for (size_t i
=0; i 
< count
; ++i
) { 
 848                                                                 ImageLoader::InterposeTuple tuple
; 
 849                                                                 tuple
.replacement               
= interposeArray
[i
].replacement
; 
 850                                                                 tuple
.neverImage                
= this; 
 851                                                                 tuple
.onlyImage             
= NULL
; 
 852                                                                 tuple
.replacee                  
= interposeArray
[i
].replacee
; 
 853                                                                 // <rdar://problem/7937695> verify that replacement is in this image 
 854                                                                 if ( this->containsAddress((void*)tuple
.replacement
) ) { 
 855                                                                         // chain to any existing interpositions 
 856                                                                         for (std::vector
<InterposeTuple
>::iterator it
=fgInterposingTuples
.begin(); it 
!= fgInterposingTuples
.end(); it
++) { 
 857                                                                                 if ( it
->replacee 
== tuple
.replacee 
) { 
 858                                                                                         tuple
.replacee 
= it
->replacement
; 
 861                                                                         ImageLoader::fgInterposingTuples
.push_back(tuple
); 
 869                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 873 uint32_t ImageLoaderMachO::sdkVersion() const 
 875         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 876         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 877         const struct load_command
* cmd 
= cmds
; 
 878         const struct version_min_command
* versCmd
; 
 879         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 880                 switch ( cmd
->cmd 
) { 
 881                         case LC_VERSION_MIN_MACOSX
: 
 882                         case LC_VERSION_MIN_IPHONEOS
: 
 883                                 versCmd 
= (version_min_command
*)cmd
; 
 886                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 891 uint32_t ImageLoaderMachO::minOSVersion(const mach_header
* mh
) 
 893         const uint32_t cmd_count 
= mh
->ncmds
; 
 894         const struct load_command
* const cmds 
= (struct load_command
*)(((char*)mh
) + sizeof(macho_header
)); 
 895         const struct load_command
* cmd 
= cmds
; 
 896         const struct version_min_command
* versCmd
; 
 897         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 898                 switch ( cmd
->cmd 
) { 
 899                         case LC_VERSION_MIN_MACOSX
: 
 900                         case LC_VERSION_MIN_IPHONEOS
: 
 901                                 versCmd 
= (version_min_command
*)cmd
; 
 902                                 return versCmd
->version
; 
 904                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 909 uint32_t ImageLoaderMachO::minOSVersion() const 
 911         return ImageLoaderMachO::minOSVersion(machHeader()); 
 915 void* ImageLoaderMachO::getThreadPC() const 
 917         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 918         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 919         const struct load_command
* cmd 
= cmds
; 
 920         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 921                 if ( cmd
->cmd 
== LC_MAIN 
) { 
 922                         entry_point_command
* mainCmd 
= (entry_point_command
*)cmd
; 
 923                         void* entry 
= (void*)(mainCmd
->entryoff 
+ (char*)fMachOData
); 
 924                         // <rdar://problem/8543820&9228031> verify entry point is in image 
 925                         if ( this->containsAddress(entry
) ) 
 928                                 throw "LC_MAIN entryoff is out of range"; 
 930                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 936 void* ImageLoaderMachO::getMain() const 
 938         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 939         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 940         const struct load_command
* cmd 
= cmds
; 
 941         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 946                                 const i386_thread_state_t
* registers 
= (i386_thread_state_t
*)(((char*)cmd
) + 16); 
 947                                 void* entry 
= (void*)(registers
->eip 
+ fSlide
); 
 949                                 const x86_thread_state64_t
* registers 
= (x86_thread_state64_t
*)(((char*)cmd
) + 16); 
 950                                 void* entry 
= (void*)(registers
->rip 
+ fSlide
); 
 952                                 const arm_thread_state_t
* registers 
= (arm_thread_state_t
*)(((char*)cmd
) + 16); 
 953                                 void* entry 
= (void*)(registers
->__pc 
+ fSlide
); 
 955                                 const arm_thread_state64_t
* registers 
= (arm_thread_state64_t
*)(((char*)cmd
) + 16); 
 956                                 void* entry 
= (void*)(registers
->__pc 
+ fSlide
); 
 958                                 #warning need processor specific code 
 960                                 // <rdar://problem/8543820&9228031> verify entry point is in image 
 961                                 if ( this->containsAddress(entry
) ) { 
 967                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 969         throw "no valid entry point"; 
 972 bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount
, const macho_header
* mh
) 
 974         // <rdar://problem/6357561> ensure that every image depends on something which depends on libSystem 
 978         // <rdar://problem/6409800> dyld implicit-libSystem breaks valgrind 
 979         if ( mh
->filetype 
== MH_EXECUTE 
)  
 982         bool isNonOSdylib 
= false; 
 983         const uint32_t cmd_count 
= mh
->ncmds
; 
 984         const struct load_command
* const cmds 
= (struct load_command
*)((uint8_t*)mh
+sizeof(macho_header
)); 
 985         const struct load_command
* cmd 
= cmds
; 
 986         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 989                         case LC_LOAD_WEAK_DYLIB
: 
 990                         case LC_REEXPORT_DYLIB
: 
 991                         case LC_LOAD_UPWARD_DYLIB
: 
 995                                 const dylib_command
* dylibID 
= (dylib_command
*)cmd
; 
 996                                 const char* installPath 
= (char*)cmd 
+ dylibID
->dylib
.name
.offset
; 
 997                                 // It is OK for OS dylibs (libSystem or libmath or Rosetta shims) to have no dependents 
 998                                 // but all other dylibs must depend on libSystem for initialization to initialize libSystem first 
 999                                 // <rdar://problem/6497528> rosetta circular dependency spew 
1000                                 isNonOSdylib 
= ( (strncmp(installPath
, "/usr/lib/", 9) != 0) && (strncmp(installPath
, "/usr/libexec/oah/Shims", 9) != 0) ); 
1004                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1006         return isNonOSdylib
; 
1010 void ImageLoaderMachO::doGetDependentLibraries(DependentLibraryInfo libs
[]) 
1012         if ( needsAddedLibSystemDepency(libraryCount(), (macho_header
*)fMachOData
) ) { 
1013                 DependentLibraryInfo
* lib 
= &libs
[0]; 
1014                 lib
->name 
= "/usr/lib/libSystem.B.dylib"; 
1015                 lib
->info
.checksum 
= 0; 
1016                 lib
->info
.minVersion 
= 0; 
1017                 lib
->info
.maxVersion 
= 0; 
1018                 lib
->required 
= false; 
1019                 lib
->reExported 
= false; 
1020                 lib
->upward 
= false; 
1024                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1025                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1026                 const struct load_command
* cmd 
= cmds
; 
1027                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1030                                 case LC_LOAD_WEAK_DYLIB
: 
1031                                 case LC_REEXPORT_DYLIB
: 
1032                                 case LC_LOAD_UPWARD_DYLIB
: 
1034                                         const struct dylib_command
* dylib 
= (struct dylib_command
*)cmd
; 
1035                                         DependentLibraryInfo
* lib 
= &libs
[index
++]; 
1036                                         lib
->name 
= (char*)cmd 
+ dylib
->dylib
.name
.offset
; 
1037                                         //lib->name = strdup((char*)cmd + dylib->dylib.name.offset); 
1038                                         lib
->info
.checksum 
= dylib
->dylib
.timestamp
; 
1039                                         lib
->info
.minVersion 
= dylib
->dylib
.compatibility_version
; 
1040                                         lib
->info
.maxVersion 
= dylib
->dylib
.current_version
; 
1041                                         lib
->required 
= (cmd
->cmd 
!= LC_LOAD_WEAK_DYLIB
); 
1042                                         lib
->reExported 
= (cmd
->cmd 
== LC_REEXPORT_DYLIB
); 
1043                                         lib
->upward 
= (cmd
->cmd 
== LC_LOAD_UPWARD_DYLIB
); 
1047                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1052 ImageLoader::LibraryInfo 
ImageLoaderMachO::doGetLibraryInfo() 
1055         if ( fDylibIDOffset 
!= 0 ) { 
1056                 const dylib_command
* dylibID 
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]); 
1057                 info
.minVersion 
= dylibID
->dylib
.compatibility_version
; 
1058                 info
.maxVersion 
= dylibID
->dylib
.current_version
; 
1059                 info
.checksum 
= dylibID
->dylib
.timestamp
; 
1062                 info
.minVersion 
= 0; 
1063                 info
.maxVersion 
= 0;             
1069 void ImageLoaderMachO::getRPaths(const LinkContext
& context
, std::vector
<const char*>& paths
) const 
1071         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1072         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1073         const struct load_command
* cmd 
= cmds
; 
1074         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1077                                 const char* pathToAdd 
= NULL
; 
1078                                 const char* path 
= (char*)cmd 
+ ((struct rpath_command
*)cmd
)->path
.offset
; 
1079                                 if ( (strncmp(path
, "@loader_path", 12) == 0) && ((path
[12] == '/') || (path
[12] == '\0')) ) { 
1080                                         if ( context
.processIsRestricted  
&& (context
.mainExecutable 
== this) ) { 
1081                                                 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @loader_path\n", path
, this->getPath()); 
1084                                         char resolvedPath
[PATH_MAX
]; 
1085                                         if ( realpath(this->getPath(), resolvedPath
) != NULL 
) { 
1086                                                 char newRealPath
[strlen(resolvedPath
) + strlen(path
)]; 
1087                                                 strcpy(newRealPath
, resolvedPath
); 
1088                                                 char* addPoint 
= strrchr(newRealPath
,'/'); 
1089                                                 if ( addPoint 
!= NULL 
) { 
1090                                                         strcpy(addPoint
, &path
[12]); 
1091                                                         pathToAdd 
= strdup(newRealPath
); 
1095                                 else if ( (strncmp(path
, "@executable_path", 16) == 0) && ((path
[16] == '/') || (path
[16] == '\0')) ) { 
1096                                         if ( context
.processIsRestricted 
) { 
1097                                                 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @executable_path\n", path
, this->getPath()); 
1100                                         char resolvedPath
[PATH_MAX
]; 
1101                                         if ( realpath(context
.mainExecutable
->getPath(), resolvedPath
) != NULL 
) { 
1102                                                 char newRealPath
[strlen(resolvedPath
) + strlen(path
)]; 
1103                                                 strcpy(newRealPath
, resolvedPath
); 
1104                                                 char* addPoint 
= strrchr(newRealPath
,'/'); 
1105                                                 if ( addPoint 
!= NULL 
) { 
1106                                                         strcpy(addPoint
, &path
[16]); 
1107                                                         pathToAdd 
= strdup(newRealPath
); 
1111                                 else if ( (path
[0] != '/') && context
.processIsRestricted 
) { 
1112                                         dyld::warn("LC_RPATH %s in %s being ignored in restricted program because it is a relative path\n", path
, this->getPath()); 
1115                                 else if ( (path
[0] == '/') && (context
.rootPaths 
!= NULL
) ) { 
1116                                         // <rdar://problem/5869973> DYLD_ROOT_PATH should apply to LC_RPATH rpaths 
1117                                         // DYLD_ROOT_PATH can be a list of paths, but at this point we can only support one, so use first combination that exists 
1119                                         for(const char** rp 
= context
.rootPaths
; *rp 
!= NULL
; ++rp
) { 
1120                                                 char newPath
[PATH_MAX
]; 
1121                                                 strlcpy(newPath
, *rp
, PATH_MAX
); 
1122                                                 strlcat(newPath
, path
, PATH_MAX
); 
1123                                                 struct stat stat_buf
; 
1124                                                 if ( stat(newPath
, &stat_buf
) != -1 ) { 
1125                                                         //dyld::log("combined DYLD_ROOT_PATH and LC_RPATH: %s\n", newPath); 
1126                                                         pathToAdd 
= strdup(newPath
); 
1132                                                 // make copy so that all elements of 'paths' can be freed 
1133                                                 pathToAdd 
= strdup(path
); 
1137                                         // make copy so that all elements of 'paths' can be freed 
1138                                         pathToAdd 
= strdup(path
); 
1140                                 if ( pathToAdd 
!= NULL 
) 
1141                                         paths
.push_back(pathToAdd
); 
1144                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1149 bool ImageLoaderMachO::getUUID(uuid_t uuid
) const 
1151         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1152         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1153         const struct load_command
* cmd 
= cmds
; 
1154         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1157                                 uuid_command
* uc 
= (uuid_command
*)cmd
; 
1158                                 memcpy(uuid
, uc
->uuid
, 16); 
1161                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1167 void ImageLoaderMachO::doRebase(const LinkContext
& context
) 
1169         // if prebound and loaded at prebound address, then no need to rebase 
1170         if ( this->usablePrebinding(context
) ) { 
1171                 // skip rebasing because prebinding is valid 
1172                 ++fgImagesWithUsedPrebinding
; // bump totals for statistics 
1176         // print why prebinding was not used 
1177         if ( context
.verbosePrebinding 
) { 
1178                 if ( !this->isPrebindable() ) { 
1179                         dyld::log("dyld: image not prebound, so could not use prebinding in %s\n", this->getPath()); 
1181                 else if ( fSlide 
!= 0 ) { 
1182                         dyld::log("dyld: image slid, so could not use prebinding in %s\n", this->getPath()); 
1184                 else if ( !this->allDependentLibrariesAsWhenPreBound() ) { 
1185                         dyld::log("dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath()); 
1187                 else if ( !this->usesTwoLevelNameSpace() ){ 
1188                         dyld::log("dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath()); 
1191                         dyld::log("dyld: environment variable disabled use of prebinding in %s\n", this->getPath()); 
1195         //dyld::log("slide=0x%08lX for %s\n", slide, this->getPath()); 
1197 #if PREBOUND_IMAGE_SUPPORT 
1198         // if prebound and we got here, then prebinding is not valid, so reset all lazy pointers 
1199         // if this image is in the shared cache, do not reset, they will be bound in doBind() 
1200         if ( this->isPrebindable() && !fInSharedCache 
) 
1201                 this->resetPreboundLazyPointers(context
); 
1204         // if loaded at preferred address, no rebasing necessary 
1205         if ( this->fSlide 
== 0 )  
1208 #if TEXT_RELOC_SUPPORT 
1209         // if there are __TEXT fixups, temporarily make __TEXT writable 
1210         if ( fTextSegmentRebases 
)  
1211                 this->makeTextSegmentWritable(context
, true); 
1214         // do actual rebasing 
1215         this->rebase(context
); 
1217 #if TEXT_RELOC_SUPPORT 
1218         // if there were __TEXT fixups, restore write protection 
1219         if ( fTextSegmentRebases 
)  
1220                 this->makeTextSegmentWritable(context
, false); 
1225 #if TEXT_RELOC_SUPPORT 
1226 void ImageLoaderMachO::makeTextSegmentWritable(const LinkContext
& context
, bool writeable
) 
1228         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
1229                 if ( segExecutable(i
) ) { 
1231                                 segMakeWritable(i
, context
); 
1234                         #if !__i386__ && !__x86_64__ 
1235                                 // some processors require range to be invalidated before it is made executable 
1236                                 sys_icache_invalidate((void*)segActualLoadAddress(i
), segSize(textSegmentIndex
)); 
1238                                 segProtect(i
, context
); 
1246 const ImageLoader::Symbol
* ImageLoaderMachO::findExportedSymbol(const char* name
, bool searchReExports
, const ImageLoader
** foundIn
) const 
1248         // look in this image first 
1249         const ImageLoader::Symbol
* result 
= this->findExportedSymbol(name
, foundIn
); 
1250         if ( result 
!= NULL 
) 
1253         if ( searchReExports 
) { 
1254                 for(unsigned int i
=0; i 
< libraryCount(); ++i
){ 
1255                         if ( libReExported(i
) ) { 
1256                                 ImageLoader
* image 
= libImage(i
); 
1257                                 if ( image 
!= NULL 
) { 
1258                                         const Symbol
* result 
= image
->findExportedSymbol(name
, searchReExports
, foundIn
); 
1259                                         if ( result 
!= NULL 
) 
1272 uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,  
1273                                                                                         const ImageLoader
* requestor
, bool runResolver
) const 
1275         return this->getSymbolAddress(sym
, requestor
, context
, runResolver
); 
1278 uintptr_t ImageLoaderMachO::getSymbolAddress(const Symbol
* sym
, const ImageLoader
* requestor
,  
1279                                                                                                 const LinkContext
& context
, bool runResolver
) const 
1281         uintptr_t result 
= exportedSymbolAddress(context
, sym
, requestor
, runResolver
); 
1282         // check for interposing overrides 
1283         result 
= interposedAddress(context
, result
, requestor
); 
1287 ImageLoader::DefinitionFlags 
ImageLoaderMachO::getExportedSymbolInfo(const Symbol
* sym
) const 
1289         if ( exportedSymbolIsWeakDefintion(sym
) ) 
1290                 return kWeakDefinition
; 
1292                 return kNoDefinitionOptions
; 
1295 const char* ImageLoaderMachO::getExportedSymbolName(const Symbol
* sym
) const 
1297         return exportedSymbolName(sym
); 
1300 uint32_t ImageLoaderMachO::getExportedSymbolCount() const 
1302         return exportedSymbolCount(); 
1306 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index
) const 
1308         return exportedSymbolIndexed(index
); 
1312 uint32_t ImageLoaderMachO::getImportedSymbolCount() const 
1314         return importedSymbolCount(); 
1318 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index
) const 
1320         return importedSymbolIndexed(index
); 
1324 ImageLoader::ReferenceFlags 
ImageLoaderMachO::getImportedSymbolInfo(const ImageLoader::Symbol
* sym
) const 
1326         ImageLoader::ReferenceFlags flags 
= kNoReferenceOptions
; 
1331 const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol
* sym
) const 
1333         return importedSymbolName(sym
); 
1337 bool ImageLoaderMachO::getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) 
1339         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1340         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1341         const struct load_command
* cmd 
= cmds
; 
1342         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1344                         case LC_SEGMENT_COMMAND
: 
1346                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1347                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1348                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1349                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1350                                                 if ( (strcmp(sect
->segname
, segmentName
) == 0) && (strcmp(sect
->sectname
, sectionName
) == 0) ) { 
1351                                                         *start 
= (uintptr_t*)(sect
->addr 
+ fSlide
); 
1352                                                         *length 
= sect
->size
; 
1359                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1366 void ImageLoaderMachO::getUnwindInfo(dyld_unwind_sections
* info
) 
1368         info
->mh 
= this->machHeader(); 
1369         info
->dwarf_section 
= 0; 
1370         info
->dwarf_section_length 
= 0; 
1371         info
->compact_unwind_section 
= 0; 
1372         info
->compact_unwind_section_length 
= 0; 
1373         if ( fEHFrameSectionOffset 
!= 0 ) { 
1374                 const macho_section
* sect 
= (macho_section
*)&fMachOData
[fEHFrameSectionOffset
]; 
1375                 info
->dwarf_section 
= (void*)(sect
->addr 
+ fSlide
); 
1376                 info
->dwarf_section_length 
= sect
->size
; 
1378         if ( fUnwindInfoSectionOffset 
!= 0 ) { 
1379                 const macho_section
* sect 
= (macho_section
*)&fMachOData
[fUnwindInfoSectionOffset
]; 
1380                 info
->compact_unwind_section 
= (void*)(sect
->addr 
+ fSlide
); 
1381                 info
->compact_unwind_section_length 
= sect
->size
; 
1386 bool ImageLoaderMachO::findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) 
1388         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1389         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1390         const struct load_command
* cmd 
= cmds
; 
1391         const uintptr_t unslidInteriorAddress 
= (uintptr_t)imageInterior 
- this->getSlide(); 
1392         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1394                         case LC_SEGMENT_COMMAND
: 
1396                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1397                                         if ( (unslidInteriorAddress 
>= seg
->vmaddr
) && (unslidInteriorAddress 
< (seg
->vmaddr
+seg
->vmsize
)) ) { 
1398                                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1399                                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1400                                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1401                                                         if ((sect
->addr 
<= unslidInteriorAddress
) && (unslidInteriorAddress 
< (sect
->addr
+sect
->size
))) { 
1402                                                                 if ( segmentName 
!= NULL 
) 
1403                                                                         *segmentName 
= sect
->segname
; 
1404                                                                 if ( sectionName 
!= NULL 
) 
1405                                                                         *sectionName 
= sect
->sectname
; 
1406                                                                 if ( sectionOffset 
!= NULL 
) 
1407                                                                         *sectionOffset 
= unslidInteriorAddress 
- sect
->addr
; 
1415                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1421 void __attribute__((noreturn
)) ImageLoaderMachO::throwSymbolNotFound(const LinkContext
& context
, const char* symbol
,  
1422                                                                                                                                         const char* referencedFrom
, const char* fromVersMismatch
, 
1423                                                                                                                                         const char* expectedIn
) 
1425         // record values for possible use by CrashReporter or Finder 
1426         (*context
.setErrorStrings
)(dyld_error_kind_symbol_missing
, referencedFrom
, expectedIn
, symbol
); 
1427         dyld::throwf("Symbol not found: %s\n  Referenced from: %s%s\n  Expected in: %s\n", 
1428                                         symbol
, referencedFrom
, fromVersMismatch
, expectedIn
); 
1431 const mach_header
* ImageLoaderMachO::machHeader() const 
1433         return (mach_header
*)fMachOData
; 
1436 uintptr_t ImageLoaderMachO::getSlide() const 
1441 // hmm. maybe this should be up in ImageLoader?? 
1442 const void* ImageLoaderMachO::getEnd() const 
1444         uintptr_t lastAddress 
= 0; 
1445         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
1446                 uintptr_t segEnd 
= segActualEndAddress(i
); 
1447                 if ( strcmp(segName(i
), "__UNIXSTACK") != 0 ) { 
1448                         if ( segEnd 
> lastAddress 
) 
1449                                 lastAddress 
= segEnd
; 
1452         return (const void*)lastAddress
; 
1456 uintptr_t ImageLoaderMachO::bindLocation(const LinkContext
& context
, uintptr_t location
, uintptr_t value
,  
1457                                                                                 const ImageLoader
* targetImage
, uint8_t type
, const char* symbolName
,  
1458                                                                                 intptr_t addend
, const char* msg
) 
1461         if ( context
.verboseBind 
) { 
1463                         dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX + %ld\n", 
1464                                                 msg
, this->getShortName(), (uintptr_t)location
, 
1465                                                 ((targetImage 
!= NULL
) ? targetImage
->getShortName() : "<weak_import-missing>"), 
1466                                                 symbolName
, (uintptr_t)location
, value
, addend
); 
1468                         dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX\n", 
1469                                                 msg
, this->getShortName(), (uintptr_t)location
, 
1470                                                 ((targetImage 
!= NULL
) ? targetImage
->getShortName() : "<weak>import-missing>"), 
1471                                                  symbolName
, (uintptr_t)location
, value
); 
1474 //      dyld::logBindings("%s: %s\n", targetImage->getShortName(), symbolName); 
1478         uintptr_t* locationToFix 
= (uintptr_t*)location
; 
1480         uintptr_t newValue 
= value
+addend
; 
1483                 case BIND_TYPE_POINTER
: 
1484                         // test first so we don't needless dirty pages 
1485                         if ( *locationToFix 
!= newValue 
) 
1486                                 *locationToFix 
= newValue
; 
1488                 case BIND_TYPE_TEXT_ABSOLUTE32
: 
1489                         loc32 
= (uint32_t*)locationToFix
; 
1490                         value32 
= (uint32_t)newValue
; 
1491                         if ( *loc32 
!= value32 
) 
1494                 case BIND_TYPE_TEXT_PCREL32
: 
1495                         loc32 
= (uint32_t*)locationToFix
; 
1496                         value32 
= (uint32_t)(newValue 
- (((uintptr_t)locationToFix
) + 4)); 
1497                         if ( *loc32 
!= value32 
) 
1501                         dyld::throwf("bad bind type %d", type
); 
1504         // update statistics 
1505         ++fgTotalBindFixups
; 
1514 #if SUPPORT_OLD_CRT_INITIALIZATION 
1515 // first 16 bytes of "start" in crt1.o 
1517         static uint8_t sStandardEntryPointInstructions
[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 }; 
1522         void*                   dyldLazyBinder
;         // filled in at launch by dyld to point into dyld to &stub_binding_helper 
1523         void*                   dyldFuncLookup
;         // filled in at launch by dyld to point into dyld to &_dyld_func_lookup 
1524         // the following only exist in main executables built for 10.5 or later 
1528 // These are defined in dyldStartup.s 
1529 extern "C" void stub_binding_helper(); 
1532 void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext
& context
) 
1534         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
1535         const uint32_t cmd_count 
= mh
->ncmds
; 
1536         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1537         const struct load_command
* cmd
; 
1538         // There used to be some optimizations to skip this section scan, but we need to handle the  
1539         // __dyld section in libdyld.dylib, so everything needs to be scanned for now. 
1540         // <rdar://problem/10910062> CrashTracer: 1,295 crashes in bash at bash: getenv 
1543                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1544                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1545                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1546                                 if ( strcmp(seg
->segname
, "__DATA") == 0 ) { 
1547                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1548                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1549                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1550                                                 if ( strcmp(sect
->sectname
, "__dyld" ) == 0 ) { 
1551                                                         struct DATAdyld
* dd 
= (struct DATAdyld
*)(sect
->addr 
+ fSlide
); 
1553                                                         if ( sect
->size 
> offsetof(DATAdyld
, dyldLazyBinder
) ) { 
1554                                                                 if ( dd
->dyldLazyBinder 
!= (void*)&stub_binding_helper 
) 
1555                                                                         dd
->dyldLazyBinder 
= (void*)&stub_binding_helper
; 
1557                                 #endif // !__arm64__ 
1558                                                         if ( sect
->size 
> offsetof(DATAdyld
, dyldFuncLookup
) ) { 
1559                                                                 if ( dd
->dyldFuncLookup 
!= (void*)&_dyld_func_lookup 
) 
1560                                                                         dd
->dyldFuncLookup 
= (void*)&_dyld_func_lookup
; 
1562                                                         if ( mh
->filetype 
== MH_EXECUTE 
) { 
1563                                                                 // there are two ways to get the program variables 
1564                                                                 if ( (sect
->size 
> offsetof(DATAdyld
, vars
)) && (dd
->vars
.mh 
== mh
) ) { 
1565                                                                         // some really old binaries have space for vars, but it is zero filled 
1566                                                                         // main executable has 10.5 style __dyld section that has program variable pointers 
1567                                                                         context
.setNewProgramVars(dd
->vars
); 
1570                                                                         // main executable is pre-10.5 and requires the symbols names to be looked up 
1571                                                                         this->lookupProgramVars(context
); 
1572                                 #if SUPPORT_OLD_CRT_INITIALIZATION 
1573                                                                         // If the first 16 bytes of the entry point's instructions do not  
1574                                                                         // match what crt1.o supplies, then the program has a custom entry point. 
1575                                                                         // This means it might be doing something that needs to be executed before  
1576                                                                         // initializers are run.  
1577                                                                         if ( memcmp(this->getMain(), sStandardEntryPointInstructions
, 16) != 0 ) { 
1578                                                                                 if ( context
.verboseInit 
) 
1579                                                                                         dyld::log("dyld: program uses non-standard entry point so delaying running of initializers\n"); 
1580                                                                                 context
.setRunInitialzersOldWay(); 
1585                                                         else if ( mh
->filetype 
== MH_DYLIB 
) { 
1586                                                                 const char* installPath 
= this->getInstallPath(); 
1587                                                                 if ( (installPath 
!= NULL
) && (strncmp(installPath
, "/usr/lib/", 9) == 0) ) { 
1588                                                                         if ( sect
->size 
> offsetof(DATAdyld
, vars
) ) { 
1589                                                                                 // use ProgramVars from libdyld.dylib but tweak mh field to correct value 
1590                                                                                 dd
->vars
.mh 
= context
.mainExecutable
->machHeader(); 
1591                                                                                 context
.setNewProgramVars(dd
->vars
); 
1596                                                 else if ( (strcmp(sect
->sectname
, "__program_vars" ) == 0) && (mh
->filetype 
== MH_EXECUTE
) ) { 
1597                                                         // this is a Mac OS X 10.6 or later main executable  
1598                                                         struct ProgramVars
* pv 
= (struct ProgramVars
*)(sect
->addr 
+ fSlide
); 
1599                                                         context
.setNewProgramVars(*pv
); 
1604                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1610 void ImageLoaderMachO::lookupProgramVars(const LinkContext
& context
) const 
1612         ProgramVars vars 
= context
.programVars
; 
1613         const ImageLoader::Symbol
* sym
; 
1615         // get mach header directly 
1616         vars
.mh 
= (macho_header
*)fMachOData
; 
1619         sym 
= this->findExportedSymbol("_NXArgc", false, NULL
); 
1621                 vars
.NXArgcPtr 
= (int*)this->getExportedSymbolAddress(sym
, context
, this, false); 
1624         sym 
= this->findExportedSymbol("_NXArgv", false, NULL
); 
1626                 vars
.NXArgvPtr 
= (const char***)this->getExportedSymbolAddress(sym
, context
, this, false); 
1629         sym 
= this->findExportedSymbol("_environ", false, NULL
); 
1631                 vars
.environPtr 
= (const char***)this->getExportedSymbolAddress(sym
, context
, this, false); 
1633         // lookup __progname 
1634         sym 
= this->findExportedSymbol("___progname", false, NULL
); 
1636                 vars
.__prognamePtr 
= (const char**)this->getExportedSymbolAddress(sym
, context
, this, false); 
1638         context
.setNewProgramVars(vars
); 
1642 bool ImageLoaderMachO::usablePrebinding(const LinkContext
& context
) const 
1644         // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind 
1645         if ( ((this->isPrebindable() && (this->getSlide() == 0)) || fInSharedCache
) 
1646                 && this->usesTwoLevelNameSpace() 
1647                 && this->allDependentLibrariesAsWhenPreBound() ) { 
1648                 // allow environment variables to disable prebinding 
1649                 if ( context
.bindFlat 
) 
1651                 switch ( context
.prebindUsage 
) { 
1652                         case kUseAllPrebinding
: 
1654                         case kUseSplitSegPrebinding
: 
1655                                 return this->fIsSplitSeg
; 
1656                         case kUseAllButAppPredbinding
: 
1657                                 return (this != context
.mainExecutable
); 
1658                         case kUseNoPrebinding
: 
1666 void ImageLoaderMachO::doImageInit(const LinkContext
& context
) 
1668         if ( fHasDashInit 
) { 
1669                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1670                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1671                 const struct load_command
* cmd 
= cmds
; 
1672                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1674                                 case LC_ROUTINES_COMMAND
: 
1675                                         Initializer func 
= (Initializer
)(((struct macho_routines_command
*)cmd
)->init_address 
+ fSlide
); 
1676                                         // <rdar://problem/8543820&9228031> verify initializers are in image 
1677                                         if ( ! this->containsAddress((void*)func
) ) { 
1678                                                 dyld::throwf("initializer function %p not in mapped image for %s\n", func
, this->getPath()); 
1680                                         if ( context
.verboseInit 
) 
1681                                                 dyld::log("dyld: calling -init function %p in %s\n", func
, this->getPath()); 
1682                                         func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
); 
1685                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1690 void ImageLoaderMachO::doModInitFunctions(const LinkContext
& context
) 
1692         if ( fHasInitializers 
) { 
1693                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1694                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1695                 const struct load_command
* cmd 
= cmds
; 
1696                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1697                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1698                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1699                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1700                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1701                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1702                                         const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
1703                                         if ( type 
== S_MOD_INIT_FUNC_POINTERS 
) { 
1704                                                 Initializer
* inits 
= (Initializer
*)(sect
->addr 
+ fSlide
); 
1705                                                 const size_t count 
= sect
->size 
/ sizeof(uintptr_t); 
1706                                                 for (size_t i
=0; i 
< count
; ++i
) { 
1707                                                         Initializer func 
= inits
[i
]; 
1708                                                         // <rdar://problem/8543820&9228031> verify initializers are in image 
1709                                                         if ( ! this->containsAddress((void*)func
) ) { 
1710                                                                 dyld::throwf("initializer function %p not in mapped image for %s\n", func
, this->getPath()); 
1712                                                         if ( context
.verboseInit 
) 
1713                                                                 dyld::log("dyld: calling initializer function %p in %s\n", func
, this->getPath()); 
1714                                                         func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
); 
1719                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1729 void ImageLoaderMachO::doGetDOFSections(const LinkContext
& context
, std::vector
<ImageLoader::DOFInfo
>& dofs
) 
1731         if ( fHasDOFSections 
) { 
1732                 // walk load commands (mapped in at start of __TEXT segment) 
1733                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1734                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1735                 const struct load_command
* cmd 
= cmds
; 
1736                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1738                                 case LC_SEGMENT_COMMAND
: 
1740                                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1741                                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1742                                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1743                                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1744                                                         if ( (sect
->flags 
& SECTION_TYPE
) == S_DTRACE_DOF 
) { 
1745                                                                 ImageLoader::DOFInfo info
; 
1746                                                                 info
.dof                        
= (void*)(sect
->addr 
+ fSlide
); 
1747                                                                 info
.imageHeader        
= this->machHeader(); 
1748                                                                 info
.imageShortName 
= this->getShortName(); 
1749                                                                 dofs
.push_back(info
); 
1755                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1761 bool ImageLoaderMachO::doInitialization(const LinkContext
& context
) 
1763         CRSetCrashLogMessage2(this->getPath()); 
1765         // mach-o has -init and static initializers 
1766         doImageInit(context
); 
1767         doModInitFunctions(context
); 
1769         CRSetCrashLogMessage2(NULL
); 
1771         return (fHasDashInit 
|| fHasInitializers
); 
1774 bool ImageLoaderMachO::needsInitialization() 
1776         return ( fHasDashInit 
|| fHasInitializers 
); 
1780 bool ImageLoaderMachO::needsTermination() 
1782         return fHasTerminators
; 
1786 void ImageLoaderMachO::doTermination(const LinkContext
& context
) 
1788         if ( fHasTerminators 
) { 
1789                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1790                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1791                 const struct load_command
* cmd 
= cmds
; 
1792                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1793                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1794                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1795                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1796                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1797                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1798                                         const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
1799                                         if ( type 
== S_MOD_TERM_FUNC_POINTERS 
) { 
1800                                                 Terminator
* terms 
= (Terminator
*)(sect
->addr 
+ fSlide
); 
1801                                                 const size_t count 
= sect
->size 
/ sizeof(uintptr_t); 
1802                                                 for (size_t i
=count
; i 
> 0; --i
) { 
1803                                                         Terminator func 
= terms
[i
-1]; 
1804                                                         // <rdar://problem/8543820&9228031> verify terminators are in image 
1805                                                         if ( ! this->containsAddress((void*)func
) ) { 
1806                                                                 dyld::throwf("termination function %p not in mapped image for %s\n", func
, this->getPath()); 
1808                                                         if ( context
.verboseInit 
) 
1809                                                                 dyld::log("dyld: calling termination function %p in %s\n", func
, this->getPath()); 
1815                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1821 void ImageLoaderMachO::printStatistics(unsigned int imageCount
, const InitializerTimingList
& timingInfo
) 
1823         ImageLoader::printStatistics(imageCount
, timingInfo
); 
1824         dyld::log("total symbol trie searches:    %d\n", fgSymbolTrieSearchs
); 
1825         dyld::log("total symbol table binary searches:    %d\n", fgSymbolTableBinarySearchs
); 
1826         dyld::log("total images defining weak symbols:  %u\n", fgImagesHasWeakDefinitions
); 
1827         dyld::log("total images using weak symbols:  %u\n", fgImagesRequiringCoalescing
); 
1831 intptr_t ImageLoaderMachO::assignSegmentAddresses(const LinkContext
& context
) 
1833         // preflight and calculate slide if needed 
1834         const bool inPIE 
= (fgNextPIEDylibAddress 
!= 0); 
1836         if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) { 
1837                 bool needsToSlide 
= false; 
1838                 bool imageHasPreferredLoadAddress 
= segHasPreferredLoadAddress(0); 
1839                 uintptr_t lowAddr 
= (unsigned long)(-1); 
1840                 uintptr_t highAddr 
= 0; 
1841                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1842                         const uintptr_t segLow 
= segPreferredLoadAddress(i
); 
1843                         const uintptr_t segHigh 
= dyld_page_round(segLow 
+ segSize(i
)); 
1844                         if ( segLow 
< highAddr 
) { 
1845                                 if ( dyld_page_size 
> 4096 ) 
1846                                         dyld::throwf("can't map segments into 16KB pages"); 
1848                                         dyld::throwf("overlapping segments"); 
1850                         if ( segLow 
< lowAddr 
) 
1852                         if ( segHigh 
> highAddr 
) 
1855                         if ( needsToSlide 
|| !imageHasPreferredLoadAddress 
|| inPIE 
|| !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) ) 
1856                                 needsToSlide 
= true; 
1858                 if ( needsToSlide 
) { 
1859                         // find a chunk of address space to hold all segments 
1860                         uintptr_t addr 
= reserveAnAddressRange(highAddr
-lowAddr
, context
); 
1861                         slide 
= addr 
- lowAddr
; 
1864         else if ( ! this->segmentsCanSlide() ) { 
1865                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1866                         if ( strcmp(segName(i
), "__PAGEZERO") == 0 ) 
1868                         if ( !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) ) 
1869                                 dyld::throwf("can't map unslidable segment %s to 0x%lX with size 0x%lX", segName(i
), segPreferredLoadAddress(i
), segSize(i
)); 
1873                 throw "mach-o does not support independently sliding segments"; 
1879 uintptr_t ImageLoaderMachO::reserveAnAddressRange(size_t length
, const ImageLoader::LinkContext
& context
) 
1881         vm_address_t addr 
= 0; 
1882         vm_size_t size 
= length
; 
1883         // in PIE programs, load initial dylibs after main executable so they don't have fixed addresses either 
1884         if ( fgNextPIEDylibAddress 
!= 0 ) { 
1885                  // add small (0-3 pages) random padding between dylibs 
1886                 addr 
= fgNextPIEDylibAddress 
+ (__stack_chk_guard
/fgNextPIEDylibAddress 
& (sizeof(long)-1))*dyld_page_size
; 
1887                 //dyld::log("padding 0x%08llX, guard=0x%08llX\n", (long long)(addr - fgNextPIEDylibAddress), (long long)(__stack_chk_guard)); 
1888                 kern_return_t r 
= vm_alloc(&addr
, size
, VM_FLAGS_FIXED 
| VM_MAKE_TAG(VM_MEMORY_DYLIB
)); 
1889                 if ( r 
== KERN_SUCCESS 
) { 
1890                         fgNextPIEDylibAddress 
= addr 
+ size
; 
1893                 fgNextPIEDylibAddress 
= 0; 
1895         kern_return_t r 
= vm_alloc(&addr
, size
, VM_FLAGS_ANYWHERE 
| VM_MAKE_TAG(VM_MEMORY_DYLIB
)); 
1896         if ( r 
!= KERN_SUCCESS 
)  
1897                 throw "out of address space"; 
1902 bool ImageLoaderMachO::reserveAddressRange(uintptr_t start
, size_t length
) 
1904         vm_address_t addr 
= start
; 
1905         vm_size_t size 
= length
; 
1906         kern_return_t r 
= vm_alloc(&addr
, size
, VM_FLAGS_FIXED 
| VM_MAKE_TAG(VM_MEMORY_DYLIB
)); 
1907         if ( r 
!= KERN_SUCCESS 
)  
1914 void ImageLoaderMachO::mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
) 
1916         // find address range for image 
1917         intptr_t slide 
= this->assignSegmentAddresses(context
); 
1918         if ( context
.verboseMapping 
) { 
1919                 if ( offsetInFat 
!= 0 ) 
1920                         dyld::log("dyld: Mapping %s (slice offset=%llu)\n", this->getPath(), (unsigned long long)offsetInFat
); 
1922                         dyld::log("dyld: Mapping %s\n", this->getPath()); 
1924         // map in all segments 
1925         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1926                 vm_offset_t fileOffset 
= segFileOffset(i
) + offsetInFat
; 
1927                 vm_size_t size 
= segFileSize(i
); 
1928                 uintptr_t requestedLoadAddress 
= segPreferredLoadAddress(i
) + slide
; 
1930                 if ( !segUnaccessible(i
) ) { 
1931                         // If has text-relocs, don't set x-bit initially. 
1932                         // Instead set it later after text-relocs have been done. 
1933                         if ( segExecutable(i
) && !(segHasRebaseFixUps(i
) && (slide 
!= 0)) ) 
1934                                 protection   
|= PROT_EXEC
; 
1935                         if ( segReadable(i
) ) 
1936                                 protection   
|= PROT_READ
; 
1937                         if ( segWriteable(i
) ) 
1938                                 protection   
|= PROT_WRITE
; 
1941                 // initially map __IMPORT segments R/W so dyld can update them 
1942                 if ( segIsReadOnlyImport(i
) ) 
1943                         protection 
|= PROT_WRITE
; 
1945                 // wholly zero-fill segments have nothing to mmap() in 
1947                         if ( (fileOffset
+size
) > fileLen 
) { 
1948                                 dyld::throwf("truncated mach-o error: segment %s extends to %llu which is past end of file %llu",  
1949                                                                 segName(i
), (uint64_t)(fileOffset
+size
), fileLen
); 
1951                         void* loadAddress 
= xmmap((void*)requestedLoadAddress
, size
, protection
, MAP_FIXED 
| MAP_PRIVATE
, fd
, fileOffset
); 
1952                         if ( loadAddress 
== ((void*)(-1)) ) { 
1953                                 dyld::throwf("mmap() error %d at address=0x%08lX, size=0x%08lX segment=%s in Segment::map() mapping %s",  
1954                                         errno
, requestedLoadAddress
, (uintptr_t)size
, segName(i
), getPath()); 
1958                 ++ImageLoader::fgTotalSegmentsMapped
; 
1959                 ImageLoader::fgTotalBytesMapped 
+= size
; 
1960                 if ( context
.verboseMapping 
) 
1961                         dyld::log("%18s at 0x%08lX->0x%08lX with permissions %c%c%c\n", segName(i
), requestedLoadAddress
, requestedLoadAddress
+size
-1, 
1962                                 (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' ); 
1965         // update slide to reflect load location                         
1966         this->setSlide(slide
); 
1969 void ImageLoaderMachO::mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
) 
1971         // find address range for image 
1972         intptr_t slide 
= this->assignSegmentAddresses(context
); 
1973         if ( context
.verboseMapping 
) 
1974                 dyld::log("dyld: Mapping memory %p\n", memoryImage
); 
1975         // map in all segments 
1976         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1977                 vm_address_t loadAddress 
= segPreferredLoadAddress(i
) + slide
; 
1978                 vm_address_t srcAddr 
= (uintptr_t)memoryImage 
+ segFileOffset(i
); 
1979                 vm_size_t size 
= segFileSize(i
); 
1980                 kern_return_t r 
= vm_copy(mach_task_self(), srcAddr
, size
, loadAddress
); 
1981                 if ( r 
!= KERN_SUCCESS 
)  
1982                         throw "can't map segment"; 
1983                 if ( context
.verboseMapping 
) 
1984                         dyld::log("%18s at 0x%08lX->0x%08lX\n", segName(i
), (uintptr_t)loadAddress
, (uintptr_t)loadAddress
+size
-1); 
1986         // update slide to reflect load location                         
1987         this->setSlide(slide
); 
1988         // set R/W permissions on all segments at slide location 
1989         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1990                 segProtect(i
, context
);          
1995 void ImageLoaderMachO::segProtect(unsigned int segIndex
, const ImageLoader::LinkContext
& context
) 
1997         vm_prot_t protection 
= 0; 
1998         if ( !segUnaccessible(segIndex
) ) { 
1999                 if ( segExecutable(segIndex
) ) 
2000                         protection   
|= PROT_EXEC
; 
2001                 if ( segReadable(segIndex
) ) 
2002                         protection   
|= PROT_READ
; 
2003                 if ( segWriteable(segIndex
) ) 
2004                         protection   
|= PROT_WRITE
; 
2006         vm_address_t addr 
= segActualLoadAddress(segIndex
); 
2007         vm_size_t size 
= segSize(segIndex
); 
2008         const bool setCurrentPermissions 
= false; 
2009         kern_return_t r 
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
); 
2010         if ( r 
!= KERN_SUCCESS 
) { 
2011         dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s", 
2012             (long long)addr
, (long long)size
, protection
, r
, segName(segIndex
), this->getPath()); 
2014         if ( context
.verboseMapping 
) { 
2015                 dyld::log("%18s at 0x%08lX->0x%08lX altered permissions to %c%c%c\n", segName(segIndex
), (uintptr_t)addr
, (uintptr_t)addr
+size
-1, 
2016                         (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' ); 
2020 void ImageLoaderMachO::segMakeWritable(unsigned int segIndex
, const ImageLoader::LinkContext
& context
) 
2022         vm_address_t addr 
= segActualLoadAddress(segIndex
); 
2023         vm_size_t size 
= segSize(segIndex
); 
2024         const bool setCurrentPermissions 
= false; 
2025         vm_prot_t protection 
= VM_PROT_WRITE 
| VM_PROT_READ
; 
2026         if ( segExecutable(segIndex
) && !segHasRebaseFixUps(segIndex
) ) 
2027                 protection 
|= VM_PROT_EXECUTE
; 
2028         kern_return_t r 
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
); 
2029         if ( r 
!= KERN_SUCCESS 
) { 
2030         dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s", 
2031             (long long)addr
, (long long)size
, protection
, r
, segName(segIndex
), this->getPath()); 
2033         if ( context
.verboseMapping 
) { 
2034                 dyld::log("%18s at 0x%08lX->0x%08lX altered permissions to %c%c%c\n", segName(segIndex
), (uintptr_t)addr
, (uintptr_t)addr
+size
-1, 
2035                         (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' );