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