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 <libkern/OSAtomic.h> 
  44 #include <libkern/OSCacheControl.h> 
  47 #include "ImageLoaderMachO.h" 
  48 #include "ImageLoaderMachOCompressed.h" 
  49 #include "ImageLoaderMachOClassic.h" 
  50 #include "mach-o/dyld_images.h" 
  52 // <rdar://problem/8718137> use stack guard random value to add padding between dylibs 
  53 extern "C" long __stack_chk_guard
; 
  55 #ifndef LC_LOAD_UPWARD_DYLIB 
  56         #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */ 
  59 // relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables 
  61         #define LC_SEGMENT_COMMAND              LC_SEGMENT_64 
  62         #define LC_ROUTINES_COMMAND             LC_ROUTINES_64 
  63         struct macho_segment_command    
: public segment_command_64  
{}; 
  64         struct macho_section                    
: public section_64  
{};         
  65         struct macho_routines_command   
: public routines_command_64  
{};        
  67         #define LC_SEGMENT_COMMAND              LC_SEGMENT 
  68         #define LC_ROUTINES_COMMAND             LC_ROUTINES 
  69         struct macho_segment_command    
: public segment_command 
{}; 
  70         struct macho_section                    
: public section  
{};    
  71         struct macho_routines_command   
: public routines_command  
{};   
  74 uint32_t ImageLoaderMachO::fgSymbolTableBinarySearchs 
= 0; 
  75 uint32_t ImageLoaderMachO::fgSymbolTrieSearchs 
= 0; 
  78 ImageLoaderMachO::ImageLoaderMachO(const macho_header
* mh
, const char* path
, unsigned int segCount
,  
  79                                                                                                                                 uint32_t segOffsets
[], unsigned int libCount
) 
  80  : ImageLoader(path
, libCount
), fMachOData((uint8_t*)mh
), fLinkEditBase(NULL
), fSlide(0),  
  81         fEHFrameSectionOffset(0), fUnwindInfoSectionOffset(0), fDylibIDOffset(0),  
  82         fSegmentsCount(segCount
), fIsSplitSeg(false), fInSharedCache(false),   
  83 #if TEXT_RELOC_SUPPORT 
  84         fTextSegmentRebases(false), 
  85         fTextSegmentBinds(false), 
  88         fReadOnlyImportSegment(false), 
  90         fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false), 
  91         fHasInitializers(false), fHasTerminators(false), fRegisteredAsRequiresCoalescing(false) 
  93         fIsSplitSeg 
= ((mh
->flags 
& MH_SPLIT_SEGS
) != 0);         
  95         // construct SegmentMachO object for each LC_SEGMENT cmd using "placement new" to put  
  96         // each SegmentMachO object in array at end of ImageLoaderMachO object 
  97         const uint32_t cmd_count 
= mh
->ncmds
; 
  98         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
  99         const struct load_command
* cmd 
= cmds
; 
 100         for (uint32_t i 
= 0, segIndex
=0; i 
< cmd_count
; ++i
) { 
 101                 if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
 102                         const struct macho_segment_command
* segCmd 
= (struct macho_segment_command
*)cmd
; 
 103                         // ignore zero-sized segments 
 104                         if ( segCmd
->vmsize 
!= 0 ) { 
 105                                 // record offset of load command 
 106                                 segOffsets
[segIndex
++] = (uint8_t*)segCmd 
- fMachOData
; 
 109                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 115 // determine if this mach-o file has classic or compressed LINKEDIT and number of segments it has 
 116 void ImageLoaderMachO::sniffLoadCommands(const macho_header
* mh
, const char* path
, bool* compressed
,  
 117                                                                                         unsigned int* segCount
, unsigned int* libCount
, 
 118                                                                                         const linkedit_data_command
** codeSigCmd
) 
 124         struct macho_segment_command
* segCmd
; 
 125 #if CODESIGNING_SUPPORT 
 126         bool foundLoadCommandSegment 
= false; 
 128         const uint32_t cmd_count 
= mh
->ncmds
; 
 129         const struct load_command
* const startCmds    
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
)); 
 130         const struct load_command
* const endCmds 
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
) + mh
->sizeofcmds
); 
 131         const struct load_command
* cmd 
= startCmds
; 
 132         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 135                         case LC_DYLD_INFO_ONLY
: 
 138                         case LC_SEGMENT_COMMAND
: 
 139                                 segCmd 
= (struct macho_segment_command
*)cmd
; 
 140                                 // ignore zero-sized segments 
 141                                 if ( segCmd
->vmsize 
!= 0 ) 
 143 #if CODESIGNING_SUPPORT 
 144                                 // <rdar://problem/7942521> all load commands must be in an executable segment 
 145                                 if ( (segCmd
->fileoff 
< mh
->sizeofcmds
) && (segCmd
->filesize 
!= 0) ) { 
 146                                         if ( (segCmd
->fileoff 
!= 0) || (segCmd
->filesize 
< (mh
->sizeofcmds
+sizeof(macho_header
))) )  
 147                                                 dyld::throwf("malformed mach-o image: segment %s does not span all load commands", segCmd
->segname
);  
 148                                         if ( segCmd
->initprot 
!= (VM_PROT_READ 
| VM_PROT_EXECUTE
) )  
 149                                                 dyld::throwf("malformed mach-o image: load commands found in segment %s with wrong permissions", segCmd
->segname
);  
 150                                         foundLoadCommandSegment 
= true; 
 155                         case LC_LOAD_WEAK_DYLIB
: 
 156                         case LC_REEXPORT_DYLIB
: 
 157                         case LC_LOAD_UPWARD_DYLIB
: 
 160                         case LC_CODE_SIGNATURE
: 
 161                                 *codeSigCmd 
= (struct linkedit_data_command
*)cmd
; // only support one LC_CODE_SIGNATURE per image 
 164                 uint32_t cmdLength 
= cmd
->cmdsize
; 
 165                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmdLength
); 
 166                 if ( (cmd 
> endCmds
) || (cmd 
< startCmds
) ) { 
 167                         dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s",  
 168                                                         i
, cmdLength
, mh
->sizeofcmds
, path
); 
 172 #if CODESIGNING_SUPPORT 
 173         if ( ! foundLoadCommandSegment 
) 
 174                 throw "load commands not in a segment"; 
 177         // fSegmentsArrayCount is only 8-bits 
 178         if ( *segCount 
> 255 ) 
 179                 dyld::throwf("malformed mach-o image: more than 255 segments in %s", path
); 
 181         // fSegmentsArrayCount is only 8-bits 
 182         if ( *libCount 
> 4095 ) 
 183                 dyld::throwf("malformed mach-o image: more than 4095 dependent libraries in %s", path
); 
 185         if ( needsAddedLibSystemDepency(*libCount
, mh
) ) 
 191 // create image for main executable 
 192 ImageLoader
* ImageLoaderMachO::instantiateMainExecutable(const macho_header
* mh
, uintptr_t slide
, const char* path
, const LinkContext
& context
) 
 194         //dyld::log("ImageLoader=%ld, ImageLoaderMachO=%ld, ImageLoaderMachOClassic=%ld, ImageLoaderMachOCompressed=%ld\n", 
 195         //      sizeof(ImageLoader), sizeof(ImageLoaderMachO), sizeof(ImageLoaderMachOClassic), sizeof(ImageLoaderMachOCompressed)); 
 197         unsigned int segCount
; 
 198         unsigned int libCount
; 
 199         const linkedit_data_command
* codeSigCmd
; 
 200         sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
, &codeSigCmd
); 
 201         // instantiate concrete class based on content of load commands 
 203                 return ImageLoaderMachOCompressed::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
); 
 205                 return ImageLoaderMachOClassic::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
); 
 209 // create image by mapping in a mach-o file 
 210 ImageLoader
* ImageLoaderMachO::instantiateFromFile(const char* path
, int fd
, const uint8_t firstPage
[4096], uint64_t offsetInFat
,  
 211                                                                         uint64_t lenInFat
, const struct stat
& info
, const LinkContext
& context
) 
 214         const unsigned int dataSize 
= sizeof(macho_header
) + ((macho_header
*)firstPage
)->sizeofcmds
; 
 215         uint8_t buffer
[dataSize
]; 
 216         const uint8_t* fileData 
= firstPage
; 
 217         if ( dataSize 
> 4096 ) { 
 218                 // only read more if cmds take up more space than first page 
 220                 memcpy(buffer
, firstPage
, 4096); 
 221                 pread(fd
, &buffer
[4096], dataSize
-4096, offsetInFat
+4096); 
 225         unsigned int segCount
; 
 226         unsigned int libCount
; 
 227         const linkedit_data_command
* codeSigCmd
; 
 228         sniffLoadCommands((const macho_header
*)fileData
, path
, &compressed
, &segCount
, &libCount
, &codeSigCmd
); 
 229         // instantiate concrete class based on content of load commands 
 231                 return ImageLoaderMachOCompressed::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, codeSigCmd
, context
); 
 233                 return ImageLoaderMachOClassic::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, codeSigCmd
, context
); 
 236 // create image by using cached mach-o file 
 237 ImageLoader
* ImageLoaderMachO::instantiateFromCache(const macho_header
* mh
, const char* path
, long slide
, const struct stat
& info
, const LinkContext
& context
) 
 239         // instantiate right concrete class 
 241         unsigned int segCount
; 
 242         unsigned int libCount
; 
 243         const linkedit_data_command
* codeSigCmd
; 
 244         sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
, &codeSigCmd
); 
 245         // instantiate concrete class based on content of load commands 
 247                 return ImageLoaderMachOCompressed::instantiateFromCache(mh
, path
, slide
, info
, segCount
, libCount
, context
); 
 249                 return ImageLoaderMachOClassic::instantiateFromCache(mh
, path
, slide
, info
, segCount
, libCount
, context
); 
 252 // create image by copying an in-memory mach-o file 
 253 ImageLoader
* ImageLoaderMachO::instantiateFromMemory(const char* moduleName
, const macho_header
* mh
, uint64_t len
, const LinkContext
& context
) 
 256         unsigned int segCount
; 
 257         unsigned int libCount
; 
 258         const linkedit_data_command
* sigcmd
; 
 259         sniffLoadCommands(mh
, moduleName
, &compressed
, &segCount
, &libCount
, &sigcmd
); 
 260         // instantiate concrete class based on content of load commands 
 262                 return ImageLoaderMachOCompressed::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
); 
 264                 return ImageLoaderMachOClassic::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
); 
 269 void ImageLoaderMachO::parseLoadCmds() 
 271         // now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide 
 272         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
 273                 // set up pointer to __LINKEDIT segment 
 274                 if ( strcmp(segName(i
),"__LINKEDIT") == 0 )  
 275                         fLinkEditBase 
= (uint8_t*)(segActualLoadAddress(i
) - segFileOffset(i
)); 
 276 #if TEXT_RELOC_SUPPORT 
 277                 // __TEXT segment always starts at beginning of file and contains mach_header and load commands 
 278                 if ( strcmp(segName(i
),"__TEXT") == 0 ) { 
 279                         if ( segHasRebaseFixUps(i
) && (fSlide 
!= 0) ) 
 280                                 fTextSegmentRebases 
= true; 
 281                         if ( segHasBindFixUps(i
) ) 
 282                                 fTextSegmentBinds 
= true; 
 286                 if ( segIsReadOnlyImport(i
) ) 
 287                         fReadOnlyImportSegment 
= true; 
 289                 // some segment always starts at beginning of file and contains mach_header and load commands 
 290                 if ( (segFileOffset(i
) == 0) && (segFileSize(i
) != 0) ) { 
 291                         fMachOData 
= (uint8_t*)(segActualLoadAddress(i
)); 
 295         // keep count of prebound images with weak exports 
 296         if ( this->participatesInCoalescing() ) { 
 297                 ++fgImagesRequiringCoalescing
; 
 298                 fRegisteredAsRequiresCoalescing 
= true; 
 299                 if ( this->hasCoalescedExports() )  
 300                         ++fgImagesHasWeakDefinitions
; 
 303         // keep count of images used in shared cache 
 304         if ( fInSharedCache 
) 
 305                 ++fgImagesUsedFromSharedCache
; 
 307         // walk load commands (mapped in at start of __TEXT segment) 
 308         const dyld_info_command
* dyldInfo 
= NULL
; 
 309         const macho_nlist
* symbolTable 
= NULL
; 
 310         const char* symbolTableStrings 
= NULL
; 
 311         const struct load_command
* firstUnknownCmd 
= NULL
; 
 312         const struct version_min_command
* minOSVersionCmd 
= NULL
; 
 313         const dysymtab_command
* dynSymbolTable 
= NULL
; 
 314         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 315         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 316         const struct load_command
* cmd 
= cmds
; 
 317         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 321                                         const struct symtab_command
* symtab 
= (struct symtab_command
*)cmd
; 
 322                                         symbolTableStrings 
= (const char*)&fLinkEditBase
[symtab
->stroff
]; 
 323                                         symbolTable 
= (macho_nlist
*)(&fLinkEditBase
[symtab
->symoff
]); 
 327                                 dynSymbolTable 
= (struct dysymtab_command
*)cmd
; 
 329                         case LC_SUB_UMBRELLA
: 
 330                                 fHasSubUmbrella 
= true; 
 332                         case LC_SUB_FRAMEWORK
: 
 336                                 fHasSubLibraries 
= true; 
 338                         case LC_ROUTINES_COMMAND
: 
 342                         case LC_DYLD_INFO_ONLY
: 
 343                                 dyldInfo 
= (struct dyld_info_command
*)cmd
; 
 345                         case LC_SEGMENT_COMMAND
: 
 347                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
 348                                         const bool isTextSeg 
= (strcmp(seg
->segname
, "__TEXT") == 0); 
 349                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
 350                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
 351                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 352                                                 const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
 353                                                 if ( type 
== S_MOD_INIT_FUNC_POINTERS 
) 
 354                                                         fHasInitializers 
= true; 
 355                                                 else if ( type 
== S_MOD_TERM_FUNC_POINTERS 
) 
 356                                                         fHasTerminators 
= true; 
 357                                                 else if ( type 
== S_DTRACE_DOF 
) 
 358                                                         fHasDOFSections 
= true; 
 359                                                 else if ( isTextSeg 
&& (strcmp(sect
->sectname
, "__eh_frame") == 0) ) 
 360                                                         fEHFrameSectionOffset 
= (uint8_t*)sect 
- fMachOData
; 
 361                                                 else if ( isTextSeg 
&& (strcmp(sect
->sectname
, "__unwind_info") == 0) ) 
 362                                                         fUnwindInfoSectionOffset 
= (uint8_t*)sect 
- fMachOData
;; 
 366                         case LC_TWOLEVEL_HINTS
: 
 367                                 // no longer supported 
 371                                         fDylibIDOffset 
= (uint8_t*)cmd 
- fMachOData
; 
 375                         case LC_LOAD_WEAK_DYLIB
: 
 376                     case LC_REEXPORT_DYLIB
: 
 377                         case LC_LOAD_UPWARD_DYLIB
: 
 379                                 // do nothing, just prevent LC_REQ_DYLD exception from occuring 
 381                         case LC_VERSION_MIN_MACOSX
: 
 382                         case LC_VERSION_MIN_IPHONEOS
: 
 383                                 minOSVersionCmd 
= (version_min_command
*)cmd
; 
 386                                 if ( (cmd
->cmd 
& LC_REQ_DYLD
) != 0 ) { 
 387                                         if ( firstUnknownCmd 
== NULL 
) 
 388                                                 firstUnknownCmd 
= cmd
; 
 392                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 394         if ( firstUnknownCmd 
!= NULL 
) { 
 395                 if ( minOSVersionCmd 
!= NULL 
)  { 
 396                         dyld::throwf("cannot load '%s' because it was built for OS version %u.%u (load command 0x%08X is unknown)",  
 397                                                  this->getShortName(), 
 398                                                  minOSVersionCmd
->version 
>> 16, ((minOSVersionCmd
->version 
>> 8) & 0xff),  
 399                                                  firstUnknownCmd
->cmd
); 
 402                         dyld::throwf("cannot load '%s' (load command 0x%08X is unknown)", this->getShortName(), firstUnknownCmd
->cmd
); 
 407         if ( dyldInfo 
!= NULL 
) 
 408                 this->setDyldInfo(dyldInfo
); 
 409         if ( symbolTable 
!= NULL
) 
 410                 this->setSymbolTableInfo(symbolTable
, symbolTableStrings
, dynSymbolTable
); 
 414 // don't do this work in destructor because we need object to be full subclass 
 415 // for UnmapSegments() to work 
 416 void ImageLoaderMachO::destroy() 
 418         // update count of images with weak exports 
 419         if ( fRegisteredAsRequiresCoalescing 
) { 
 420                 --fgImagesRequiringCoalescing
; 
 421                 if ( this->hasCoalescedExports() )  
 422                         --fgImagesHasWeakDefinitions
; 
 425         // keep count of images used in shared cache 
 426         if ( fInSharedCache 
) 
 427                 --fgImagesUsedFromSharedCache
; 
 429         // unmap image when done 
 434 unsigned int ImageLoaderMachO::segmentCount() const 
 436         return fSegmentsCount
; 
 440 const macho_segment_command
* ImageLoaderMachO::segLoadCommand(unsigned int segIndex
) const 
 442         uint32_t* lcOffsets 
= this->segmentCommandOffsets(); 
 443         uint32_t lcOffset 
=     lcOffsets
[segIndex
]; 
 444         return (macho_segment_command
*)(&fMachOData
[lcOffset
]); 
 447 const char*     ImageLoaderMachO::segName(unsigned int segIndex
) const 
 449         return segLoadCommand(segIndex
)->segname
; 
 453 uintptr_t ImageLoaderMachO::segSize(unsigned int segIndex
) const 
 455         return segLoadCommand(segIndex
)->vmsize
; 
 459 uintptr_t ImageLoaderMachO::segFileSize(unsigned int segIndex
) const 
 461         return segLoadCommand(segIndex
)->filesize
; 
 465 bool ImageLoaderMachO::segHasTrailingZeroFill(unsigned int segIndex
) 
 467         return ( segWriteable(segIndex
) && (segSize(segIndex
) > segFileSize(segIndex
)) ); 
 471 uintptr_t ImageLoaderMachO::segFileOffset(unsigned int segIndex
) const 
 473         return segLoadCommand(segIndex
)->fileoff
; 
 477 bool ImageLoaderMachO::segReadable(unsigned int segIndex
) const 
 479         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_READ
) != 0); 
 483 bool ImageLoaderMachO::segWriteable(unsigned int segIndex
) const 
 485         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_WRITE
) != 0); 
 489 bool ImageLoaderMachO::segExecutable(unsigned int segIndex
) const 
 491         return ( (segLoadCommand(segIndex
)->initprot 
& VM_PROT_EXECUTE
) != 0); 
 495 bool ImageLoaderMachO::segUnaccessible(unsigned int segIndex
) const 
 497         return (segLoadCommand(segIndex
)->initprot 
== 0); 
 500 bool ImageLoaderMachO::segHasPreferredLoadAddress(unsigned int segIndex
) const 
 502         return (segLoadCommand(segIndex
)->vmaddr 
!= 0); 
 505 uintptr_t ImageLoaderMachO::segPreferredLoadAddress(unsigned int segIndex
) const 
 507         return segLoadCommand(segIndex
)->vmaddr
; 
 510 uintptr_t ImageLoaderMachO::segActualLoadAddress(unsigned int segIndex
) const 
 512         return segLoadCommand(segIndex
)->vmaddr 
+ fSlide
; 
 516 uintptr_t ImageLoaderMachO::segActualEndAddress(unsigned int segIndex
) const 
 518         return segActualLoadAddress(segIndex
) + segSize(segIndex
); 
 521 bool ImageLoaderMachO::segHasRebaseFixUps(unsigned int segIndex
) const 
 523         // scan sections for fix-up bit 
 524         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 525         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)segCmd 
+ sizeof(struct macho_segment_command
)); 
 526         const struct macho_section
* const sectionsEnd 
= §ionsStart
[segCmd
->nsects
]; 
 527         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 528                 if ( (sect
->flags 
& S_ATTR_LOC_RELOC
) != 0 ) 
 534 bool ImageLoaderMachO::segHasBindFixUps(unsigned int segIndex
) const 
 536         // scan sections for fix-up bit 
 537         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 538         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)segCmd 
+ sizeof(struct macho_segment_command
)); 
 539         const struct macho_section
* const sectionsEnd 
= §ionsStart
[segCmd
->nsects
]; 
 540         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 541                 if ( (sect
->flags 
& S_ATTR_EXT_RELOC
) != 0 ) 
 548 bool ImageLoaderMachO::segIsReadOnlyImport(unsigned int segIndex
) const 
 550         const macho_segment_command
* segCmd 
= segLoadCommand(segIndex
); 
 551         return (    (segCmd
->initprot 
& VM_PROT_EXECUTE
)  
 552                         && ((segCmd
->initprot 
& VM_PROT_WRITE
) == 0)  
 553                         && (strcmp(segCmd
->segname
, "__IMPORT") == 0) ); 
 558 void ImageLoaderMachO::UnmapSegments() 
 560         // usually unmap image when done 
 561         if ( ! this->leaveMapped() && (this->getState() >= dyld_image_state_mapped
) ) { 
 562                 // unmap TEXT segment last because it contains load command being inspected 
 563                 unsigned int textSegmentIndex 
= 0; 
 564                 for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
 565                         //dyld::log("unmap %s at 0x%08lX\n", seg->getName(), seg->getActualLoadAddress(this)); 
 566                         if ( strcmp(segName(i
), "__TEXT") == 0 ) { 
 567                                 textSegmentIndex 
= i
; 
 571                                 --ImageLoader::fgTotalSegmentsMapped
; 
 572                                 ImageLoader::fgTotalBytesMapped 
-= segSize(i
); 
 573                                 munmap((void*)segActualLoadAddress(i
), segSize(i
)); 
 577                 --ImageLoader::fgTotalSegmentsMapped
; 
 578                 ImageLoader::fgTotalBytesMapped 
-= segSize(textSegmentIndex
); 
 579                 munmap((void*)segActualLoadAddress(textSegmentIndex
), segSize(textSegmentIndex
)); 
 584 // prefetch __DATA/__OBJC pages during launch, but not for dynamically loaded code 
 585 void ImageLoaderMachO::preFetchDATA(int fd
, uint64_t offsetInFat
, const LinkContext
& context
) 
 587         if ( context
.linkingMainExecutable 
) { 
 588                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
 589                         if ( segWriteable(i
) && (segFileSize(i
) > 0) ) { 
 590                                 // prefetch writable segment that have mmap'ed regions 
 592                                 advice
.ra_offset 
= offsetInFat 
+ segFileOffset(i
); 
 593                                 advice
.ra_count 
= segFileSize(i
); 
 594                                 // limit prefetch to 1MB (256 pages) 
 595                                 if ( advice
.ra_count 
> 1024*1024 ) 
 596                                         advice
.ra_count 
= 1024*1024; 
 597                                 // don't prefetch single pages, let them fault in 
 598                                 fgTotalBytesPreFetched 
+= advice
.ra_count
; 
 599                                 fcntl(fd
, F_RDADVISE
, &advice
); 
 600                                 if ( context
.verboseMapping 
) { 
 601                                         dyld::log("%18s prefetching 0x%0lX -> 0x%0lX\n",  
 602                                                 segName(i
), segActualLoadAddress(i
), segActualLoadAddress(i
)+advice
.ra_count
-1); 
 610 bool ImageLoaderMachO::segmentsMustSlideTogether() const  
 615 bool ImageLoaderMachO::segmentsCanSlide() const  
 617         return (this->isDylib() || this->isBundle() || this->isPositionIndependentExecutable()); 
 620 bool ImageLoaderMachO::isBundle() const  
 622         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 623         return ( mh
->filetype 
== MH_BUNDLE 
); 
 626 bool ImageLoaderMachO::isDylib() const  
 628         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 629         return ( mh
->filetype 
== MH_DYLIB 
); 
 632 bool ImageLoaderMachO::isExecutable() const  
 634         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 635         return ( mh
->filetype 
== MH_EXECUTE 
); 
 638 bool ImageLoaderMachO::isPositionIndependentExecutable() const  
 640         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 641         return ( (mh
->filetype 
== MH_EXECUTE
) && ((mh
->flags 
& MH_PIE
) != 0) ); 
 645 bool ImageLoaderMachO::forceFlat() const  
 647         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 648         return ( (mh
->flags 
& MH_FORCE_FLAT
) != 0 ); 
 651 bool ImageLoaderMachO::usesTwoLevelNameSpace() const 
 653         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 654         return ( (mh
->flags 
& MH_TWOLEVEL
) != 0 ); 
 657 bool ImageLoaderMachO::isPrebindable() const  
 659         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 660         return ( (mh
->flags 
& MH_PREBOUND
) != 0 ); 
 663 bool ImageLoaderMachO::hasCoalescedExports() const  
 665         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 666         return ( (mh
->flags 
& MH_WEAK_DEFINES
) != 0 ); 
 669 bool ImageLoaderMachO::hasReferencesToWeakSymbols() const  
 671         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 672         return ( (mh
->flags 
& MH_BINDS_TO_WEAK
) != 0 ); 
 675 bool ImageLoaderMachO::participatesInCoalescing() const  
 677         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
 678         // if image is loaded with RTLD_LOCAL, then its symbols' visibility 
 679         // is reduced and it can't coalesce with other images 
 680         if ( this->hasHiddenExports() ) 
 682         return ( (mh
->flags 
& (MH_WEAK_DEFINES
|MH_BINDS_TO_WEAK
)) != 0 ); 
 687 void ImageLoaderMachO::setSlide(intptr_t slide
) 
 692 #if CODESIGNING_SUPPORT 
 693 void ImageLoaderMachO::loadCodeSignature(const struct linkedit_data_command
* codeSigCmd
, int fd
,  uint64_t offsetInFatFile
) 
 695         fsignatures_t siginfo
; 
 696         siginfo
.fs_file_start
=offsetInFatFile
;                  // start of mach-o slice in fat file  
 697         siginfo
.fs_blob_start
=(void*)(codeSigCmd
->dataoff
);     // start of CD in mach-o file 
 698         siginfo
.fs_blob_size
=codeSigCmd
->datasize
;                      // size of CD 
 699         int result 
= fcntl(fd
, F_ADDFILESIGS
, &siginfo
); 
 701                 dyld::log("dyld: F_ADDFILESIGS failed for %s with errno=%d\n", this->getPath(), errno
); 
 702         //dyld::log("dyld: registered code signature for %s\n", this->getPath()); 
 707 const char* ImageLoaderMachO::getInstallPath() const 
 709         if ( fDylibIDOffset 
!= 0 ) { 
 710                 const dylib_command
* dylibID 
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]); 
 711                 return (char*)dylibID 
+ dylibID
->dylib
.name
.offset
; 
 716 void ImageLoaderMachO::registerInterposing() 
 718         // mach-o files advertise interposing by having a __DATA __interpose section 
 719         struct InterposeData 
{ uintptr_t replacement
; uintptr_t replacee
; }; 
 720         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 721         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 722         const struct load_command
* cmd 
= cmds
; 
 723         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 725                         case LC_SEGMENT_COMMAND
: 
 727                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
 728                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
 729                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
 730                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
 731                                                 if ( ((sect
->flags 
& SECTION_TYPE
) == S_INTERPOSING
) || ((strcmp(sect
->sectname
, "__interpose") == 0) && (strcmp(seg
->segname
, "__DATA") == 0)) ) { 
 732                                                         const InterposeData
* interposeArray 
= (InterposeData
*)(sect
->addr 
+ fSlide
); 
 733                                                         const unsigned int count 
= sect
->size 
/ sizeof(InterposeData
); 
 734                                                         for (uint32_t i
=0; i 
< count
; ++i
) { 
 735                                                                 ImageLoader::InterposeTuple tuple
; 
 736                                                                 tuple
.replacement               
= interposeArray
[i
].replacement
; 
 737                                                                 tuple
.replacementImage  
= this; 
 738                                                                 tuple
.replacee                  
= interposeArray
[i
].replacee
; 
 739                                                                 // <rdar://problem/7937695> verify that replacement is in this image 
 740                                                                 if ( this->containsAddress((void*)tuple
.replacement
) ) { 
 741                                                                         for (std::vector
<InterposeTuple
>::iterator it
=fgInterposingTuples
.begin(); it 
!= fgInterposingTuples
.end(); it
++) { 
 742                                                                                 if ( it
->replacee 
== tuple
.replacee 
) { 
 743                                                                                         tuple
.replacee 
= it
->replacement
; 
 746                                                                         ImageLoader::fgInterposingTuples
.push_back(tuple
); 
 754                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 758 void* ImageLoaderMachO::getThreadPC() const 
 760         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 761         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 762         const struct load_command
* cmd 
= cmds
; 
 763         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 764                 if ( cmd
->cmd 
== LC_MAIN 
) { 
 765                         entry_point_command
* mainCmd 
= (entry_point_command
*)cmd
; 
 766                         void* entry 
= (void*)(mainCmd
->entryoff 
+ (char*)fMachOData
); 
 767                         // <rdar://problem/8543820&9228031> verify entry point is in image 
 768                         if ( this->containsAddress(entry
) ) 
 771                                 throw "LC_MAIN entryoff is out of range"; 
 773                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 779 void* ImageLoaderMachO::getMain() const 
 781         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 782         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 783         const struct load_command
* cmd 
= cmds
; 
 784         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 789                                 const i386_thread_state_t
* registers 
= (i386_thread_state_t
*)(((char*)cmd
) + 16); 
 790                                 void* entry 
= (void*)(registers
->eip 
+ fSlide
); 
 792                                 const x86_thread_state64_t
* registers 
= (x86_thread_state64_t
*)(((char*)cmd
) + 16); 
 793                                 void* entry 
= (void*)(registers
->rip 
+ fSlide
); 
 795                                 const arm_thread_state_t
* registers 
= (arm_thread_state_t
*)(((char*)cmd
) + 16); 
 796                                 void* entry 
= (void*)(registers
->__pc 
+ fSlide
); 
 798                                 #warning need processor specific code 
 800                                 // <rdar://problem/8543820&9228031> verify entry point is in image 
 801                                 if ( this->containsAddress(entry
) ) { 
 807                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 809         throw "no valid entry point"; 
 812 bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount
, const macho_header
* mh
) 
 814         // <rdar://problem/6357561> ensure that every image depends on something which depends on libSystem 
 818         // <rdar://problem/6409800> dyld implicit-libSystem breaks valgrind 
 819         if ( mh
->filetype 
== MH_EXECUTE 
)  
 822         bool isNonOSdylib 
= false; 
 823         const uint32_t cmd_count 
= mh
->ncmds
; 
 824         const struct load_command
* const cmds 
= (struct load_command
*)((uint8_t*)mh
+sizeof(macho_header
)); 
 825         const struct load_command
* cmd 
= cmds
; 
 826         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 829                         case LC_LOAD_WEAK_DYLIB
: 
 830                         case LC_REEXPORT_DYLIB
: 
 831                         case LC_LOAD_UPWARD_DYLIB
: 
 835                                 const dylib_command
* dylibID 
= (dylib_command
*)cmd
; 
 836                                 const char* installPath 
= (char*)cmd 
+ dylibID
->dylib
.name
.offset
; 
 837                                 // It is OK for OS dylibs (libSystem or libmath or Rosetta shims) to have no dependents 
 838                                 // but all other dylibs must depend on libSystem for initialization to initialize libSystem first 
 839                                 // <rdar://problem/6497528> rosetta circular dependency spew 
 840                                 isNonOSdylib 
= ( (strncmp(installPath
, "/usr/lib/", 9) != 0) && (strncmp(installPath
, "/usr/libexec/oah/Shims", 9) != 0) ); 
 844                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 850 void ImageLoaderMachO::doGetDependentLibraries(DependentLibraryInfo libs
[]) 
 852         if ( needsAddedLibSystemDepency(libraryCount(), (macho_header
*)fMachOData
) ) { 
 853                 DependentLibraryInfo
* lib 
= &libs
[0]; 
 854                 lib
->name 
= "/usr/lib/libSystem.B.dylib"; 
 855                 lib
->info
.checksum 
= 0; 
 856                 lib
->info
.minVersion 
= 0; 
 857                 lib
->info
.maxVersion 
= 0; 
 858                 lib
->required 
= false; 
 859                 lib
->reExported 
= false; 
 864                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 865                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 866                 const struct load_command
* cmd 
= cmds
; 
 867                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 870                                 case LC_LOAD_WEAK_DYLIB
: 
 871                                 case LC_REEXPORT_DYLIB
: 
 872                                 case LC_LOAD_UPWARD_DYLIB
: 
 874                                         const struct dylib_command
* dylib 
= (struct dylib_command
*)cmd
; 
 875                                         DependentLibraryInfo
* lib 
= &libs
[index
++]; 
 876                                         lib
->name 
= (char*)cmd 
+ dylib
->dylib
.name
.offset
; 
 877                                         //lib->name = strdup((char*)cmd + dylib->dylib.name.offset); 
 878                                         lib
->info
.checksum 
= dylib
->dylib
.timestamp
; 
 879                                         lib
->info
.minVersion 
= dylib
->dylib
.compatibility_version
; 
 880                                         lib
->info
.maxVersion 
= dylib
->dylib
.current_version
; 
 881                                         lib
->required 
= (cmd
->cmd 
!= LC_LOAD_WEAK_DYLIB
); 
 882                                         lib
->reExported 
= (cmd
->cmd 
== LC_REEXPORT_DYLIB
); 
 883                                         lib
->upward 
= (cmd
->cmd 
== LC_LOAD_UPWARD_DYLIB
); 
 887                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 892 ImageLoader::LibraryInfo 
ImageLoaderMachO::doGetLibraryInfo() 
 895         if ( fDylibIDOffset 
!= 0 ) { 
 896                 const dylib_command
* dylibID 
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]); 
 897                 info
.minVersion 
= dylibID
->dylib
.compatibility_version
; 
 898                 info
.maxVersion 
= dylibID
->dylib
.current_version
; 
 899                 info
.checksum 
= dylibID
->dylib
.timestamp
; 
 909 void ImageLoaderMachO::getRPaths(const LinkContext
& context
, std::vector
<const char*>& paths
) const 
 911         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 912         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 913         const struct load_command
* cmd 
= cmds
; 
 914         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 917                                 const char* pathToAdd 
= NULL
; 
 918                                 const char* path 
= (char*)cmd 
+ ((struct rpath_command
*)cmd
)->path
.offset
; 
 919                                 if ( strncmp(path
, "@loader_path/", 13) == 0 ) { 
 920                                         if ( context
.processIsRestricted  
&& (context
.mainExecutable 
== this) ) { 
 921                                                 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @loader_path\n", path
, this->getPath()); 
 924                                         char resolvedPath
[PATH_MAX
]; 
 925                                         if ( realpath(this->getPath(), resolvedPath
) != NULL 
) { 
 926                                                 char newRealPath
[strlen(resolvedPath
) + strlen(path
)]; 
 927                                                 strcpy(newRealPath
, resolvedPath
); 
 928                                                 char* addPoint 
= strrchr(newRealPath
,'/'); 
 929                                                 if ( addPoint 
!= NULL 
) 
 930                                                         strcpy(&addPoint
[1], &path
[13]); 
 932                                                         strcpy(newRealPath
, &path
[13]); 
 933                                                 pathToAdd 
= strdup(newRealPath
); 
 936                                 else if ( strncmp(path
, "@executable_path/", 17) == 0 ) { 
 937                                         if ( context
.processIsRestricted 
) { 
 938                                                 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @executable_path\n", path
, this->getPath()); 
 941                                         char resolvedPath
[PATH_MAX
]; 
 942                                         if ( realpath(context
.mainExecutable
->getPath(), resolvedPath
) != NULL 
) { 
 943                                                 char newRealPath
[strlen(resolvedPath
) + strlen(path
)]; 
 944                                                 strcpy(newRealPath
, resolvedPath
); 
 945                                                 char* addPoint 
= strrchr(newRealPath
,'/'); 
 946                                                 if ( addPoint 
!= NULL 
) 
 947                                                         strcpy(&addPoint
[1], &path
[17]); 
 949                                                         strcpy(newRealPath
, &path
[17]); 
 950                                                 pathToAdd 
= strdup(newRealPath
); 
 953                                 else if ( (path
[0] != '/') && context
.processIsRestricted 
) { 
 954                                         dyld::warn("LC_RPATH %s in %s being ignored in restricted program because it is a relative path\n", path
, this->getPath()); 
 957                                 else if ( (path
[0] == '/') && (context
.rootPaths 
!= NULL
) ) { 
 958                                         // <rdar://problem/5869973> DYLD_ROOT_PATH should apply to LC_RPATH rpaths 
 959                                         // DYLD_ROOT_PATH can be a list of paths, but at this point we can only support one, so use first combination that exists 
 961                                         for(const char** rp 
= context
.rootPaths
; *rp 
!= NULL
; ++rp
) { 
 962                                                 char newPath
[PATH_MAX
]; 
 963                                                 strcpy(newPath
, *rp
); 
 964                                                 strcat(newPath
, path
); 
 965                                                 struct stat stat_buf
; 
 966                                                 if ( stat(newPath
, &stat_buf
) != -1 ) { 
 967                                                         //dyld::log("combined DYLD_ROOT_PATH and LC_RPATH: %s\n", newPath); 
 968                                                         pathToAdd 
= strdup(newPath
); 
 974                                                 // make copy so that all elements of 'paths' can be freed 
 975                                                 pathToAdd 
= strdup(path
); 
 979                                         // make copy so that all elements of 'paths' can be freed 
 980                                         pathToAdd 
= strdup(path
); 
 982                                 if ( pathToAdd 
!= NULL 
) 
 983                                         paths
.push_back(pathToAdd
); 
 986                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
 990 bool ImageLoaderMachO::getUUID(uuid_t uuid
) const 
 992         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
 993         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
 994         const struct load_command
* cmd 
= cmds
; 
 995         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
 998                                 uuid_command
* uc 
= (uuid_command
*)cmd
; 
 999                                 memcpy(uuid
, uc
->uuid
, 16); 
1002                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1008 void ImageLoaderMachO::doRebase(const LinkContext
& context
) 
1010         // if prebound and loaded at prebound address, then no need to rebase 
1011         if ( this->usablePrebinding(context
) ) { 
1012                 // skip rebasing because prebinding is valid 
1013                 ++fgImagesWithUsedPrebinding
; // bump totals for statistics 
1017         // print why prebinding was not used 
1018         if ( context
.verbosePrebinding 
) { 
1019                 if ( !this->isPrebindable() ) { 
1020                         dyld::log("dyld: image not prebound, so could not use prebinding in %s\n", this->getPath()); 
1022                 else if ( fSlide 
!= 0 ) { 
1023                         dyld::log("dyld: image slid, so could not use prebinding in %s\n", this->getPath()); 
1025                 else if ( !this->allDependentLibrariesAsWhenPreBound() ) { 
1026                         dyld::log("dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath()); 
1028                 else if ( !this->usesTwoLevelNameSpace() ){ 
1029                         dyld::log("dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath()); 
1032                         dyld::log("dyld: environment variable disabled use of prebinding in %s\n", this->getPath()); 
1036         //dyld::log("slide=0x%08lX for %s\n", slide, this->getPath()); 
1038 #if PREBOUND_IMAGE_SUPPORT 
1039         // if prebound and we got here, then prebinding is not valid, so reset all lazy pointers 
1040         // if this image is in the shared cache, do not reset, they will be bound in doBind() 
1041         if ( this->isPrebindable() && !fInSharedCache 
) 
1042                 this->resetPreboundLazyPointers(context
); 
1045         // if loaded at preferred address, no rebasing necessary 
1046         if ( this->fSlide 
== 0 )  
1049 #if TEXT_RELOC_SUPPORT 
1050         // if there are __TEXT fixups, temporarily make __TEXT writable 
1051         if ( fTextSegmentRebases 
)  
1052                 this->makeTextSegmentWritable(context
, true); 
1055         // do actual rebasing 
1056         this->rebase(context
); 
1058 #if TEXT_RELOC_SUPPORT 
1059         // if there were __TEXT fixups, restore write protection 
1060         if ( fTextSegmentRebases 
)  
1061                 this->makeTextSegmentWritable(context
, false); 
1066 #if TEXT_RELOC_SUPPORT 
1067 void ImageLoaderMachO::makeTextSegmentWritable(const LinkContext
& context
, bool writeable
) 
1069         int textSegmentIndex 
= 0; 
1070         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
1071                 if ( strcmp(segName(i
), "__TEXT") == 0 ) { 
1072                         textSegmentIndex 
= i
; 
1078                 segMakeWritable(textSegmentIndex
, context
); 
1081                 // iPhoneOS requires range to be invalidated before it is made executable 
1082                 sys_icache_invalidate((void*)segActualLoadAddress(textSegmentIndex
), segSize(textSegmentIndex
)); 
1083                 segProtect(textSegmentIndex
, context
); 
1088 const ImageLoader::Symbol
* ImageLoaderMachO::findExportedSymbol(const char* name
, bool searchReExports
, const ImageLoader
** foundIn
) const 
1090         // look in this image first 
1091         const ImageLoader::Symbol
* result 
= this->findExportedSymbol(name
, foundIn
); 
1092         if ( result 
!= NULL 
) 
1095         if ( searchReExports 
) { 
1096                 for(unsigned int i
=0; i 
< libraryCount(); ++i
){ 
1097                         if ( libReExported(i
) ) { 
1098                                 ImageLoader
* image 
= libImage(i
); 
1099                                 if ( image 
!= NULL 
) { 
1100                                         const Symbol
* result 
= image
->findExportedSymbol(name
, searchReExports
, foundIn
); 
1101                                         if ( result 
!= NULL 
) 
1114 uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,  
1115                                                                                         const ImageLoader
* requestor
, bool runResolver
) const 
1117         return this->getSymbolAddress(sym
, requestor
, context
, runResolver
); 
1120 uintptr_t ImageLoaderMachO::getSymbolAddress(const Symbol
* sym
, const ImageLoader
* requestor
,  
1121                                                                                                 const LinkContext
& context
, bool runResolver
) const 
1123         uintptr_t result 
= exportedSymbolAddress(context
, sym
, runResolver
); 
1124         // check for interposing overrides 
1125         for (std::vector
<InterposeTuple
>::iterator it
=fgInterposingTuples
.begin(); it 
!= fgInterposingTuples
.end(); it
++) { 
1126                 // replace all references to 'replacee' with 'replacement' 
1127                 if ( (result 
== it
->replacee
) && (requestor 
!= it
->replacementImage
) ) { 
1128                         if ( context
.verboseInterposing 
) { 
1129                                 dyld::log("dyld interposing: replace 0x%lX with 0x%lX in %s\n",  
1130                                         it
->replacee
, it
->replacement
, this->getPath()); 
1132                         result 
= it
->replacement
; 
1138 ImageLoader::DefinitionFlags 
ImageLoaderMachO::getExportedSymbolInfo(const Symbol
* sym
) const 
1140         if ( exportedSymbolIsWeakDefintion(sym
) ) 
1141                 return kWeakDefinition
; 
1143                 return kNoDefinitionOptions
; 
1146 const char* ImageLoaderMachO::getExportedSymbolName(const Symbol
* sym
) const 
1148         return exportedSymbolName(sym
); 
1151 uint32_t ImageLoaderMachO::getExportedSymbolCount() const 
1153         return exportedSymbolCount(); 
1157 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index
) const 
1159         return exportedSymbolIndexed(index
); 
1163 uint32_t ImageLoaderMachO::getImportedSymbolCount() const 
1165         return importedSymbolCount(); 
1169 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index
) const 
1171         return importedSymbolIndexed(index
); 
1175 ImageLoader::ReferenceFlags 
ImageLoaderMachO::getImportedSymbolInfo(const ImageLoader::Symbol
* sym
) const 
1177         ImageLoader::ReferenceFlags flags 
= kNoReferenceOptions
; 
1182 const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol
* sym
) const 
1184         return importedSymbolName(sym
); 
1188 bool ImageLoaderMachO::getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) 
1190         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1191         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1192         const struct load_command
* cmd 
= cmds
; 
1193         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1195                         case LC_SEGMENT_COMMAND
: 
1197                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1198                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1199                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1200                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1201                                                 if ( (strcmp(sect
->segname
, segmentName
) == 0) && (strcmp(sect
->sectname
, sectionName
) == 0) ) { 
1202                                                         *start 
= (uintptr_t*)(sect
->addr 
+ fSlide
); 
1203                                                         *length 
= sect
->size
; 
1210                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1217 void ImageLoaderMachO::getUnwindInfo(dyld_unwind_sections
* info
) 
1219         info
->mh 
= this->machHeader(); 
1220         info
->dwarf_section 
= 0; 
1221         info
->dwarf_section_length 
= 0; 
1222         info
->compact_unwind_section 
= 0; 
1223         info
->compact_unwind_section_length 
= 0; 
1224         if ( fEHFrameSectionOffset 
!= 0 ) { 
1225                 const macho_section
* sect 
= (macho_section
*)&fMachOData
[fEHFrameSectionOffset
]; 
1226                 info
->dwarf_section 
= (void*)(sect
->addr 
+ fSlide
); 
1227                 info
->dwarf_section_length 
= sect
->size
; 
1229         if ( fUnwindInfoSectionOffset 
!= 0 ) { 
1230                 const macho_section
* sect 
= (macho_section
*)&fMachOData
[fUnwindInfoSectionOffset
]; 
1231                 info
->compact_unwind_section 
= (void*)(sect
->addr 
+ fSlide
); 
1232                 info
->compact_unwind_section_length 
= sect
->size
; 
1237 bool ImageLoaderMachO::findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) 
1239         const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1240         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1241         const struct load_command
* cmd 
= cmds
; 
1242         const uintptr_t unslidInteriorAddress 
= (uintptr_t)imageInterior 
- this->getSlide(); 
1243         for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1245                         case LC_SEGMENT_COMMAND
: 
1247                                         const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1248                                         if ( (unslidInteriorAddress 
>= seg
->vmaddr
) && (unslidInteriorAddress 
< (seg
->vmaddr
+seg
->vmsize
)) ) { 
1249                                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1250                                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1251                                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1252                                                         if ((sect
->addr 
<= unslidInteriorAddress
) && (unslidInteriorAddress 
< (sect
->addr
+sect
->size
))) { 
1253                                                                 if ( segmentName 
!= NULL 
) 
1254                                                                         *segmentName 
= sect
->segname
; 
1255                                                                 if ( sectionName 
!= NULL 
) 
1256                                                                         *sectionName 
= sect
->sectname
; 
1257                                                                 if ( sectionOffset 
!= NULL 
) 
1258                                                                         *sectionOffset 
= unslidInteriorAddress 
- sect
->addr
; 
1266                 cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1272 void __attribute__((noreturn
)) ImageLoaderMachO::throwSymbolNotFound(const LinkContext
& context
, const char* symbol
,  
1273                                                                                                                                         const char* referencedFrom
, const char* expectedIn
) 
1275         // record values for possible use by CrashReporter or Finder 
1276         (*context
.setErrorStrings
)(dyld_error_kind_symbol_missing
, referencedFrom
, expectedIn
, symbol
); 
1277         dyld::throwf("Symbol not found: %s\n  Referenced from: %s\n  Expected in: %s\n", symbol
, referencedFrom
, expectedIn
);  
1280 const mach_header
* ImageLoaderMachO::machHeader() const 
1282         return (mach_header
*)fMachOData
; 
1285 uintptr_t ImageLoaderMachO::getSlide() const 
1290 // hmm. maybe this should be up in ImageLoader?? 
1291 const void* ImageLoaderMachO::getEnd() const 
1293         uintptr_t lastAddress 
= 0; 
1294         for(unsigned int i
=0; i 
< fSegmentsCount
; ++i
) { 
1295                 uintptr_t segEnd 
= segActualEndAddress(i
); 
1296                 if ( strcmp(segName(i
), "__UNIXSTACK") != 0 ) { 
1297                         if ( segEnd 
> lastAddress 
) 
1298                                 lastAddress 
= segEnd
; 
1301         return (const void*)lastAddress
; 
1305 uintptr_t ImageLoaderMachO::bindLocation(const LinkContext
& context
, uintptr_t location
, uintptr_t value
,  
1306                                                                                 const ImageLoader
* targetImage
, uint8_t type
, const char* symbolName
,  
1307                                                                                 intptr_t addend
, const char* msg
) 
1310         if ( context
.verboseBind 
) { 
1312                         dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX + %ld\n", 
1313                                                 msg
, this->getShortName(), (uintptr_t)location
, 
1314                                                 ((targetImage 
!= NULL
) ? targetImage
->getShortName() : "<weak_import-missing>"), 
1315                                                 symbolName
, (uintptr_t)location
, value
, addend
); 
1317                         dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX\n", 
1318                                                 msg
, this->getShortName(), (uintptr_t)location
, 
1319                                                 ((targetImage 
!= NULL
) ? targetImage
->getShortName() : "<weak>import-missing>"), 
1320                                                  symbolName
, (uintptr_t)location
, value
); 
1323 //      dyld::logBindings("%s: %s\n", targetImage->getShortName(), symbolName); 
1327         uintptr_t* locationToFix 
= (uintptr_t*)location
; 
1329         uintptr_t newValue 
= value
+addend
; 
1332                 case BIND_TYPE_POINTER
: 
1333                         // test first so we don't needless dirty pages 
1334                         if ( *locationToFix 
!= newValue 
) 
1335                                 *locationToFix 
= newValue
; 
1337                 case BIND_TYPE_TEXT_ABSOLUTE32
: 
1338                         loc32 
= (uint32_t*)locationToFix
; 
1339                         value32 
= (uint32_t)newValue
; 
1340                         if ( *loc32 
!= value32 
) 
1343                 case BIND_TYPE_TEXT_PCREL32
: 
1344                         loc32 
= (uint32_t*)locationToFix
; 
1345                         value32 
= (uint32_t)newValue 
- (((uintptr_t)locationToFix
) + 4); 
1346                         if ( *loc32 
!= value32 
) 
1350                         dyld::throwf("bad bind type %d", type
); 
1353         // update statistics 
1354         ++fgTotalBindFixups
; 
1363 #if SUPPORT_OLD_CRT_INITIALIZATION 
1364 // first 16 bytes of "start" in crt1.o 
1366         static uint8_t sStandardEntryPointInstructions
[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 }; 
1371         void*                   dyldLazyBinder
;         // filled in at launch by dyld to point into dyld to &stub_binding_helper_interface 
1372         void*                   dyldFuncLookup
;         // filled in at launch by dyld to point into dyld to &_dyld_func_lookup 
1373         // the following only exist in main executables built for 10.5 or later 
1377 // These are defined in dyldStartup.s 
1378 extern "C" void stub_binding_helper(); 
1379 extern "C" bool dyld_func_lookup(const char* name
, uintptr_t* address
); 
1382 void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext
& context
) 
1384         const macho_header
* mh 
= (macho_header
*)fMachOData
; 
1385         const uint32_t cmd_count 
= mh
->ncmds
; 
1386         const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1387         const struct load_command
* cmd
; 
1388         // There used to be some optimizations to skip this section scan, but we need to handle the  
1389         // __dyld section in libdyld.dylib, so everything needs to be scanned for now. 
1390         // <rdar://problem/10910062> CrashTracer: 1,295 crashes in bash at bash: getenv 
1393                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1394                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1395                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1396                                 if ( strcmp(seg
->segname
, "__DATA") == 0 ) { 
1397                                         const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1398                                         const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1399                                         for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1400                                                 if ( strcmp(sect
->sectname
, "__dyld" ) == 0 ) { 
1401                                                         struct DATAdyld
* dd 
= (struct DATAdyld
*)(sect
->addr 
+ fSlide
); 
1402                                                         if ( sect
->size 
> offsetof(DATAdyld
, dyldLazyBinder
) ) { 
1403                                                                 if ( dd
->dyldLazyBinder 
!= (void*)&stub_binding_helper 
) 
1404                                                                         dd
->dyldLazyBinder 
= (void*)&stub_binding_helper
; 
1406                                                         if ( sect
->size 
> offsetof(DATAdyld
, dyldFuncLookup
) ) { 
1407                                                                 if ( dd
->dyldFuncLookup 
!= (void*)&dyld_func_lookup 
) 
1408                                                                         dd
->dyldFuncLookup 
= (void*)&dyld_func_lookup
; 
1410                                                         if ( mh
->filetype 
== MH_EXECUTE 
) { 
1411                                                                 // there are two ways to get the program variables 
1412                                                                 if ( (sect
->size 
> offsetof(DATAdyld
, vars
)) && (dd
->vars
.mh 
== mh
) ) { 
1413                                                                         // some really old binaries have space for vars, but it is zero filled 
1414                                                                         // main executable has 10.5 style __dyld section that has program variable pointers 
1415                                                                         context
.setNewProgramVars(dd
->vars
); 
1418                                                                         // main executable is pre-10.5 and requires the symbols names to be looked up 
1419                                                                         this->lookupProgramVars(context
); 
1420                                 #if SUPPORT_OLD_CRT_INITIALIZATION 
1421                                                                         // If the first 16 bytes of the entry point's instructions do not  
1422                                                                         // match what crt1.o supplies, then the program has a custom entry point. 
1423                                                                         // This means it might be doing something that needs to be executed before  
1424                                                                         // initializers are run.  
1425                                                                         if ( memcmp(this->getMain(), sStandardEntryPointInstructions
, 16) != 0 ) { 
1426                                                                                 if ( context
.verboseInit 
) 
1427                                                                                         dyld::log("dyld: program uses non-standard entry point so delaying running of initializers\n"); 
1428                                                                                 context
.setRunInitialzersOldWay(); 
1433                                                         else if ( mh
->filetype 
== MH_DYLIB 
) { 
1434                                                                 const char* installPath 
= this->getInstallPath(); 
1435                                                                 if ( (installPath 
!= NULL
) && (strncmp(installPath
, "/usr/lib/", 9) == 0) ) { 
1436                                                                         if ( sect
->size 
> offsetof(DATAdyld
, vars
) ) { 
1437                                                                                 // use ProgramVars from libdyld.dylib but tweak mh field to correct value 
1438                                                                                 dd
->vars
.mh 
= context
.mainExecutable
->machHeader(); 
1439                                                                                 context
.setNewProgramVars(dd
->vars
); 
1444                                                 else if ( (strcmp(sect
->sectname
, "__program_vars" ) == 0) && (mh
->filetype 
== MH_EXECUTE
) ) { 
1445                                                         // this is a Mac OS X 10.6 or later main executable  
1446                                                         struct ProgramVars
* pv 
= (struct ProgramVars
*)(sect
->addr 
+ fSlide
); 
1447                                                         context
.setNewProgramVars(*pv
); 
1452                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1458 void ImageLoaderMachO::lookupProgramVars(const LinkContext
& context
) const 
1460         ProgramVars vars 
= context
.programVars
; 
1461         const ImageLoader::Symbol
* sym
; 
1463         // get mach header directly 
1464         vars
.mh 
= (macho_header
*)fMachOData
; 
1467         sym 
= this->findExportedSymbol("_NXArgc", false, NULL
); 
1469                 vars
.NXArgcPtr 
= (int*)this->getExportedSymbolAddress(sym
, context
, this, false); 
1472         sym 
= this->findExportedSymbol("_NXArgv", false, NULL
); 
1474                 vars
.NXArgvPtr 
= (const char***)this->getExportedSymbolAddress(sym
, context
, this, false); 
1477         sym 
= this->findExportedSymbol("_environ", false, NULL
); 
1479                 vars
.environPtr 
= (const char***)this->getExportedSymbolAddress(sym
, context
, this, false); 
1481         // lookup __progname 
1482         sym 
= this->findExportedSymbol("___progname", false, NULL
); 
1484                 vars
.__prognamePtr 
= (const char**)this->getExportedSymbolAddress(sym
, context
, this, false); 
1486         context
.setNewProgramVars(vars
); 
1490 bool ImageLoaderMachO::usablePrebinding(const LinkContext
& context
) const 
1492         // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind 
1493         if ( ((this->isPrebindable() && (this->getSlide() == 0)) || fInSharedCache
) 
1494                 && this->usesTwoLevelNameSpace() 
1495                 && this->allDependentLibrariesAsWhenPreBound() ) { 
1496                 // allow environment variables to disable prebinding 
1497                 if ( context
.bindFlat 
) 
1499                 switch ( context
.prebindUsage 
) { 
1500                         case kUseAllPrebinding
: 
1502                         case kUseSplitSegPrebinding
: 
1503                                 return this->fIsSplitSeg
; 
1504                         case kUseAllButAppPredbinding
: 
1505                                 return (this != context
.mainExecutable
); 
1506                         case kUseNoPrebinding
: 
1514 void ImageLoaderMachO::doImageInit(const LinkContext
& context
) 
1516         if ( fHasDashInit 
) { 
1517                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1518                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1519                 const struct load_command
* cmd 
= cmds
; 
1520                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1522                                 case LC_ROUTINES_COMMAND
: 
1523                                         Initializer func 
= (Initializer
)(((struct macho_routines_command
*)cmd
)->init_address 
+ fSlide
); 
1524                                         // <rdar://problem/8543820&9228031> verify initializers are in image 
1525                                         if ( ! this->containsAddress((void*)func
) ) { 
1526                                                 dyld::throwf("initializer function %p not in mapped image for %s\n", func
, this->getPath()); 
1528                                         if ( context
.verboseInit 
) 
1529                                                 dyld::log("dyld: calling -init function 0x%p in %s\n", func
, this->getPath()); 
1530                                         func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
); 
1533                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1538 void ImageLoaderMachO::doModInitFunctions(const LinkContext
& context
) 
1540         if ( fHasInitializers 
) { 
1541                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1542                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1543                 const struct load_command
* cmd 
= cmds
; 
1544                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1545                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1546                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
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                                         const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
1551                                         if ( type 
== S_MOD_INIT_FUNC_POINTERS 
) { 
1552                                                 Initializer
* inits 
= (Initializer
*)(sect
->addr 
+ fSlide
); 
1553                                                 const uint32_t count 
= sect
->size 
/ sizeof(uintptr_t); 
1554                                                 for (uint32_t i
=0; i 
< count
; ++i
) { 
1555                                                         Initializer func 
= inits
[i
]; 
1556                                                         // <rdar://problem/8543820&9228031> verify initializers are in image 
1557                                                         if ( ! this->containsAddress((void*)func
) ) { 
1558                                                                 dyld::throwf("initializer function %p not in mapped image for %s\n", func
, this->getPath()); 
1560                                                         if ( context
.verboseInit 
) 
1561                                                                 dyld::log("dyld: calling initializer function %p in %s\n", func
, this->getPath()); 
1562                                                         func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
); 
1567                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1577 void ImageLoaderMachO::doGetDOFSections(const LinkContext
& context
, std::vector
<ImageLoader::DOFInfo
>& dofs
) 
1579         if ( fHasDOFSections 
) { 
1580                 // walk load commands (mapped in at start of __TEXT segment) 
1581                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1582                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1583                 const struct load_command
* cmd 
= cmds
; 
1584                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1586                                 case LC_SEGMENT_COMMAND
: 
1588                                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1589                                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1590                                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1591                                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1592                                                         if ( (sect
->flags 
& SECTION_TYPE
) == S_DTRACE_DOF 
) { 
1593                                                                 ImageLoader::DOFInfo info
; 
1594                                                                 info
.dof                        
= (void*)(sect
->addr 
+ fSlide
); 
1595                                                                 info
.imageHeader        
= this->machHeader(); 
1596                                                                 info
.imageShortName 
= this->getShortName(); 
1597                                                                 dofs
.push_back(info
); 
1603                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1609 bool ImageLoaderMachO::doInitialization(const LinkContext
& context
) 
1611         CRSetCrashLogMessage2(this->getPath()); 
1613         // mach-o has -init and static initializers 
1614         doImageInit(context
); 
1615         doModInitFunctions(context
); 
1617         CRSetCrashLogMessage2(NULL
); 
1619         return (fHasDashInit 
|| fHasInitializers
); 
1622 bool ImageLoaderMachO::needsInitialization() 
1624         return ( fHasDashInit 
|| fHasInitializers 
); 
1628 bool ImageLoaderMachO::needsTermination() 
1630         return fHasTerminators
; 
1634 void ImageLoaderMachO::doTermination(const LinkContext
& context
) 
1636         if ( fHasTerminators 
) { 
1637                 const uint32_t cmd_count 
= ((macho_header
*)fMachOData
)->ncmds
; 
1638                 const struct load_command
* const cmds 
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)]; 
1639                 const struct load_command
* cmd 
= cmds
; 
1640                 for (uint32_t i 
= 0; i 
< cmd_count
; ++i
) { 
1641                         if ( cmd
->cmd 
== LC_SEGMENT_COMMAND 
) { 
1642                                 const struct macho_segment_command
* seg 
= (struct macho_segment_command
*)cmd
; 
1643                                 const struct macho_section
* const sectionsStart 
= (struct macho_section
*)((char*)seg 
+ sizeof(struct macho_segment_command
)); 
1644                                 const struct macho_section
* const sectionsEnd 
= §ionsStart
[seg
->nsects
]; 
1645                                 for (const struct macho_section
* sect
=sectionsStart
; sect 
< sectionsEnd
; ++sect
) { 
1646                                         const uint8_t type 
= sect
->flags 
& SECTION_TYPE
; 
1647                                         if ( type 
== S_MOD_TERM_FUNC_POINTERS 
) { 
1648                                                 Terminator
* terms 
= (Terminator
*)(sect
->addr 
+ fSlide
); 
1649                                                 const uint32_t count 
= sect
->size 
/ sizeof(uintptr_t); 
1650                                                 for (uint32_t i
=count
; i 
> 0; --i
) { 
1651                                                         Terminator func 
= terms
[i
-1]; 
1652                                                         // <rdar://problem/8543820&9228031> verify terminators are in image 
1653                                                         if ( ! this->containsAddress((void*)func
) ) { 
1654                                                                 dyld::throwf("termination function %p not in mapped image for %s\n", func
, this->getPath()); 
1656                                                         if ( context
.verboseInit 
) 
1657                                                                 dyld::log("dyld: calling termination function %p in %s\n", func
, this->getPath()); 
1663                         cmd 
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
); 
1669 void ImageLoaderMachO::printStatistics(unsigned int imageCount
, const InitializerTimingList
& timingInfo
) 
1671         ImageLoader::printStatistics(imageCount
, timingInfo
); 
1672         dyld::log("total symbol trie searches:    %d\n", fgSymbolTrieSearchs
); 
1673         dyld::log("total symbol table binary searches:    %d\n", fgSymbolTableBinarySearchs
); 
1674         dyld::log("total images defining weak symbols:  %u\n", fgImagesHasWeakDefinitions
); 
1675         dyld::log("total images using weak symbols:  %u\n", fgImagesRequiringCoalescing
); 
1679 intptr_t ImageLoaderMachO::assignSegmentAddresses(const LinkContext
& context
) 
1681         // preflight and calculate slide if needed 
1682         const bool inPIE 
= (fgNextPIEDylibAddress 
!= 0); 
1684         if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) { 
1685                 bool needsToSlide 
= false; 
1686                 bool imageHasPreferredLoadAddress 
= segHasPreferredLoadAddress(0); 
1687                 uintptr_t lowAddr 
= (unsigned long)(-1); 
1688                 uintptr_t highAddr 
= 0; 
1689                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1690                         const uintptr_t segLow 
= segPreferredLoadAddress(i
); 
1691                         const uintptr_t segHigh 
= (segLow 
+ segSize(i
) + 4095) & -4096; 
1692                         if ( segLow 
< lowAddr 
) 
1694                         if ( segHigh 
> highAddr 
) 
1697                         if ( needsToSlide 
|| !imageHasPreferredLoadAddress 
|| inPIE 
|| !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) ) 
1698                                 needsToSlide 
= true; 
1700                 if ( needsToSlide 
) { 
1701                         // find a chunk of address space to hold all segments 
1702                         uintptr_t addr 
= reserveAnAddressRange(highAddr
-lowAddr
, context
); 
1703                         slide 
= addr 
- lowAddr
; 
1706         else if ( ! this->segmentsCanSlide() ) { 
1707                 for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1708                         if ( strcmp(segName(i
), "__PAGEZERO") == 0 ) 
1710                         if ( !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) ) 
1711                                 dyld::throwf("can't map unslidable segment %s to 0x%lX with size 0x%lX", segName(i
), segPreferredLoadAddress(i
), segSize(i
)); 
1715                 throw "mach-o does not support independently sliding segments"; 
1721 uintptr_t ImageLoaderMachO::reserveAnAddressRange(size_t length
, const ImageLoader::LinkContext
& context
) 
1723         vm_address_t addr 
= 0; 
1724         vm_size_t size 
= length
; 
1725         // in PIE programs, load initial dylibs after main executable so they don't have fixed addresses either 
1726         if ( fgNextPIEDylibAddress 
!= 0 ) { 
1727                  // add small (0-3 pages) random padding between dylibs 
1728                 addr 
= fgNextPIEDylibAddress 
+ (__stack_chk_guard
/fgNextPIEDylibAddress 
& (sizeof(long)-1))*4096; 
1729                 //dyld::log("padding 0x%08llX, guard=0x%08llX\n", (long long)(addr - fgNextPIEDylibAddress), (long long)(__stack_chk_guard)); 
1730                 kern_return_t r 
= vm_allocate(mach_task_self(), &addr
, size
, VM_FLAGS_FIXED
); 
1731                 if ( r 
== KERN_SUCCESS 
) { 
1732                         fgNextPIEDylibAddress 
= addr 
+ size
; 
1735                 fgNextPIEDylibAddress 
= 0; 
1737         kern_return_t r 
= vm_allocate(mach_task_self(), &addr
, size
, VM_FLAGS_ANYWHERE
); 
1738         if ( r 
!= KERN_SUCCESS 
)  
1739                 throw "out of address space"; 
1744 bool ImageLoaderMachO::reserveAddressRange(uintptr_t start
, size_t length
) 
1746         vm_address_t addr 
= start
; 
1747         vm_size_t size 
= length
; 
1748         kern_return_t r 
= vm_allocate(mach_task_self(), &addr
, size
, false /*only this range*/); 
1749         if ( r 
!= KERN_SUCCESS 
)  
1756 void ImageLoaderMachO::mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
) 
1758         // find address range for image 
1759         intptr_t slide 
= this->assignSegmentAddresses(context
); 
1760         if ( context
.verboseMapping 
) 
1761                 dyld::log("dyld: Mapping %s\n", this->getPath()); 
1762         // map in all segments 
1763         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1764                 vm_offset_t fileOffset 
= segFileOffset(i
) + offsetInFat
; 
1765                 vm_size_t size 
= segFileSize(i
); 
1766                 uintptr_t requestedLoadAddress 
= segPreferredLoadAddress(i
) + slide
; 
1768                 if ( !segUnaccessible(i
) ) { 
1769                         // If has text-relocs, don't set x-bit initially. 
1770                         // Instead set it later after text-relocs have been done. 
1771                         // The iPhone OS does not like it when you make executable code writable. 
1772                         if ( segExecutable(i
) && !(segHasRebaseFixUps(i
) && (slide 
!= 0)) ) 
1773                                 protection   
|= PROT_EXEC
; 
1774                         if ( segReadable(i
) ) 
1775                                 protection   
|= PROT_READ
; 
1776                         if ( segWriteable(i
) ) 
1777                                 protection   
|= PROT_WRITE
; 
1780                 // initially map __IMPORT segments R/W so dyld can update them 
1781                 if ( segIsReadOnlyImport(i
) ) 
1782                         protection 
|= PROT_WRITE
; 
1784                 // wholly zero-fill segments have nothing to mmap() in 
1786                         if ( (fileOffset
+size
) > fileLen 
) { 
1787                                 dyld::throwf("truncated mach-o error: segment %s extends to %llu which is past end of file %llu",  
1788                                                                 segName(i
), (uint64_t)(fileOffset
+size
), fileLen
); 
1790                         void* loadAddress 
= mmap((void*)requestedLoadAddress
, size
, protection
, MAP_FIXED 
| MAP_PRIVATE
, fd
, fileOffset
); 
1791                         if ( loadAddress 
== ((void*)(-1)) ) { 
1792                                 dyld::throwf("mmap() error %d at address=0x%08lX, size=0x%08lX segment=%s in Segment::map() mapping %s",  
1793                                         errno
, requestedLoadAddress
, (uintptr_t)size
, segName(i
), getPath()); 
1797                 ++ImageLoader::fgTotalSegmentsMapped
; 
1798                 ImageLoader::fgTotalBytesMapped 
+= size
; 
1799                 if ( context
.verboseMapping 
) 
1800                         dyld::log("%18s at 0x%08lX->0x%08lX with permissions %c%c%c\n", segName(i
), requestedLoadAddress
, requestedLoadAddress
+size
-1, 
1801                                 (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' ); 
1804         // update slide to reflect load location                         
1805         this->setSlide(slide
); 
1808 void ImageLoaderMachO::mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
) 
1810         // find address range for image 
1811         intptr_t slide 
= this->assignSegmentAddresses(context
); 
1812         if ( context
.verboseMapping 
) 
1813                 dyld::log("dyld: Mapping memory %p\n", memoryImage
); 
1814         // map in all segments 
1815         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1816                 vm_address_t loadAddress 
= segPreferredLoadAddress(i
) + slide
; 
1817                 vm_address_t srcAddr 
= (uintptr_t)memoryImage 
+ segFileOffset(i
); 
1818                 vm_size_t size 
= segFileSize(i
); 
1819                 kern_return_t r 
= vm_copy(mach_task_self(), srcAddr
, size
, loadAddress
); 
1820                 if ( r 
!= KERN_SUCCESS 
)  
1821                         throw "can't map segment"; 
1822                 if ( context
.verboseMapping 
) 
1823                         dyld::log("%18s at 0x%08lX->0x%08lX\n", segName(i
), (uintptr_t)loadAddress
, (uintptr_t)loadAddress
+size
-1); 
1825         // update slide to reflect load location                         
1826         this->setSlide(slide
); 
1827         // set R/W permissions on all segments at slide location 
1828         for(unsigned int i
=0, e
=segmentCount(); i 
< e
; ++i
) { 
1829                 segProtect(i
, context
);          
1834 void ImageLoaderMachO::segProtect(unsigned int segIndex
, const ImageLoader::LinkContext
& context
) 
1836         vm_prot_t protection 
= 0; 
1837         if ( !segUnaccessible(segIndex
) ) { 
1838                 if ( segExecutable(segIndex
) ) 
1839                         protection   
|= PROT_EXEC
; 
1840                 if ( segReadable(segIndex
) ) 
1841                         protection   
|= PROT_READ
; 
1842                 if ( segWriteable(segIndex
) ) 
1843                         protection   
|= PROT_WRITE
; 
1845         vm_address_t addr 
= segActualLoadAddress(segIndex
); 
1846         vm_size_t size 
= segSize(segIndex
); 
1847         const bool setCurrentPermissions 
= false; 
1848         kern_return_t r 
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
); 
1849         if ( r 
!= KERN_SUCCESS 
) { 
1850         dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s", 
1851             (long long)addr
, (long long)size
, protection
, r
, segName(segIndex
), this->getPath()); 
1853         if ( context
.verboseMapping 
) { 
1854                 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, 
1855                         (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' ); 
1859 void ImageLoaderMachO::segMakeWritable(unsigned int segIndex
, const ImageLoader::LinkContext
& context
) 
1861         vm_address_t addr 
= segActualLoadAddress(segIndex
); 
1862         vm_size_t size 
= segSize(segIndex
); 
1863         const bool setCurrentPermissions 
= false; 
1864         vm_prot_t protection 
= VM_PROT_WRITE 
| VM_PROT_READ
; 
1865         if ( segExecutable(segIndex
) && !segHasRebaseFixUps(segIndex
) ) 
1866                 protection 
|= VM_PROT_EXECUTE
; 
1867         kern_return_t r 
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
); 
1868         if ( r 
!= KERN_SUCCESS 
) { 
1869         dyld::throwf("vm_protect(0x%08llX, 0x%08llX, false, 0x%02X) failed, result=%d for segment %s in %s", 
1870             (long long)addr
, (long long)size
, protection
, r
, segName(segIndex
), this->getPath()); 
1872         if ( context
.verboseMapping 
) { 
1873                 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, 
1874                         (protection 
& PROT_READ
) ? 'r' : '.',  (protection 
& PROT_WRITE
) ? 'w' : '.',  (protection 
& PROT_EXEC
) ? 'x' : '.' );