1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004 Apple Computer, 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
35 #include "mach-o/dyld_gdb.h"
39 __attribute__((noreturn
)) void throwf(const char* format
, ...);
42 // ImageLoader is an abstract base class. To support loading a particular executable
43 // file format, you make a concrete subclass of ImageLoader.
45 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
47 // The ImageLoader base class does the work of linking together images, but it knows nothing
48 // about any particular file format.
54 typedef uint32_t DefinitionFlags
;
55 static const DefinitionFlags kNoDefinitionOptions
= 0;
56 static const DefinitionFlags kWeakDefinition
= 1;
58 typedef uint32_t ReferenceFlags
;
59 static const ReferenceFlags kNoReferenceOptions
= 0;
60 static const ReferenceFlags kWeakReference
= 1;
61 static const ReferenceFlags kTentativeDefinition
= 2;
64 enum BindingLaziness
{ kNonLazyOnly
, kLazyAndNonLazy
, kLazyOnly
, kLazyOnlyNoDependents
};
65 enum InitializerRunning
{ kDontRunInitializers
, kRunInitializers
, kDontRunInitializersButTellObjc
};
66 enum PrebindMode
{ kUseAllPrebinding
, kUseSplitSegPrebinding
, kUseAllButAppPredbinding
, kUseNoPrebinding
};
67 enum BindingOptions
{ kBindingNone
, kBindingLazyPointers
, kBindingNeverSetLazyPointers
};
68 enum SharedRegionMode
{ kUseSharedRegion
, kUsePrivateSharedRegion
, kDontUseSharedRegion
};
70 struct Symbol
; // abstact symbol
76 typedef std::vector
<MappedRegion
> RegionsVector
;
79 ImageLoader
* (*loadLibrary
)(const char* libraryName
, bool search
, const char* origin
, const char* rpath
[]);
80 uint32_t (*imageNotification
)(ImageLoader
* image
, uint32_t startIndex
);
81 void (*terminationRecorder
)(ImageLoader
* image
);
82 bool (*flatExportFinder
)(const char* name
, const Symbol
** sym
, ImageLoader
** image
);
83 bool (*coalescedExportFinder
)(const char* name
, const Symbol
** sym
, ImageLoader
** image
);
84 void (*undefinedHandler
)(const char* name
);
85 void (*addImageNeedingNotification
)(ImageLoader
* image
);
86 void (*notifyAdding
)(std::vector
<ImageLoader
*>& images
);
87 void (*getAllMappedRegions
)(RegionsVector
&);
88 void * (*bindingHandler
)(const char *, const char *, void *);
89 BindingOptions bindingOptions
;
94 ImageLoader
* mainExecutable
;
95 const char* imageSuffix
;
96 PrebindMode prebindUsage
;
97 SharedRegionMode sharedRegionMode
;
99 bool slideAndPackDylibs
;
106 bool verbosePrebinding
;
107 bool verboseWarnings
;
110 // constructor is protected, but anyone can delete an image
111 virtual ~ImageLoader();
113 // link() takes a newly instantiated ImageLoader and does all
114 // fixups needed to make it usable by the process
115 void link(const LinkContext
& context
, BindingLaziness mode
, InitializerRunning inits
, uint32_t notifyCount
);
117 // runInitializers() is normally called in link() but the main executable must
118 // run crt code before initializers
119 void runInitializers(const LinkContext
& context
);
121 // runNotification() is normally called in link() but the main executable must
122 // run crt code before initializers
123 void runNotification(const LinkContext
& context
, uint32_t notifyCount
);
125 // used by dyld to see if a requested library is already loaded (might be symlink)
126 bool statMatch(const struct stat
& stat_buf
) const;
128 // get short name of this image
129 const char* getShortName() const;
131 // get path used to load this image, not necessarily the "real" path
132 const char* getPath() const { return fPath
; }
134 uint32_t getPathHash() const { return fPathHash
; }
136 // get path used to load this image represents (ZeroLink only) which image this .o is part of
137 const char* getLogicalPath() const;
139 // get path this image is intended to be placed on disk or NULL if no preferred install location
140 virtual const char* getInstallPath() const = 0;
142 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
143 bool matchInstallPath() const;
144 void setMatchInstallPath(bool);
146 // if path was a fat file, offset of image loaded in that fat file
147 uint64_t getOffsetInFatFile() const;
149 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
150 void setHideExports(bool hide
= true);
152 // check if this image's exported symbols should be ignored when linking other images
153 bool hasHiddenExports() const;
155 // checks if this image is already linked into the process
156 bool isLinked() const;
158 // even if image is deleted, leave segments mapped in
159 void setLeaveMapped();
161 // checks if the specifed address is within one of this image's segments
162 virtual bool containsAddress(const void* addr
) const;
164 // adds to list of ranges of memory mapped in
165 void addMappedRegions(RegionsVector
& regions
) const;
167 // st_mtime from stat() on file
168 time_t lastModified();
170 // image should create prebound version of itself and return freespace remaining on disk
171 uint64_t reprebind(const LinkContext
& context
, time_t timestamp
);
173 // if 'commit', the prebound version should be swapped in, otherwise deleted
174 void reprebindCommit(const LinkContext
& context
, bool commit
, bool unmapOld
);
176 // only valid for main executables, returns a pointer its entry point
177 virtual void* getMain() const = 0;
179 // dyld API's require each image to have an associated mach_header
180 virtual const struct mach_header
* machHeader() const = 0;
182 // dyld API's require each image to have a slide (actual load address minus preferred load address)
183 virtual uintptr_t getSlide() const = 0;
185 // dyld API's require each image to have a slide (actual load address minus preferred load address)
186 virtual const void* getBaseAddress() const = 0;
188 // image has exports that participate in runtime coalescing
189 virtual bool hasCoalescedExports() const = 0;
191 // search symbol table of definitions in this image for requested name
192 virtual const Symbol
* findExportedSymbol(const char* name
, const void* hint
, bool searchReExports
, ImageLoader
** foundIn
) const = 0;
194 // gets address of implementation (code) of the specified exported symbol
195 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
) const = 0;
197 // gets attributes of the specified exported symbol
198 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const = 0;
200 // gets name of the specified exported symbol
201 virtual const char* getExportedSymbolName(const Symbol
* sym
) const = 0;
203 // gets how many symbols are exported by this image
204 virtual uint32_t getExportedSymbolCount() const = 0;
206 // gets the i'th exported symbol
207 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const = 0;
209 // find exported symbol as if imported by this image
211 virtual const Symbol
* findExportedSymbolInDependentImages(const char* name
, ImageLoader
** foundIn
) const;
213 // find exported symbol as if imported by this image
215 virtual const Symbol
* findExportedSymbolInImageOrDependentImages(const char* name
, ImageLoader
** foundIn
) const;
217 // gets how many symbols are imported by this image
218 virtual uint32_t getImportedSymbolCount() const = 0;
220 // gets the i'th imported symbol
221 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const = 0;
223 // gets attributes of the specified imported symbol
224 virtual ReferenceFlags
geImportedSymbolInfo(const Symbol
* sym
) const = 0;
226 // gets name of the specified imported symbol
227 virtual const char* getImportedSymbolName(const Symbol
* sym
) const = 0;
229 // checks if this image is a bundle and can be loaded but not linked
230 virtual bool isBundle() const = 0;
232 // checks if this image is a dylib
233 virtual bool isDylib() const = 0;
235 // only for main executable
236 virtual bool forceFlat() const = 0;
238 // called at runtime when a lazily bound function is first called
239 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
) = 0;
241 // calls termination routines (e.g. C++ static destructors for image)
242 virtual void doTermination(const LinkContext
& context
) = 0;
244 // tell this image about other images
245 virtual void doNotification(enum dyld_image_mode mode
, uint32_t infoCount
, const struct dyld_image_info info
[]) = 0;
247 // return if this image has initialization routines
248 virtual bool needsInitialization() = 0;
250 // return if this image has a routine to be called when any image is loaded or unloaded
251 virtual bool hasImageNotification() = 0;
253 // return if this image has specified section and set start and length
254 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) = 0;
256 // given a pointer into an image, find which segment and section it is in
257 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) = 0;
259 // the image supports being prebound
260 virtual bool isPrebindable() const = 0;
262 // the image is prebindable and its prebinding is valid
263 virtual bool usablePrebinding(const LinkContext
& context
) const = 0;
265 // used to implement refernce counting of images
266 void incrementReferenceCount();
267 bool decrementReferenceCount();
269 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
270 static void printStatistics(unsigned int imageCount
);
272 // used with DYLD_IMAGE_SUFFIX
273 static void addSuffix(const char* path
, const char* suffix
, char* result
);
275 static uint32_t hash(const char*);
278 void setPath(const char* path
); // only called for images created from memory
279 void setLogicalPath(const char* path
);
283 // abstract base class so all constructors protected
284 ImageLoader(const char* path
, uint64_t offsetInFat
, const struct stat
& info
);
285 ImageLoader(const char* moduleName
);
286 ImageLoader(const ImageLoader
&);
287 void operator=(const ImageLoader
&);
296 struct DependentLibrary
{
301 bool checksumMatches
;
306 typedef void (*Initializer
)(int argc
, const char* argv
[], const char* envp
[],const char* apple
[]);
307 typedef void (*Terminator
)(void);
309 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
310 // These methods do the above, exactly once, and it the right order
311 void recursiveLoadLibraries(const LinkContext
& context
);
312 void recursiveRebase(const LinkContext
& context
);
313 void recursiveBind(const LinkContext
& context
, BindingLaziness bindness
);
314 void recursiveImageAnnouncement(const LinkContext
& context
, std::vector
<ImageLoader
*>& newImages
);
315 void recursiveImageNotification(const LinkContext
& context
, uint32_t addImageCount
);
316 void recursiveInitialization(const LinkContext
& context
);
318 // map any segments this image has into memory and build fSegments
319 // this is called before doGetDependentLibraryCount so if metadata is in segments it is mapped in
320 virtual void instantiateSegments(const uint8_t* fileData
) = 0;
322 // return how many libraries this image depends on
323 virtual uint32_t doGetDependentLibraryCount() = 0;
325 // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
326 virtual void doGetDependentLibraries(DependentLibrary libs
[]) = 0;
328 // called on images that are libraries, returns info about itself
329 virtual LibraryInfo
doGetLibraryInfo() = 0;
331 // do any fix ups in this image that depend only on the load address of the image
332 virtual void doRebase(const LinkContext
& context
) = 0;
334 // do any symbolic fix ups in this image
335 virtual void doBind(const LinkContext
& context
, BindingLaziness bindness
) = 0;
337 // run any initialization routines in this image
338 virtual void doInitialization(const LinkContext
& context
) = 0;
340 // write prebinding updates to mapped file fileToPrebind
341 virtual void doPrebinding(const LinkContext
& context
, time_t timestamp
, uint8_t* fileToPrebind
) = 0;
343 // return if this image has termination routines
344 virtual bool needsTermination() = 0;
346 // support for runtimes in which segments don't have to maintain their relative positions
347 virtual bool segmentsMustSlideTogether() const = 0;
349 // built with PIC code and can load at any address
350 virtual bool segmentsCanSlide() const = 0;
352 // set how much all segments slide
353 virtual void setSlide(intptr_t slide
) = 0;
355 // utility routine to map in all segements in fSegments from a file
356 virtual void mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
);
358 // utility routine to map in all segements in fSegments from a memory image
359 virtual void mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
);
361 // returns if all dependent libraries checksum's were as expected and none slide
362 bool allDependentLibrariesAsWhenPreBound() const;
364 // in mach-o a child tells it parent to re-export, instead of the other way around...
365 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const = 0;
367 // in mach-o a parent library knows name of sub libraries it re-exports..
368 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const = 0;
370 // file has been reprebound on disk, unmap this file so original file is released
371 virtual void prebindUnmap(const LinkContext
& context
) = 0;
373 static uint32_t fgImagesWithUsedPrebinding
;
374 static uint32_t fgTotalRebaseFixups
;
375 static uint32_t fgTotalBindFixups
;
376 static uint32_t fgTotalLazyBindFixups
;
377 static uint32_t fgTotalPossibleLazyBindFixups
;
378 static uint64_t fgTotalLoadLibrariesTime
;
379 static uint64_t fgTotalRebaseTime
;
380 static uint64_t fgTotalBindTime
;
381 static uint64_t fgTotalNotifyTime
;
382 static uint64_t fgTotalInitTime
;
383 static uintptr_t fgNextSplitSegAddress
;
385 const char* fLogicalPath
; // for ZeroLink - the image which this bundle is part of
388 time_t fLastModified
;
389 uint64_t fOffsetInFatFile
;
390 std::vector
<class Segment
*> fSegments
;
391 DependentLibrary
* fLibraries
;
392 uint32_t fLibrariesCount
;
394 uint32_t fReferenceCount
;
395 bool fAllLibraryChecksumsAndLoadAddressesMatch
;
396 bool fLeaveMapped
; // when unloaded, leave image mapped in cause some other code may have pointers into it
400 void init(const char* path
, uint64_t offsetInFat
, dev_t device
, ino_t inode
, time_t modDate
);
401 intptr_t assignSegmentAddresses(const LinkContext
& context
);
402 uint64_t copyAndMap(const char* tempFile
, uint8_t** fileToPrebind
, uint64_t* fileToPrebindSize
);
403 const ImageLoader::Symbol
* findExportedSymbolInDependentImagesExcept(const char* name
, std::set
<const ImageLoader
*>& dontSearchImages
, ImageLoader
** foundIn
) const;
406 bool fHideSymbols
; // ignore this image's exported symbols when linking other images
407 bool fMatchByInstallName
;// look at image's install-path not its load path
408 bool fLibrariesLoaded
;
410 bool fBoundAllNonLazy
;
414 uint16_t fNextAddImageIndex
;
419 // Segment is an abstract base class. A segment is a chunk of an executable
420 // file that is mapped into memory. Each subclass of ImageLoader typically
421 // implements its own concrete subclass of Segment.
426 virtual ~Segment() {}
428 virtual const ImageLoader
* getImage() = 0;
429 virtual const char* getName() = 0;
430 virtual uintptr_t getSize() = 0;
431 virtual uintptr_t getFileSize() = 0;
432 virtual bool hasTrailingZeroFill();
433 virtual uintptr_t getFileOffset() = 0;
434 virtual bool readable() = 0;
435 virtual bool writeable() = 0;
436 virtual bool executable() = 0;
437 virtual bool unaccessible() = 0;
438 virtual bool hasFixUps() = 0;
439 virtual uintptr_t getActualLoadAddress() = 0;
440 virtual uintptr_t getPreferredLoadAddress() = 0;
441 virtual void setUnMapWhenDestructed(bool unmap
) = 0;
444 // abstract base class so all constructors protected
446 Segment(const Segment
&);
447 void operator=(const Segment
&);
449 virtual bool hasPreferredLoadAddress() = 0;
450 //virtual void setActualLoadAddress(uint64_t addr) = 0;
452 static bool reserveAddressRange(uintptr_t start
, size_t length
);
453 static uintptr_t reserveAnAddressRange(size_t length
, const ImageLoader::LinkContext
& context
);
454 static uintptr_t fgNextNonSplitSegAddress
;
457 void map(int fd
, uint64_t offsetInFatWrapper
, intptr_t slide
, const ImageLoader::LinkContext
& context
);
458 void map(const void* memoryImage
, intptr_t slide
, const ImageLoader::LinkContext
& context
);
459 void setPermissions();
462 friend class ImageLoader
;
463 friend class ImageLoaderMachO
;