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