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