1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2004-2009 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 __IMAGELOADERMACHO__
27 #define __IMAGELOADERMACHO__
30 #include <mach-o/loader.h>
31 #include <mach-o/nlist.h>
32 #include <uuid/uuid.h>
33 #include <mach-o/dyld_images.h>
35 #if __has_feature(ptrauth_calls)
39 #include "ImageLoader.h"
41 #define BIND_TYPE_THREADED_BIND 100
44 #define BIND_TYPE_THREADED_REBASE 102
48 // ImageLoaderMachO is a subclass of ImageLoader which loads mach-o format files.
51 class ImageLoaderMachO
: public ImageLoader
{
53 static ImageLoader
* instantiateMainExecutable(const macho_header
* mh
, uintptr_t slide
, const char* path
, const LinkContext
& context
);
54 static ImageLoader
* instantiateFromFile(const char* path
, int fd
, const uint8_t firstPages
[], size_t firstPagesSize
, uint64_t offsetInFat
,
55 uint64_t lenInFat
, const struct stat
& info
, const LinkContext
& context
);
56 static ImageLoader
* instantiateFromCache(const macho_header
* mh
, const char* path
, long slide
, const struct stat
& info
, const LinkContext
& context
);
57 static ImageLoader
* instantiateFromMemory(const char* moduleName
, const macho_header
* mh
, uint64_t len
, const LinkContext
& context
);
60 bool inSharedCache() const { return fInSharedCache
; }
61 void disableCoverageCheck() { fCoveredCodeLength
= UINT64_MAX
; }
63 const char* getInstallPath() const;
64 virtual void* getEntryFromLC_UNIXTHREAD() const;
65 virtual void* getEntryFromLC_MAIN() const;
66 virtual const struct mach_header
* machHeader() const;
67 virtual uintptr_t getSlide() const;
68 virtual const void* getEnd() const;
69 virtual bool hasCoalescedExports() const;
70 virtual const Symbol
* findExportedSymbol(const char* name
, bool searchReExports
, const char* thisPath
, const ImageLoader
** foundIn
) const;
71 virtual uintptr_t getExportedSymbolAddress(const Symbol
* sym
, const LinkContext
& context
,
72 const ImageLoader
* requestor
, bool runResolver
, const char*) const;
73 virtual DefinitionFlags
getExportedSymbolInfo(const Symbol
* sym
) const;
74 virtual const char* getExportedSymbolName(const Symbol
* sym
) const;
75 virtual uint32_t getExportedSymbolCount() const;
76 virtual const Symbol
* getIndexedExportedSymbol(uint32_t index
) const;
77 virtual uint32_t getImportedSymbolCount() const;
78 virtual const Symbol
* getIndexedImportedSymbol(uint32_t index
) const;
79 virtual ReferenceFlags
getImportedSymbolInfo(const Symbol
* sym
) const;
80 virtual const char* getImportedSymbolName(const Symbol
* sym
) const;
81 virtual bool isBundle() const;
82 virtual bool isDylib() const;
83 virtual bool isExecutable() const;
84 virtual bool isPositionIndependentExecutable() const;
85 virtual bool forceFlat() const;
86 virtual bool participatesInCoalescing() const;
87 virtual const char* findClosestSymbol(const void* addr
, const void** closestAddr
) const = 0;
88 virtual void initializeCoalIterator(CoalIterator
&, unsigned int loadOrder
, unsigned) = 0;
89 virtual bool incrementCoalIterator(CoalIterator
&) = 0;
90 virtual uintptr_t getAddressCoalIterator(CoalIterator
&, const LinkContext
& contex
) = 0;
91 virtual void updateUsesCoalIterator(CoalIterator
&, uintptr_t newAddr
, ImageLoader
* target
, unsigned targetIndex
, const LinkContext
& context
) = 0;
92 virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer
, const LinkContext
& context
,
93 DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) = 0;
94 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset
, const LinkContext
& context
, void (*lock
)(), void (*unlock
)()) = 0;
95 virtual void doTermination(const LinkContext
& context
);
96 virtual bool needsInitialization();
97 virtual bool getSectionContent(const char* segmentName
, const char* sectionName
, void** start
, size_t* length
);
98 virtual void getUnwindInfo(dyld_unwind_sections
* info
);
99 virtual const struct macho_section
* findSection(const void* imageInterior
) const;
100 virtual bool findSection(const void* imageInterior
, const char** segmentName
, const char** sectionName
, size_t* sectionOffset
);
101 virtual bool usablePrebinding(const LinkContext
& context
) const;
102 virtual unsigned int segmentCount() const;
103 virtual const char* segName(unsigned int) const;
104 virtual uintptr_t segSize(unsigned int) const;
105 virtual uintptr_t segFileSize(unsigned int) const;
106 virtual bool segHasTrailingZeroFill(unsigned int);
107 virtual uintptr_t segFileOffset(unsigned int) const;
108 virtual bool segReadable(unsigned int) const;
109 virtual bool segWriteable(unsigned int) const;
110 virtual bool segExecutable(unsigned int) const;
111 virtual bool segUnaccessible(unsigned int) const;
112 virtual bool segHasPreferredLoadAddress(unsigned int) const;
113 virtual uintptr_t segActualLoadAddress(unsigned int) const;
114 virtual uintptr_t segPreferredLoadAddress(unsigned int) const;
115 virtual uintptr_t segActualEndAddress(unsigned int) const;
116 virtual void registerInterposing(const LinkContext
& context
);
117 virtual uint32_t sdkVersion() const;
118 virtual uint32_t minOSVersion() const;
119 virtual const char* libPath(unsigned int) const;
120 virtual bool notifyObjC() const { return fNotifyObjC
; }
121 virtual bool overridesCachedDylib(uint32_t& num
) const { num
= fOverrideOfCacheImageNum
; return (num
!= 0); }
122 virtual void setOverridesCachedDylib(uint32_t num
) { fOverrideOfCacheImageNum
= num
; }
125 static void printStatisticsDetails(unsigned int imageCount
, const InitializerTimingList
&);
126 static uint32_t minOSVersion(const mach_header
*);
127 static uint32_t sdkVersion(const mach_header
* mh
);
128 static intptr_t computeSlide(const mach_header
* mh
);
129 static bool findSection(const mach_header
* mh
, const char* segmentName
, const char* sectionName
, void** sectAddress
, uintptr_t* sectSize
);
130 static const dyld_info_command
* findDyldInfoLoadCommand(const mach_header
* mh
);
131 static const char* findClosestSymbol(const mach_header
* mh
, const void* addr
, const void** closestAddr
);
132 static bool getLazyBindingInfo(uint32_t& lazyBindingInfoOffset
, const uint8_t* lazyInfoStart
, const uint8_t* lazyInfoEnd
,
133 uint8_t* segIndex
, uintptr_t* segOffset
, int* ordinal
, const char** symbolName
, bool* doneAfterBind
);
134 static uintptr_t segPreferredAddress(const mach_header
* mh
, unsigned segIndex
);
136 uintptr_t imageBaseAddress() const;
138 struct ExtraBindData
{
139 ExtraBindData() = default;
140 explicit ExtraBindData(uint64_t d
) : data(d
) { }
145 bool operator==(const ExtraBindData
& other
) const {
146 return this->data
== other
.data
;
148 bool operator!=(const ExtraBindData
& other
) const {
149 return !(*this == other
);
151 bool operator<(const ExtraBindData
& other
) const {
152 return data
< other
.data
;
157 static uintptr_t bindLocation(const LinkContext
& context
, uintptr_t baseVMAddress
,
158 uintptr_t location
, uintptr_t value
,
159 uint8_t type
, const char* symbolName
,
160 intptr_t addend
, const char* inPath
, const char* toPath
, const char* msg
,
161 ExtraBindData
*extraBindData
,
163 virtual void rebase(const LinkContext
& context
, uintptr_t slide
) = 0;
168 ImageLoaderMachO(const ImageLoaderMachO
&);
169 ImageLoaderMachO(const macho_header
* mh
, const char* path
, unsigned int segCount
,
170 uint32_t segOffsets
[], unsigned int libCount
);
171 virtual ~ImageLoaderMachO() {}
173 void operator=(const ImageLoaderMachO
&);
175 virtual void setDyldInfo(const struct dyld_info_command
*) = 0;
176 virtual void setChainedFixups(const linkedit_data_command
*) = 0;
177 virtual void setExportsTrie(const linkedit_data_command
*) = 0;
178 virtual void setSymbolTableInfo(const macho_nlist
*, const char*, const dysymtab_command
*) = 0;
179 virtual bool isSubframeworkOf(const LinkContext
& context
, const ImageLoader
* image
) const = 0;
180 virtual bool hasSubLibrary(const LinkContext
& context
, const ImageLoader
* child
) const = 0;
181 virtual uint32_t* segmentCommandOffsets() const = 0;
182 virtual const ImageLoader
::Symbol
* findShallowExportedSymbol(const char* name
, const ImageLoader
** foundIn
) const = 0;
183 virtual bool containsSymbol(const void* addr
) const = 0;
184 virtual uintptr_t exportedSymbolAddress(const LinkContext
& context
, const Symbol
* symbol
, const ImageLoader
* requestor
, bool runResolver
) const = 0;
185 virtual bool exportedSymbolIsWeakDefintion(const Symbol
* symbol
) const = 0;
186 virtual const char* exportedSymbolName(const Symbol
* symbol
) const = 0;
187 virtual unsigned int exportedSymbolCount() const = 0;
188 virtual const ImageLoader
::Symbol
* exportedSymbolIndexed(unsigned int) const = 0;
189 virtual unsigned int importedSymbolCount() const = 0;
190 virtual const ImageLoader
::Symbol
* importedSymbolIndexed(unsigned int) const = 0;
191 virtual const char* importedSymbolName(const Symbol
* symbol
) const = 0;
192 #if PREBOUND_IMAGE_SUPPORT
193 virtual void resetPreboundLazyPointers(const LinkContext
& context
) = 0;
197 virtual void doGetDependentLibraries(DependentLibraryInfo libs
[]);
198 virtual LibraryInfo
doGetLibraryInfo(const LibraryInfo
& requestorInfo
);
199 virtual void getRPaths(const LinkContext
& context
, std
::vector
<const char*>&) const;
200 virtual bool getUUID(uuid_t
) const;
201 virtual void doRebase(const LinkContext
& context
);
202 virtual void doBind(const LinkContext
& context
, bool forceLazysBound
, const ImageLoader
* reExportParent
) = 0;
203 virtual void doBindJustLazies(const LinkContext
& context
, DyldSharedCache
::DataConstLazyScopedWriter
& patcher
) = 0;
204 virtual bool doInitialization(const LinkContext
& context
);
205 virtual void doGetDOFSections(const LinkContext
& context
, std
::vector
<ImageLoader
::DOFInfo
>& dofs
);
206 virtual bool needsTermination();
207 virtual bool segmentsMustSlideTogether() const;
208 virtual bool segmentsCanSlide() const;
209 virtual void setSlide(intptr_t slide
);
210 virtual bool usesTwoLevelNameSpace() const;
211 virtual bool isPrebindable() const;
216 static void sniffLoadCommands(const macho_header
* mh
, const char* path
, bool inCache
, bool* compressed
,
217 unsigned int* segCount
, unsigned int* libCount
, const LinkContext
& context
,
218 const linkedit_data_command
** codeSigCmd
,
219 const encryption_info_command
** encryptCmd
);
220 static bool needsAddedLibSystemDepency(unsigned int libCount
, const macho_header
* mh
);
221 void loadCodeSignature(const struct linkedit_data_command
* codeSigCmd
, int fd
, uint64_t offsetInFatFile
, const LinkContext
& context
);
222 void validateFirstPages(const struct linkedit_data_command
* codeSigCmd
, int fd
, const uint8_t *fileData
, size_t lenFileData
, off_t offsetInFat
, const LinkContext
& context
);
223 const struct macho_segment_command
* segLoadCommand(unsigned int segIndex
) const;
224 void parseLoadCmds(const ImageLoader
::LinkContext
& context
);
225 int crashIfInvalidCodeSignature();
226 bool segHasRebaseFixUps(unsigned int) const;
227 bool segHasBindFixUps(unsigned int) const;
228 void segProtect(unsigned int segIndex
, const ImageLoader
::LinkContext
& context
);
229 void segMakeWritable(unsigned int segIndex
, const ImageLoader
::LinkContext
& context
);
231 bool segIsReadOnlyImport(unsigned int) const;
233 bool segIsReadOnlyData(unsigned int) const;
234 intptr_t assignSegmentAddresses(const LinkContext
& context
, size_t extraAllocationSize
);
235 uintptr_t reserveAnAddressRange(size_t length
, const ImageLoader
::LinkContext
& context
);
236 bool reserveAddressRange(uintptr_t start
, size_t length
);
237 void mapSegments(int fd
, uint64_t offsetInFat
, uint64_t lenInFat
, uint64_t fileLen
, const LinkContext
& context
);
238 void mapSegments(const void* memoryImage
, uint64_t imageLen
, const LinkContext
& context
);
239 void UnmapSegments();
240 void __attribute__((noreturn
)) throwSymbolNotFound(const LinkContext
& context
, const char* symbol
,
241 const char* referencedFrom
, const char* fromVersMismatch
,
242 const char* expectedIn
);
243 void doImageInit(const LinkContext
& context
);
244 void doModInitFunctions(const LinkContext
& context
);
245 void setupLazyPointerHandler(const LinkContext
& context
);
246 void lookupProgramVars(const LinkContext
& context
) const;
248 void makeTextSegmentWritable(const LinkContext
& context
, bool writeable
);
251 void doInterpose(const LinkContext
& context
) = 0;
252 bool hasReferencesToWeakSymbols() const;
253 uintptr_t getSymbolAddress(const Symbol
* sym
, const ImageLoader
* requestor
,
254 const LinkContext
& context
, bool runResolver
) const;
256 static uintptr_t bindLazySymbol(const mach_header
*, uintptr_t* lazyPointer
);
258 uint64_t fCoveredCodeLength
;
259 const uint8_t* fMachOData
;
260 const uint8_t* fLinkEditBase
; // add any internal "offset" to this to get mapped address
262 uint32_t fEHFrameSectionOffset
;
263 uint32_t fUnwindInfoSectionOffset
;
264 uint32_t fDylibIDOffset
;
265 uint32_t fSegmentsCount
: 8,
268 #if TEXT_RELOC_SUPPORT
269 fTextSegmentRebases
: 1,
270 fTextSegmentBinds
: 1,
272 fReadOnlyDataSegment
: 1,
275 fReadOnlyImportSegment
: 1,
277 fHasSubLibraries
: 1,
282 fHasInitializers
: 1,
286 fRegisteredAsRequiresCoalescing
: 1, // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount
287 fOverrideOfCacheImageNum
: 12;
290 static uint32_t fgSymbolTableBinarySearchs
;
294 #endif // __IMAGELOADERMACHO__