]> git.saurik.com Git - apple/dyld.git/blob - src/ImageLoader.h
4e00826c1f334b54fc34500f79b6dc13a78a895c
[apple/dyld.git] / src / ImageLoader.h
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2010 Apple 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 <unistd.h>
31 #include <stdlib.h>
32 #include <mach/mach_time.h> // struct mach_timebase_info
33 #include <mach/mach_init.h> // struct mach_thread_self
34 #include <mach/shared_region.h>
35 #include <mach-o/loader.h>
36 #include <mach-o/nlist.h>
37 #include <stdint.h>
38 #include <stdlib.h>
39 #include <TargetConditionals.h>
40 #include <vector>
41 #include <new>
42
43 #if __MAC_OS_X_VERSION_MIN_REQUIRED
44 #include <CrashReporterClient.h>
45 #else
46 // work around until iOS has CrashReporterClient.h
47 #define CRSetCrashLogMessage(x)
48 #define CRSetCrashLogMessage2(x)
49 #endif
50
51 #define LOG_BINDINGS 0
52
53 #include "mach-o/dyld_images.h"
54 #include "mach-o/dyld_priv.h"
55
56 #if __i386__
57 #define SHARED_REGION_BASE SHARED_REGION_BASE_I386
58 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_I386
59 #elif __x86_64__
60 #define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
61 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
62 #elif __arm__
63 #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
64 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
65 #endif
66
67 #ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
68 #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
69 #endif
70 #ifndef EXPORT_SYMBOL_FLAGS_REEXPORT
71 #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
72 #endif
73
74 #ifndef LC_MAIN
75 #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
76 struct entry_point_command {
77 uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */
78 uint32_t cmdsize; /* 24 */
79 uint64_t entryoff; /* file (__TEXT) offset of main() */
80 uint64_t stacksize;/* if not zero, initial stack size */
81 };
82 #endif
83
84 #if __IPHONE_OS_VERSION_MIN_REQUIRED
85 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
86 #define SPLIT_SEG_DYLIB_SUPPORT 0
87 #define PREBOUND_IMAGE_SUPPORT 0
88 #define TEXT_RELOC_SUPPORT __i386__
89 #define DYLD_SHARED_CACHE_SUPPORT __arm__
90 #define SUPPORT_OLD_CRT_INITIALIZATION 0
91 #define SUPPORT_LC_DYLD_ENVIRONMENT 0
92 #define SUPPORT_VERSIONED_PATHS 0
93 #define SUPPORT_CLASSIC_MACHO __arm__
94 #define CORESYMBOLICATION_SUPPORT __arm__
95 #define INITIAL_IMAGE_COUNT 256
96 #else
97 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
98 #define SPLIT_SEG_DYLIB_SUPPORT __i386__
99 #define PREBOUND_IMAGE_SUPPORT __i386__
100 #define TEXT_RELOC_SUPPORT __i386__
101 #define DYLD_SHARED_CACHE_SUPPORT 1
102 #define SUPPORT_OLD_CRT_INITIALIZATION __i386__
103 #define SUPPORT_LC_DYLD_ENVIRONMENT (__i386__ || __x86_64__)
104 #define SUPPORT_VERSIONED_PATHS 1
105 #define SUPPORT_CLASSIC_MACHO 1
106 #define CORESYMBOLICATION_SUPPORT 1
107 #define INITIAL_IMAGE_COUNT 200
108 #endif
109
110
111
112 // <rdar://problem/13590567> optimize away dyld's initializers
113 #define VECTOR_NEVER_DESTRUCTED(type) \
114 namespace std { \
115 template <> \
116 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
117 }
118 #define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \
119 namespace std { \
120 template <> \
121 __vector_base<type, std::allocator<type> >::~__vector_base(); \
122 }
123 #define VECTOR_NEVER_DESTRUCTED_IMPL(type) \
124 namespace std { \
125 template <> \
126 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
127 }
128
129 // utilities
130 namespace dyld {
131 extern __attribute__((noreturn)) void throwf(const char* format, ...) __attribute__((format(printf, 1, 2)));
132 extern void log(const char* format, ...) __attribute__((format(printf, 1, 2)));
133 extern void warn(const char* format, ...) __attribute__((format(printf, 1, 2)));
134 extern const char* mkstringf(const char* format, ...) __attribute__((format(printf, 1, 2)));
135 #if LOG_BINDINGS
136 extern void logBindings(const char* format, ...) __attribute__((format(printf, 1, 2)));
137 #endif
138 }
139 extern "C" int vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags);
140 extern "C" void* xmmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset);
141
142
143 #if __LP64__
144 struct macho_header : public mach_header_64 {};
145 struct macho_nlist : public nlist_64 {};
146 #else
147 struct macho_header : public mach_header {};
148 struct macho_nlist : public nlist {};
149 #endif
150
151
152 struct ProgramVars
153 {
154 const void* mh;
155 int* NXArgcPtr;
156 const char*** NXArgvPtr;
157 const char*** environPtr;
158 const char** __prognamePtr;
159 };
160
161
162
163 //
164 // ImageLoader is an abstract base class. To support loading a particular executable
165 // file format, you make a concrete subclass of ImageLoader.
166 //
167 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
168 //
169 // The ImageLoader base class does the work of linking together images, but it knows nothing
170 // about any particular file format.
171 //
172 //
173 class ImageLoader {
174 public:
175
176 typedef uint32_t DefinitionFlags;
177 static const DefinitionFlags kNoDefinitionOptions = 0;
178 static const DefinitionFlags kWeakDefinition = 1;
179
180 typedef uint32_t ReferenceFlags;
181 static const ReferenceFlags kNoReferenceOptions = 0;
182 static const ReferenceFlags kWeakReference = 1;
183 static const ReferenceFlags kTentativeDefinition = 2;
184
185 enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
186 enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
187 enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion, kSharedRegionIsSharedCache };
188
189 struct Symbol; // abstact symbol
190
191 struct MappedRegion {
192 uintptr_t address;
193 size_t size;
194 };
195
196 struct RPathChain {
197 RPathChain(const RPathChain* n, std::vector<const char*>* p) : next(n), paths(p) {};
198 const RPathChain* next;
199 std::vector<const char*>* paths;
200 };
201
202 struct DOFInfo {
203 void* dof;
204 const mach_header* imageHeader;
205 const char* imageShortName;
206 };
207
208 struct DynamicReference {
209 ImageLoader* from;
210 ImageLoader* to;
211 };
212
213 struct LinkContext {
214 ImageLoader* (*loadLibrary)(const char* libraryName, bool search, const char* origin, const RPathChain* rpaths);
215 void (*terminationRecorder)(ImageLoader* image);
216 bool (*flatExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
217 bool (*coalescedExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
218 unsigned int (*getCoalescedImages)(ImageLoader* images[]);
219 void (*undefinedHandler)(const char* name);
220 MappedRegion* (*getAllMappedRegions)(MappedRegion*);
221 void * (*bindingHandler)(const char *, const char *, void *);
222 void (*notifySingle)(dyld_image_states, const ImageLoader* image);
223 void (*notifyBatch)(dyld_image_states state);
224 void (*removeImage)(ImageLoader* image);
225 void (*registerDOFs)(const std::vector<DOFInfo>& dofs);
226 void (*clearAllDepths)();
227 void (*printAllDepths)();
228 unsigned int (*imageCount)();
229 void (*setNewProgramVars)(const ProgramVars&);
230 bool (*inSharedCache)(const char* path);
231 void (*setErrorStrings)(unsigned errorCode, const char* errorClientOfDylibPath,
232 const char* errorTargetDylibPath, const char* errorSymbol);
233 ImageLoader* (*findImageContainingAddress)(const void* addr);
234 void (*addDynamicReference)(ImageLoader* from, ImageLoader* to);
235
236 #if SUPPORT_OLD_CRT_INITIALIZATION
237 void (*setRunInitialzersOldWay)();
238 #endif
239 BindingOptions bindingOptions;
240 int argc;
241 const char** argv;
242 const char** envp;
243 const char** apple;
244 const char* progname;
245 ProgramVars programVars;
246 ImageLoader* mainExecutable;
247 const char* imageSuffix;
248 const char** rootPaths;
249 PrebindMode prebindUsage;
250 SharedRegionMode sharedRegionMode;
251 bool dyldLoadedAtSameAddressNeededBySharedCache;
252 bool codeSigningEnforced;
253 bool mainExecutableCodeSigned;
254 bool preFetchDisabled;
255 bool prebinding;
256 bool bindFlat;
257 bool linkingMainExecutable;
258 bool startedInitializingMainExecutable;
259 bool processIsRestricted;
260 bool verboseOpts;
261 bool verboseEnv;
262 bool verboseMapping;
263 bool verboseRebase;
264 bool verboseBind;
265 bool verboseWeakBind;
266 bool verboseInit;
267 bool verboseDOF;
268 bool verbosePrebinding;
269 bool verboseCoreSymbolication;
270 bool verboseWarnings;
271 bool verboseRPaths;
272 bool verboseInterposing;
273 bool verboseCodeSignatures;
274 };
275
276 struct CoalIterator
277 {
278 ImageLoader* image;
279 const char* symbolName;
280 unsigned int loadOrder;
281 bool weakSymbol;
282 bool symbolMatches;
283 bool done;
284 // the following are private to the ImageLoader subclass
285 uintptr_t curIndex;
286 uintptr_t endIndex;
287 uintptr_t address;
288 uintptr_t type;
289 uintptr_t addend;
290 };
291
292 virtual void initializeCoalIterator(CoalIterator&, unsigned int loadOrder) = 0;
293 virtual bool incrementCoalIterator(CoalIterator&) = 0;
294 virtual uintptr_t getAddressCoalIterator(CoalIterator&, const LinkContext& context) = 0;
295 virtual void updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, const LinkContext& context) = 0;
296
297 struct InitializerTimingList
298 {
299 uintptr_t count;
300 struct {
301 ImageLoader* image;
302 uint64_t initTime;
303 } images[1];
304 };
305
306
307 // constructor is protected, but anyone can delete an image
308 virtual ~ImageLoader();
309
310 // link() takes a newly instantiated ImageLoader and does all
311 // fixups needed to make it usable by the process
312 void link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths);
313
314 // runInitializers() is normally called in link() but the main executable must
315 // run crt code before initializers
316 void runInitializers(const LinkContext& context, InitializerTimingList& timingInfo);
317
318 // called after link() forces all lazy pointers to be bound
319 void bindAllLazyPointers(const LinkContext& context, bool recursive);
320
321 // used by dyld to see if a requested library is already loaded (might be symlink)
322 bool statMatch(const struct stat& stat_buf) const;
323
324 // get short name of this image
325 const char* getShortName() const;
326
327 // get path used to load this image, not necessarily the "real" path
328 const char* getPath() const { return fPath; }
329
330 uint32_t getPathHash() const { return fPathHash; }
331
332 // get the "real" path for this image (e.g. no @rpath)
333 const char* getRealPath() const;
334
335 // get path this image is intended to be placed on disk or NULL if no preferred install location
336 virtual const char* getInstallPath() const = 0;
337
338 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
339 bool matchInstallPath() const;
340 void setMatchInstallPath(bool);
341
342 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
343 void setHideExports(bool hide = true);
344
345 // check if this image's exported symbols should be ignored when linking other images
346 bool hasHiddenExports() const;
347
348 // checks if this image is already linked into the process
349 bool isLinked() const;
350
351 // even if image is deleted, leave segments mapped in
352 void setLeaveMapped();
353
354 // even if image is deleted, leave segments mapped in
355 bool leaveMapped() { return fLeaveMapped; }
356
357 // image resides in dyld shared cache
358 virtual bool inSharedCache() const = 0;
359
360 // checks if the specifed address is within one of this image's segments
361 virtual bool containsAddress(const void* addr) const;
362
363 // checks if the specifed symbol is within this image's symbol table
364 virtual bool containsSymbol(const void* addr) const = 0;
365
366 // checks if the specifed address range overlaps any of this image's segments
367 virtual bool overlapsWithAddressRange(const void* start, const void* end) const;
368
369 // adds to list of ranges of memory mapped in
370 void getMappedRegions(MappedRegion*& region) const;
371
372 // st_mtime from stat() on file
373 time_t lastModified() const;
374
375 // only valid for main executables, returns a pointer its entry point from LC_UNIXTHREAD
376 virtual void* getThreadPC() const = 0;
377
378 // only valid for main executables, returns a pointer its main from LC_<MAIN
379 virtual void* getMain() const = 0;
380
381 // dyld API's require each image to have an associated mach_header
382 virtual const struct mach_header* machHeader() const = 0;
383
384 // dyld API's require each image to have a slide (actual load address minus preferred load address)
385 virtual uintptr_t getSlide() const = 0;
386
387 // last address mapped by image
388 virtual const void* getEnd() const = 0;
389
390 // image has exports that participate in runtime coalescing
391 virtual bool hasCoalescedExports() const = 0;
392
393 // search symbol table of definitions in this image for requested name
394 virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const = 0;
395
396 // gets address of implementation (code) of the specified exported symbol
397 virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context,
398 const ImageLoader* requestor=NULL, bool runResolver=false) const = 0;
399
400 // gets attributes of the specified exported symbol
401 virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0;
402
403 // gets name of the specified exported symbol
404 virtual const char* getExportedSymbolName(const Symbol* sym) const = 0;
405
406 // gets how many symbols are exported by this image
407 virtual uint32_t getExportedSymbolCount() const = 0;
408
409 // gets the i'th exported symbol
410 virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0;
411
412 // find exported symbol as if imported by this image
413 // used by RTLD_NEXT
414 virtual const Symbol* findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
415
416 // find exported symbol as if imported by this image
417 // used by RTLD_SELF
418 virtual const Symbol* findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
419
420 // gets how many symbols are imported by this image
421 virtual uint32_t getImportedSymbolCount() const = 0;
422
423 // gets the i'th imported symbol
424 virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0;
425
426 // gets attributes of the specified imported symbol
427 virtual ReferenceFlags getImportedSymbolInfo(const Symbol* sym) const = 0;
428
429 // gets name of the specified imported symbol
430 virtual const char* getImportedSymbolName(const Symbol* sym) const = 0;
431
432 // find the closest symbol before addr
433 virtual const char* findClosestSymbol(const void* addr, const void** closestAddr) const = 0;
434
435 // checks if this image is a bundle and can be loaded but not linked
436 virtual bool isBundle() const = 0;
437
438 // checks if this image is a dylib
439 virtual bool isDylib() const = 0;
440
441 // checks if this image is a main executable
442 virtual bool isExecutable() const = 0;
443
444 // checks if this image is a main executable
445 virtual bool isPositionIndependentExecutable() const = 0;
446
447 // only for main executable
448 virtual bool forceFlat() const = 0;
449
450 // called at runtime when a lazily bound function is first called
451 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
452
453 // called at runtime when a fast lazily bound function is first called
454 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context,
455 void (*lock)(), void (*unlock)()) = 0;
456
457 // calls termination routines (e.g. C++ static destructors for image)
458 virtual void doTermination(const LinkContext& context) = 0;
459
460 // return if this image has initialization routines
461 virtual bool needsInitialization() = 0;
462
463 // return if this image has specified section and set start and length
464 virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
465
466 // fills in info about __eh_frame and __unwind_info sections
467 virtual void getUnwindInfo(dyld_unwind_sections* info) = 0;
468
469 // given a pointer into an image, find which segment and section it is in
470 virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
471
472 // the image supports being prebound
473 virtual bool isPrebindable() const = 0;
474
475 // the image is prebindable and its prebinding is valid
476 virtual bool usablePrebinding(const LinkContext& context) const = 0;
477
478 // add all RPATH paths this image contains
479 virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const = 0;
480
481 // image has or uses weak definitions that need runtime coalescing
482 virtual bool participatesInCoalescing() const = 0;
483
484 // if image has a UUID, copy into parameter and return true
485 virtual bool getUUID(uuid_t) const = 0;
486
487
488 //
489 // A segment is a chunk of an executable file that is mapped into memory.
490 //
491 virtual unsigned int segmentCount() const = 0;
492 virtual const char* segName(unsigned int) const = 0;
493 virtual uintptr_t segSize(unsigned int) const = 0;
494 virtual uintptr_t segFileSize(unsigned int) const = 0;
495 virtual bool segHasTrailingZeroFill(unsigned int) = 0;
496 virtual uintptr_t segFileOffset(unsigned int) const = 0;
497 virtual bool segReadable(unsigned int) const = 0;
498 virtual bool segWriteable(unsigned int) const = 0;
499 virtual bool segExecutable(unsigned int) const = 0;
500 virtual bool segUnaccessible(unsigned int) const = 0;
501 virtual bool segHasPreferredLoadAddress(unsigned int) const = 0;
502 virtual uintptr_t segPreferredLoadAddress(unsigned int) const = 0;
503 virtual uintptr_t segActualLoadAddress(unsigned int) const = 0;
504 virtual uintptr_t segActualEndAddress(unsigned int) const = 0;
505
506
507 virtual uint32_t sdkVersion() const = 0;
508
509 // if the image contains interposing functions, register them
510 virtual void registerInterposing() = 0;
511
512 // when resolving symbols look in subImage if symbol can't be found
513 void reExport(ImageLoader* subImage);
514
515 void weakBind(const LinkContext& context);
516
517 void applyInterposing(const LinkContext& context);
518
519 dyld_image_states getState() { return (dyld_image_states)fState; }
520
521 // used to sort images bottom-up
522 int compare(const ImageLoader* right) const;
523
524 void incrementDlopenReferenceCount() { ++fDlopenReferenceCount; }
525
526 bool decrementDlopenReferenceCount();
527
528 void printReferenceCounts();
529
530 uint32_t dlopenCount() const { return fDlopenReferenceCount; }
531
532 void setCanUnload() { fNeverUnload = false; fLeaveMapped = false; }
533
534 bool neverUnload() const { return fNeverUnload; }
535
536 void setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; }
537 void setNeverUnloadRecursive();
538
539 bool isReferencedDownward() { return fIsReferencedDownward; }
540
541
542 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
543 static void printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
544
545 // used with DYLD_IMAGE_SUFFIX
546 static void addSuffix(const char* path, const char* suffix, char* result);
547
548 static uint32_t hash(const char*);
549
550 // used instead of directly deleting image
551 static void deleteImage(ImageLoader*);
552
553 bool dependsOn(ImageLoader* image);
554
555 void setPath(const char* path);
556 void setPaths(const char* path, const char* realPath);
557 void setPathUnowned(const char* path);
558
559 void clearDepth() { fDepth = 0; }
560 int getDepth() { return fDepth; }
561
562 void setBeingRemoved() { fBeingRemoved = true; }
563 bool isBeingRemoved() const { return fBeingRemoved; }
564
565 void markNotUsed() { fMarkedInUse = false; }
566 void markedUsedRecursive(const std::vector<DynamicReference>&);
567 bool isMarkedInUse() const { return fMarkedInUse; }
568
569 void setAddFuncNotified() { fAddFuncNotified = true; }
570 bool addFuncNotified() const { return fAddFuncNotified; }
571
572 struct InterposeTuple {
573 uintptr_t replacement;
574 ImageLoader* replacementImage; // don't apply replacement to this image
575 uintptr_t replacee;
576 };
577
578 protected:
579 // abstract base class so all constructors protected
580 ImageLoader(const char* path, unsigned int libCount);
581 ImageLoader(const ImageLoader&);
582 void operator=(const ImageLoader&);
583 void operator delete(void* image) throw() { ::free(image); }
584
585
586 struct LibraryInfo {
587 uint32_t checksum;
588 uint32_t minVersion;
589 uint32_t maxVersion;
590 };
591
592 struct DependentLibrary {
593 ImageLoader* image;
594 uint32_t required : 1,
595 checksumMatches : 1,
596 isReExported : 1,
597 isSubFramework : 1;
598 };
599
600 struct DependentLibraryInfo {
601 const char* name;
602 LibraryInfo info;
603 bool required;
604 bool reExported;
605 bool upward;
606 };
607
608
609 typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[], const ProgramVars* vars);
610 typedef void (*Terminator)(void);
611
612
613
614 unsigned int libraryCount() const { return fLibraryCount; }
615 virtual ImageLoader* libImage(unsigned int) const = 0;
616 virtual bool libReExported(unsigned int) const = 0;
617 virtual bool libIsUpward(unsigned int) const = 0;
618 virtual void setLibImage(unsigned int, ImageLoader*, bool, bool) = 0;
619
620 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
621 // These methods do the above, exactly once, and it the right order
622 void recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths);
623 void recursiveUnLoadMappedLibraries(const LinkContext& context);
624 unsigned int recursiveUpdateDepth(unsigned int maxDepth);
625 void recursiveValidate(const LinkContext& context);
626 void recursiveRebase(const LinkContext& context);
627 void recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload);
628 void recursiveApplyInterposing(const LinkContext& context);
629 void recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs);
630 void recursiveInitialization(const LinkContext& context, mach_port_t this_thread, ImageLoader::InitializerTimingList&);
631
632 // fill in information about dependent libraries (array length is fLibraryCount)
633 virtual void doGetDependentLibraries(DependentLibraryInfo libs[]) = 0;
634
635 // called on images that are libraries, returns info about itself
636 virtual LibraryInfo doGetLibraryInfo() = 0;
637
638 // do any fix ups in this image that depend only on the load address of the image
639 virtual void doRebase(const LinkContext& context) = 0;
640
641 // do any symbolic fix ups in this image
642 virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0;
643
644 // called later via API to force all lazy pointer to be bound
645 virtual void doBindJustLazies(const LinkContext& context) = 0;
646
647 // if image has any dtrace DOF sections, append them to list to be registered
648 virtual void doGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs) = 0;
649
650 // do interpose
651 virtual void doInterpose(const LinkContext& context) = 0;
652
653 // run any initialization routines in this image
654 virtual bool doInitialization(const LinkContext& context) = 0;
655
656 // return if this image has termination routines
657 virtual bool needsTermination() = 0;
658
659 // support for runtimes in which segments don't have to maintain their relative positions
660 virtual bool segmentsMustSlideTogether() const = 0;
661
662 // built with PIC code and can load at any address
663 virtual bool segmentsCanSlide() const = 0;
664
665 // set how much all segments slide
666 virtual void setSlide(intptr_t slide) = 0;
667
668 // returns if all dependent libraries checksum's were as expected and none slide
669 bool allDependentLibrariesAsWhenPreBound() const;
670
671 // in mach-o a child tells it parent to re-export, instead of the other way around...
672 virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
673
674 // in mach-o a parent library knows name of sub libraries it re-exports..
675 virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0;
676
677 // set fState to dyld_image_state_memory_mapped
678 void setMapped(const LinkContext& context);
679
680 void setFileInfo(dev_t device, ino_t inode, time_t modDate);
681
682 static uintptr_t fgNextPIEDylibAddress;
683 static uint32_t fgImagesWithUsedPrebinding;
684 static uint32_t fgImagesUsedFromSharedCache;
685 static uint32_t fgImagesHasWeakDefinitions;
686 static uint32_t fgImagesRequiringCoalescing;
687 static uint32_t fgTotalRebaseFixups;
688 static uint32_t fgTotalBindFixups;
689 static uint32_t fgTotalBindSymbolsResolved;
690 static uint32_t fgTotalBindImageSearches;
691 static uint32_t fgTotalLazyBindFixups;
692 static uint32_t fgTotalPossibleLazyBindFixups;
693 static uint32_t fgTotalSegmentsMapped;
694 static uint64_t fgTotalBytesMapped;
695 static uint64_t fgTotalBytesPreFetched;
696 static uint64_t fgTotalLoadLibrariesTime;
697 static uint64_t fgTotalRebaseTime;
698 static uint64_t fgTotalBindTime;
699 static uint64_t fgTotalWeakBindTime;
700 static uint64_t fgTotalDOF;
701 static uint64_t fgTotalInitTime;
702 static std::vector<InterposeTuple> fgInterposingTuples;
703
704 const char* fPath;
705 const char* fRealPath;
706 dev_t fDevice;
707 ino_t fInode;
708 time_t fLastModified;
709 uint32_t fPathHash;
710 uint32_t fDlopenReferenceCount; // count of how many dlopens have been done on this image
711
712 private:
713 struct recursive_lock {
714 recursive_lock(mach_port_t t) : thread(t), count(0) {}
715 mach_port_t thread;
716 int count;
717 };
718 void recursiveSpinLock(recursive_lock&);
719 void recursiveSpinUnLock();
720
721 const ImageLoader::Symbol* findExportedSymbolInDependentImagesExcept(const char* name, const ImageLoader** dsiStart,
722 const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const;
723
724
725
726 recursive_lock* fInitializerRecursiveLock;
727 uint16_t fDepth;
728 uint16_t fLoadOrder;
729 uint32_t fState : 8,
730 fLibraryCount : 10,
731 fAllLibraryChecksumsAndLoadAddressesMatch : 1,
732 fLeaveMapped : 1, // when unloaded, leave image mapped in cause some other code may have pointers into it
733 fNeverUnload : 1, // image was statically loaded by main executable
734 fHideSymbols : 1, // ignore this image's exported symbols when linking other images
735 fMatchByInstallName : 1,// look at image's install-path not its load path
736 fInterposed : 1,
737 fRegisteredDOF : 1,
738 fAllLazyPointersBound : 1,
739 fMarkedInUse : 1,
740 fBeingRemoved : 1,
741 fAddFuncNotified : 1,
742 fPathOwnedByImage : 1,
743 fIsReferencedDownward : 1,
744 fWeakSymbolsBound : 1;
745
746 static uint16_t fgLoadOrdinal;
747 };
748
749
750 VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
751
752
753 #endif
754