1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
26 #ifndef __IMAGELOADER__
27 #define __IMAGELOADER__
29 #include <sys/types.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>
41 #include <TargetConditionals.h>
44 #include <uuid/uuid.h>
46 #if !TARGET_OS_DRIVERKIT && (BUILDING_LIBDYLD || BUILDING_DYLD)
47 #include <CrashReporterClient.h>
49 #define CRSetCrashLogMessage(x)
50 #define CRSetCrashLogMessage2(x)
53 #include "DyldSharedCache.h"
55 #include "PointerAuth.h"
58 #include <mach/vm_page_size.h>
62 #ifndef SHARED_REGION_BASE_ARM64
63 #define SHARED_REGION_BASE_ARM64 0x7FFF80000000LL
66 #ifndef SHARED_REGION_SIZE_ARM64
67 #define SHARED_REGION_SIZE_ARM64 0x10000000LL
71 #define LOG_BINDINGS 0
75 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
76 #define SPLIT_SEG_DYLIB_SUPPORT 0
77 #define PREBOUND_IMAGE_SUPPORT __arm__
78 #define TEXT_RELOC_SUPPORT __i386__
79 #define SUPPORT_OLD_CRT_INITIALIZATION 0
80 #define SUPPORT_LC_DYLD_ENVIRONMENT 1
81 #define SUPPORT_VERSIONED_PATHS 0
82 #define SUPPORT_CLASSIC_MACHO __arm__
83 #define SUPPORT_ZERO_COST_EXCEPTIONS (!__USING_SJLJ_EXCEPTIONS__)
84 #define INITIAL_IMAGE_COUNT 150
85 #define SUPPORT_ACCELERATE_TABLES 0
86 #define SUPPORT_ROOT_PATH TARGET_OS_SIMULATOR
88 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
89 #define SPLIT_SEG_DYLIB_SUPPORT __i386__
90 #define PREBOUND_IMAGE_SUPPORT __i386__
91 #define TEXT_RELOC_SUPPORT __i386__
92 #define SUPPORT_OLD_CRT_INITIALIZATION __i386__
93 #define SUPPORT_LC_DYLD_ENVIRONMENT 1
94 #define SUPPORT_VERSIONED_PATHS 1
95 #define SUPPORT_CLASSIC_MACHO 1
96 #define SUPPORT_ZERO_COST_EXCEPTIONS 1
97 #define INITIAL_IMAGE_COUNT 200
98 #define SUPPORT_ACCELERATE_TABLES 0
99 #define SUPPORT_ROOT_PATH 1
102 #define MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE (32*1024)
105 // <rdar://problem/13590567> optimize away dyld's initializers
106 #define VECTOR_NEVER_DESTRUCTED(type) \
109 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
111 #define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \
114 __vector_base<type, std::allocator<type> >::~__vector_base(); \
116 #define VECTOR_NEVER_DESTRUCTED_IMPL(type) \
119 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
124 extern __attribute__((noreturn
)) void throwf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
125 extern void log(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
126 extern void warn(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
127 extern const char* mkstringf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
129 extern void logBindings(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
132 extern "C" int vm_alloc(vm_address_t
* addr
, vm_size_t size
, uint32_t flags
);
133 extern "C" void* xmmap(void* addr
, size_t len
, int prot
, int flags
, int fd
, off_t offset
);
137 struct macho_header
: public mach_header_64
{};
138 struct macho_nlist
: public nlist_64
{};
140 struct macho_header
: public mach_header
{};
141 struct macho_nlist
: public nlist
{};
146 #define dyld_page_trunc(__addr) (__addr & (-16384))
147 #define dyld_page_round(__addr) ((__addr + 16383) & (-16384))
148 #define dyld_page_size 16384
150 #define dyld_page_trunc(__addr) trunc_page_kernel(__addr)
151 #define dyld_page_round(__addr) round_page_kernel(__addr)
152 #define dyld_page_size vm_kernel_page_size
154 #define dyld_page_trunc(__addr) (__addr & (-4096))
155 #define dyld_page_round(__addr) ((__addr + 4095) & (-4096))
156 #define dyld_page_size 4096
160 #define DYLD_PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
166 const char*** NXArgvPtr
;
167 const char*** environPtr
;
168 const char** __prognamePtr
;
173 enum dyld_image_states
175 dyld_image_state_mapped
= 10, // No batch notification for this
176 dyld_image_state_dependents_mapped
= 20, // Only batch notification for this
177 dyld_image_state_rebased
= 30,
178 dyld_image_state_bound
= 40,
179 dyld_image_state_dependents_initialized
= 45, // Only single notification for this
180 dyld_image_state_initialized
= 50,
181 dyld_image_state_terminated
= 60 // Only single notification for this
183 typedef const char* (*dyld_image_state_change_handler
)(enum dyld_image_states state
, uint32_t infoCount
, const struct dyld_image_info info
[]);
186 // ImageLoader is an abstract base class. To support loading a particular executable
187 // file format, you make a concrete subclass of ImageLoader.
189 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
191 // The ImageLoader base class does the work of linking together images, but it knows nothing
192 // about any particular file format.
198 typedef uint32_t DefinitionFlags
;
199 static const DefinitionFlags kNoDefinitionOptions
= 0;
200 static const DefinitionFlags kWeakDefinition
= 1;
202 typedef uint32_t ReferenceFlags
;
203 static const ReferenceFlags kNoReferenceOptions
= 0;
204 static const ReferenceFlags kWeakReference
= 1;
205 static const ReferenceFlags kTentativeDefinition
= 2;
207 enum PrebindMode
{ kUseAllPrebinding
, kUseSplitSegPrebinding
, kUseAllButAppPredbinding
, kUseNoPrebinding
};
208 enum BindingOptions
{ kBindingNone
, kBindingLazyPointers
, kBindingNeverSetLazyPointers
};
209 enum SharedRegionMode
{ kUseSharedRegion
, kUsePrivateSharedRegion
, kDontUseSharedRegion
, kSharedRegionIsSharedCache
};
211 struct Symbol
; // abstact symbol
213 struct MappedRegion
{
219 RPathChain(const RPathChain
* n
, std
::vector
<const char*>* p
) : next(n
), paths(p
) {};
220 const RPathChain
* next
;
221 std
::vector
<const char*>* paths
;
226 const mach_header
* imageHeader
;
227 const char* imageShortName
;
230 struct DynamicReference
{
235 struct InitializerTimingList
239 const char* shortName
;
243 void addTime(const char* name
, uint64_t time
);
246 typedef void (^CoalesceNotifier
)(const Symbol
* implSym
, const ImageLoader
* implIn
, const mach_header
* implMh
);
249 static size_t hash(const char* v
);
252 struct EqualCString
{
253 static bool equal(const char* s1
, const char* s2
);
257 ImageLoader
* (*loadLibrary
)(const char* libraryName
, bool search
, const char* origin
, const RPathChain
* rpaths
, unsigned& cacheIndex
);
258 void (*terminationRecorder
)(ImageLoader
* image
);
259 bool (*flatExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
);
260 bool (*coalescedExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
, CoalesceNotifier
);
261 unsigned int (*getCoalescedImages
)(ImageLoader
* images
[], unsigned imageIndex
[]);
262 void (*undefinedHandler
)(const char* name
);
263 MappedRegion
* (*getAllMappedRegions
)(MappedRegion
*);
264 void * (*bindingHandler
)(const char *, const char *, void *);
265 void (*notifySingle
)(dyld_image_states
, const ImageLoader
* image
, InitializerTimingList
*);
266 void (*notifyBatch
)(dyld_image_states state
, bool preflightOnly
);
267 void (*removeImage
)(ImageLoader
* image
);
268 void (*registerDOFs
)(const std
::vector
<DOFInfo
>& dofs
);
269 void (*clearAllDepths
)();
270 void (*printAllDepths
)();
271 unsigned int (*imageCount
)();
272 void (*setNewProgramVars
)(const ProgramVars
&);
273 bool (*inSharedCache
)(const char* path
);
274 void (*setErrorStrings
)(unsigned errorCode
, const char* errorClientOfDylibPath
,
275 const char* errorTargetDylibPath
, const char* errorSymbol
);
276 ImageLoader
* (*findImageContainingAddress
)(const void* addr
);
277 void (*addDynamicReference
)(ImageLoader
* from
, ImageLoader
* to
);
278 #if SUPPORT_ACCELERATE_TABLES
279 void (*notifySingleFromCache
)(dyld_image_states
, const mach_header
* mh
, const char* path
);
280 dyld_image_state_change_handler (*getPreInitNotifyHandler
)(unsigned index
);
281 dyld_image_state_change_handler (*getBoundBatchHandler
)(unsigned index
);
284 #if SUPPORT_OLD_CRT_INITIALIZATION
285 void (*setRunInitialzersOldWay
)();
287 BindingOptions bindingOptions
;
292 const char* progname
;
293 ProgramVars programVars
;
294 ImageLoader
* mainExecutable
;
295 const char* const * imageSuffix
;
296 #if SUPPORT_ROOT_PATH
297 const char** rootPaths
;
299 const DyldSharedCache
* dyldCache
;
300 const dyld_interpose_tuple
* dynamicInterposeArray
;
301 size_t dynamicInterposeCount
;
302 PrebindMode prebindUsage
;
303 SharedRegionMode sharedRegionMode
;
304 mutable dyld3
::Map
<const char*, std
::pair
<const ImageLoader
*, uintptr_t>, HashCString
, EqualCString
> weakDefMap
;
305 mutable bool weakDefMapInitialized
= false;
306 mutable bool weakDefMapProcessedLaunchDefs
= false;
307 mutable bool useNewWeakBind
= false;
308 bool dyldLoadedAtSameAddressNeededBySharedCache
;
309 bool strictMachORequired
;
311 bool allowEnvVarsPrint
;
312 bool allowEnvVarsPath
;
313 bool allowEnvVarsSharedCache
;
314 bool allowClassicFallbackPaths
;
315 bool allowInsertFailures
;
316 bool allowInterposing
;
317 bool mainExecutableCodeSigned
;
320 bool linkingMainExecutable
;
321 bool startedInitializingMainExecutable
;
324 // dyld doesn't build for driverKit, so we use the macOS define to control whether driverKit is supported
333 bool verboseWeakBind
;
336 bool verbosePrebinding
;
337 bool verboseCoreSymbolication
;
338 bool verboseWarnings
;
340 bool verboseInterposing
;
341 bool verboseCodeSignatures
;
347 const char* symbolName
;
348 unsigned int loadOrder
;
352 // the following are private to the ImageLoader subclass
358 uintptr_t imageIndex
;
361 virtual void initializeCoalIterator(CoalIterator
&, unsigned int loadOrder
, unsigned imageIndex
) = 0;
362 virtual bool incrementCoalIterator(CoalIterator
&) = 0;
363 virtual uintptr_t getAddressCoalIterator(CoalIterator
&, const LinkContext
& context
) = 0;
364 virtual void updateUsesCoalIterator(CoalIterator
&, uintptr_t newAddr
, ImageLoader
* target
, unsigned targetIndex
, const LinkContext
& context
) = 0;
366 struct UninitedUpwards
369 std
::pair
<ImageLoader
*, const char*> imagesAndPaths
[1];
373 // constructor is protected, but anyone can delete an image
374 virtual ~ImageLoader();
376 // link() takes a newly instantiated ImageLoader and does all
377 // fixups needed to make it usable by the process
378 void link(const LinkContext
& context
, bool forceLazysBound
, bool preflight
, bool neverUnload
, const RPathChain
& loaderRPaths
, const char* imagePath
);
380 // runInitializers() is normally called in link() but the main executable must
381 // run crt code before initializers
382 void runInitializers(const LinkContext
& context
, InitializerTimingList
& timingInfo
);
384 // called after link() forces all lazy pointers to be bound
385 void bindAllLazyPointers(const LinkContext
& context
, bool recursive
);
387 // used by dyld to see if a requested library is already loaded (might be symlink)
388 bool statMatch(const struct stat
& stat_buf
) const;
390 // get short name of this image
391 const char* getShortName() const;
394 static const char* shortName(const char* fullName
);
396 // get path used to load this image, not necessarily the "real" path
397 const char* getPath() const { return fPath
; }
399 uint32_t getPathHash() const { return fPathHash
; }
401 // get the "real" path for this image (e.g. no @rpath)
402 const char* getRealPath() const;
404 // get path this image is intended to be placed on disk or NULL if no preferred install location
405 virtual const char* getInstallPath() const = 0;
407 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
408 bool matchInstallPath() const;
409 void setMatchInstallPath(bool);
411 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
412 void setHideExports(bool hide
= true);
414 // check if this image's exported symbols should be ignored when linking other images
415 bool hasHiddenExports() const;
417 // checks if this image is already linked into the process
418 bool isLinked() const;
420 // even if image is deleted, leave segments mapped in
421 void setLeaveMapped();
423 // even if image is deleted, leave segments mapped in
424 bool leaveMapped() { return fLeaveMapped
; }
426 // image resides in dyld shared cache
427 virtual bool inSharedCache() const { return false; };
429 // checks if the specifed address is within one of this image's segments
430 virtual bool containsAddress(const void* addr
) const;
432 // checks if the specifed symbol is within this image's symbol table
433 virtual bool containsSymbol(const void* addr
) const = 0;
435 // checks if the specifed address range overlaps any of this image's segments
436 virtual bool overlapsWithAddressRange(const void* start
, const void* end
) const;
438 // adds to list of ranges of memory mapped in
439 void getMappedRegions(MappedRegion
*& region
) const;
441 // st_mtime from stat() on file
442 time_t lastModified() const;
444 // only valid for main executables, returns a pointer its entry point from LC_MAIN
445 virtual void* getEntryFromLC_MAIN() const = 0;
447 // only valid for main executables, returns a pointer its main from LC_UNIXTHREAD
448 virtual void* getEntryFromLC_UNIXTHREAD() const = 0;
450 // dyld API's require each image to have an associated mach_header
451 virtual const struct mach_header
* machHeader() const = 0;
453 // dyld API's require each image to have a slide (actual load address minus preferred load address)
454 virtual uintptr_t getSlide() const = 0;
456 // last address mapped by image
457 virtual const void* getEnd() const = 0;
459 // image has exports that participate in runtime coalescing
460 virtual bool hasCoalescedExports() const = 0;
462 // search symbol table of definitions in this image for requested name
463 virtual bool findExportedSymbolAddress(const LinkContext
& context
, const char* symbolName
,
464 const ImageLoader
* requestorImage
, int requestorOrdinalOfDef
,
465 bool runResolver
, const ImageLoader
** foundIn
, uintptr_t* address
) const;
467 // search symbol table of definitions in this image for requested name
468 virtual const Symbol
* findExportedSymbol(const char* name
, bool searchReExports
, const char* thisPath
, const ImageLoader
** foundIn
) const = 0;
470 // search symbol table of definitions in this image for requested name
471 virtual const Symbol
* findExportedSymbol(const char* name
, bool searchReExports
, const ImageLoader
** foundIn
) const {
472 return findExportedSymbol(name
, searchReExports
, this->getPath(), foundIn
);
475 // gets address of implementation (code) of the specified exported symbol
476 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,
477 const ImageLoader
* requestor
=NULL
, bool runResolver
=false, const char* symbolName
=NULL
) const = 0;
479 // gets attributes of the specified exported symbol
480 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const = 0;
482 // gets name of the specified exported symbol
483 virtual const char* getExportedSymbolName(const Symbol
* sym
) const = 0;
485 // gets how many symbols are exported by this image
486 virtual uint32_t getExportedSymbolCount() const = 0;
488 // gets the i'th exported symbol
489 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const = 0;
491 // find exported symbol as if imported by this image
493 virtual const Symbol
* findExportedSymbolInDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
495 // find exported symbol as if imported by this image
497 virtual const Symbol
* findExportedSymbolInImageOrDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
499 // gets how many symbols are imported by this image
500 virtual uint32_t getImportedSymbolCount() const = 0;
502 // gets the i'th imported symbol
503 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const = 0;
505 // gets attributes of the specified imported symbol
506 virtual ReferenceFlags
getImportedSymbolInfo(const Symbol
* sym
) const = 0;
508 // gets name of the specified imported symbol
509 virtual const char* getImportedSymbolName(const Symbol
* sym
) const = 0;
511 // find the closest symbol before addr
512 virtual const char* findClosestSymbol(const void* addr
, const void** closestAddr
) const = 0;
514 // for use with accelerator tables
515 virtual const char* getIndexedPath(unsigned) const { return getPath(); }
516 virtual const char* getIndexedShortName(unsigned) const { return getShortName(); }
518 // checks if this image is a bundle and can be loaded but not linked
519 virtual bool isBundle() const = 0;
521 // checks if this image is a dylib
522 virtual bool isDylib() const = 0;
524 // checks if this image is a main executable
525 virtual bool isExecutable() const = 0;
527 // checks if this image is a main executable
528 virtual bool isPositionIndependentExecutable() const = 0;
530 // only for main executable
531 virtual bool forceFlat() const = 0;
533 // called at runtime when a lazily bound function is first called
534 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
,
535 DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) = 0;
537 // called at runtime when a fast lazily bound function is first called
538 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset
, const LinkContext
& context
,
539 void (*lock
)(), void (*unlock
)()) = 0;
541 // calls termination routines (e.g. C++ static destructors for image)
542 virtual void doTermination(const LinkContext
& context
) = 0;
544 // return if this image has initialization routines
545 virtual bool needsInitialization() = 0;
547 // return if this image has specified section and set start and length
548 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) = 0;
550 // fills in info about __eh_frame and __unwind_info sections
551 virtual void getUnwindInfo(dyld_unwind_sections
* info
) = 0;
553 // given a pointer into an image, find which segment and section it is in
554 virtual const struct macho_section
* findSection(const void* imageInterior
) const = 0;
556 // given a pointer into an image, find which segment and section it is in
557 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) = 0;
559 // the image supports being prebound
560 virtual bool isPrebindable() const = 0;
562 // the image is prebindable and its prebinding is valid
563 virtual bool usablePrebinding(const LinkContext
& context
) const = 0;
565 // add all RPATH paths this image contains
566 virtual void getRPaths(const LinkContext
& context
, std
::vector
<const char*>&) const = 0;
568 // image has or uses weak definitions that need runtime coalescing
569 virtual bool participatesInCoalescing() const = 0;
571 // if image has a UUID, copy into parameter and return true
572 virtual bool getUUID(uuid_t
) const = 0;
574 // dynamic interpose values onto this image
575 virtual void dynamicInterpose(const LinkContext
& context
) = 0;
577 // record interposing for any late binding
578 void addDynamicInterposingTuples(const struct dyld_interpose_tuple array
[], size_t count
);
580 virtual const char* libPath(unsigned int) const = 0;
582 // Image has objc sections, so information objc about when it comes and goes
583 virtual bool notifyObjC() const { return false; }
585 virtual bool overridesCachedDylib(uint32_t& num
) const { return false; }
586 virtual void setOverridesCachedDylib(uint32_t num
) { }
590 // A segment is a chunk of an executable file that is mapped into memory.
592 virtual unsigned int segmentCount() const = 0;
593 virtual const char* segName(unsigned int) const = 0;
594 virtual uintptr_t segSize(unsigned int) const = 0;
595 virtual uintptr_t segFileSize(unsigned int) const = 0;
596 virtual bool segHasTrailingZeroFill(unsigned int) = 0;
597 virtual uintptr_t segFileOffset(unsigned int) const = 0;
598 virtual bool segReadable(unsigned int) const = 0;
599 virtual bool segWriteable(unsigned int) const = 0;
600 virtual bool segExecutable(unsigned int) const = 0;
601 virtual bool segUnaccessible(unsigned int) const = 0;
602 virtual bool segHasPreferredLoadAddress(unsigned int) const = 0;
603 virtual uintptr_t segPreferredLoadAddress(unsigned int) const = 0;
604 virtual uintptr_t segActualLoadAddress(unsigned int) const = 0;
605 virtual uintptr_t segActualEndAddress(unsigned int) const = 0;
608 // info from LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
609 virtual uint32_t sdkVersion() const = 0;
610 virtual uint32_t minOSVersion() const = 0;
612 // if the image contains interposing functions, register them
613 virtual void registerInterposing(const LinkContext
& context
) = 0;
615 virtual bool usesChainedFixups() const { return false; }
617 virtual void makeDataReadOnly() const {}
619 // when resolving symbols look in subImage if symbol can't be found
620 void reExport(ImageLoader
* subImage
);
622 virtual void recursiveBind(const LinkContext
& context
, bool forceLazysBound
, bool neverUnload
, const ImageLoader
* parent
);
623 void recursiveBindWithAccounting(const LinkContext
& context
, bool forceLazysBound
, bool neverUnload
);
624 void recursiveRebaseWithAccounting(const LinkContext
& context
);
625 void weakBind(const LinkContext
& context
);
627 void applyInterposing(const LinkContext
& context
);
629 dyld_image_states
getState() { return (dyld_image_states
)fState
; }
631 ino_t
getInode() const { return fInode
; }
632 dev_t
getDevice() const { return fDevice
; }
634 // used to sort images bottom-up
635 int compare(const ImageLoader
* right
) const;
637 void incrementDlopenReferenceCount() { ++fDlopenReferenceCount
; }
639 bool decrementDlopenReferenceCount();
641 void printReferenceCounts();
643 uint32_t dlopenCount() const { return fDlopenReferenceCount
; }
645 void setCanUnload() { fNeverUnload
= false; fLeaveMapped
= false; }
647 bool neverUnload() const { return fNeverUnload
; }
649 void setNeverUnload() { fNeverUnload
= true; fLeaveMapped
= true; }
650 void setNeverUnloadRecursive();
652 void forEachReExportDependent( void (^callback
)(const ImageLoader
*, bool& stop
)) const;
654 bool isReferencedDownward() { return fIsReferencedDownward
; }
656 virtual void recursiveMakeDataReadOnly(const LinkContext
& context
);
658 virtual uintptr_t resolveWeak(const LinkContext
& context
, const char* symbolName
, bool weak_import
, bool runResolver
,
659 const ImageLoader
** foundIn
,
660 DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) { return 0; }
662 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
663 static void printStatistics(unsigned int imageCount
, const InitializerTimingList
& timingInfo
);
664 static void printStatisticsDetails(unsigned int imageCount
, const InitializerTimingList
& timingInfo
);
666 // used with DYLD_IMAGE_SUFFIX
667 static void addSuffix(const char* path
, const char* suffix
, char* result
);
669 static uint32_t hash(const char*);
671 static const uint8_t* trieWalk(const uint8_t* start
, const uint8_t* end
, const char* stringToFind
);
673 // used instead of directly deleting image
674 static void deleteImage(ImageLoader
*);
676 static bool haveInterposingTuples() { return !fgInterposingTuples
.empty(); }
677 static void clearInterposingTuples() { fgInterposingTuples
.clear(); }
679 static void applyInterposingToDyldCache(const LinkContext
& context
);
681 bool dependsOn(ImageLoader
* image
);
683 void setPath(const char* path
);
684 void setPaths(const char* path
, const char* realPath
);
685 void setPathUnowned(const char* path
);
687 void clearDepth() { fDepth
= 0; }
688 int getDepth() { return fDepth
; }
690 void setBeingRemoved() { fBeingRemoved
= true; }
691 bool isBeingRemoved() const { return fBeingRemoved
; }
693 void markNotUsed() { fMarkedInUse
= false; }
694 void markedUsedRecursive(const std
::vector
<DynamicReference
>&);
695 bool isMarkedInUse() const { return fMarkedInUse
; }
697 void setAddFuncNotified() { fAddFuncNotified
= true; }
698 bool addFuncNotified() const { return fAddFuncNotified
; }
700 void setObjCMappedNotified() { fObjCMappedNotified
= true; }
701 bool objCMappedNotified() const { return fObjCMappedNotified
; }
703 struct InterposeTuple
{
704 uintptr_t replacement
;
705 dyld3
::AuthenticatedValue
<const ImageLoader
*> neverImage
; // don't apply replacement to this image
706 dyld3
::AuthenticatedValue
<const ImageLoader
*> onlyImage
; // only apply replacement to this image
710 static uintptr_t read_uleb128(const uint8_t*& p
, const uint8_t* end
);
711 static intptr_t read_sleb128(const uint8_t*& p
, const uint8_t* end
);
713 void vmAccountingSetSuspended(const LinkContext
& context
, bool suspend
);
716 // abstract base class so all constructors protected
717 ImageLoader(const char* path
, unsigned int libCount
);
718 ImageLoader(const ImageLoader
&);
719 void operator=(const ImageLoader
&);
720 void operator delete(void* image
) throw() { ::free(image
); }
729 struct DependentLibrary
{
731 uint32_t required
: 1,
737 struct DependentLibraryInfo
{
746 typedef void (*Initializer
)(int argc
, const char* argv
[], const char* envp
[], const char* apple
[], const ProgramVars
* vars
);
747 typedef void (*Terminator
)(void);
751 unsigned int libraryCount() const { return fLibraryCount
; }
752 virtual ImageLoader
* libImage(unsigned int) const = 0;
753 virtual bool libReExported(unsigned int) const = 0;
754 virtual bool libIsUpward(unsigned int) const = 0;
755 virtual void setLibImage(unsigned int, ImageLoader
*, bool, bool) = 0;
757 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
758 // These methods do the above, exactly once, and it the right order
759 virtual void recursiveLoadLibraries(const LinkContext
& context
, bool preflightOnly
, const RPathChain
& loaderRPaths
, const char* loadPath
);
760 virtual unsigned recursiveUpdateDepth(unsigned int maxDepth
, dyld3
::Array
<ImageLoader
*>& danglingUpwards
);
761 virtual unsigned updateDepth(unsigned int maxDepth
);
762 virtual void recursiveRebase(const LinkContext
& context
);
763 virtual void recursiveApplyInterposing(const LinkContext
& context
);
764 virtual void recursiveGetDOFSections(const LinkContext
& context
, std
::vector
<DOFInfo
>& dofs
);
765 virtual void recursiveInitialization(const LinkContext
& context
, mach_port_t this_thread
, const char* pathToInitialize
,
766 ImageLoader
::InitializerTimingList
&, ImageLoader
::UninitedUpwards
&);
768 // fill in information about dependent libraries (array length is fLibraryCount)
769 virtual void doGetDependentLibraries(DependentLibraryInfo libs
[]) = 0;
771 // called on images that are libraries, returns info about itself
772 virtual LibraryInfo
doGetLibraryInfo(const LibraryInfo
& requestorInfo
) = 0;
774 // do any fix ups in this image that depend only on the load address of the image
775 virtual void doRebase(const LinkContext
& context
) = 0;
777 // do any symbolic fix ups in this image
778 virtual void doBind(const LinkContext
& context
, bool forceLazysBound
, const ImageLoader
* reExportParent
) = 0;
780 // called later via API to force all lazy pointer to be bound
781 virtual void doBindJustLazies(const LinkContext
& context
, DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) = 0;
783 // if image has any dtrace DOF sections, append them to list to be registered
784 virtual void doGetDOFSections(const LinkContext
& context
, std
::vector
<DOFInfo
>& dofs
) = 0;
787 virtual void doInterpose(const LinkContext
& context
) = 0;
789 // run any initialization routines in this image
790 virtual bool doInitialization(const LinkContext
& context
) = 0;
792 // return if this image has termination routines
793 virtual bool needsTermination() = 0;
795 // support for runtimes in which segments don't have to maintain their relative positions
796 virtual bool segmentsMustSlideTogether() const = 0;
798 // built with PIC code and can load at any address
799 virtual bool segmentsCanSlide() const = 0;
801 // set how much all segments slide
802 virtual void setSlide(intptr_t slide
) = 0;
804 // returns if all dependent libraries checksum's were as expected and none slide
805 bool allDependentLibrariesAsWhenPreBound() const;
807 // in mach-o a child tells it parent to re-export, instead of the other way around...
808 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const = 0;
810 // in mach-o a parent library knows name of sub libraries it re-exports..
811 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const = 0;
813 virtual bool weakSymbolsBound(unsigned index
) const { return fWeakSymbolsBound
; }
814 virtual void setWeakSymbolsBound(unsigned index
) { fWeakSymbolsBound
= true; }
816 // set fState to dyld_image_state_memory_mapped
817 void setMapped(const LinkContext
& context
);
819 void setFileInfo(dev_t device
, ino_t inode
, time_t modDate
);
821 void setDepth(uint16_t depth
) { fDepth
= depth
; }
823 static uintptr_t interposedAddress(const LinkContext
& context
, uintptr_t address
, const ImageLoader
* notInImage
, const ImageLoader
* onlyInImage
=NULL
);
825 static uintptr_t fgNextPIEDylibAddress
;
826 static uint32_t fgImagesWithUsedPrebinding
;
827 static uint32_t fgImagesUsedFromSharedCache
;
828 static uint32_t fgImagesHasWeakDefinitions
;
829 static uint32_t fgImagesRequiringCoalescing
;
830 static uint32_t fgTotalRebaseFixups
;
831 static uint32_t fgTotalBindFixups
;
832 static uint32_t fgTotalBindSymbolsResolved
;
833 static uint32_t fgTotalBindImageSearches
;
834 static uint32_t fgTotalLazyBindFixups
;
835 static uint32_t fgTotalPossibleLazyBindFixups
;
836 static uint32_t fgTotalSegmentsMapped
;
837 static uint32_t fgSymbolTrieSearchs
;
838 static uint64_t fgTotalBytesMapped
;
839 static uint64_t fgTotalLoadLibrariesTime
;
841 static uint64_t fgTotalObjCSetupTime
;
842 static uint64_t fgTotalDebuggerPausedTime
;
843 static uint64_t fgTotalRebindCacheTime
;
844 static uint64_t fgTotalRebaseTime
;
845 static uint64_t fgTotalBindTime
;
846 static uint64_t fgTotalWeakBindTime
;
847 static uint64_t fgTotalDOF
;
848 static uint64_t fgTotalInitTime
;
851 static std
::vector
<InterposeTuple
> fgInterposingTuples
;
854 const char* fAotPath
;
857 const char* fRealPath
;
860 time_t fLastModified
;
862 uint32_t fDlopenReferenceCount
; // count of how many dlopens have been done on this image
864 struct recursive_lock
{
865 recursive_lock(mach_port_t t
) : thread(t
), count(0) {}
869 void recursiveSpinLock(recursive_lock
&);
870 void recursiveSpinUnLock();
873 const ImageLoader
::Symbol
* findExportedSymbolInDependentImagesExcept(const char* name
, const ImageLoader
** dsiStart
,
874 const ImageLoader
**& dsiCur
, const ImageLoader
** dsiEnd
, const ImageLoader
** foundIn
) const;
876 void processInitializers(const LinkContext
& context
, mach_port_t this_thread
,
877 InitializerTimingList
& timingInfo
, ImageLoader
::UninitedUpwards
& ups
);
879 void weakBindOld(const LinkContext
& context
);
882 recursive_lock
* fInitializerRecursiveLock
;
886 uint16_t fDepth
: 15,
887 fObjCMappedNotified
: 1;
891 fAllLibraryChecksumsAndLoadAddressesMatch
: 1,
892 fLeaveMapped
: 1, // when unloaded, leave image mapped in cause some other code may have pointers into it
893 fNeverUnload
: 1, // image was statically loaded by main executable
894 fHideSymbols
: 1, // ignore this image's exported symbols when linking other images
895 fMatchByInstallName
: 1,// look at image's install-path not its load path
898 fAllLazyPointersBound
: 1,
901 fAddFuncNotified
: 1,
902 fPathOwnedByImage
: 1,
903 fIsReferencedDownward
: 1,
904 fWeakSymbolsBound
: 1;
908 static_assert(sizeof(sizeOfData
) == 8, "Bad data size");
910 static uint16_t fgLoadOrdinal
;
915 VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader
::InterposeTuple
);