]> git.saurik.com Git - apple/dyld.git/blob - src/ImageLoader.h
4a8a9d89cdc33ac1d3b93f70a1619728d8278971
[apple/dyld.git] / src / ImageLoader.h
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26 #ifndef __IMAGELOADER__
27 #define __IMAGELOADER__
28
29 #include <sys/types.h>
30 #include <mach/mach_time.h> // struct mach_timebase_info
31 #include <stdint.h>
32 #include <vector>
33 #include <set>
34
35 #include "mach-o/dyld_gdb.h"
36
37
38 // utility
39 __attribute__((noreturn)) void throwf(const char* format, ...);
40
41 //
42 // ImageLoader is an abstract base class. To support loading a particular executable
43 // file format, you make a concrete subclass of ImageLoader.
44 //
45 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
46 //
47 // The ImageLoader base class does the work of linking together images, but it knows nothing
48 // about any particular file format.
49 //
50 //
51 class ImageLoader {
52 public:
53
54 typedef uint32_t DefinitionFlags;
55 static const DefinitionFlags kNoDefinitionOptions = 0;
56 static const DefinitionFlags kWeakDefinition = 1;
57
58 typedef uint32_t ReferenceFlags;
59 static const ReferenceFlags kNoReferenceOptions = 0;
60 static const ReferenceFlags kWeakReference = 1;
61 static const ReferenceFlags kTentativeDefinition = 2;
62
63
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 };
69
70 struct Symbol; // abstact symbol
71
72 struct MappedRegion {
73 uintptr_t address;
74 size_t size;
75 };
76 typedef std::vector<MappedRegion> RegionsVector;
77
78 struct LinkContext {
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;
90 int argc;
91 const char** argv;
92 const char** envp;
93 const char** apple;
94 ImageLoader* mainExecutable;
95 const char* imageSuffix;
96 PrebindMode prebindUsage;
97 SharedRegionMode sharedRegionMode;
98 bool prebinding;
99 bool bindFlat;
100 bool slideAndPackDylibs;
101 bool verboseOpts;
102 bool verboseEnv;
103 bool verboseMapping;
104 bool verboseRebase;
105 bool verboseBind;
106 bool verboseInit;
107 bool verbosePrebinding;
108 bool verboseWarnings;
109 };
110
111 // constructor is protected, but anyone can delete an image
112 virtual ~ImageLoader();
113
114 // link() takes a newly instantiated ImageLoader and does all
115 // fixups needed to make it usable by the process
116 void link(const LinkContext& context, BindingLaziness mode, InitializerRunning inits, uint32_t notifyCount);
117
118 // runInitializers() is normally called in link() but the main executable must
119 // run crt code before initializers
120 void runInitializers(const LinkContext& context);
121
122 // runNotification() is normally called in link() but the main executable must
123 // run crt code before initializers
124 void runNotification(const LinkContext& context, uint32_t notifyCount);
125
126 // used by dyld to see if a requested library is already loaded (might be symlink)
127 bool statMatch(const struct stat& stat_buf) const;
128
129 // get short name of this image
130 const char* getShortName() const;
131
132 // get path used to load this image, not necessarily the "real" path
133 const char* getPath() const { return fPath; }
134
135 uint32_t getPathHash() const { return fPathHash; }
136
137 // get path used to load this image represents (ZeroLink only) which image this .o is part of
138 const char* getLogicalPath() const;
139
140 // get path this image is intended to be placed on disk or NULL if no preferred install location
141 virtual const char* getInstallPath() const = 0;
142
143 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
144 bool matchInstallPath() const;
145 void setMatchInstallPath(bool);
146
147 // if path was a fat file, offset of image loaded in that fat file
148 uint64_t getOffsetInFatFile() const;
149
150 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
151 void setHideExports(bool hide = true);
152
153 // check if this image's exported symbols should be ignored when linking other images
154 bool hasHiddenExports() const;
155
156 // checks if this image is already linked into the process
157 bool isLinked() const;
158
159 // even if image is deleted, leave segments mapped in
160 void setLeaveMapped();
161
162 // checks if the specifed address is within one of this image's segments
163 virtual bool containsAddress(const void* addr) const;
164
165 // adds to list of ranges of memory mapped in
166 void addMappedRegions(RegionsVector& regions) const;
167
168 // st_mtime from stat() on file
169 time_t lastModified();
170
171 // image should create prebound version of itself and return freespace remaining on disk
172 uint64_t reprebind(const LinkContext& context, time_t timestamp);
173
174 // if 'commit', the prebound version should be swapped in, otherwise deleted
175 void reprebindCommit(const LinkContext& context, bool commit, bool unmapOld);
176
177 // only valid for main executables, returns a pointer its entry point
178 virtual void* getMain() const = 0;
179
180 // dyld API's require each image to have an associated mach_header
181 virtual const struct mach_header* machHeader() const = 0;
182
183 // dyld API's require each image to have a slide (actual load address minus preferred load address)
184 virtual uintptr_t getSlide() const = 0;
185
186 // dyld API's require each image to have a slide (actual load address minus preferred load address)
187 virtual const void* getBaseAddress() const = 0;
188
189 // image has exports that participate in runtime coalescing
190 virtual bool hasCoalescedExports() const = 0;
191
192 // search symbol table of definitions in this image for requested name
193 virtual const Symbol* findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const = 0;
194
195 // gets address of implementation (code) of the specified exported symbol
196 virtual uintptr_t getExportedSymbolAddress(const Symbol* sym) const = 0;
197
198 // gets attributes of the specified exported symbol
199 virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0;
200
201 // gets name of the specified exported symbol
202 virtual const char* getExportedSymbolName(const Symbol* sym) const = 0;
203
204 // gets how many symbols are exported by this image
205 virtual uint32_t getExportedSymbolCount() const = 0;
206
207 // gets the i'th exported symbol
208 virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0;
209
210 // find exported symbol as if imported by this image
211 // used by RTLD_NEXT
212 virtual const Symbol* findExportedSymbolInDependentImages(const char* name, ImageLoader** foundIn) const;
213
214 // find exported symbol as if imported by this image
215 // used by RTLD_SELF
216 virtual const Symbol* findExportedSymbolInImageOrDependentImages(const char* name, ImageLoader** foundIn) const;
217
218 // gets how many symbols are imported by this image
219 virtual uint32_t getImportedSymbolCount() const = 0;
220
221 // gets the i'th imported symbol
222 virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0;
223
224 // gets attributes of the specified imported symbol
225 virtual ReferenceFlags geImportedSymbolInfo(const Symbol* sym) const = 0;
226
227 // gets name of the specified imported symbol
228 virtual const char* getImportedSymbolName(const Symbol* sym) const = 0;
229
230 // checks if this image is a bundle and can be loaded but not linked
231 virtual bool isBundle() const = 0;
232
233 // checks if this image is a dylib
234 virtual bool isDylib() const = 0;
235
236 // only for main executable
237 virtual bool forceFlat() const = 0;
238
239 // called at runtime when a lazily bound function is first called
240 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
241
242 // calls termination routines (e.g. C++ static destructors for image)
243 virtual void doTermination(const LinkContext& context) = 0;
244
245 // tell this image about other images
246 virtual void doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]) = 0;
247
248 // return if this image has initialization routines
249 virtual bool needsInitialization() = 0;
250
251 // return if this image has a routine to be called when any image is loaded or unloaded
252 virtual bool hasImageNotification() = 0;
253
254 // return if this image has specified section and set start and length
255 virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
256
257 // given a pointer into an image, find which segment and section it is in
258 virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
259
260 // the image supports being prebound
261 virtual bool isPrebindable() const = 0;
262
263 // the image is prebindable and its prebinding is valid
264 virtual bool usablePrebinding(const LinkContext& context) const = 0;
265
266 // used to implement refernce counting of images
267 void incrementReferenceCount();
268 bool decrementReferenceCount();
269
270 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
271 static void printStatistics(unsigned int imageCount);
272
273 // used with DYLD_IMAGE_SUFFIX
274 static void addSuffix(const char* path, const char* suffix, char* result);
275
276 static uint32_t hash(const char*);
277
278
279 void setPath(const char* path); // only called for images created from memory
280 void setLogicalPath(const char* path);
281
282
283 protected:
284 // abstract base class so all constructors protected
285 ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info);
286 ImageLoader(const char* moduleName);
287 ImageLoader(const ImageLoader&);
288 void operator=(const ImageLoader&);
289
290
291 struct LibraryInfo {
292 uint64_t checksum;
293 uint32_t minVersion;
294 uint32_t maxVersion;
295 };
296
297 struct DependentLibrary {
298 const char* name;
299 ImageLoader* image;
300 LibraryInfo info;
301 bool required;
302 bool checksumMatches;
303 bool isReExported;
304 bool isSubFramework;
305 };
306
307 typedef void (*Initializer)(int argc, const char* argv[], const char* envp[],const char* apple[]);
308 typedef void (*Terminator)(void);
309
310 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
311 // These methods do the above, exactly once, and it the right order
312 void recursiveLoadLibraries(const LinkContext& context);
313 void recursiveRebase(const LinkContext& context);
314 void recursiveBind(const LinkContext& context, BindingLaziness bindness);
315 void recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages);
316 void recursiveImageNotification(const LinkContext& context, uint32_t addImageCount);
317 void recursiveInitialization(const LinkContext& context);
318
319 // map any segments this image has into memory and build fSegments
320 // this is called before doGetDependentLibraryCount so if metadata is in segments it is mapped in
321 virtual void instantiateSegments(const uint8_t* fileData) = 0;
322
323 // return how many libraries this image depends on
324 virtual uint32_t doGetDependentLibraryCount() = 0;
325
326 // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
327 virtual void doGetDependentLibraries(DependentLibrary libs[]) = 0;
328
329 // called on images that are libraries, returns info about itself
330 virtual LibraryInfo doGetLibraryInfo() = 0;
331
332 // do any fix ups in this image that depend only on the load address of the image
333 virtual void doRebase(const LinkContext& context) = 0;
334
335 // do any symbolic fix ups in this image
336 virtual void doBind(const LinkContext& context, BindingLaziness bindness) = 0;
337
338 // run any initialization routines in this image
339 virtual void doInitialization(const LinkContext& context) = 0;
340
341 // write prebinding updates to mapped file fileToPrebind
342 virtual void doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind) = 0;
343
344 // return if this image has termination routines
345 virtual bool needsTermination() = 0;
346
347 // support for runtimes in which segments don't have to maintain their relative positions
348 virtual bool segmentsMustSlideTogether() const = 0;
349
350 // built with PIC code and can load at any address
351 virtual bool segmentsCanSlide() const = 0;
352
353 // set how much all segments slide
354 virtual void setSlide(intptr_t slide) = 0;
355
356 // utility routine to map in all segements in fSegments from a file
357 virtual void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
358
359 // utility routine to map in all segements in fSegments from a memory image
360 virtual void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context);
361
362 // returns if all dependent libraries checksum's were as expected and none slide
363 bool allDependentLibrariesAsWhenPreBound() const;
364
365 // in mach-o a child tells it parent to re-export, instead of the other way around...
366 virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
367
368 // in mach-o a parent library knows name of sub libraries it re-exports..
369 virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0;
370
371 // file has been reprebound on disk, unmap this file so original file is released
372 virtual void prebindUnmap(const LinkContext& context) = 0;
373
374 static uint32_t fgImagesWithUsedPrebinding;
375 static uint32_t fgTotalRebaseFixups;
376 static uint32_t fgTotalBindFixups;
377 static uint32_t fgTotalLazyBindFixups;
378 static uint32_t fgTotalPossibleLazyBindFixups;
379 static uint64_t fgTotalLoadLibrariesTime;
380 static uint64_t fgTotalRebaseTime;
381 static uint64_t fgTotalBindTime;
382 static uint64_t fgTotalNotifyTime;
383 static uint64_t fgTotalInitTime;
384 static uintptr_t fgNextSplitSegAddress;
385 const char* fPath;
386 const char* fLogicalPath; // for ZeroLink - the image which this bundle is part of
387 dev_t fDevice;
388 ino_t fInode;
389 time_t fLastModified;
390 uint64_t fOffsetInFatFile;
391 std::vector<class Segment*> fSegments;
392 DependentLibrary* fLibraries;
393 uint32_t fLibrariesCount;
394 uint32_t fPathHash;
395 uint32_t fReferenceCount;
396 bool fAllLibraryChecksumsAndLoadAddressesMatch;
397 bool fLeaveMapped; // when unloaded, leave image mapped in cause some other code may have pointers into it
398
399
400 private:
401 void init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate);
402 intptr_t assignSegmentAddresses(const LinkContext& context);
403 uint64_t copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize);
404 const ImageLoader::Symbol* findExportedSymbolInDependentImagesExcept(const char* name, std::set<const ImageLoader*>& dontSearchImages, ImageLoader** foundIn) const;
405
406
407 bool fHideSymbols; // ignore this image's exported symbols when linking other images
408 bool fMatchByInstallName;// look at image's install-path not its load path
409 bool fLibrariesLoaded;
410 bool fBased;
411 bool fBoundAllNonLazy;
412 bool fBoundAllLazy;
413 bool fAnnounced;
414 bool fInitialized;
415 uint16_t fNextAddImageIndex;
416 };
417
418
419 //
420 // Segment is an abstract base class. A segment is a chunk of an executable
421 // file that is mapped into memory. Each subclass of ImageLoader typically
422 // implements its own concrete subclass of Segment.
423 //
424 //
425 class Segment {
426 public:
427 virtual ~Segment() {}
428
429 virtual const ImageLoader* getImage() = 0;
430 virtual const char* getName() = 0;
431 virtual uintptr_t getSize() = 0;
432 virtual uintptr_t getFileSize() = 0;
433 virtual bool hasTrailingZeroFill();
434 virtual uintptr_t getFileOffset() = 0;
435 virtual bool readable() = 0;
436 virtual bool writeable() = 0;
437 virtual bool executable() = 0;
438 virtual bool unaccessible() = 0;
439 virtual bool hasFixUps() = 0;
440 virtual uintptr_t getActualLoadAddress() = 0;
441 virtual uintptr_t getPreferredLoadAddress() = 0;
442 virtual void setUnMapWhenDestructed(bool unmap) = 0;
443
444 protected:
445 // abstract base class so all constructors protected
446 Segment() {}
447 Segment(const Segment&);
448 void operator=(const Segment&);
449
450 virtual bool hasPreferredLoadAddress() = 0;
451 //virtual void setActualLoadAddress(uint64_t addr) = 0;
452
453 static bool reserveAddressRange(uintptr_t start, size_t length);
454 static uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context);
455 static uintptr_t fgNextNonSplitSegAddress;
456
457 private:
458 void map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context);
459 void map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context);
460 void setPermissions();
461 void tempWritable();
462
463 friend class ImageLoader;
464 friend class ImageLoaderMachO;
465 };
466
467
468
469 #endif
470