]> git.saurik.com Git - apple/dyld.git/blob - src/ImageLoader.h
dyld-44.2.tar.gz
[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 bindFlat;
99 bool slideAndPackDylibs;
100 bool verboseOpts;
101 bool verboseEnv;
102 bool verboseMapping;
103 bool verboseRebase;
104 bool verboseBind;
105 bool verboseInit;
106 bool verbosePrebinding;
107 bool verboseWarnings;
108 };
109
110 // constructor is protected, but anyone can delete an image
111 virtual ~ImageLoader();
112
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);
116
117 // runInitializers() is normally called in link() but the main executable must
118 // run crt code before initializers
119 void runInitializers(const LinkContext& context);
120
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);
124
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;
127
128 // get short name of this image
129 const char* getShortName() const;
130
131 // get path used to load this image, not necessarily the "real" path
132 const char* getPath() const { return fPath; }
133
134 uint32_t getPathHash() const { return fPathHash; }
135
136 // get path used to load this image represents (ZeroLink only) which image this .o is part of
137 const char* getLogicalPath() const;
138
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;
141
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);
145
146 // if path was a fat file, offset of image loaded in that fat file
147 uint64_t getOffsetInFatFile() const;
148
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);
151
152 // check if this image's exported symbols should be ignored when linking other images
153 bool hasHiddenExports() const;
154
155 // checks if this image is already linked into the process
156 bool isLinked() const;
157
158 // even if image is deleted, leave segments mapped in
159 void setLeaveMapped();
160
161 // checks if the specifed address is within one of this image's segments
162 virtual bool containsAddress(const void* addr) const;
163
164 // adds to list of ranges of memory mapped in
165 void addMappedRegions(RegionsVector& regions) const;
166
167 // st_mtime from stat() on file
168 time_t lastModified();
169
170 // image should create prebound version of itself and return freespace remaining on disk
171 uint64_t reprebind(const LinkContext& context, time_t timestamp);
172
173 // if 'commit', the prebound version should be swapped in, otherwise deleted
174 void reprebindCommit(const LinkContext& context, bool commit, bool unmapOld);
175
176 // only valid for main executables, returns a pointer its entry point
177 virtual void* getMain() const = 0;
178
179 // dyld API's require each image to have an associated mach_header
180 virtual const struct mach_header* machHeader() const = 0;
181
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;
184
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;
187
188 // image has exports that participate in runtime coalescing
189 virtual bool hasCoalescedExports() const = 0;
190
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;
193
194 // gets address of implementation (code) of the specified exported symbol
195 virtual uintptr_t getExportedSymbolAddress(const Symbol* sym) const = 0;
196
197 // gets attributes of the specified exported symbol
198 virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0;
199
200 // gets name of the specified exported symbol
201 virtual const char* getExportedSymbolName(const Symbol* sym) const = 0;
202
203 // gets how many symbols are exported by this image
204 virtual uint32_t getExportedSymbolCount() const = 0;
205
206 // gets the i'th exported symbol
207 virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0;
208
209 // find exported symbol as if imported by this image
210 // used by RTLD_NEXT
211 virtual const Symbol* findExportedSymbolInDependentImages(const char* name, ImageLoader** foundIn) const;
212
213 // find exported symbol as if imported by this image
214 // used by RTLD_SELF
215 virtual const Symbol* findExportedSymbolInImageOrDependentImages(const char* name, ImageLoader** foundIn) const;
216
217 // gets how many symbols are imported by this image
218 virtual uint32_t getImportedSymbolCount() const = 0;
219
220 // gets the i'th imported symbol
221 virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0;
222
223 // gets attributes of the specified imported symbol
224 virtual ReferenceFlags geImportedSymbolInfo(const Symbol* sym) const = 0;
225
226 // gets name of the specified imported symbol
227 virtual const char* getImportedSymbolName(const Symbol* sym) const = 0;
228
229 // checks if this image is a bundle and can be loaded but not linked
230 virtual bool isBundle() const = 0;
231
232 // checks if this image is a dylib
233 virtual bool isDylib() const = 0;
234
235 // only for main executable
236 virtual bool forceFlat() const = 0;
237
238 // called at runtime when a lazily bound function is first called
239 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
240
241 // calls termination routines (e.g. C++ static destructors for image)
242 virtual void doTermination(const LinkContext& context) = 0;
243
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;
246
247 // return if this image has initialization routines
248 virtual bool needsInitialization() = 0;
249
250 // return if this image has a routine to be called when any image is loaded or unloaded
251 virtual bool hasImageNotification() = 0;
252
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;
255
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;
258
259 // the image supports being prebound
260 virtual bool isPrebindable() const = 0;
261
262 // the image is prebindable and its prebinding is valid
263 virtual bool usablePrebinding(const LinkContext& context) const = 0;
264
265 // used to implement refernce counting of images
266 void incrementReferenceCount();
267 bool decrementReferenceCount();
268
269 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
270 static void printStatistics(unsigned int imageCount);
271
272 // used with DYLD_IMAGE_SUFFIX
273 static void addSuffix(const char* path, const char* suffix, char* result);
274
275 static uint32_t hash(const char*);
276
277
278 void setPath(const char* path); // only called for images created from memory
279 void setLogicalPath(const char* path);
280
281
282 protected:
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&);
288
289
290 struct LibraryInfo {
291 uint64_t checksum;
292 uint32_t minVersion;
293 uint32_t maxVersion;
294 };
295
296 struct DependentLibrary {
297 const char* name;
298 ImageLoader* image;
299 LibraryInfo info;
300 bool required;
301 bool checksumMatches;
302 bool isReExported;
303 bool isSubFramework;
304 };
305
306 typedef void (*Initializer)(int argc, const char* argv[], const char* envp[],const char* apple[]);
307 typedef void (*Terminator)(void);
308
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);
317
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;
321
322 // return how many libraries this image depends on
323 virtual uint32_t doGetDependentLibraryCount() = 0;
324
325 // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
326 virtual void doGetDependentLibraries(DependentLibrary libs[]) = 0;
327
328 // called on images that are libraries, returns info about itself
329 virtual LibraryInfo doGetLibraryInfo() = 0;
330
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;
333
334 // do any symbolic fix ups in this image
335 virtual void doBind(const LinkContext& context, BindingLaziness bindness) = 0;
336
337 // run any initialization routines in this image
338 virtual void doInitialization(const LinkContext& context) = 0;
339
340 // write prebinding updates to mapped file fileToPrebind
341 virtual void doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind) = 0;
342
343 // return if this image has termination routines
344 virtual bool needsTermination() = 0;
345
346 // support for runtimes in which segments don't have to maintain their relative positions
347 virtual bool segmentsMustSlideTogether() const = 0;
348
349 // built with PIC code and can load at any address
350 virtual bool segmentsCanSlide() const = 0;
351
352 // set how much all segments slide
353 virtual void setSlide(intptr_t slide) = 0;
354
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);
357
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);
360
361 // returns if all dependent libraries checksum's were as expected and none slide
362 bool allDependentLibrariesAsWhenPreBound() const;
363
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;
366
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;
369
370 // file has been reprebound on disk, unmap this file so original file is released
371 virtual void prebindUnmap(const LinkContext& context) = 0;
372
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;
384 const char* fPath;
385 const char* fLogicalPath; // for ZeroLink - the image which this bundle is part of
386 dev_t fDevice;
387 ino_t fInode;
388 time_t fLastModified;
389 uint64_t fOffsetInFatFile;
390 std::vector<class Segment*> fSegments;
391 DependentLibrary* fLibraries;
392 uint32_t fLibrariesCount;
393 uint32_t fPathHash;
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
397
398
399 private:
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;
404
405
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;
409 bool fBased;
410 bool fBoundAllNonLazy;
411 bool fBoundAllLazy;
412 bool fAnnounced;
413 bool fInitialized;
414 uint16_t fNextAddImageIndex;
415 };
416
417
418 //
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.
422 //
423 //
424 class Segment {
425 public:
426 virtual ~Segment() {}
427
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;
442
443 protected:
444 // abstract base class so all constructors protected
445 Segment() {}
446 Segment(const Segment&);
447 void operator=(const Segment&);
448
449 virtual bool hasPreferredLoadAddress() = 0;
450 //virtual void setActualLoadAddress(uint64_t addr) = 0;
451
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;
455
456 private:
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();
460 void tempWritable();
461
462 friend class ImageLoader;
463 friend class ImageLoaderMachO;
464 };
465
466
467
468 #endif
469