1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2007 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 #ifndef __IMAGELOADER__
27 #define __IMAGELOADER__
29 #include <sys/types.h>
30 #include <mach/mach_time.h> // struct mach_timebase_info
31 #include <mach/mach_init.h> // struct mach_thread_self
36 #include "mach-o/dyld_images.h"
37 #include "mach-o/dyld_priv.h"
40 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
41 #define SPLIT_SEG_DYLIB_SUPPORT (__ppc__ || __i386__)
42 #define TEXT_RELOC_SUPPORT (__ppc__ || __i386__)
43 #define DYLD_SHARED_CACHE_SUPPORT (__ppc__ || __i386__ || __ppc64__ || __x86_64__)
44 #define IMAGE_NOTIFY_SUPPORT 0
45 #define RECURSIVE_INITIALIZER_LOCK 1
46 #define SUPPORT_OLD_CRT_INITIALIZATION (__ppc__ || __i386__)
51 extern __attribute__((noreturn
)) void throwf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
52 extern void log(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
53 extern void warn(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
54 extern const char* mkstringf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
62 const char*** NXArgvPtr
;
63 const char*** environPtr
;
64 const char** __prognamePtr
;
70 // ImageLoader is an abstract base class. To support loading a particular executable
71 // file format, you make a concrete subclass of ImageLoader.
73 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
75 // The ImageLoader base class does the work of linking together images, but it knows nothing
76 // about any particular file format.
82 typedef uint32_t DefinitionFlags
;
83 static const DefinitionFlags kNoDefinitionOptions
= 0;
84 static const DefinitionFlags kWeakDefinition
= 1;
86 typedef uint32_t ReferenceFlags
;
87 static const ReferenceFlags kNoReferenceOptions
= 0;
88 static const ReferenceFlags kWeakReference
= 1;
89 static const ReferenceFlags kTentativeDefinition
= 2;
91 enum PrebindMode
{ kUseAllPrebinding
, kUseSplitSegPrebinding
, kUseAllButAppPredbinding
, kUseNoPrebinding
};
92 enum BindingOptions
{ kBindingNone
, kBindingLazyPointers
, kBindingNeverSetLazyPointers
};
93 enum SharedRegionMode
{ kUseSharedRegion
, kUsePrivateSharedRegion
, kDontUseSharedRegion
, kSharedRegionIsSharedCache
};
95 struct Symbol
; // abstact symbol
103 RPathChain(const RPathChain
* n
, std::vector
<const char*>* p
) : next(n
), paths(p
) {};
104 const RPathChain
* next
;
105 std::vector
<const char*>* paths
;
110 const mach_header
* imageHeader
;
111 const char* imageShortName
;
115 ImageLoader
* (*loadLibrary
)(const char* libraryName
, bool search
, bool findDLL
, const char* origin
, const RPathChain
* rpaths
);
116 void (*terminationRecorder
)(ImageLoader
* image
);
117 bool (*flatExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
);
118 bool (*coalescedExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
);
119 void (*undefinedHandler
)(const char* name
);
120 #if IMAGE_NOTIFY_SUPPORT
121 void (*addImageNeedingNotification
)(ImageLoader
* image
);
122 void (*notifyAdding
)(const ImageLoader
* const * images
, unsigned int count
);
124 MappedRegion
* (*getAllMappedRegions
)(MappedRegion
*);
125 void * (*bindingHandler
)(const char *, const char *, void *);
126 void (*notifySingle
)(dyld_image_states
, const struct mach_header
*, const char* path
, time_t modDate
);
127 void (*notifyBatch
)(dyld_image_states state
);
128 void (*removeImage
)(ImageLoader
* image
);
129 void (*registerDOFs
)(const std::vector
<DOFInfo
>& dofs
);
130 void (*clearAllDepths
)();
131 unsigned int (*imageCount
)();
132 void (*notifySharedCacheInvalid
)();
134 void (*makeSharedCacheImportSegmentsWritable
)(bool writable
);
136 void (*setNewProgramVars
)(const ProgramVars
&);
137 #if SUPPORT_OLD_CRT_INITIALIZATION
138 void (*setRunInitialzersOldWay
)();
140 BindingOptions bindingOptions
;
145 const char* progname
;
146 ProgramVars programVars
;
147 ImageLoader
* mainExecutable
;
148 const char* imageSuffix
;
149 PrebindMode prebindUsage
;
150 SharedRegionMode sharedRegionMode
;
151 bool dyldLoadedAtSameAddressNeededBySharedCache
;
152 bool preFetchDisabled
;
155 bool linkingMainExecutable
;
163 bool verbosePrebinding
;
164 bool verboseWarnings
;
167 // constructor is protected, but anyone can delete an image
168 virtual ~ImageLoader();
170 // link() takes a newly instantiated ImageLoader and does all
171 // fixups needed to make it usable by the process
172 void link(const LinkContext
& context
, bool forceLazysBound
, bool preflight
, const RPathChain
& loaderRPaths
);
174 // runInitializers() is normally called in link() but the main executable must
175 // run crt code before initializers
176 void runInitializers(const LinkContext
& context
);
178 // called after link() forces all lazy pointers to be bound
179 void bindAllLazyPointers(const LinkContext
& context
, bool recursive
);
181 // used by dyld to see if a requested library is already loaded (might be symlink)
182 bool statMatch(const struct stat
& stat_buf
) const;
184 // get short name of this image
185 const char* getShortName() const;
187 // get path used to load this image, not necessarily the "real" path
188 const char* getPath() const { return fPath
; }
190 uint32_t getPathHash() const { return fPathHash
; }
192 // get path used to load this image represents (ZeroLink only) which image this .o is part of
193 const char* getLogicalPath() const;
195 // get path this image is intended to be placed on disk or NULL if no preferred install location
196 virtual const char* getInstallPath() const = 0;
198 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
199 bool matchInstallPath() const;
200 void setMatchInstallPath(bool);
202 // if path was a fat file, offset of image loaded in that fat file
203 uint64_t getOffsetInFatFile() const;
205 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
206 void setHideExports(bool hide
= true);
208 // check if this image's exported symbols should be ignored when linking other images
209 bool hasHiddenExports() const;
211 // checks if this image is already linked into the process
212 bool isLinked() const;
214 // even if image is deleted, leave segments mapped in
215 void setLeaveMapped();
217 // even if image is deleted, leave segments mapped in
218 bool leaveMapped() { return fLeaveMapped
; }
220 // checks if the specifed address is within one of this image's segments
221 virtual bool containsAddress(const void* addr
) const;
223 // checks if the specifed address range overlaps any of this image's segments
224 virtual bool overlapsWithAddressRange(const void* start
, const void* end
) const;
226 // adds to list of ranges of memory mapped in
227 void getMappedRegions(MappedRegion
*& region
) const;
229 // st_mtime from stat() on file
230 time_t lastModified() const;
232 // only valid for main executables, returns a pointer its entry point
233 virtual void* getMain() const = 0;
235 // dyld API's require each image to have an associated mach_header
236 virtual const struct mach_header
* machHeader() const = 0;
238 // dyld API's require each image to have a slide (actual load address minus preferred load address)
239 virtual uintptr_t getSlide() const = 0;
241 // last address mapped by image
242 virtual const void* getEnd() const = 0;
244 // image has exports that participate in runtime coalescing
245 virtual bool hasCoalescedExports() const = 0;
247 // search symbol table of definitions in this image for requested name
248 virtual const Symbol
* findExportedSymbol(const char* name
, const void* hint
, bool searchReExports
, const ImageLoader
** foundIn
) const = 0;
250 // gets address of implementation (code) of the specified exported symbol
251 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
, const ImageLoader
* requestor
=NULL
) const = 0;
253 // gets attributes of the specified exported symbol
254 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const = 0;
256 // gets name of the specified exported symbol
257 virtual const char* getExportedSymbolName(const Symbol
* sym
) const = 0;
259 // gets how many symbols are exported by this image
260 virtual uint32_t getExportedSymbolCount() const = 0;
262 // gets the i'th exported symbol
263 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const = 0;
265 // find exported symbol as if imported by this image
267 virtual const Symbol
* findExportedSymbolInDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
269 // find exported symbol as if imported by this image
271 virtual const Symbol
* findExportedSymbolInImageOrDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
273 // gets how many symbols are imported by this image
274 virtual uint32_t getImportedSymbolCount() const = 0;
276 // gets the i'th imported symbol
277 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const = 0;
279 // gets attributes of the specified imported symbol
280 virtual ReferenceFlags
geImportedSymbolInfo(const Symbol
* sym
) const = 0;
282 // gets name of the specified imported symbol
283 virtual const char* getImportedSymbolName(const Symbol
* sym
) const = 0;
285 // checks if this image is a bundle and can be loaded but not linked
286 virtual bool isBundle() const = 0;
288 // checks if this image is a dylib
289 virtual bool isDylib() const = 0;
291 // only for main executable
292 virtual bool forceFlat() const = 0;
294 // called at runtime when a lazily bound function is first called
295 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
) = 0;
297 // calls termination routines (e.g. C++ static destructors for image)
298 virtual void doTermination(const LinkContext
& context
) = 0;
300 #if IMAGE_NOTIFY_SUPPORT
301 // tell this image about other images
302 virtual void doNotification(enum dyld_image_mode mode
, uint32_t infoCount
, const struct dyld_image_info info
[]) = 0;
304 // return if this image has initialization routines
305 virtual bool needsInitialization() = 0;
307 #if IMAGE_NOTIFY_SUPPORT
308 // return if this image has a routine to be called when any image is loaded or unloaded
309 virtual bool hasImageNotification() = 0;
311 // return if this image has specified section and set start and length
312 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) = 0;
314 // given a pointer into an image, find which segment and section it is in
315 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) = 0;
317 // the image supports being prebound
318 virtual bool isPrebindable() const = 0;
320 // the image is prebindable and its prebinding is valid
321 virtual bool usablePrebinding(const LinkContext
& context
) const = 0;
323 // add all RPATH paths this image contains
324 virtual void getRPaths(const LinkContext
& context
, std::vector
<const char*>&) const = 0;
328 dyld_image_states
getState() { return (dyld_image_states
)fState
; }
330 // used to sort images bottom-up
331 int compare(const ImageLoader
* right
) const;
333 void incrementDlopenReferenceCount() { ++fDlopenReferenceCount
; }
335 bool decrementDlopenReferenceCount();
337 void printReferenceCounts();
339 uint32_t referenceCount() const { return fDlopenReferenceCount
+ fStaticReferenceCount
+ fDynamicReferenceCount
; }
341 bool neverUnload() const { return fNeverUnload
; }
343 void setNeverUnload() { fNeverUnload
= true; fLeaveMapped
= true; }
345 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
346 static void printStatistics(unsigned int imageCount
);
348 // used with DYLD_IMAGE_SUFFIX
349 static void addSuffix(const char* path
, const char* suffix
, char* result
);
351 static uint32_t hash(const char*);
353 void setPath(const char* path
); // only called for images created from memory
354 void setPathUnowned(const char* path
);
356 void setLogicalPath(const char* path
);
358 void clearDepth() { fDepth
= 0; }
360 void setBeingRemoved() { fBeingRemoved
= true; }
361 bool isBeingRemoved() const { return fBeingRemoved
; }
365 struct DependentLibrary
;
367 friend class iterator
;
372 iterator
& operator++() { ++fLocation
; return *this; }
373 bool operator!=(const iterator
& it
) const { return (it
.fLocation
!= this->fLocation
); }
374 ImageLoader
* operator*() const { return fLocation
->image
; }
376 friend class ImageLoader
;
377 iterator(DependentLibrary
* loc
) : fLocation(loc
) {}
378 DependentLibrary
* fLocation
;
381 iterator
beginDependents() { return iterator(fLibraries
); }
382 iterator
endDependents() { return iterator(&fLibraries
[fLibrariesCount
]); }
386 friend class Segment
;
389 // abstract base class so all constructors protected
390 ImageLoader(const char* path
, uint64_t offsetInFat
, const struct stat
& info
);
391 ImageLoader(const char* moduleName
);
392 ImageLoader(const ImageLoader
&);
393 void operator=(const ImageLoader
&);
402 struct DependentLibrary
{
404 uint32_t required
: 1,
410 struct DependentLibraryInfo
{
417 class SegmentIterator
420 SegmentIterator
& operator++(); // use inline later to work around circular reference
421 bool operator!=(const SegmentIterator
& it
) const { return (it
.fLocation
!= this->fLocation
); }
422 class Segment
* operator*() const { return fLocation
; }
423 SegmentIterator(class Segment
* loc
) : fLocation(loc
) {}
425 class Segment
* fLocation
;
428 typedef void (*Initializer
)(int argc
, const char* argv
[], const char* envp
[], const char* apple
[], const ProgramVars
* vars
);
429 typedef void (*Terminator
)(void);
431 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
432 // These methods do the above, exactly once, and it the right order
433 void recursiveLoadLibraries(const LinkContext
& context
, const RPathChain
& loaderRPaths
);
434 void recursiveUnLoadMappedLibraries(const LinkContext
& context
);
435 unsigned int recursiveUpdateDepth(unsigned int maxDepth
);
436 void recursiveValidate(const LinkContext
& context
);
437 void recursiveRebase(const LinkContext
& context
);
438 void recursiveBind(const LinkContext
& context
, bool forceLazysBound
);
439 void recursiveGetDOFSections(const LinkContext
& context
, std::vector
<DOFInfo
>& dofs
);
440 #if IMAGE_NOTIFY_SUPPORT
441 void recursiveImageAnnouncement(const LinkContext
& context
, ImageLoader
**& newImages
);
443 void recursiveInitialization(const LinkContext
& context
, mach_port_t this_thread
);
445 // return how many libraries this image depends on
446 virtual uint32_t doGetDependentLibraryCount() = 0;
448 // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
449 virtual void doGetDependentLibraries(DependentLibraryInfo libs
[]) = 0;
451 // called on images that are libraries, returns info about itself
452 virtual LibraryInfo
doGetLibraryInfo() = 0;
454 // do any fix ups in this image that depend only on the load address of the image
455 virtual void doRebase(const LinkContext
& context
) = 0;
457 // do any symbolic fix ups in this image
458 virtual void doBind(const LinkContext
& context
, bool forceLazysBound
) = 0;
460 // update any segment permissions
461 virtual void doUpdateMappingPermissions(const LinkContext
& context
) = 0;
463 // if image has any dtrace DOF sections, append them to list to be registered
464 virtual void doGetDOFSections(const LinkContext
& context
, std::vector
<DOFInfo
>& dofs
) = 0;
466 // run any initialization routines in this image
467 virtual void doInitialization(const LinkContext
& context
) = 0;
469 // return if this image has termination routines
470 virtual bool needsTermination() = 0;
472 // support for runtimes in which segments don't have to maintain their relative positions
473 virtual bool segmentsMustSlideTogether() const = 0;
475 // built with PIC code and can load at any address
476 virtual bool segmentsCanSlide() const = 0;
478 // set how much all segments slide
479 virtual void setSlide(intptr_t slide
) = 0;
481 // utility routine to map in all segements in fSegments from a file
482 virtual void mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
);
484 // utility routine to map in all segements in fSegments from a memory image
485 virtual void mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
);
487 // returns if all dependent libraries checksum's were as expected and none slide
488 bool allDependentLibrariesAsWhenPreBound() const;
490 // in mach-o a child tells it parent to re-export, instead of the other way around...
491 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const = 0;
493 // in mach-o a parent library knows name of sub libraries it re-exports..
494 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const = 0;
496 // set fState to dyld_image_state_memory_mapped
497 void setMapped(const LinkContext
& context
);
499 // mark that target should not be unloaded unless this is also unloaded
500 void addDynamicReference(const ImageLoader
* target
);
502 // used to start iterating Segments
503 virtual SegmentIterator
beginSegments() const = 0;
505 // used to end iterating Segments
506 virtual SegmentIterator
endSegments() const = 0;
509 static uint32_t fgImagesWithUsedPrebinding
;
510 static uint32_t fgImagesUsedFromSharedCache
;
511 static uint32_t fgImagesRequiringNoFixups
;
512 static uint32_t fgTotalRebaseFixups
;
513 static uint32_t fgTotalBindFixups
;
514 static uint32_t fgTotalBindSymbolsResolved
;
515 static uint32_t fgTotalBindImageSearches
;
516 static uint32_t fgTotalLazyBindFixups
;
517 static uint32_t fgTotalPossibleLazyBindFixups
;
518 static uint32_t fgTotalSegmentsMapped
;
519 static uint64_t fgTotalBytesMapped
;
520 static uint64_t fgTotalBytesPreFetched
;
521 static uint64_t fgTotalLoadLibrariesTime
;
522 static uint64_t fgTotalRebaseTime
;
523 static uint64_t fgTotalBindTime
;
524 static uint64_t fgTotalInitTime
;
525 static uintptr_t fgNextSplitSegAddress
;
527 const char* fLogicalPath
; // for ZeroLink - the image which this bundle is part of
530 time_t fLastModified
;
531 uint64_t fOffsetInFatFile
;
532 DependentLibrary
* fLibraries
;
533 uint32_t fLibrariesCount
;
535 uint32_t fDlopenReferenceCount
; // count of how many dlopens have been done on this image
536 uint32_t fStaticReferenceCount
; // count of images that have a fLibraries entry pointing to this image
537 uint32_t fDynamicReferenceCount
; // count of images that have a fDynamicReferences entry pointer to this image
538 std::set
<const ImageLoader
*>* fDynamicReferences
; // list of all images this image used because of a flat/coalesced lookup
541 #if RECURSIVE_INITIALIZER_LOCK
542 struct recursive_lock
{
543 recursive_lock(mach_port_t t
) : thread(t
), count(0) {}
547 void recursiveSpinLock(recursive_lock
&);
548 void recursiveSpinUnLock();
551 void init(const char* path
, uint64_t offsetInFat
, dev_t device
, ino_t inode
, time_t modDate
);
552 intptr_t assignSegmentAddresses(const LinkContext
& context
);
553 const ImageLoader::Symbol
* findExportedSymbolInDependentImagesExcept(const char* name
, const ImageLoader
** dsiStart
,
554 const ImageLoader
**& dsiCur
, const ImageLoader
** dsiEnd
, const ImageLoader
** foundIn
) const;
561 fAllLibraryChecksumsAndLoadAddressesMatch
: 1,
562 fLeaveMapped
: 1, // when unloaded, leave image mapped in cause some other code may have pointers into it
563 fNeverUnload
: 1, // image was statically loaded by main executable
564 fHideSymbols
: 1, // ignore this image's exported symbols when linking other images
565 fMatchByInstallName
: 1,// look at image's install-path not its load path
567 #if IMAGE_NOTIFY_SUPPORT
570 fAllLazyPointersBound
: 1,
572 fPathOwnedByImage
: 1;
574 #if RECURSIVE_INITIALIZER_LOCK
575 recursive_lock
* fInitializerRecursiveLock
;
577 uint32_t fInitializerLock
;
579 static uint16_t fgLoadOrdinal
;
584 // Segment is an abstract base class. A segment is a chunk of an executable
585 // file that is mapped into memory. Each subclass of ImageLoader typically
586 // implements its own concrete subclass of Segment.
591 virtual ~Segment() {}
593 virtual const char* getName() = 0;
594 virtual uintptr_t getSize() = 0;
595 virtual uintptr_t getFileSize() = 0;
596 virtual bool hasTrailingZeroFill();
597 virtual uintptr_t getFileOffset() = 0;
598 virtual bool readable() = 0;
599 virtual bool writeable() = 0;
600 virtual bool executable() = 0;
601 virtual bool unaccessible() = 0;
602 virtual uintptr_t getActualLoadAddress(const ImageLoader
*) = 0;
603 virtual uintptr_t getPreferredLoadAddress() = 0;
604 virtual void unmap(const ImageLoader
*) = 0;
605 virtual Segment
* next(Segment
*) = 0;
607 virtual bool readOnlyImportStubs() = 0;
612 // abstract base class so all constructors protected
614 Segment(const Segment
&);
615 void operator=(const Segment
&);
617 virtual bool hasPreferredLoadAddress() = 0;
618 //virtual void setActualLoadAddress(uint64_t addr) = 0;
619 virtual void map(int fd
, uint64_t offsetInFatWrapper
, intptr_t slide
, const ImageLoader
* image
, const ImageLoader::LinkContext
& context
);
621 static bool reserveAddressRange(uintptr_t start
, size_t length
);
622 static uintptr_t reserveAnAddressRange(size_t length
, const class ImageLoader::LinkContext
& context
);
623 static uintptr_t fgNextPIEDylibAddress
;
626 void setPermissions(const ImageLoader::LinkContext
& context
, const ImageLoader
* image
);
627 void map(const void* memoryImage
, intptr_t slide
, const ImageLoader
* image
, const ImageLoader::LinkContext
& context
);
628 void tempWritable(const ImageLoader::LinkContext
& context
, const ImageLoader
* image
);
630 friend class ImageLoader
;
631 friend class ImageLoaderMachO
;
634 inline ImageLoader::SegmentIterator
& ImageLoader::SegmentIterator::operator++() { fLocation
= fLocation
->next(fLocation
); return *this; }