1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2015 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_MEGADYLIB__
27 #define __IMAGELOADER_MEGADYLIB__
31 #include <uuid/uuid.h>
33 #include "ImageLoaderMachO.h"
34 #include "dyld_cache_format.h"
38 // ImageLoaderMegaDylib is the concrete subclass of ImageLoader which represents
39 // all dylibs in the shared cache.
41 class ImageLoaderMegaDylib
: public ImageLoader
{
43 static ImageLoaderMegaDylib
* makeImageLoaderMegaDylib(const dyld_cache_header
*, long slide
, const macho_header
* mainMH
, const LinkContext
&);
46 virtual ~ImageLoaderMegaDylib();
48 void appendImagesNeedingCoalescing(ImageLoader
* images
[], unsigned imageIndex
[], unsigned& count
);
49 virtual void initializeCoalIterator(CoalIterator
&, unsigned int loadOrder
, unsigned imageIndex
);
50 virtual bool incrementCoalIterator(CoalIterator
&);
51 virtual uintptr_t getAddressCoalIterator(CoalIterator
&, const LinkContext
& contex
);
52 virtual void updateUsesCoalIterator(CoalIterator
&, uintptr_t newAddr
, ImageLoader
* target
, unsigned imageIndex
, const LinkContext
& context
);
54 virtual const char* getIndexedPath(unsigned index
) const;
55 virtual const char* getIndexedShortName(unsigned) const;
56 virtual const char* getInstallPath() const;
57 virtual bool inSharedCache() const { return true; }
58 virtual bool containsSymbol(const void* addr
) const { unreachable(); }
59 virtual void* getEntryFromLC_MAIN() const { unreachable(); }
60 virtual void* getEntryFromLC_UNIXTHREAD() const { unreachable(); }
61 virtual const struct mach_header
* machHeader() const { unreachable(); }
62 virtual uintptr_t getSlide() const { return _slide
; }
63 virtual const void* getEnd() const { unreachable(); }
64 virtual bool hasCoalescedExports() const { unreachable(); }
65 virtual bool findExportedSymbolAddress(const LinkContext
& context
, const char* symbolName
,
66 const ImageLoader
* requestorImage
, int requestorOrdinalOfDef
,
67 bool runResolver
, const ImageLoader
** foundIn
, uintptr_t* address
) const;
68 virtual const Symbol
* findExportedSymbol(const char* name
, bool searchReExports
, const char* thisPath
, const ImageLoader
** foundIn
) const;
69 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,
70 const ImageLoader
* requestor
, bool runResolver
, const char* symbolName
) const;
71 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const { unreachable(); }
72 virtual const char* getExportedSymbolName(const Symbol
* sym
) const { unreachable(); }
73 virtual uint32_t getExportedSymbolCount() const { unreachable(); }
74 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const { unreachable(); }
76 virtual uint32_t getImportedSymbolCount() const { unreachable(); }
77 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const { unreachable(); }
78 virtual ReferenceFlags
getImportedSymbolInfo(const Symbol
* sym
) const { unreachable(); }
79 virtual const char* getImportedSymbolName(const Symbol
* sym
) const { unreachable(); }
80 virtual const char* findClosestSymbol(const void* addr
, const void** closestAddr
) const { unreachable(); }
81 virtual bool isBundle() const { return false; }
82 virtual bool isDylib() const { return true; }
83 virtual bool isExecutable() const { unreachable(); }
84 virtual bool isPositionIndependentExecutable() const { unreachable(); }
85 virtual bool forceFlat() const { unreachable(); }
86 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
,
87 DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) { unreachable(); }
88 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset
, const LinkContext
& context
,
89 void (*lock
)(), void (*unlock
)()) { unreachable(); }
90 virtual void doTermination(const LinkContext
& context
) { unreachable(); }
91 virtual bool needsInitialization() { unreachable(); }
92 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
) { unreachable(); }
93 virtual void getUnwindInfo(dyld_unwind_sections
* info
) { unreachable(); }
94 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
) { unreachable(); }
95 virtual const struct macho_section
* findSection(const void* imageInterior
) const { unreachable(); }
96 virtual bool isPrebindable() const { unreachable(); }
97 virtual bool usablePrebinding(const LinkContext
& context
) const { unreachable(); }
98 virtual void getRPaths(const LinkContext
& context
, std
::vector
<const char*>&) const { }
99 virtual bool participatesInCoalescing() const { unreachable(); }
100 virtual bool getUUID(uuid_t
) const { unreachable(); }
101 virtual void dynamicInterpose(const LinkContext
& context
) { unreachable(); }
102 void addDynamicInterposingTuples(const struct dyld_interpose_tuple array
[], size_t count
) { unreachable(); }
103 virtual unsigned int segmentCount() const { unreachable(); }
104 virtual const char* segName(unsigned int) const { unreachable(); }
105 virtual uintptr_t segSize(unsigned int) const { unreachable(); }
106 virtual uintptr_t segFileSize(unsigned int) const { unreachable(); }
107 virtual bool segHasTrailingZeroFill(unsigned int) { unreachable(); }
108 virtual uintptr_t segFileOffset(unsigned int) const { unreachable(); }
109 virtual bool segReadable(unsigned int) const { unreachable(); }
110 virtual bool segWriteable(unsigned int) const { unreachable(); }
111 virtual bool segExecutable(unsigned int) const { unreachable(); }
112 virtual bool segUnaccessible(unsigned int) const { unreachable(); }
113 virtual bool segHasPreferredLoadAddress(unsigned int) const { unreachable(); }
114 virtual uintptr_t segPreferredLoadAddress(unsigned int) const { unreachable(); }
115 virtual uintptr_t segActualLoadAddress(unsigned int) const { unreachable(); }
116 virtual uintptr_t segActualEndAddress(unsigned int) const { unreachable(); }
119 // info from LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
120 virtual uint32_t sdkVersion() const { unreachable(); }
121 virtual uint32_t minOSVersion() const { unreachable(); }
123 // if the image contains interposing functions, register them
124 virtual void registerInterposing(const LinkContext
& context
) { unreachable(); }
126 virtual ImageLoader
* libImage(unsigned int) const { unreachable(); }
127 virtual bool libReExported(unsigned int) const { unreachable(); }
128 virtual bool libIsUpward(unsigned int) const { unreachable(); }
129 virtual void setLibImage(unsigned int, ImageLoader
*, bool, bool) { unreachable(); }
130 virtual const char* libPath(unsigned int) const { unreachable(); }
132 unsigned appendImagesToNotify(dyld_image_states state
, bool orLater
, dyld_image_info
* infos
);
133 const char* notify(dyld_image_states state
, bool orLater
, dyld_image_state_change_handler
);
134 bool dlopenFromCache(const LinkContext
& context
, const char* path
, int mode
, void** handle
);
135 bool makeCacheHandle(const LinkContext
& context
, unsigned cacheIndex
, int mode
, void** result
);
136 void* dlsymFromCache(const LinkContext
& context
, void* handle
, const char* symName
, unsigned index
);
137 bool isCacheHandle(void* handle
, unsigned* index
, uint8_t* flags
);
138 bool hasDylib(const char* path
, unsigned* index
) const;
139 bool addressInCache(const void* address
, const mach_header
** mh
, const char** path
, unsigned* index
);
140 bool findUnwindSections(const void* addr
, dyld_unwind_sections
* info
);
141 bool dladdrFromCache(const void* address
, Dl_info
* info
);
142 uintptr_t bindLazy(uintptr_t lazyBindingInfoOffset
, const LinkContext
& context
, const mach_header
* mh
, unsigned index
);
143 bool flatFindSymbol(const char* name
, bool onlyInCoalesced
, const ImageLoader
::Symbol
** sym
, const ImageLoader
** image
, ImageLoader
::CoalesceNotifier
);
144 void getDylibUUID(unsigned int index
, uuid_t
) const;
147 virtual void setDyldInfo(const dyld_info_command
* dyldInfo
) { unreachable(); }
148 virtual void setChainedFixups(const linkedit_data_command
* fixups
) { unreachable(); }
149 virtual void setExportsTrie(const linkedit_data_command
*) { unreachable(); }
150 virtual void setSymbolTableInfo(const macho_nlist
*, const char*, const dysymtab_command
*) { unreachable(); }
151 virtual uint32_t* segmentCommandOffsets() const { unreachable(); }
152 virtual void rebase(const LinkContext
& context
, uintptr_t slide
) { unreachable(); }
153 virtual uintptr_t exportedSymbolAddress(const LinkContext
& context
, const Symbol
* symbol
, const ImageLoader
* requestor
, bool runResolver
) const { unreachable(); }
154 virtual bool exportedSymbolIsWeakDefintion(const Symbol
* symbol
) const { unreachable(); }
155 virtual const char* exportedSymbolName(const Symbol
* symbol
) const { unreachable(); }
156 virtual unsigned int exportedSymbolCount() const { unreachable(); }
157 virtual const ImageLoader
::Symbol
* exportedSymbolIndexed(unsigned int) const { unreachable(); }
158 virtual unsigned int importedSymbolCount() const { unreachable(); }
159 virtual const ImageLoader
::Symbol
* importedSymbolIndexed(unsigned int) const { unreachable(); }
160 virtual const char* importedSymbolName(const Symbol
* symbol
) const { unreachable(); }
161 #if PREBOUND_IMAGE_SUPPORT
162 virtual void resetPreboundLazyPointers(const LinkContext
& context
) { unreachable(); }
165 virtual void recursiveLoadLibraries(const LinkContext
& context
, bool preflightOnly
, const RPathChain
& loaderRPaths
, const char* loadPath
);
166 virtual unsigned updateDepth(unsigned int maxDepth
);
167 virtual void recursiveRebase(const LinkContext
& context
) { }
168 virtual void recursiveBind(const LinkContext
& context
, bool forceLazysBound
, bool neverUnload
, const ImageLoader
* parent
);
169 virtual void recursiveApplyInterposing(const LinkContext
& context
);
170 virtual void recursiveMakeDataReadOnly(const LinkContext
& context
) {}
171 virtual void recursiveGetDOFSections(const LinkContext
& context
, std
::vector
<DOFInfo
>& dofs
) { }
172 virtual void recursiveInitialization(const LinkContext
& context
, mach_port_t this_thread
, const char* pathToInitialize
,
173 ImageLoader
::InitializerTimingList
&, ImageLoader
::UninitedUpwards
&);
175 virtual void doGetDependentLibraries(DependentLibraryInfo libs
[]) { unreachable(); }
176 virtual LibraryInfo
doGetLibraryInfo(const LibraryInfo
& requestorInfo
) { return requestorInfo
; }
177 virtual void doRebase(const LinkContext
& context
) { unreachable(); }
178 virtual void doBind(const LinkContext
& context
, bool forceLazysBound
, const ImageLoader
* reExportParent
) { unreachable(); }
179 virtual void doBindJustLazies(const LinkContext
& context
, DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) { unreachable(); }
180 virtual void doGetDOFSections(const LinkContext
& context
, std
::vector
<DOFInfo
>& dofs
) { unreachable(); }
181 virtual void doInterpose(const LinkContext
& context
) { unreachable(); }
182 virtual bool doInitialization(const LinkContext
& context
) { unreachable(); }
183 virtual bool needsTermination() { unreachable(); }
184 virtual bool segmentsMustSlideTogether() const { unreachable(); }
185 virtual bool segmentsCanSlide() const { unreachable(); }
186 virtual void setSlide(intptr_t slide
) { unreachable(); }
187 bool allDependentLibrariesAsWhenPreBound() const { unreachable(); }
188 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const { return false; }
189 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const { return false; }
190 virtual bool weakSymbolsBound(unsigned index
) const;
191 virtual void setWeakSymbolsBound(unsigned index
);
194 ImageLoaderMegaDylib(const dyld_cache_header
*, long slide
, const macho_header
* mainMH
, const LinkContext
&);
202 const macho_header
* getIndexedMachHeader(unsigned index
) const;
203 const uint8_t* getIndexedTrie(unsigned index
, uint32_t& trieSize
) const;
204 unsigned findImageIndex(const LinkContext
& context
, const char* path
) const;
205 void recursiveMarkLoaded(const LinkContext
& context
, unsigned imageIndex
);
206 void markAllbound(const LinkContext
& context
);
207 bool findInChainedTries(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
,
208 const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const;
209 bool findInChainedTriesAndDependents(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
,
210 const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const;
211 bool findInChainedTriesAndDependentsExcept(const LinkContext
& context
, const char* symbolName
, unsigned imageIndex
,
212 const ImageLoader
* requestorImage
, bool runResolver
, bool alreadyVisited
[], uintptr_t* address
) const;
213 bool exportTrieHasNodeRecursive(const char* symbolName
, unsigned index
,
214 const uint8_t** exportNode
, const uint8_t** exportTrieEnd
,
215 unsigned* foundinIndex
) const;
216 bool exportTrieHasNode(const char* symbolName
, unsigned index
,
217 const uint8_t** exportNode
, const uint8_t** exportTrieEnd
) const;
219 void initAllLoaded(const LinkContext
& context
, InitializerTimingList
& timingInfo
);
220 void printSegments(const macho_header
* mh
) const;
221 void* makeCacheHandle(unsigned index
, int mode
);
222 uint8_t flagsFromCacheHandle(void* handle
);
223 void processExportNode(const LinkContext
& context
, const char* symbolName
, unsigned definedImageIndex
,
224 const uint8_t* exportNode
, const uint8_t* exportTrieEnd
,
225 const ImageLoader
* requestorImage
, bool runResolver
, uintptr_t* address
) const;
226 static uint8_t dyldStateToCacheState(dyld_image_states state
);
227 void recursiveInitialization(const LinkContext
& context
, mach_port_t this_thread
, unsigned int imageIndex
,
228 InitializerTimingList
& timingInfo
, UpwardIndexes
&);
229 void recursiveSpinLockAcquire(unsigned int imageIndex
, mach_port_t thisThread
);
230 void recursiveSpinLockRelease(unsigned int imageIndex
, mach_port_t thisThread
);
232 __attribute__((noreturn
))
233 void unreachable() const;
235 enum { kStateUnused
=0, kStateLoaded
=1, kStateFlagBound
=2, kStateFlagWeakBound
=3, kStateFlagInitialized
=4 };
238 const dyld_cache_header
* _header
;
239 const void* _endOfCacheInMemory
;
240 const uint8_t* _linkEditBias
;
241 const dyld_cache_image_info
* _images
;
242 const dyld_cache_image_info_extra
* _imageExtras
;
244 const dyld_cache_accelerator_initializer
* _initializers
;
245 const dyld_cache_range_entry
* _rangeTable
;
246 const uint16_t* _reExportsArray
;
247 const uint16_t* _dependenciesArray
;
248 const uint16_t* _bottomUpArray
;
249 const uint8_t* _dylibsTrieStart
;
250 const uint8_t* _dylibsTrieEnd
;
251 const dyld_cache_image_text_info
* _imageTextInfo
;
252 uint8_t* _stateFlags
;
253 uint32_t _imageCount
;
254 uint32_t _initializerCount
;
255 uint32_t _rangeTableCount
;
256 pthread_mutex_t _lockArrayGuard
;
257 ImageLoader
::recursive_lock
* _lockArray
;
258 unsigned int _lockArrayInUseCount
;
263 #endif // __IMAGELOADER_MEGADYLIB__