]> git.saurik.com Git - apple/dyld.git/blob - src/ImageLoaderMachO.h
cf8325be2d8be8d762e5f774438608fff4fbe9bf
[apple/dyld.git] / src / ImageLoaderMachO.h
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2004-2009 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 __IMAGELOADERMACHO__
27 #define __IMAGELOADERMACHO__
28
29 #include <stdint.h>
30 #include <mach-o/loader.h>
31 #include <mach-o/nlist.h>
32 #include <uuid/uuid.h>
33 #include <mach-o/dyld_images.h>
34
35 #if __has_feature(ptrauth_calls)
36 #include <ptrauth.h>
37 #endif
38
39 #include "ImageLoader.h"
40
41 #define BIND_TYPE_THREADED_BIND 100
42
43
44 #define BIND_TYPE_THREADED_REBASE 102
45
46
47 //
48 // ImageLoaderMachO is a subclass of ImageLoader which loads mach-o format files.
49 //
50 //
51 class ImageLoaderMachO : public ImageLoader {
52 public:
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);
58
59
60 bool inSharedCache() const { return fInSharedCache; }
61 void disableCoverageCheck() { fCoveredCodeLength = UINT64_MAX; }
62
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) = 0;
93 virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context, void (*lock)(), void (*unlock)()) = 0;
94 virtual void doTermination(const LinkContext& context);
95 virtual bool needsInitialization();
96 virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length);
97 virtual void getUnwindInfo(dyld_unwind_sections* info);
98 virtual const struct macho_section* findSection(const void* imageInterior) const;
99 virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset);
100 virtual bool usablePrebinding(const LinkContext& context) const;
101 virtual unsigned int segmentCount() const;
102 virtual const char* segName(unsigned int) const;
103 virtual uintptr_t segSize(unsigned int) const;
104 virtual uintptr_t segFileSize(unsigned int) const;
105 virtual bool segHasTrailingZeroFill(unsigned int);
106 virtual uintptr_t segFileOffset(unsigned int) const;
107 virtual bool segReadable(unsigned int) const;
108 virtual bool segWriteable(unsigned int) const;
109 virtual bool segExecutable(unsigned int) const;
110 virtual bool segUnaccessible(unsigned int) const;
111 virtual bool segHasPreferredLoadAddress(unsigned int) const;
112 virtual uintptr_t segActualLoadAddress(unsigned int) const;
113 virtual uintptr_t segPreferredLoadAddress(unsigned int) const;
114 virtual uintptr_t segActualEndAddress(unsigned int) const;
115 virtual void registerInterposing(const LinkContext& context);
116 virtual uint32_t sdkVersion() const;
117 virtual uint32_t minOSVersion() const;
118 virtual const char* libPath(unsigned int) const;
119 virtual bool notifyObjC() const { return fNotifyObjC; }
120 virtual bool overridesCachedDylib(uint32_t& num) const { num = fOverrideOfCacheImageNum; return (num != 0); }
121 virtual void setOverridesCachedDylib(uint32_t num) { fOverrideOfCacheImageNum = num; }
122
123
124 static void printStatisticsDetails(unsigned int imageCount, const InitializerTimingList&);
125 static uint32_t minOSVersion(const mach_header*);
126 static uint32_t sdkVersion(const mach_header* mh);
127 static intptr_t computeSlide(const mach_header* mh);
128 static bool findSection(const mach_header* mh, const char* segmentName, const char* sectionName, void** sectAddress, uintptr_t* sectSize);
129 static const dyld_info_command* findDyldInfoLoadCommand(const mach_header* mh);
130 static const char* findClosestSymbol(const mach_header* mh, const void* addr, const void** closestAddr);
131 static bool getLazyBindingInfo(uint32_t& lazyBindingInfoOffset, const uint8_t* lazyInfoStart, const uint8_t* lazyInfoEnd,
132 uint8_t* segIndex, uintptr_t* segOffset, int* ordinal, const char** symbolName, bool* doneAfterBind);
133 static uintptr_t segPreferredAddress(const mach_header* mh, unsigned segIndex);
134
135 uintptr_t imageBaseAddress() const;
136
137 struct ExtraBindData {
138 ExtraBindData() = default;
139 explicit ExtraBindData(uint64_t d) : data(d) { }
140
141 union {
142 uint64_t data = 0;
143 };
144 bool operator==(const ExtraBindData& other) const {
145 return this->data == other.data;
146 }
147 bool operator!=(const ExtraBindData& other) const {
148 return !(*this == other);
149 }
150 bool operator<(const ExtraBindData& other) const {
151 return data < other.data;
152 }
153
154 };
155
156 static uintptr_t bindLocation(const LinkContext& context, uintptr_t baseVMAddress,
157 uintptr_t location, uintptr_t value,
158 uint8_t type, const char* symbolName,
159 intptr_t addend, const char* inPath, const char* toPath, const char* msg,
160 ExtraBindData *extraBindData,
161 uintptr_t fSlide);
162 virtual void rebase(const LinkContext& context, uintptr_t slide) = 0;
163
164
165
166 protected:
167 ImageLoaderMachO(const ImageLoaderMachO&);
168 ImageLoaderMachO(const macho_header* mh, const char* path, unsigned int segCount,
169 uint32_t segOffsets[], unsigned int libCount);
170 virtual ~ImageLoaderMachO() {}
171
172 void operator=(const ImageLoaderMachO&);
173
174 virtual void setDyldInfo(const struct dyld_info_command*) = 0;
175 virtual void setChainedFixups(const linkedit_data_command*) = 0;
176 virtual void setExportsTrie(const linkedit_data_command*) = 0;
177 virtual void setSymbolTableInfo(const macho_nlist*, const char*, const dysymtab_command*) = 0;
178 virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
179 virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0;
180 virtual uint32_t* segmentCommandOffsets() const = 0;
181 virtual const ImageLoader::Symbol* findShallowExportedSymbol(const char* name, const ImageLoader** foundIn) const = 0;
182 virtual bool containsSymbol(const void* addr) const = 0;
183 virtual uintptr_t exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, const ImageLoader* requestor, bool runResolver) const = 0;
184 virtual bool exportedSymbolIsWeakDefintion(const Symbol* symbol) const = 0;
185 virtual const char* exportedSymbolName(const Symbol* symbol) const = 0;
186 virtual unsigned int exportedSymbolCount() const = 0;
187 virtual const ImageLoader::Symbol* exportedSymbolIndexed(unsigned int) const = 0;
188 virtual unsigned int importedSymbolCount() const = 0;
189 virtual const ImageLoader::Symbol* importedSymbolIndexed(unsigned int) const = 0;
190 virtual const char* importedSymbolName(const Symbol* symbol) const = 0;
191 #if PREBOUND_IMAGE_SUPPORT
192 virtual void resetPreboundLazyPointers(const LinkContext& context) = 0;
193 #endif
194
195
196 virtual void doGetDependentLibraries(DependentLibraryInfo libs[]);
197 virtual LibraryInfo doGetLibraryInfo(const LibraryInfo& requestorInfo);
198 virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const;
199 virtual bool getUUID(uuid_t) const;
200 virtual void doRebase(const LinkContext& context);
201 virtual void doBind(const LinkContext& context, bool forceLazysBound, const ImageLoader* reExportParent) = 0;
202 virtual void doBindJustLazies(const LinkContext& context) = 0;
203 virtual bool doInitialization(const LinkContext& context);
204 virtual void doGetDOFSections(const LinkContext& context, std::vector<ImageLoader::DOFInfo>& dofs);
205 virtual bool needsTermination();
206 virtual bool segmentsMustSlideTogether() const;
207 virtual bool segmentsCanSlide() const;
208 virtual void setSlide(intptr_t slide);
209 virtual bool usesTwoLevelNameSpace() const;
210 virtual bool isPrebindable() const;
211
212 protected:
213
214 void destroy();
215 static void sniffLoadCommands(const macho_header* mh, const char* path, bool inCache, bool* compressed,
216 unsigned int* segCount, unsigned int* libCount, const LinkContext& context,
217 const linkedit_data_command** codeSigCmd,
218 const encryption_info_command** encryptCmd);
219 static bool needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh);
220 void loadCodeSignature(const struct linkedit_data_command* codeSigCmd, int fd, uint64_t offsetInFatFile, const LinkContext& context);
221 void validateFirstPages(const struct linkedit_data_command* codeSigCmd, int fd, const uint8_t *fileData, size_t lenFileData, off_t offsetInFat, const LinkContext& context);
222 const struct macho_segment_command* segLoadCommand(unsigned int segIndex) const;
223 void parseLoadCmds(const ImageLoader::LinkContext& context);
224 int crashIfInvalidCodeSignature();
225 bool segHasRebaseFixUps(unsigned int) const;
226 bool segHasBindFixUps(unsigned int) const;
227 void segProtect(unsigned int segIndex, const ImageLoader::LinkContext& context);
228 void segMakeWritable(unsigned int segIndex, const ImageLoader::LinkContext& context);
229 #if __i386__
230 bool segIsReadOnlyImport(unsigned int) const;
231 #endif
232 bool segIsReadOnlyData(unsigned int) const;
233 intptr_t assignSegmentAddresses(const LinkContext& context, size_t extraAllocationSize);
234 uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context);
235 bool reserveAddressRange(uintptr_t start, size_t length);
236 void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
237 void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context);
238 void UnmapSegments();
239 void __attribute__((noreturn)) throwSymbolNotFound(const LinkContext& context, const char* symbol,
240 const char* referencedFrom, const char* fromVersMismatch,
241 const char* expectedIn);
242 void doImageInit(const LinkContext& context);
243 void doModInitFunctions(const LinkContext& context);
244 void setupLazyPointerHandler(const LinkContext& context);
245 void lookupProgramVars(const LinkContext& context) const;
246
247 void makeTextSegmentWritable(const LinkContext& context, bool writeable);
248
249
250 void doInterpose(const LinkContext& context) = 0;
251 bool hasReferencesToWeakSymbols() const;
252 uintptr_t getSymbolAddress(const Symbol* sym, const ImageLoader* requestor,
253 const LinkContext& context, bool runResolver) const;
254
255 static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer);
256 protected:
257 uint64_t fCoveredCodeLength;
258 const uint8_t* fMachOData;
259 const uint8_t* fLinkEditBase; // add any internal "offset" to this to get mapped address
260 uintptr_t fSlide;
261 uint32_t fEHFrameSectionOffset;
262 uint32_t fUnwindInfoSectionOffset;
263 uint32_t fDylibIDOffset;
264 uint32_t fSegmentsCount : 8,
265 fIsSplitSeg : 1,
266 fInSharedCache : 1,
267 #if TEXT_RELOC_SUPPORT
268 fTextSegmentRebases : 1,
269 fTextSegmentBinds : 1,
270 #else
271 fReadOnlyDataSegment : 1,
272 #endif
273 #if __i386__
274 fReadOnlyImportSegment : 1,
275 #endif
276 fHasSubLibraries : 1,
277 fHasSubUmbrella : 1,
278 fInUmbrella : 1,
279 fHasDOFSections : 1,
280 fHasDashInit : 1,
281 fHasInitializers : 1,
282 fHasTerminators : 1,
283 fNotifyObjC : 1,
284 fRetainForObjC : 1,
285 fRegisteredAsRequiresCoalescing : 1, // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount
286 fOverrideOfCacheImageNum : 12;
287
288
289 static uint32_t fgSymbolTableBinarySearchs;
290 };
291
292
293 #endif // __IMAGELOADERMACHO__
294
295
296
297