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