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>
39 #include <TargetConditionals.h>
44 #include <mach/vm_page_size.h>
47 #if __x86_64__ || __i386__
48 #include <CrashReporterClient.h>
50 // work around until iOS has CrashReporterClient.h
51 #define CRSetCrashLogMessage(x)
52 #define CRSetCrashLogMessage2(x)
55 #ifndef SHARED_REGION_BASE_ARM64
56 #define SHARED_REGION_BASE_ARM64 0x7FFF80000000LL
59 #ifndef SHARED_REGION_SIZE_ARM64
60 #define SHARED_REGION_SIZE_ARM64 0x10000000LL
64 #define LOG_BINDINGS 0
66 #include "mach-o/dyld_images.h"
67 #include "mach-o/dyld_priv.h"
70 #define SHARED_REGION_BASE SHARED_REGION_BASE_I386
71 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_I386
73 #define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
74 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
76 #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
77 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
79 #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM64
80 #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM64
83 #ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
84 #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
86 #ifndef EXPORT_SYMBOL_FLAGS_REEXPORT
87 #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
91 #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
92 struct entry_point_command
{
93 uint32_t cmd
; /* LC_MAIN only used in MH_EXECUTE filetypes */
94 uint32_t cmdsize
; /* 24 */
95 uint64_t entryoff
; /* file (__TEXT) offset of main() */
96 uint64_t stacksize
;/* if not zero, initial stack size */
100 #if __IPHONE_OS_VERSION_MIN_REQUIRED
101 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
102 #define SPLIT_SEG_DYLIB_SUPPORT 0
103 #define PREBOUND_IMAGE_SUPPORT __arm__
104 #define TEXT_RELOC_SUPPORT __i386__
105 #define DYLD_SHARED_CACHE_SUPPORT (__arm__ || __arm64__)
106 #define SUPPORT_OLD_CRT_INITIALIZATION 0
107 #define SUPPORT_LC_DYLD_ENVIRONMENT 1
108 #define SUPPORT_VERSIONED_PATHS 1
109 #define SUPPORT_CLASSIC_MACHO __arm__
110 #define SUPPORT_ZERO_COST_EXCEPTIONS (!__USING_SJLJ_EXCEPTIONS__)
111 #define INITIAL_IMAGE_COUNT 256
113 #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
114 #define SPLIT_SEG_DYLIB_SUPPORT __i386__
115 #define PREBOUND_IMAGE_SUPPORT __i386__
116 #define TEXT_RELOC_SUPPORT __i386__
117 #define DYLD_SHARED_CACHE_SUPPORT 1
118 #define SUPPORT_OLD_CRT_INITIALIZATION __i386__
119 #define SUPPORT_LC_DYLD_ENVIRONMENT (__i386__ || __x86_64__)
120 #define SUPPORT_VERSIONED_PATHS 1
121 #define SUPPORT_CLASSIC_MACHO 1
122 #define SUPPORT_ZERO_COST_EXCEPTIONS 1
123 #define INITIAL_IMAGE_COUNT 200
128 // <rdar://problem/13590567> optimize away dyld's initializers
129 #define VECTOR_NEVER_DESTRUCTED(type) \
132 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
134 #define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \
137 __vector_base<type, std::allocator<type> >::~__vector_base(); \
139 #define VECTOR_NEVER_DESTRUCTED_IMPL(type) \
142 __vector_base<type, std::allocator<type> >::~__vector_base() { } \
147 extern __attribute__((noreturn
)) void throwf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
148 extern void log(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
149 extern void warn(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
150 extern const char* mkstringf(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
152 extern void logBindings(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
155 extern "C" int vm_alloc(vm_address_t
* addr
, vm_size_t size
, uint32_t flags
);
156 extern "C" void* xmmap(void* addr
, size_t len
, int prot
, int flags
, int fd
, off_t offset
);
160 struct macho_header
: public mach_header_64
{};
161 struct macho_nlist
: public nlist_64
{};
163 struct macho_header
: public mach_header
{};
164 struct macho_nlist
: public nlist
{};
169 #define dyld_page_trunc(__addr) (__addr & (-16384))
170 #define dyld_page_round(__addr) ((__addr + 16383) & (-16384))
171 #define dyld_page_size 16384
173 #define dyld_page_trunc(__addr) trunc_page_kernel(__addr)
174 #define dyld_page_round(__addr) round_page_kernel(__addr)
175 #define dyld_page_size vm_kernel_page_size
177 #define dyld_page_trunc(__addr) (__addr & (-4096))
178 #define dyld_page_round(__addr) ((__addr + 4095) & (-4096))
179 #define dyld_page_size 4096
188 const char*** NXArgvPtr
;
189 const char*** environPtr
;
190 const char** __prognamePtr
;
196 // ImageLoader is an abstract base class. To support loading a particular executable
197 // file format, you make a concrete subclass of ImageLoader.
199 // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
201 // The ImageLoader base class does the work of linking together images, but it knows nothing
202 // about any particular file format.
208 typedef uint32_t DefinitionFlags
;
209 static const DefinitionFlags kNoDefinitionOptions
= 0;
210 static const DefinitionFlags kWeakDefinition
= 1;
212 typedef uint32_t ReferenceFlags
;
213 static const ReferenceFlags kNoReferenceOptions
= 0;
214 static const ReferenceFlags kWeakReference
= 1;
215 static const ReferenceFlags kTentativeDefinition
= 2;
217 enum PrebindMode
{ kUseAllPrebinding
, kUseSplitSegPrebinding
, kUseAllButAppPredbinding
, kUseNoPrebinding
};
218 enum BindingOptions
{ kBindingNone
, kBindingLazyPointers
, kBindingNeverSetLazyPointers
};
219 enum SharedRegionMode
{ kUseSharedRegion
, kUsePrivateSharedRegion
, kDontUseSharedRegion
, kSharedRegionIsSharedCache
};
221 struct Symbol
; // abstact symbol
223 struct MappedRegion
{
229 RPathChain(const RPathChain
* n
, std::vector
<const char*>* p
) : next(n
), paths(p
) {};
230 const RPathChain
* next
;
231 std::vector
<const char*>* paths
;
236 const mach_header
* imageHeader
;
237 const char* imageShortName
;
240 struct DynamicReference
{
246 ImageLoader
* (*loadLibrary
)(const char* libraryName
, bool search
, const char* origin
, const RPathChain
* rpaths
);
247 void (*terminationRecorder
)(ImageLoader
* image
);
248 bool (*flatExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
);
249 bool (*coalescedExportFinder
)(const char* name
, const Symbol
** sym
, const ImageLoader
** image
);
250 unsigned int (*getCoalescedImages
)(ImageLoader
* images
[]);
251 void (*undefinedHandler
)(const char* name
);
252 MappedRegion
* (*getAllMappedRegions
)(MappedRegion
*);
253 void * (*bindingHandler
)(const char *, const char *, void *);
254 void (*notifySingle
)(dyld_image_states
, const ImageLoader
* image
);
255 void (*notifyBatch
)(dyld_image_states state
);
256 void (*removeImage
)(ImageLoader
* image
);
257 void (*registerDOFs
)(const std::vector
<DOFInfo
>& dofs
);
258 void (*clearAllDepths
)();
259 void (*printAllDepths
)();
260 unsigned int (*imageCount
)();
261 void (*setNewProgramVars
)(const ProgramVars
&);
262 bool (*inSharedCache
)(const char* path
);
263 void (*setErrorStrings
)(unsigned errorCode
, const char* errorClientOfDylibPath
,
264 const char* errorTargetDylibPath
, const char* errorSymbol
);
265 ImageLoader
* (*findImageContainingAddress
)(const void* addr
);
266 void (*addDynamicReference
)(ImageLoader
* from
, ImageLoader
* to
);
268 #if SUPPORT_OLD_CRT_INITIALIZATION
269 void (*setRunInitialzersOldWay
)();
271 BindingOptions bindingOptions
;
276 const char* progname
;
277 ProgramVars programVars
;
278 ImageLoader
* mainExecutable
;
279 const char* imageSuffix
;
280 const char** rootPaths
;
281 const dyld_interpose_tuple
* dynamicInterposeArray
;
282 size_t dynamicInterposeCount
;
283 PrebindMode prebindUsage
;
284 SharedRegionMode sharedRegionMode
;
285 bool dyldLoadedAtSameAddressNeededBySharedCache
;
286 bool codeSigningEnforced
;
287 bool mainExecutableCodeSigned
;
288 bool preFetchDisabled
;
291 bool linkingMainExecutable
;
292 bool startedInitializingMainExecutable
;
293 bool processIsRestricted
;
294 bool processRequiresLibraryValidation
;
300 bool verboseWeakBind
;
303 bool verbosePrebinding
;
304 bool verboseCoreSymbolication
;
305 bool verboseWarnings
;
307 bool verboseInterposing
;
308 bool verboseCodeSignatures
;
314 const char* symbolName
;
315 unsigned int loadOrder
;
319 // the following are private to the ImageLoader subclass
327 virtual void initializeCoalIterator(CoalIterator
&, unsigned int loadOrder
) = 0;
328 virtual bool incrementCoalIterator(CoalIterator
&) = 0;
329 virtual uintptr_t getAddressCoalIterator(CoalIterator
&, const LinkContext
& context
) = 0;
330 virtual void updateUsesCoalIterator(CoalIterator
&, uintptr_t newAddr
, ImageLoader
* target
, const LinkContext
& context
) = 0;
332 struct InitializerTimingList
341 struct UninitedUpwards
344 ImageLoader
* images
[1];
348 // constructor is protected, but anyone can delete an image
349 virtual ~ImageLoader();
351 // link() takes a newly instantiated ImageLoader and does all
352 // fixups needed to make it usable by the process
353 void link(const LinkContext
& context
, bool forceLazysBound
, bool preflight
, bool neverUnload
, const RPathChain
& loaderRPaths
);
355 // runInitializers() is normally called in link() but the main executable must
356 // run crt code before initializers
357 void runInitializers(const LinkContext
& context
, InitializerTimingList
& timingInfo
);
359 // called after link() forces all lazy pointers to be bound
360 void bindAllLazyPointers(const LinkContext
& context
, bool recursive
);
362 // used by dyld to see if a requested library is already loaded (might be symlink)
363 bool statMatch(const struct stat
& stat_buf
) const;
365 // get short name of this image
366 const char* getShortName() const;
368 // get path used to load this image, not necessarily the "real" path
369 const char* getPath() const { return fPath
; }
371 uint32_t getPathHash() const { return fPathHash
; }
373 // get the "real" path for this image (e.g. no @rpath)
374 const char* getRealPath() const;
376 // get path this image is intended to be placed on disk or NULL if no preferred install location
377 virtual const char* getInstallPath() const = 0;
379 // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
380 bool matchInstallPath() const;
381 void setMatchInstallPath(bool);
383 // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
384 void setHideExports(bool hide
= true);
386 // check if this image's exported symbols should be ignored when linking other images
387 bool hasHiddenExports() const;
389 // checks if this image is already linked into the process
390 bool isLinked() const;
392 // even if image is deleted, leave segments mapped in
393 void setLeaveMapped();
395 // even if image is deleted, leave segments mapped in
396 bool leaveMapped() { return fLeaveMapped
; }
398 // image resides in dyld shared cache
399 virtual bool inSharedCache() const = 0;
401 // checks if the specifed address is within one of this image's segments
402 virtual bool containsAddress(const void* addr
) const;
404 // checks if the specifed symbol is within this image's symbol table
405 virtual bool containsSymbol(const void* addr
) const = 0;
407 // checks if the specifed address range overlaps any of this image's segments
408 virtual bool overlapsWithAddressRange(const void* start
, const void* end
) const;
410 // adds to list of ranges of memory mapped in
411 void getMappedRegions(MappedRegion
*& region
) const;
413 // st_mtime from stat() on file
414 time_t lastModified() const;
416 // only valid for main executables, returns a pointer its entry point from LC_UNIXTHREAD
417 virtual void* getThreadPC() const = 0;
419 // only valid for main executables, returns a pointer its main from LC_<MAIN
420 virtual void* getMain() const = 0;
422 // dyld API's require each image to have an associated mach_header
423 virtual const struct mach_header
* machHeader() const = 0;
425 // dyld API's require each image to have a slide (actual load address minus preferred load address)
426 virtual uintptr_t getSlide() const = 0;
428 // last address mapped by image
429 virtual const void* getEnd() const = 0;
431 // image has exports that participate in runtime coalescing
432 virtual bool hasCoalescedExports() const = 0;
434 // search symbol table of definitions in this image for requested name
435 virtual const Symbol
* findExportedSymbol(const char* name
, bool searchReExports
, const ImageLoader
** foundIn
) const = 0;
437 // gets address of implementation (code) of the specified exported symbol
438 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,
439 const ImageLoader
* requestor
=NULL
, bool runResolver
=false) const = 0;
441 // gets attributes of the specified exported symbol
442 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const = 0;
444 // gets name of the specified exported symbol
445 virtual const char* getExportedSymbolName(const Symbol
* sym
) const = 0;
447 // gets how many symbols are exported by this image
448 virtual uint32_t getExportedSymbolCount() const = 0;
450 // gets the i'th exported symbol
451 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const = 0;
453 // find exported symbol as if imported by this image
455 virtual const Symbol
* findExportedSymbolInDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
457 // find exported symbol as if imported by this image
459 virtual const Symbol
* findExportedSymbolInImageOrDependentImages(const char* name
, const LinkContext
& context
, const ImageLoader
** foundIn
) const;
461 // gets how many symbols are imported by this image
462 virtual uint32_t getImportedSymbolCount() const = 0;
464 // gets the i'th imported symbol
465 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const = 0;
467 // gets attributes of the specified imported symbol
468 virtual ReferenceFlags
getImportedSymbolInfo(const Symbol
* sym
) const = 0;
470 // gets name of the specified imported symbol
471 virtual const char* getImportedSymbolName(const Symbol
* sym
) const = 0;
473 // find the closest symbol before addr
474 virtual const char* findClosestSymbol(const void* addr
, const void** closestAddr
) const = 0;
476 // checks if this image is a bundle and can be loaded but not linked
477 virtual bool isBundle() const = 0;
479 // checks if this image is a dylib
480 virtual bool isDylib() const = 0;
482 // checks if this image is a main executable
483 virtual bool isExecutable() const = 0;
485 // checks if this image is a main executable
486 virtual bool isPositionIndependentExecutable() const = 0;
488 // only for main executable
489 virtual bool forceFlat() const = 0;
491 // called at runtime when a lazily bound function is first called
492 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
) = 0;
494 // called at runtime when a fast lazily bound function is first called
495 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset
, const LinkContext
& context
,
496 void (*lock
)(), void (*unlock
)()) = 0;
498 // calls termination routines (e.g. C++ static destructors for image)
499 virtual void doTermination(const LinkContext
& context
) = 0;
501 // return if this image has initialization routines
502 virtual bool needsInitialization() = 0;
504 // return if this image has specified section and set start and length
505 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) = 0;
507 // fills in info about __eh_frame and __unwind_info sections
508 virtual void getUnwindInfo(dyld_unwind_sections
* info
) = 0;
510 // given a pointer into an image, find which segment and section it is in
511 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) = 0;
513 // the image supports being prebound
514 virtual bool isPrebindable() const = 0;
516 // the image is prebindable and its prebinding is valid
517 virtual bool usablePrebinding(const LinkContext
& context
) const = 0;
519 // add all RPATH paths this image contains
520 virtual void getRPaths(const LinkContext
& context
, std::vector
<const char*>&) const = 0;
522 // image has or uses weak definitions that need runtime coalescing
523 virtual bool participatesInCoalescing() const = 0;
525 // if image has a UUID, copy into parameter and return true
526 virtual bool getUUID(uuid_t
) const = 0;
528 // dynamic interpose values onto this image
529 virtual void dynamicInterpose(const LinkContext
& context
) = 0;
531 // record interposing for any late binding
532 void addDynamicInterposingTuples(const struct dyld_interpose_tuple array
[], size_t count
);
535 // A segment is a chunk of an executable file that is mapped into memory.
537 virtual unsigned int segmentCount() const = 0;
538 virtual const char* segName(unsigned int) const = 0;
539 virtual uintptr_t segSize(unsigned int) const = 0;
540 virtual uintptr_t segFileSize(unsigned int) const = 0;
541 virtual bool segHasTrailingZeroFill(unsigned int) = 0;
542 virtual uintptr_t segFileOffset(unsigned int) const = 0;
543 virtual bool segReadable(unsigned int) const = 0;
544 virtual bool segWriteable(unsigned int) const = 0;
545 virtual bool segExecutable(unsigned int) const = 0;
546 virtual bool segUnaccessible(unsigned int) const = 0;
547 virtual bool segHasPreferredLoadAddress(unsigned int) const = 0;
548 virtual uintptr_t segPreferredLoadAddress(unsigned int) const = 0;
549 virtual uintptr_t segActualLoadAddress(unsigned int) const = 0;
550 virtual uintptr_t segActualEndAddress(unsigned int) const = 0;
553 // info from LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
554 virtual uint32_t sdkVersion() const = 0;
555 virtual uint32_t minOSVersion() const = 0;
557 // if the image contains interposing functions, register them
558 virtual void registerInterposing() = 0;
560 // when resolving symbols look in subImage if symbol can't be found
561 void reExport(ImageLoader
* subImage
);
563 void weakBind(const LinkContext
& context
);
565 void applyInterposing(const LinkContext
& context
);
567 dyld_image_states
getState() { return (dyld_image_states
)fState
; }
569 // used to sort images bottom-up
570 int compare(const ImageLoader
* right
) const;
572 void incrementDlopenReferenceCount() { ++fDlopenReferenceCount
; }
574 bool decrementDlopenReferenceCount();
576 void printReferenceCounts();
578 uint32_t dlopenCount() const { return fDlopenReferenceCount
; }
580 void setCanUnload() { fNeverUnload
= false; fLeaveMapped
= false; }
582 bool neverUnload() const { return fNeverUnload
; }
584 void setNeverUnload() { fNeverUnload
= true; fLeaveMapped
= true; }
585 void setNeverUnloadRecursive();
587 bool isReferencedDownward() { return fIsReferencedDownward
; }
590 // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
591 static void printStatistics(unsigned int imageCount
, const InitializerTimingList
& timingInfo
);
593 // used with DYLD_IMAGE_SUFFIX
594 static void addSuffix(const char* path
, const char* suffix
, char* result
);
596 static uint32_t hash(const char*);
598 // used instead of directly deleting image
599 static void deleteImage(ImageLoader
*);
601 bool dependsOn(ImageLoader
* image
);
603 void setPath(const char* path
);
604 void setPaths(const char* path
, const char* realPath
);
605 void setPathUnowned(const char* path
);
607 void clearDepth() { fDepth
= 0; }
608 int getDepth() { return fDepth
; }
610 void setBeingRemoved() { fBeingRemoved
= true; }
611 bool isBeingRemoved() const { return fBeingRemoved
; }
613 void markNotUsed() { fMarkedInUse
= false; }
614 void markedUsedRecursive(const std::vector
<DynamicReference
>&);
615 bool isMarkedInUse() const { return fMarkedInUse
; }
617 void setAddFuncNotified() { fAddFuncNotified
= true; }
618 bool addFuncNotified() const { return fAddFuncNotified
; }
620 struct InterposeTuple
{
621 uintptr_t replacement
;
622 ImageLoader
* neverImage
; // don't apply replacement to this image
623 ImageLoader
* onlyImage
; // only apply replacement to this image
628 // abstract base class so all constructors protected
629 ImageLoader(const char* path
, unsigned int libCount
);
630 ImageLoader(const ImageLoader
&);
631 void operator=(const ImageLoader
&);
632 void operator delete(void* image
) throw() { ::free(image
); }
641 struct DependentLibrary
{
643 uint32_t required
: 1,
649 struct DependentLibraryInfo
{
658 typedef void (*Initializer
)(int argc
, const char* argv
[], const char* envp
[], const char* apple
[], const ProgramVars
* vars
);
659 typedef void (*Terminator
)(void);
663 unsigned int libraryCount() const { return fLibraryCount
; }
664 virtual ImageLoader
* libImage(unsigned int) const = 0;
665 virtual bool libReExported(unsigned int) const = 0;
666 virtual bool libIsUpward(unsigned int) const = 0;
667 virtual void setLibImage(unsigned int, ImageLoader
*, bool, bool) = 0;
669 // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
670 // These methods do the above, exactly once, and it the right order
671 void recursiveLoadLibraries(const LinkContext
& context
, bool preflightOnly
, const RPathChain
& loaderRPaths
);
672 void recursiveUnLoadMappedLibraries(const LinkContext
& context
);
673 unsigned int recursiveUpdateDepth(unsigned int maxDepth
);
674 void recursiveValidate(const LinkContext
& context
);
675 void recursiveRebase(const LinkContext
& context
);
676 void recursiveBind(const LinkContext
& context
, bool forceLazysBound
, bool neverUnload
);
677 void recursiveApplyInterposing(const LinkContext
& context
);
678 void recursiveGetDOFSections(const LinkContext
& context
, std::vector
<DOFInfo
>& dofs
);
679 void recursiveInitialization(const LinkContext
& context
, mach_port_t this_thread
,
680 ImageLoader::InitializerTimingList
&, ImageLoader::UninitedUpwards
&);
682 // fill in information about dependent libraries (array length is fLibraryCount)
683 virtual void doGetDependentLibraries(DependentLibraryInfo libs
[]) = 0;
685 // called on images that are libraries, returns info about itself
686 virtual LibraryInfo
doGetLibraryInfo() = 0;
688 // do any fix ups in this image that depend only on the load address of the image
689 virtual void doRebase(const LinkContext
& context
) = 0;
691 // do any symbolic fix ups in this image
692 virtual void doBind(const LinkContext
& context
, bool forceLazysBound
) = 0;
694 // called later via API to force all lazy pointer to be bound
695 virtual void doBindJustLazies(const LinkContext
& context
) = 0;
697 // if image has any dtrace DOF sections, append them to list to be registered
698 virtual void doGetDOFSections(const LinkContext
& context
, std::vector
<DOFInfo
>& dofs
) = 0;
701 virtual void doInterpose(const LinkContext
& context
) = 0;
703 // run any initialization routines in this image
704 virtual bool doInitialization(const LinkContext
& context
) = 0;
706 // return if this image has termination routines
707 virtual bool needsTermination() = 0;
709 // support for runtimes in which segments don't have to maintain their relative positions
710 virtual bool segmentsMustSlideTogether() const = 0;
712 // built with PIC code and can load at any address
713 virtual bool segmentsCanSlide() const = 0;
715 // set how much all segments slide
716 virtual void setSlide(intptr_t slide
) = 0;
718 // returns if all dependent libraries checksum's were as expected and none slide
719 bool allDependentLibrariesAsWhenPreBound() const;
721 // in mach-o a child tells it parent to re-export, instead of the other way around...
722 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const = 0;
724 // in mach-o a parent library knows name of sub libraries it re-exports..
725 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const = 0;
727 // set fState to dyld_image_state_memory_mapped
728 void setMapped(const LinkContext
& context
);
730 void setFileInfo(dev_t device
, ino_t inode
, time_t modDate
);
732 static uintptr_t interposedAddress(const LinkContext
& context
, uintptr_t address
, const ImageLoader
* notInImage
, const ImageLoader
* onlyInImage
=NULL
);
734 static uintptr_t fgNextPIEDylibAddress
;
735 static uint32_t fgImagesWithUsedPrebinding
;
736 static uint32_t fgImagesUsedFromSharedCache
;
737 static uint32_t fgImagesHasWeakDefinitions
;
738 static uint32_t fgImagesRequiringCoalescing
;
739 static uint32_t fgTotalRebaseFixups
;
740 static uint32_t fgTotalBindFixups
;
741 static uint32_t fgTotalBindSymbolsResolved
;
742 static uint32_t fgTotalBindImageSearches
;
743 static uint32_t fgTotalLazyBindFixups
;
744 static uint32_t fgTotalPossibleLazyBindFixups
;
745 static uint32_t fgTotalSegmentsMapped
;
746 static uint64_t fgTotalBytesMapped
;
747 static uint64_t fgTotalBytesPreFetched
;
748 static uint64_t fgTotalLoadLibrariesTime
;
749 static uint64_t fgTotalRebaseTime
;
750 static uint64_t fgTotalBindTime
;
751 static uint64_t fgTotalWeakBindTime
;
752 static uint64_t fgTotalDOF
;
753 static uint64_t fgTotalInitTime
;
754 static std::vector
<InterposeTuple
> fgInterposingTuples
;
757 const char* fRealPath
;
760 time_t fLastModified
;
762 uint32_t fDlopenReferenceCount
; // count of how many dlopens have been done on this image
765 struct recursive_lock
{
766 recursive_lock(mach_port_t t
) : thread(t
), count(0) {}
770 void recursiveSpinLock(recursive_lock
&);
771 void recursiveSpinUnLock();
773 const ImageLoader::Symbol
* findExportedSymbolInDependentImagesExcept(const char* name
, const ImageLoader
** dsiStart
,
774 const ImageLoader
**& dsiCur
, const ImageLoader
** dsiEnd
, const ImageLoader
** foundIn
) const;
776 void processInitializers(const LinkContext
& context
, mach_port_t this_thread
,
777 InitializerTimingList
& timingInfo
, ImageLoader::UninitedUpwards
& ups
);
780 recursive_lock
* fInitializerRecursiveLock
;
785 fAllLibraryChecksumsAndLoadAddressesMatch
: 1,
786 fLeaveMapped
: 1, // when unloaded, leave image mapped in cause some other code may have pointers into it
787 fNeverUnload
: 1, // image was statically loaded by main executable
788 fHideSymbols
: 1, // ignore this image's exported symbols when linking other images
789 fMatchByInstallName
: 1,// look at image's install-path not its load path
792 fAllLazyPointersBound
: 1,
795 fAddFuncNotified
: 1,
796 fPathOwnedByImage
: 1,
797 fIsReferencedDownward
: 1,
798 fWeakSymbolsBound
: 1;
800 static uint16_t fgLoadOrdinal
;
804 VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple
);