1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2008 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
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>
46 #include "ImageLoaderMachO.h"
47 #include "ImageLoaderMachOCompressed.h"
48 #include "ImageLoaderMachOClassic.h"
49 #include "mach-o/dyld_images.h"
53 // relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables
55 #define LC_SEGMENT_COMMAND LC_SEGMENT_64
56 #define LC_ROUTINES_COMMAND LC_ROUTINES_64
57 struct macho_segment_command
: public segment_command_64
{};
58 struct macho_section
: public section_64
{};
59 struct macho_routines_command
: public routines_command_64
{};
61 #define LC_SEGMENT_COMMAND LC_SEGMENT
62 #define LC_ROUTINES_COMMAND LC_ROUTINES
63 struct macho_segment_command
: public segment_command
{};
64 struct macho_section
: public section
{};
65 struct macho_routines_command
: public routines_command
{};
68 uint32_t ImageLoaderMachO::fgSymbolTableBinarySearchs
= 0;
69 uint32_t ImageLoaderMachO::fgSymbolTrieSearchs
= 0;
72 ImageLoaderMachO::ImageLoaderMachO(const macho_header
* mh
, const char* path
, unsigned int segCount
,
73 uint32_t segOffsets
[], unsigned int libCount
)
74 : ImageLoader(path
, libCount
), fMachOData((uint8_t*)mh
), fLinkEditBase(NULL
), fSlide(0),
75 fEHFrameSectionOffset(0), fUnwindInfoSectionOffset(0), fDylibIDOffset(0),
76 fSegmentsCount(segCount
), fIsSplitSeg(false), fInSharedCache(false),
77 #if TEXT_RELOC_SUPPORT
78 fTextSegmentRebases(false),
79 fTextSegmentBinds(false),
82 fReadOnlyImportSegment(false),
84 fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false),
85 fHasInitializers(false), fHasTerminators(false)
87 fIsSplitSeg
= ((mh
->flags
& MH_SPLIT_SEGS
) != 0);
89 // construct SegmentMachO object for each LC_SEGMENT cmd using "placement new" to put
90 // each SegmentMachO object in array at end of ImageLoaderMachO object
91 const uint32_t cmd_count
= mh
->ncmds
;
92 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
93 const struct load_command
* cmd
= cmds
;
94 for (uint32_t i
= 0, segIndex
=0; i
< cmd_count
; ++i
) {
95 if ( cmd
->cmd
== LC_SEGMENT_COMMAND
) {
96 const struct macho_segment_command
* segCmd
= (struct macho_segment_command
*)cmd
;
97 // ignore zero-sized segments
98 if ( segCmd
->vmsize
!= 0 ) {
99 // record offset of load command
100 segOffsets
[segIndex
++] = (uint8_t*)segCmd
- fMachOData
;
103 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
109 // determine if this mach-o file has classic or compressed LINKEDIT and number of segments it has
110 void ImageLoaderMachO::sniffLoadCommands(const macho_header
* mh
, const char* path
, bool* compressed
,
111 unsigned int* segCount
, unsigned int* libCount
)
116 const uint32_t cmd_count
= mh
->ncmds
;
117 const struct load_command
* const cmds
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
));
118 const struct load_command
* const endCmds
= (struct load_command
*)(((uint8_t*)mh
) + sizeof(macho_header
) + mh
->sizeofcmds
);
119 const struct load_command
* cmd
= cmds
;
120 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
123 case LC_DYLD_INFO_ONLY
:
126 case LC_SEGMENT_COMMAND
:
127 // ignore zero-sized segments
128 if ( ((struct macho_segment_command
*)cmd
)->vmsize
!= 0 )
132 case LC_LOAD_WEAK_DYLIB
:
133 case LC_REEXPORT_DYLIB
:
137 uint32_t cmdLength
= cmd
->cmdsize
;
138 cmd
= (const struct load_command
*)(((char*)cmd
)+cmdLength
);
139 if ( cmd
> endCmds
) {
140 dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s",
141 i
, cmdLength
, mh
->sizeofcmds
, path
);
144 // fSegmentsArrayCount is only 8-bits
145 if ( *segCount
> 255 )
146 dyld::throwf("malformed mach-o image: more than 255 segments in %s", path
);
148 // fSegmentsArrayCount is only 8-bits
149 if ( *libCount
> 4095 )
150 dyld::throwf("malformed mach-o image: more than 4095 dependent libraries in %s", path
);
152 if ( needsAddedLibSystemDepency(*libCount
, mh
) )
158 // create image for main executable
159 ImageLoader
* ImageLoaderMachO::instantiateMainExecutable(const macho_header
* mh
, uintptr_t slide
, const char* path
, const LinkContext
& context
)
161 //dyld::log("ImageLoader=%ld, ImageLoaderMachO=%ld, ImageLoaderMachOClassic=%ld, ImageLoaderMachOCompressed=%ld\n",
162 // sizeof(ImageLoader), sizeof(ImageLoaderMachO), sizeof(ImageLoaderMachOClassic), sizeof(ImageLoaderMachOCompressed));
164 unsigned int segCount
;
165 unsigned int libCount
;
166 sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
);
167 // instantiate concrete class based on content of load commands
169 return ImageLoaderMachOCompressed::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
);
171 return ImageLoaderMachOClassic::instantiateMainExecutable(mh
, slide
, path
, segCount
, libCount
, context
);
175 // create image by mapping in a mach-o file
176 ImageLoader
* ImageLoaderMachO::instantiateFromFile(const char* path
, int fd
, const uint8_t firstPage
[4096], uint64_t offsetInFat
,
177 uint64_t lenInFat
, const struct stat
& info
, const LinkContext
& context
)
180 const unsigned int dataSize
= sizeof(macho_header
) + ((macho_header
*)firstPage
)->sizeofcmds
;
181 uint8_t buffer
[dataSize
];
182 const uint8_t* fileData
= firstPage
;
183 if ( dataSize
> 4096 ) {
184 // only read more if cmds take up more space than first page
186 memcpy(buffer
, firstPage
, 4096);
187 pread(fd
, &buffer
[4096], dataSize
-4096, offsetInFat
+4096);
191 unsigned int segCount
;
192 unsigned int libCount
;
193 sniffLoadCommands((const macho_header
*)fileData
, path
, &compressed
, &segCount
, &libCount
);
194 // instantiate concrete class based on content of load commands
196 return ImageLoaderMachOCompressed::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, context
);
198 return ImageLoaderMachOClassic::instantiateFromFile(path
, fd
, fileData
, offsetInFat
, lenInFat
, info
, segCount
, libCount
, context
);
201 // create image by using cached mach-o file
202 ImageLoader
* ImageLoaderMachO::instantiateFromCache(const macho_header
* mh
, const char* path
, const struct stat
& info
, const LinkContext
& context
)
204 // instantiate right concrete class
206 unsigned int segCount
;
207 unsigned int libCount
;
208 sniffLoadCommands(mh
, path
, &compressed
, &segCount
, &libCount
);
209 // instantiate concrete class based on content of load commands
211 return ImageLoaderMachOCompressed::instantiateFromCache(mh
, path
, info
, segCount
, libCount
, context
);
213 return ImageLoaderMachOClassic::instantiateFromCache(mh
, path
, info
, segCount
, libCount
, context
);
216 // create image by copying an in-memory mach-o file
217 ImageLoader
* ImageLoaderMachO::instantiateFromMemory(const char* moduleName
, const macho_header
* mh
, uint64_t len
, const LinkContext
& context
)
220 unsigned int segCount
;
221 unsigned int libCount
;
222 sniffLoadCommands(mh
, moduleName
, &compressed
, &segCount
, &libCount
);
223 // instantiate concrete class based on content of load commands
225 return ImageLoaderMachOCompressed::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
);
227 return ImageLoaderMachOClassic::instantiateFromMemory(moduleName
, mh
, len
, segCount
, libCount
, context
);
232 void ImageLoaderMachO::parseLoadCmds()
234 // now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide
235 for(unsigned int i
=0; i
< fSegmentsCount
; ++i
) {
236 // set up pointer to __LINKEDIT segment
237 if ( strcmp(segName(i
),"__LINKEDIT") == 0 )
238 fLinkEditBase
= (uint8_t*)(segActualLoadAddress(i
) - segFileOffset(i
));
239 #if TEXT_RELOC_SUPPORT
240 // __TEXT segment always starts at beginning of file and contains mach_header and load commands
241 if ( strcmp(segName(i
),"__TEXT") == 0 ) {
242 if ( segHasRebaseFixUps(i
) )
243 fTextSegmentRebases
= true;
244 if ( segHasBindFixUps(i
) )
245 fTextSegmentBinds
= true;
249 if ( segIsReadOnlyImport(i
) )
250 fReadOnlyImportSegment
= true;
252 // some segment always starts at beginning of file and contains mach_header and load commands
253 if ( (segFileOffset(i
) == 0) && (segFileSize(i
) != 0) ) {
254 fMachOData
= (uint8_t*)(segActualLoadAddress(i
));
258 // keep count of prebound images with weak exports
259 if ( this->participatesInCoalescing() ) {
260 ++fgImagesRequiringCoalescing
;
261 if ( this->hasCoalescedExports() )
262 ++fgImagesHasWeakDefinitions
;
265 // keep count of images used in shared cache
266 if ( fInSharedCache
)
267 ++fgImagesUsedFromSharedCache
;
269 // walk load commands (mapped in at start of __TEXT segment)
270 const dyld_info_command
* dyldInfo
= NULL
;
271 const macho_nlist
* symbolTable
= NULL
;
272 const char* symbolTableStrings
= NULL
;
273 const dysymtab_command
* dynSymbolTable
= NULL
;
274 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
275 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
276 const struct load_command
* cmd
= cmds
;
277 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
281 const struct symtab_command
* symtab
= (struct symtab_command
*)cmd
;
282 symbolTableStrings
= (const char*)&fLinkEditBase
[symtab
->stroff
];
283 symbolTable
= (macho_nlist
*)(&fLinkEditBase
[symtab
->symoff
]);
287 dynSymbolTable
= (struct dysymtab_command
*)cmd
;
289 case LC_SUB_UMBRELLA
:
290 fHasSubUmbrella
= true;
292 case LC_SUB_FRAMEWORK
:
296 fHasSubLibraries
= true;
298 case LC_ROUTINES_COMMAND
:
302 case LC_DYLD_INFO_ONLY
:
303 dyldInfo
= (struct dyld_info_command
*)cmd
;
305 case LC_SEGMENT_COMMAND
:
307 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
308 const bool isTextSeg
= (strcmp(seg
->segname
, "__TEXT") == 0);
309 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
310 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
311 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
312 const uint8_t type
= sect
->flags
& SECTION_TYPE
;
313 if ( type
== S_MOD_INIT_FUNC_POINTERS
)
314 fHasInitializers
= true;
315 else if ( type
== S_MOD_TERM_FUNC_POINTERS
)
316 fHasTerminators
= true;
317 else if ( type
== S_DTRACE_DOF
)
318 fHasDOFSections
= true;
319 else if ( isTextSeg
&& (strcmp(sect
->sectname
, "__eh_frame") == 0) )
320 fEHFrameSectionOffset
= (uint8_t*)sect
- fMachOData
;
321 else if ( isTextSeg
&& (strcmp(sect
->sectname
, "__unwind_info") == 0) )
322 fUnwindInfoSectionOffset
= (uint8_t*)sect
- fMachOData
;;
326 case LC_TWOLEVEL_HINTS
:
327 // no longer supported
331 fDylibIDOffset
= (uint8_t*)cmd
- fMachOData
;
335 case LC_LOAD_WEAK_DYLIB
:
336 case LC_REEXPORT_DYLIB
:
337 // do nothing, just prevent LC_REQ_DYLD exception from occuring
340 if ( (cmd
->cmd
& LC_REQ_DYLD
) != 0 )
341 dyld::throwf("unknown required load command 0x%08X", cmd
->cmd
);
343 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
346 if ( dyldInfo
!= NULL
)
347 this->setDyldInfo(dyldInfo
);
348 if ( symbolTable
!= NULL
)
349 this->setSymbolTableInfo(symbolTable
, symbolTableStrings
, dynSymbolTable
);
353 // don't do this work in destructor because we need object to be full subclass
354 // for UnmapSegments() to work
355 void ImageLoaderMachO::destroy()
357 // keep count of images with weak exports
358 if ( this->participatesInCoalescing() ) {
359 --fgImagesRequiringCoalescing
;
360 if ( this->hasCoalescedExports() )
361 --fgImagesHasWeakDefinitions
;
364 // keep count of images used in shared cache
365 if ( fInSharedCache
)
366 --fgImagesUsedFromSharedCache
;
368 // unmap image when done
373 unsigned int ImageLoaderMachO::segmentCount() const
375 return fSegmentsCount
;
379 const macho_segment_command
* ImageLoaderMachO::segLoadCommand(unsigned int segIndex
) const
381 uint32_t* lcOffsets
= this->segmentCommandOffsets();
382 uint32_t lcOffset
= lcOffsets
[segIndex
];
383 return (macho_segment_command
*)(&fMachOData
[lcOffset
]);
386 const char* ImageLoaderMachO::segName(unsigned int segIndex
) const
388 return segLoadCommand(segIndex
)->segname
;
392 uintptr_t ImageLoaderMachO::segSize(unsigned int segIndex
) const
394 return segLoadCommand(segIndex
)->vmsize
;
398 uintptr_t ImageLoaderMachO::segFileSize(unsigned int segIndex
) const
400 return segLoadCommand(segIndex
)->filesize
;
404 bool ImageLoaderMachO::segHasTrailingZeroFill(unsigned int segIndex
)
406 return ( segWriteable(segIndex
) && (segSize(segIndex
) > segFileSize(segIndex
)) );
410 uintptr_t ImageLoaderMachO::segFileOffset(unsigned int segIndex
) const
412 return segLoadCommand(segIndex
)->fileoff
;
416 bool ImageLoaderMachO::segReadable(unsigned int segIndex
) const
418 return ( (segLoadCommand(segIndex
)->initprot
& VM_PROT_READ
) != 0);
422 bool ImageLoaderMachO::segWriteable(unsigned int segIndex
) const
424 return ( (segLoadCommand(segIndex
)->initprot
& VM_PROT_WRITE
) != 0);
428 bool ImageLoaderMachO::segExecutable(unsigned int segIndex
) const
430 return ( (segLoadCommand(segIndex
)->initprot
& VM_PROT_EXECUTE
) != 0);
434 bool ImageLoaderMachO::segUnaccessible(unsigned int segIndex
) const
436 return (segLoadCommand(segIndex
)->initprot
== 0);
439 bool ImageLoaderMachO::segHasPreferredLoadAddress(unsigned int segIndex
) const
441 return (segLoadCommand(segIndex
)->vmaddr
!= 0);
444 uintptr_t ImageLoaderMachO::segPreferredLoadAddress(unsigned int segIndex
) const
446 return segLoadCommand(segIndex
)->vmaddr
;
449 uintptr_t ImageLoaderMachO::segActualLoadAddress(unsigned int segIndex
) const
451 return segLoadCommand(segIndex
)->vmaddr
+ fSlide
;
455 uintptr_t ImageLoaderMachO::segActualEndAddress(unsigned int segIndex
) const
457 return segActualLoadAddress(segIndex
) + segSize(segIndex
);
460 bool ImageLoaderMachO::segHasRebaseFixUps(unsigned int segIndex
) const
462 // scan sections for fix-up bit
463 const macho_segment_command
* segCmd
= segLoadCommand(segIndex
);
464 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)segCmd
+ sizeof(struct macho_segment_command
));
465 const struct macho_section
* const sectionsEnd
= §ionsStart
[segCmd
->nsects
];
466 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
467 if ( (sect
->flags
& S_ATTR_LOC_RELOC
) != 0 )
473 bool ImageLoaderMachO::segHasBindFixUps(unsigned int segIndex
) const
475 // scan sections for fix-up bit
476 const macho_segment_command
* segCmd
= segLoadCommand(segIndex
);
477 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)segCmd
+ sizeof(struct macho_segment_command
));
478 const struct macho_section
* const sectionsEnd
= §ionsStart
[segCmd
->nsects
];
479 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
480 if ( (sect
->flags
& S_ATTR_EXT_RELOC
) != 0 )
487 bool ImageLoaderMachO::segIsReadOnlyImport(unsigned int segIndex
) const
489 const macho_segment_command
* segCmd
= segLoadCommand(segIndex
);
490 return ( (segCmd
->initprot
& VM_PROT_EXECUTE
)
491 && ((segCmd
->initprot
& VM_PROT_WRITE
) == 0)
492 && (strcmp(segCmd
->segname
, "__IMPORT") == 0) );
497 void ImageLoaderMachO::UnmapSegments()
499 // usually unmap image when done
500 if ( ! this->leaveMapped() && (this->getState() >= dyld_image_state_mapped
) ) {
501 // unmap TEXT segment last because it contains load command being inspected
502 unsigned int textSegmentIndex
= 0;
503 for(unsigned int i
=0; i
< fSegmentsCount
; ++i
) {
504 //dyld::log("unmap %s at 0x%08lX\n", seg->getName(), seg->getActualLoadAddress(this));
505 if ( strcmp(segName(i
), "__TEXT") == 0 ) {
506 textSegmentIndex
= i
;
510 --ImageLoader::fgTotalSegmentsMapped
;
511 ImageLoader::fgTotalBytesMapped
-= segSize(i
);
512 munmap((void*)segActualLoadAddress(i
), segSize(i
));
516 --ImageLoader::fgTotalSegmentsMapped
;
517 ImageLoader::fgTotalBytesMapped
-= segSize(textSegmentIndex
);
518 munmap((void*)segActualLoadAddress(textSegmentIndex
), segSize(textSegmentIndex
));
523 // prefetch __DATA/__OBJC pages during launch, but not for dynamically loaded code
524 void ImageLoaderMachO::preFetchDATA(int fd
, uint64_t offsetInFat
, const LinkContext
& context
)
526 if ( context
.linkingMainExecutable
) {
527 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
528 if ( segWriteable(i
) && (segFileSize(i
) > 0) ) {
529 // prefetch writable segment that have mmap'ed regions
531 advice
.ra_offset
= offsetInFat
+ segFileOffset(i
);
532 advice
.ra_count
= segFileSize(i
);
533 // limit prefetch to 1MB (256 pages)
534 if ( advice
.ra_count
> 1024*1024 )
535 advice
.ra_count
= 1024*1024;
536 // don't prefetch single pages, let them fault in
537 fgTotalBytesPreFetched
+= advice
.ra_count
;
538 fcntl(fd
, F_RDADVISE
, &advice
);
539 if ( context
.verboseMapping
) {
540 dyld::log("%18s prefetching 0x%0lX -> 0x%0lX\n",
541 segName(i
), segActualLoadAddress(i
), segActualLoadAddress(i
)+advice
.ra_count
-1);
549 bool ImageLoaderMachO::segmentsMustSlideTogether() const
554 bool ImageLoaderMachO::segmentsCanSlide() const
556 return (this->isDylib() || this->isBundle() || this->isPositionIndependentExecutable());
559 bool ImageLoaderMachO::isBundle() const
561 const macho_header
* mh
= (macho_header
*)fMachOData
;
562 return ( mh
->filetype
== MH_BUNDLE
);
565 bool ImageLoaderMachO::isDylib() const
567 const macho_header
* mh
= (macho_header
*)fMachOData
;
568 return ( mh
->filetype
== MH_DYLIB
);
571 bool ImageLoaderMachO::isExecutable() const
573 const macho_header
* mh
= (macho_header
*)fMachOData
;
574 return ( mh
->filetype
== MH_EXECUTE
);
577 bool ImageLoaderMachO::isPositionIndependentExecutable() const
579 const macho_header
* mh
= (macho_header
*)fMachOData
;
580 return ( (mh
->filetype
== MH_EXECUTE
) && ((mh
->flags
& MH_PIE
) != 0) );
584 bool ImageLoaderMachO::forceFlat() const
586 const macho_header
* mh
= (macho_header
*)fMachOData
;
587 return ( (mh
->flags
& MH_FORCE_FLAT
) != 0 );
590 bool ImageLoaderMachO::usesTwoLevelNameSpace() const
592 const macho_header
* mh
= (macho_header
*)fMachOData
;
593 return ( (mh
->flags
& MH_TWOLEVEL
) != 0 );
596 bool ImageLoaderMachO::isPrebindable() const
598 const macho_header
* mh
= (macho_header
*)fMachOData
;
599 return ( (mh
->flags
& MH_PREBOUND
) != 0 );
602 bool ImageLoaderMachO::hasCoalescedExports() const
604 const macho_header
* mh
= (macho_header
*)fMachOData
;
605 return ( (mh
->flags
& MH_WEAK_DEFINES
) != 0 );
608 bool ImageLoaderMachO::hasReferencesToWeakSymbols() const
610 const macho_header
* mh
= (macho_header
*)fMachOData
;
611 return ( (mh
->flags
& MH_BINDS_TO_WEAK
) != 0 );
614 bool ImageLoaderMachO::participatesInCoalescing() const
616 const macho_header
* mh
= (macho_header
*)fMachOData
;
617 // if image is loaded with RTLD_LOCAL, then its symbols' visibility
618 // is reduced and it can't coalesce with other images
619 if ( this->hasHiddenExports() )
621 return ( (mh
->flags
& (MH_WEAK_DEFINES
|MH_BINDS_TO_WEAK
)) != 0 );
626 void ImageLoaderMachO::setSlide(intptr_t slide
)
631 #if CODESIGNING_SUPPORT
632 void ImageLoaderMachO::loadCodeSignature(const uint8_t* fileData
, int fd
, uint64_t offsetInFatFile
)
634 // look for code signature load command
635 // do this in the read() memory buffer - not in the mapped __TEXT segment
636 const uint32_t cmd_count
= ((macho_header
*)fileData
)->ncmds
;
637 const struct load_command
* const cmds
= (struct load_command
*)&fileData
[sizeof(macho_header
)];
638 const struct load_command
* cmd
= cmds
;
639 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
640 if ( cmd
->cmd
== LC_CODE_SIGNATURE
) {
641 const struct linkedit_data_command
*sigcmd
= (struct linkedit_data_command
*) cmd
;
642 // fLinkEditBase is not set up yet, so compute it
643 const uint8_t* linkEditBase
= NULL
;
644 for(unsigned int i
=0; i
< fSegmentsCount
; ++i
) {
645 // set up pointer to __LINKEDIT segment
646 if ( strcmp(segName(i
),"__LINKEDIT") == 0 ) {
647 linkEditBase
= (uint8_t*)(segActualLoadAddress(i
) - segFileOffset(i
));
651 fsignatures_t siginfo
;
652 siginfo
.fs_file_start
=offsetInFatFile
; // CD coverage offset
653 siginfo
.fs_blob_start
=(void*)(linkEditBase
+sigcmd
->dataoff
); // start of CD in file
654 siginfo
.fs_blob_size
=sigcmd
->datasize
; // size of CD
655 int result
= fcntl(fd
, F_ADDSIGS
, &siginfo
);
657 dyld::log("dyld: code signature failed for %s with errno=%d\n", this->getPath(), errno
);
658 break; // only support one LC_CODE_SIGNATURE
660 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
666 const char* ImageLoaderMachO::getInstallPath() const
668 if ( fDylibIDOffset
!= 0 ) {
669 const dylib_command
* dylibID
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]);
670 return (char*)dylibID
+ dylibID
->dylib
.name
.offset
;
677 void* ImageLoaderMachO::getMain() const
679 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
680 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
681 const struct load_command
* cmd
= cmds
;
682 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
687 const ppc_thread_state_t
* registers
= (ppc_thread_state_t
*)(((char*)cmd
) + 16);
688 return (void*)(registers
->srr0
+ fSlide
);
690 const ppc_thread_state64_t
* registers
= (ppc_thread_state64_t
*)(((char*)cmd
) + 16);
691 return (void*)(registers
->srr0
+ fSlide
);
693 const i386_thread_state_t
* registers
= (i386_thread_state_t
*)(((char*)cmd
) + 16);
694 return (void*)(registers
->eip
+ fSlide
);
696 const x86_thread_state64_t
* registers
= (x86_thread_state64_t
*)(((char*)cmd
) + 16);
697 return (void*)(registers
->rip
+ fSlide
);
699 const arm_thread_state_t
* registers
= (arm_thread_state_t
*)(((char*)cmd
) + 16);
700 return (void*)(registers
->__pc
+ fSlide
);
702 #warning need processor specific code
707 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
712 bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount
, const macho_header
* mh
)
714 // <rdar://problem/6357561> ensure that every image depends on something which depends on libSystem
718 // <rdar://problem/6409800> dyld implicit-libSystem breaks valgrind
719 if ( mh
->filetype
== MH_EXECUTE
)
722 bool isNonOSdylib
= false;
723 const uint32_t cmd_count
= mh
->ncmds
;
724 const struct load_command
* const cmds
= (struct load_command
*)((uint8_t*)mh
+sizeof(macho_header
));
725 const struct load_command
* cmd
= cmds
;
726 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
729 case LC_LOAD_WEAK_DYLIB
:
730 case LC_REEXPORT_DYLIB
:
734 const dylib_command
* dylibID
= (dylib_command
*)cmd
;
735 const char* installPath
= (char*)cmd
+ dylibID
->dylib
.name
.offset
;
736 // It is OK for OS dylibs (libSystem or libmath or Rosetta shims) to have no dependents
737 // but all other dylibs must depend on libSystem for initialization to initialize libSystem first
738 // <rdar://problem/6497528> rosetta circular dependency spew
739 isNonOSdylib
= ( (strncmp(installPath
, "/usr/lib/", 9) != 0) && (strncmp(installPath
, "/usr/libexec/oah/Shims", 9) != 0) );
743 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
749 void ImageLoaderMachO::doGetDependentLibraries(DependentLibraryInfo libs
[])
751 if ( needsAddedLibSystemDepency(libraryCount(), (macho_header
*)fMachOData
) ) {
752 DependentLibraryInfo
* lib
= &libs
[0];
753 lib
->name
= "/usr/lib/libSystem.B.dylib";
754 lib
->info
.checksum
= 0;
755 lib
->info
.minVersion
= 0;
756 lib
->info
.maxVersion
= 0;
757 lib
->required
= false;
758 lib
->reExported
= false;
762 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
763 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
764 const struct load_command
* cmd
= cmds
;
765 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
768 case LC_LOAD_WEAK_DYLIB
:
769 case LC_REEXPORT_DYLIB
:
771 const struct dylib_command
* dylib
= (struct dylib_command
*)cmd
;
772 DependentLibraryInfo
* lib
= &libs
[index
++];
773 lib
->name
= (char*)cmd
+ dylib
->dylib
.name
.offset
;
774 //lib->name = strdup((char*)cmd + dylib->dylib.name.offset);
775 lib
->info
.checksum
= dylib
->dylib
.timestamp
;
776 lib
->info
.minVersion
= dylib
->dylib
.compatibility_version
;
777 lib
->info
.maxVersion
= dylib
->dylib
.current_version
;
778 lib
->required
= (cmd
->cmd
!= LC_LOAD_WEAK_DYLIB
);
779 lib
->reExported
= (cmd
->cmd
== LC_REEXPORT_DYLIB
);
783 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
788 ImageLoader::LibraryInfo
ImageLoaderMachO::doGetLibraryInfo()
791 if ( fDylibIDOffset
!= 0 ) {
792 const dylib_command
* dylibID
= (dylib_command
*)(&fMachOData
[fDylibIDOffset
]);
793 info
.minVersion
= dylibID
->dylib
.compatibility_version
;
794 info
.maxVersion
= dylibID
->dylib
.current_version
;
795 info
.checksum
= dylibID
->dylib
.timestamp
;
805 void ImageLoaderMachO::getRPaths(const LinkContext
& context
, std::vector
<const char*>& paths
) const
807 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
808 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
809 const struct load_command
* cmd
= cmds
;
810 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
813 const char* path
= (char*)cmd
+ ((struct rpath_command
*)cmd
)->path
.offset
;
814 if ( strncmp(path
, "@loader_path/", 13) == 0 ) {
815 if ( context
.processIsRestricted
&& (context
.mainExecutable
== this) ) {
816 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @loader_path\n", path
, this->getPath());
819 char resolvedPath
[PATH_MAX
];
820 if ( realpath(this->getPath(), resolvedPath
) != NULL
) {
821 char newRealPath
[strlen(resolvedPath
) + strlen(path
)];
822 strcpy(newRealPath
, resolvedPath
);
823 char* addPoint
= strrchr(newRealPath
,'/');
824 if ( addPoint
!= NULL
)
825 strcpy(&addPoint
[1], &path
[13]);
827 strcpy(newRealPath
, &path
[13]);
828 path
= strdup(newRealPath
);
831 else if ( strncmp(path
, "@executable_path/", 17) == 0 ) {
832 if ( context
.processIsRestricted
) {
833 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because of @executable_path\n", path
, this->getPath());
836 char resolvedPath
[PATH_MAX
];
837 if ( realpath(context
.mainExecutable
->getPath(), resolvedPath
) != NULL
) {
838 char newRealPath
[strlen(resolvedPath
) + strlen(path
)];
839 strcpy(newRealPath
, resolvedPath
);
840 char* addPoint
= strrchr(newRealPath
,'/');
841 if ( addPoint
!= NULL
)
842 strcpy(&addPoint
[1], &path
[17]);
844 strcpy(newRealPath
, &path
[17]);
845 path
= strdup(newRealPath
);
848 else if ( (path
[0] != '/') && context
.processIsRestricted
) {
849 dyld::warn("LC_RPATH %s in %s being ignored in restricted program because it is a relative path\n", path
, this->getPath());
852 else if ( (path
[0] == '/') && (context
.rootPaths
!= NULL
) ) {
853 // <rdar://problem/5869973> DYLD_ROOT_PATH should apply to LC_RPATH rpaths
854 // DYLD_ROOT_PATH can be a list of paths, but at this point we can only support one, so use first combination that exists
856 for(const char** rp
= context
.rootPaths
; *rp
!= NULL
; ++rp
) {
857 char newPath
[PATH_MAX
];
858 strcpy(newPath
, *rp
);
859 strcat(newPath
, path
);
860 struct stat stat_buf
;
861 if ( stat(newPath
, &stat_buf
) != -1 ) {
862 //dyld::log("combined DYLD_ROOT_PATH and LC_RPATH: %s\n", newPath);
863 path
= strdup(newPath
);
869 // make copy so that all elements of 'paths' can be freed
874 // make copy so that all elements of 'paths' can be freed
877 paths
.push_back(path
);
880 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
884 bool ImageLoaderMachO::getUUID(uuid_t uuid
) const
886 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
887 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
888 const struct load_command
* cmd
= cmds
;
889 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
892 uuid_command
* uc
= (uuid_command
*)cmd
;
893 memcpy(uuid
, uc
->uuid
, 16);
896 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
902 void ImageLoaderMachO::doRebase(const LinkContext
& context
)
904 // if prebound and loaded at prebound address, then no need to rebase
905 if ( this->usablePrebinding(context
) ) {
906 // skip rebasing because prebinding is valid
907 ++fgImagesWithUsedPrebinding
; // bump totals for statistics
911 // print why prebinding was not used
912 if ( context
.verbosePrebinding
) {
913 if ( !this->isPrebindable() ) {
914 dyld::log("dyld: image not prebound, so could not use prebinding in %s\n", this->getPath());
916 else if ( fSlide
!= 0 ) {
917 dyld::log("dyld: image slid, so could not use prebinding in %s\n", this->getPath());
919 else if ( !this->allDependentLibrariesAsWhenPreBound() ) {
920 dyld::log("dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath());
922 else if ( !this->usesTwoLevelNameSpace() ){
923 dyld::log("dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath());
926 dyld::log("dyld: environment variable disabled use of prebinding in %s\n", this->getPath());
930 //dyld::log("slide=0x%08lX for %s\n", slide, this->getPath());
932 #if PREBOUND_IMAGE_SUPPORT
933 // if prebound and we got here, then prebinding is not valid, so reset all lazy pointers
934 // if this image is in the shared cache, do not reset, they will be bound in doBind()
935 if ( this->isPrebindable() && !fInSharedCache
)
936 this->resetPreboundLazyPointers(context
);
939 // if loaded at preferred address, no rebasing necessary
940 if ( this->fSlide
== 0 )
943 #if TEXT_RELOC_SUPPORT
944 // if there are __TEXT fixups, temporarily make __TEXT writable
945 if ( fTextSegmentRebases
)
946 this->makeTextSegmentWritable(context
, true);
949 // do actual rebasing
950 this->rebase(context
);
952 #if TEXT_RELOC_SUPPORT
953 // if there were __TEXT fixups, restore write protection
954 if ( fTextSegmentRebases
)
955 this->makeTextSegmentWritable(context
, false);
960 #if TEXT_RELOC_SUPPORT
961 void ImageLoaderMachO::makeTextSegmentWritable(const LinkContext
& context
, bool writeable
)
963 int textSegmentIndex
= 0;
964 for(unsigned int i
=0; i
< fSegmentsCount
; ++i
) {
965 if ( strcmp(segName(i
), "__TEXT") == 0 ) {
966 textSegmentIndex
= i
;
972 segMakeWritable(textSegmentIndex
, context
);
975 segProtect(textSegmentIndex
, context
);
976 sys_icache_invalidate((void*)segActualLoadAddress(textSegmentIndex
), segSize(textSegmentIndex
));
981 const ImageLoader::Symbol
* ImageLoaderMachO::findExportedSymbol(const char* name
, bool searchReExports
, const ImageLoader
** foundIn
) const
983 // look in this image first
984 const ImageLoader::Symbol
* result
= this->findExportedSymbol(name
, foundIn
);
985 if ( result
!= NULL
)
988 if ( searchReExports
) {
989 for(unsigned int i
=0; i
< libraryCount(); ++i
){
990 if ( libReExported(i
) ) {
991 ImageLoader
* image
= libImage(i
);
992 if ( image
!= NULL
) {
993 const Symbol
* result
= image
->findExportedSymbol(name
, searchReExports
, foundIn
);
994 if ( result
!= NULL
)
1007 uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
, const ImageLoader
* requestor
) const
1009 return this->getSymbolAddress(sym
, requestor
, context
);
1012 uintptr_t ImageLoaderMachO::getSymbolAddress(const Symbol
* sym
, const ImageLoader
* requestor
, const LinkContext
& context
) const
1014 uintptr_t result
= exportedSymbolAddress(sym
);
1018 ImageLoader::DefinitionFlags
ImageLoaderMachO::getExportedSymbolInfo(const Symbol
* sym
) const
1020 if ( exportedSymbolIsWeakDefintion(sym
) )
1021 return kWeakDefinition
;
1023 return kNoDefinitionOptions
;
1026 const char* ImageLoaderMachO::getExportedSymbolName(const Symbol
* sym
) const
1028 return exportedSymbolName(sym
);
1031 uint32_t ImageLoaderMachO::getExportedSymbolCount() const
1033 return exportedSymbolCount();
1037 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index
) const
1039 return exportedSymbolIndexed(index
);
1043 uint32_t ImageLoaderMachO::getImportedSymbolCount() const
1045 return importedSymbolCount();
1049 const ImageLoader::Symbol
* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index
) const
1051 return importedSymbolIndexed(index
);
1055 ImageLoader::ReferenceFlags
ImageLoaderMachO::getImportedSymbolInfo(const ImageLoader::Symbol
* sym
) const
1057 ImageLoader::ReferenceFlags flags
= kNoReferenceOptions
;
1062 const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol
* sym
) const
1064 return importedSymbolName(sym
);
1068 bool ImageLoaderMachO::getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
)
1070 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1071 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1072 const struct load_command
* cmd
= cmds
;
1073 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1075 case LC_SEGMENT_COMMAND
:
1077 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1078 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1079 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1080 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1081 if ( (strcmp(sect
->segname
, segmentName
) == 0) && (strcmp(sect
->sectname
, sectionName
) == 0) ) {
1082 *start
= (uintptr_t*)(sect
->addr
+ fSlide
);
1083 *length
= sect
->size
;
1090 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1097 void ImageLoaderMachO::getUnwindInfo(dyld_unwind_sections
* info
)
1099 info
->mh
= this->machHeader();
1100 info
->dwarf_section
= 0;
1101 info
->dwarf_section_length
= 0;
1102 info
->compact_unwind_section
= 0;
1103 info
->compact_unwind_section_length
= 0;
1104 if ( fEHFrameSectionOffset
!= 0 ) {
1105 const macho_section
* sect
= (macho_section
*)&fMachOData
[fEHFrameSectionOffset
];
1106 info
->dwarf_section
= (void*)(sect
->addr
+ fSlide
);
1107 info
->dwarf_section_length
= sect
->size
;
1109 if ( fUnwindInfoSectionOffset
!= 0 ) {
1110 const macho_section
* sect
= (macho_section
*)&fMachOData
[fUnwindInfoSectionOffset
];
1111 info
->compact_unwind_section
= (void*)(sect
->addr
+ fSlide
);
1112 info
->compact_unwind_section_length
= sect
->size
;
1117 bool ImageLoaderMachO::findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
)
1119 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1120 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1121 const struct load_command
* cmd
= cmds
;
1122 const uintptr_t unslidInteriorAddress
= (uintptr_t)imageInterior
- this->getSlide();
1123 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1125 case LC_SEGMENT_COMMAND
:
1127 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1128 if ( (unslidInteriorAddress
>= seg
->vmaddr
) && (unslidInteriorAddress
< (seg
->vmaddr
+seg
->vmsize
)) ) {
1129 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1130 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1131 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1132 if ((sect
->addr
<= unslidInteriorAddress
) && (unslidInteriorAddress
< (sect
->addr
+sect
->size
))) {
1133 if ( segmentName
!= NULL
)
1134 *segmentName
= sect
->segname
;
1135 if ( sectionName
!= NULL
)
1136 *sectionName
= sect
->sectname
;
1137 if ( sectionOffset
!= NULL
)
1138 *sectionOffset
= unslidInteriorAddress
- sect
->addr
;
1146 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1152 void __attribute__((noreturn
)) ImageLoaderMachO::throwSymbolNotFound(const char* symbol
, const char* referencedFrom
, const char* expectedIn
)
1154 dyld::throwf("Symbol not found: %s\n Referenced from: %s\n Expected in: %s\n", symbol
, referencedFrom
, expectedIn
);
1157 const mach_header
* ImageLoaderMachO::machHeader() const
1159 return (mach_header
*)fMachOData
;
1162 uintptr_t ImageLoaderMachO::getSlide() const
1167 // hmm. maybe this should be up in ImageLoader??
1168 const void* ImageLoaderMachO::getEnd() const
1170 uintptr_t lastAddress
= 0;
1171 for(unsigned int i
=0; i
< fSegmentsCount
; ++i
) {
1172 uintptr_t segEnd
= segActualEndAddress(i
);
1173 if ( strcmp(segName(i
), "__UNIXSTACK") != 0 ) {
1174 if ( segEnd
> lastAddress
)
1175 lastAddress
= segEnd
;
1178 return (const void*)lastAddress
;
1182 uintptr_t ImageLoaderMachO::bindLocation(const LinkContext
& context
, uintptr_t location
, uintptr_t value
,
1183 const ImageLoader
* targetImage
, uint8_t type
, const char* symbolName
,
1184 intptr_t addend
, const char* msg
)
1187 if ( context
.verboseBind
) {
1189 dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX + %ld\n",
1190 msg
, this->getShortName(), (uintptr_t)location
,
1191 ((targetImage
!= NULL
) ? targetImage
->getShortName() : "<weak_import-missing>"),
1192 symbolName
, (uintptr_t)location
, value
, addend
);
1194 dyld::log("dyld: %sbind: %s:0x%08lX = %s:%s, *0x%08lX = 0x%08lX\n",
1195 msg
, this->getShortName(), (uintptr_t)location
,
1196 ((targetImage
!= NULL
) ? targetImage
->getShortName() : "<weak>import-missing>"),
1197 symbolName
, (uintptr_t)location
, value
);
1201 uintptr_t* locationToFix
= (uintptr_t*)location
;
1203 uintptr_t newValue
= value
+addend
;
1206 case BIND_TYPE_POINTER
:
1207 // test first so we don't needless dirty pages
1208 if ( *locationToFix
!= newValue
)
1209 *locationToFix
= newValue
;
1211 case BIND_TYPE_TEXT_ABSOLUTE32
:
1212 loc32
= (uint32_t*)locationToFix
;
1213 value32
= (uint32_t)newValue
;
1214 if ( *loc32
!= value32
)
1217 case BIND_TYPE_TEXT_PCREL32
:
1218 loc32
= (uint32_t*)locationToFix
;
1219 value32
= (uint32_t)newValue
- (((uintptr_t)locationToFix
) + 4);
1220 if ( *loc32
!= value32
)
1224 dyld::throwf("bad bind type %d", type
);
1227 // update statistics
1228 ++fgTotalBindFixups
;
1237 #if SUPPORT_OLD_CRT_INITIALIZATION
1238 // first 16 bytes of "start" in crt1.o
1240 static uint32_t sStandardEntryPointInstructions
[4] = { 0x7c3a0b78, 0x3821fffc, 0x54210034, 0x38000000 };
1242 static uint8_t sStandardEntryPointInstructions
[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 };
1247 void* dyldLazyBinder
; // filled in at launch by dyld to point into dyld to &stub_binding_helper_interface
1248 void* dyldFuncLookup
; // filled in at launch by dyld to point into dyld to &_dyld_func_lookup
1249 // the following only exist in main executables built for 10.5 or later
1253 // These are defined in dyldStartup.s
1254 extern "C" void stub_binding_helper();
1255 extern "C" bool dyld_func_lookup(const char* name
, uintptr_t* address
);
1258 void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext
& context
)
1260 const macho_header
* mh
= (macho_header
*)fMachOData
;
1261 const uint32_t cmd_count
= mh
->ncmds
;
1262 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1263 const struct load_command
* cmd
;
1264 // set up __dyld section
1266 // 1) do nothing if image is in dyld shared cache and dyld loaded at same address as when cache built
1267 // 2) first read __dyld value, if already correct don't write, this prevents dirtying a page
1268 if ( !fInSharedCache
|| !context
.dyldLoadedAtSameAddressNeededBySharedCache
) {
1270 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1271 if ( cmd
->cmd
== LC_SEGMENT_COMMAND
) {
1272 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1273 if ( strcmp(seg
->segname
, "__DATA") == 0 ) {
1274 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1275 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1276 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1277 if ( strcmp(sect
->sectname
, "__dyld" ) == 0 ) {
1278 struct DATAdyld
* dd
= (struct DATAdyld
*)(sect
->addr
+ fSlide
);
1279 if ( sect
->size
> offsetof(DATAdyld
, dyldLazyBinder
) ) {
1280 if ( dd
->dyldLazyBinder
!= (void*)&stub_binding_helper
)
1281 dd
->dyldLazyBinder
= (void*)&stub_binding_helper
;
1283 if ( sect
->size
> offsetof(DATAdyld
, dyldFuncLookup
) ) {
1284 if ( dd
->dyldFuncLookup
!= (void*)&dyld_func_lookup
)
1285 dd
->dyldFuncLookup
= (void*)&dyld_func_lookup
;
1287 if ( mh
->filetype
== MH_EXECUTE
) {
1288 // there are two ways to get the program variables
1289 if ( (sect
->size
> offsetof(DATAdyld
, vars
)) && (dd
->vars
.mh
== mh
) ) {
1290 // some really old binaries have space for vars, but it is zero filled
1291 // main executable has 10.5 style __dyld section that has program variable pointers
1292 context
.setNewProgramVars(dd
->vars
);
1295 // main executable is pre-10.5 and requires the symbols names to be looked up
1296 this->lookupProgramVars(context
);
1297 #if SUPPORT_OLD_CRT_INITIALIZATION
1298 // If the first 16 bytes of the entry point's instructions do not
1299 // match what crt1.o supplies, then the program has a custom entry point.
1300 // This means it might be doing something that needs to be executed before
1301 // initializers are run.
1302 if ( memcmp(this->getMain(), sStandardEntryPointInstructions
, 16) != 0 ) {
1303 if ( context
.verboseInit
)
1304 dyld::log("dyld: program uses non-standard entry point so delaying running of initializers\n");
1305 context
.setRunInitialzersOldWay();
1311 else if ( (strcmp(sect
->sectname
, "__program_vars" ) == 0) && (mh
->filetype
== MH_EXECUTE
) ) {
1312 // this is a Mac OS X 10.6 or later main executable
1313 struct ProgramVars
* pv
= (struct ProgramVars
*)(sect
->addr
+ fSlide
);
1314 context
.setNewProgramVars(*pv
);
1319 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1325 void ImageLoaderMachO::lookupProgramVars(const LinkContext
& context
) const
1327 ProgramVars vars
= context
.programVars
;
1328 const ImageLoader::Symbol
* sym
;
1330 // get mach header directly
1331 vars
.mh
= (macho_header
*)fMachOData
;
1334 sym
= this->findExportedSymbol("_NXArgc", false, NULL
);
1336 vars
.NXArgcPtr
= (int*)this->getExportedSymbolAddress(sym
, context
, this);
1339 sym
= this->findExportedSymbol("_NXArgv", false, NULL
);
1341 vars
.NXArgvPtr
= (const char***)this->getExportedSymbolAddress(sym
, context
, this);
1344 sym
= this->findExportedSymbol("_environ", false, NULL
);
1346 vars
.environPtr
= (const char***)this->getExportedSymbolAddress(sym
, context
, this);
1348 // lookup __progname
1349 sym
= this->findExportedSymbol("___progname", false, NULL
);
1351 vars
.__prognamePtr
= (const char**)this->getExportedSymbolAddress(sym
, context
, this);
1353 context
.setNewProgramVars(vars
);
1357 bool ImageLoaderMachO::usablePrebinding(const LinkContext
& context
) const
1359 // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
1360 if ( (this->isPrebindable() || fInSharedCache
)
1361 && (this->getSlide() == 0)
1362 && this->usesTwoLevelNameSpace()
1363 && this->allDependentLibrariesAsWhenPreBound() ) {
1364 // allow environment variables to disable prebinding
1365 if ( context
.bindFlat
)
1367 switch ( context
.prebindUsage
) {
1368 case kUseAllPrebinding
:
1370 case kUseSplitSegPrebinding
:
1371 return this->fIsSplitSeg
;
1372 case kUseAllButAppPredbinding
:
1373 return (this != context
.mainExecutable
);
1374 case kUseNoPrebinding
:
1382 void ImageLoaderMachO::doImageInit(const LinkContext
& context
)
1384 if ( fHasDashInit
) {
1385 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1386 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1387 const struct load_command
* cmd
= cmds
;
1388 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1390 case LC_ROUTINES_COMMAND
:
1391 Initializer func
= (Initializer
)(((struct macho_routines_command
*)cmd
)->init_address
+ fSlide
);
1392 if ( context
.verboseInit
)
1393 dyld::log("dyld: calling -init function 0x%p in %s\n", func
, this->getPath());
1394 func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
);
1397 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1402 void ImageLoaderMachO::doModInitFunctions(const LinkContext
& context
)
1404 if ( fHasInitializers
) {
1405 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1406 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1407 const struct load_command
* cmd
= cmds
;
1408 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1409 if ( cmd
->cmd
== LC_SEGMENT_COMMAND
) {
1410 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1411 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1412 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1413 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1414 const uint8_t type
= sect
->flags
& SECTION_TYPE
;
1415 if ( type
== S_MOD_INIT_FUNC_POINTERS
) {
1416 Initializer
* inits
= (Initializer
*)(sect
->addr
+ fSlide
);
1417 const uint32_t count
= sect
->size
/ sizeof(uintptr_t);
1418 for (uint32_t i
=0; i
< count
; ++i
) {
1419 Initializer func
= inits
[i
];
1420 if ( context
.verboseInit
)
1421 dyld::log("dyld: calling initializer function %p in %s\n", func
, this->getPath());
1422 func(context
.argc
, context
.argv
, context
.envp
, context
.apple
, &context
.programVars
);
1426 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1437 void ImageLoaderMachO::doGetDOFSections(const LinkContext
& context
, std::vector
<ImageLoader::DOFInfo
>& dofs
)
1439 if ( fHasDOFSections
) {
1440 // walk load commands (mapped in at start of __TEXT segment)
1441 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1442 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1443 const struct load_command
* cmd
= cmds
;
1444 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1446 case LC_SEGMENT_COMMAND
:
1448 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1449 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1450 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1451 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1452 if ( (sect
->flags
& SECTION_TYPE
) == S_DTRACE_DOF
) {
1453 ImageLoader::DOFInfo info
;
1454 info
.dof
= (void*)(sect
->addr
+ fSlide
);
1455 info
.imageHeader
= this->machHeader();
1456 info
.imageShortName
= this->getShortName();
1457 dofs
.push_back(info
);
1463 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1469 void ImageLoaderMachO::doInitialization(const LinkContext
& context
)
1471 // mach-o has -init and static initializers
1472 doImageInit(context
);
1473 doModInitFunctions(context
);
1476 bool ImageLoaderMachO::needsInitialization()
1478 return ( fHasDashInit
|| fHasInitializers
);
1482 bool ImageLoaderMachO::needsTermination()
1484 return fHasTerminators
;
1488 void ImageLoaderMachO::doTermination(const LinkContext
& context
)
1490 if ( fHasTerminators
) {
1491 const uint32_t cmd_count
= ((macho_header
*)fMachOData
)->ncmds
;
1492 const struct load_command
* const cmds
= (struct load_command
*)&fMachOData
[sizeof(macho_header
)];
1493 const struct load_command
* cmd
= cmds
;
1494 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1495 if ( cmd
->cmd
== LC_SEGMENT_COMMAND
) {
1496 const struct macho_segment_command
* seg
= (struct macho_segment_command
*)cmd
;
1497 const struct macho_section
* const sectionsStart
= (struct macho_section
*)((char*)seg
+ sizeof(struct macho_segment_command
));
1498 const struct macho_section
* const sectionsEnd
= §ionsStart
[seg
->nsects
];
1499 for (const struct macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1500 const uint8_t type
= sect
->flags
& SECTION_TYPE
;
1501 if ( type
== S_MOD_TERM_FUNC_POINTERS
) {
1502 Terminator
* terms
= (Terminator
*)(sect
->addr
+ fSlide
);
1503 const uint32_t count
= sect
->size
/ sizeof(uintptr_t);
1504 for (uint32_t i
=count
; i
> 0; --i
) {
1505 Terminator func
= terms
[i
-1];
1506 if ( context
.verboseInit
)
1507 dyld::log("dyld: calling termination function %p in %s\n", func
, this->getPath());
1513 cmd
= (const struct load_command
*)(((char*)cmd
)+cmd
->cmdsize
);
1519 void ImageLoaderMachO::printStatistics(unsigned int imageCount
)
1521 ImageLoader::printStatistics(imageCount
);
1522 dyld::log("total symbol trie searches: %d\n", fgSymbolTrieSearchs
);
1523 dyld::log("total symbol table binary searches: %d\n", fgSymbolTableBinarySearchs
);
1524 dyld::log("total images defining/using weak symbols: %u/%u\n", fgImagesHasWeakDefinitions
, fgImagesRequiringCoalescing
);
1528 intptr_t ImageLoaderMachO::assignSegmentAddresses(const LinkContext
& context
)
1530 // preflight and calculate slide if needed
1531 const bool inPIE
= (fgNextPIEDylibAddress
!= 0);
1533 if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) {
1534 bool needsToSlide
= false;
1535 bool imageHasPreferredLoadAddress
= segHasPreferredLoadAddress(0);
1536 uintptr_t lowAddr
= (unsigned long)(-1);
1537 uintptr_t highAddr
= 0;
1538 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
1539 const uintptr_t segLow
= segPreferredLoadAddress(i
);
1540 const uintptr_t segHigh
= (segLow
+ segSize(i
) + 4095) & -4096;
1541 if ( segLow
< lowAddr
)
1543 if ( segHigh
> highAddr
)
1546 if ( needsToSlide
|| !imageHasPreferredLoadAddress
|| inPIE
|| !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) )
1547 needsToSlide
= true;
1549 if ( needsToSlide
) {
1550 // find a chunk of address space to hold all segments
1551 uintptr_t addr
= reserveAnAddressRange(highAddr
-lowAddr
, context
);
1552 slide
= addr
- lowAddr
;
1555 else if ( ! this->segmentsCanSlide() ) {
1556 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
1557 if ( strcmp(segName(i
), "__PAGEZERO") == 0 )
1559 if ( !reserveAddressRange(segPreferredLoadAddress(i
), segSize(i
)) )
1564 throw "mach-o does not support independently sliding segments";
1570 uintptr_t ImageLoaderMachO::reserveAnAddressRange(size_t length
, const ImageLoader::LinkContext
& context
)
1572 vm_address_t addr
= 0;
1573 vm_size_t size
= length
;
1574 // in PIE programs, load initial dylibs after main executable so they don't have fixed addresses either
1575 if ( fgNextPIEDylibAddress
!= 0 ) {
1576 addr
= fgNextPIEDylibAddress
+ (arc4random() & 0x3) * 4096; // add small random padding between dylibs
1577 kern_return_t r
= vm_allocate(mach_task_self(), &addr
, size
, VM_FLAGS_FIXED
);
1578 if ( r
== KERN_SUCCESS
) {
1579 fgNextPIEDylibAddress
= addr
+ size
;
1582 fgNextPIEDylibAddress
= 0;
1584 kern_return_t r
= vm_allocate(mach_task_self(), &addr
, size
, VM_FLAGS_ANYWHERE
);
1585 if ( r
!= KERN_SUCCESS
)
1586 throw "out of address space";
1591 bool ImageLoaderMachO::reserveAddressRange(uintptr_t start
, size_t length
)
1593 vm_address_t addr
= start
;
1594 vm_size_t size
= length
;
1595 kern_return_t r
= vm_allocate(mach_task_self(), &addr
, size
, false /*only this range*/);
1596 if ( r
!= KERN_SUCCESS
)
1603 void ImageLoaderMachO::mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
)
1605 // find address range for image
1606 intptr_t slide
= this->assignSegmentAddresses(context
);
1607 if ( context
.verboseMapping
)
1608 dyld::log("dyld: Mapping %s\n", this->getPath());
1609 // map in all segments
1610 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
1611 vm_offset_t fileOffset
= segFileOffset(i
) + offsetInFat
;
1612 vm_size_t size
= segFileSize(i
);
1613 void* requestedLoadAddress
= (void*)(segPreferredLoadAddress(i
) + slide
);
1615 if ( !segUnaccessible(i
) ) {
1616 if ( segExecutable(i
) )
1617 protection
|= PROT_EXEC
;
1618 if ( segReadable(i
) )
1619 protection
|= PROT_READ
;
1620 if ( segWriteable(i
) )
1621 protection
|= PROT_WRITE
;
1624 // initially map __IMPORT segments R/W so dyld can update them
1625 if ( segIsReadOnlyImport(i
) )
1626 protection
|= PROT_WRITE
;
1628 // wholly zero-fill segments have nothing to mmap() in
1630 if ( (fileOffset
+size
) > fileLen
) {
1631 dyld::throwf("truncated mach-o error: segment %s extends to %llu which is past end of file %llu",
1632 segName(i
), (uint64_t)(fileOffset
+size
), fileLen
);
1634 void* loadAddress
= mmap(requestedLoadAddress
, size
, protection
, MAP_FIXED
| MAP_PRIVATE
, fd
, fileOffset
);
1635 if ( loadAddress
== ((void*)(-1)) ) {
1636 dyld::throwf("mmap() error %d at address=0x%08lX, size=0x%08lX segment=%s in Segment::map() mapping %s",
1637 errno
, (uintptr_t)requestedLoadAddress
, (uintptr_t)size
, segName(i
), getPath());
1641 ++ImageLoader::fgTotalSegmentsMapped
;
1642 ImageLoader::fgTotalBytesMapped
+= size
;
1643 if ( context
.verboseMapping
)
1644 dyld::log("%18s at 0x%08lX->0x%08lX with permissions %c%c%c\n", segName(i
), (uintptr_t)requestedLoadAddress
, (uintptr_t)((char*)requestedLoadAddress
+size
-1),
1645 (protection
& PROT_READ
) ? 'r' : '.', (protection
& PROT_WRITE
) ? 'w' : '.', (protection
& PROT_EXEC
) ? 'x' : '.' );
1647 // update slide to reflect load location
1648 this->setSlide(slide
);
1651 void ImageLoaderMachO::mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
)
1653 // find address range for image
1654 intptr_t slide
= this->assignSegmentAddresses(context
);
1655 if ( context
.verboseMapping
)
1656 dyld::log("dyld: Mapping memory %p\n", memoryImage
);
1657 // map in all segments
1658 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
1659 vm_address_t loadAddress
= segPreferredLoadAddress(i
) + slide
;
1660 vm_address_t srcAddr
= (uintptr_t)memoryImage
+ segFileOffset(i
);
1661 vm_size_t size
= segFileSize(i
);
1662 kern_return_t r
= vm_copy(mach_task_self(), srcAddr
, size
, loadAddress
);
1663 if ( r
!= KERN_SUCCESS
)
1664 throw "can't map segment";
1665 if ( context
.verboseMapping
)
1666 dyld::log("%18s at 0x%08lX->0x%08lX\n", segName(i
), (uintptr_t)loadAddress
, (uintptr_t)loadAddress
+size
-1);
1668 // update slide to reflect load location
1669 this->setSlide(slide
);
1670 // set R/W permissions on all segments at slide location
1671 for(unsigned int i
=0, e
=segmentCount(); i
< e
; ++i
) {
1672 segProtect(i
, context
);
1677 void ImageLoaderMachO::segProtect(unsigned int segIndex
, const ImageLoader::LinkContext
& context
)
1679 vm_prot_t protection
= 0;
1680 if ( !segUnaccessible(segIndex
) ) {
1681 if ( segExecutable(segIndex
) )
1682 protection
|= PROT_EXEC
;
1683 if ( segReadable(segIndex
) )
1684 protection
|= PROT_READ
;
1685 if ( segWriteable(segIndex
) )
1686 protection
|= PROT_WRITE
;
1688 vm_address_t addr
= segActualLoadAddress(segIndex
);
1689 vm_size_t size
= segSize(segIndex
);
1690 const bool setCurrentPermissions
= false;
1691 kern_return_t r
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
);
1692 if ( r
!= KERN_SUCCESS
)
1693 throw "can't set vm permissions for mapped segment";
1694 if ( context
.verboseMapping
) {
1695 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,
1696 (protection
& PROT_READ
) ? 'r' : '.', (protection
& PROT_WRITE
) ? 'w' : '.', (protection
& PROT_EXEC
) ? 'x' : '.' );
1700 void ImageLoaderMachO::segMakeWritable(unsigned int segIndex
, const ImageLoader::LinkContext
& context
)
1702 vm_address_t addr
= segActualLoadAddress(segIndex
);
1703 vm_size_t size
= segSize(segIndex
);
1704 const bool setCurrentPermissions
= false;
1705 vm_prot_t protection
= VM_PROT_WRITE
| VM_PROT_READ
;
1706 if ( segExecutable(segIndex
) )
1707 protection
|= VM_PROT_EXECUTE
;
1708 kern_return_t r
= vm_protect(mach_task_self(), addr
, size
, setCurrentPermissions
, protection
);
1709 if ( r
!= KERN_SUCCESS
)
1710 throw "can't set vm permissions for mapped segment";
1711 if ( context
.verboseMapping
) {
1712 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,
1713 (protection
& PROT_READ
) ? 'r' : '.', (protection
& PROT_WRITE
) ? 'w' : '.', (protection
& PROT_EXEC
) ? 'x' : '.' );