]>
Commit | Line | Data |
---|---|---|
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 | ||
33 | #include "ImageLoader.h" | |
34 | #include "mach-o/dyld_images.h" | |
35 | ||
36 | ||
37 | // | |
38 | // ImageLoaderMachO is a subclass of ImageLoader which loads mach-o format files. | |
39 | // | |
40 | // | |
41 | class ImageLoaderMachO : public ImageLoader { | |
42 | public: | |
43 | static ImageLoader* instantiateMainExecutable(const macho_header* mh, uintptr_t slide, const char* path, const LinkContext& context); | |
44 | static ImageLoader* instantiateFromFile(const char* path, int fd, const uint8_t firstPages[], size_t firstPagesSize, uint64_t offsetInFat, | |
45 | uint64_t lenInFat, const struct stat& info, const LinkContext& context); | |
46 | static ImageLoader* instantiateFromCache(const macho_header* mh, const char* path, long slide, const struct stat& info, const LinkContext& context); | |
47 | static ImageLoader* instantiateFromMemory(const char* moduleName, const macho_header* mh, uint64_t len, const LinkContext& context); | |
48 | ||
49 | ||
50 | bool inSharedCache() const { return fInSharedCache; } | |
51 | void disableCoverageCheck() { fCoveredCodeLength = UINT64_MAX; } | |
52 | ||
53 | const char* getInstallPath() const; | |
54 | virtual void* getMain() const; | |
55 | virtual void* getThreadPC() const; | |
56 | virtual const struct mach_header* machHeader() const; | |
57 | virtual uintptr_t getSlide() const; | |
58 | virtual const void* getEnd() const; | |
59 | virtual bool hasCoalescedExports() const; | |
60 | virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const char* thisPath, const ImageLoader** foundIn) const; | |
61 | virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, | |
62 | const ImageLoader* requestor, bool runResolver, const char*) const; | |
63 | virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const; | |
64 | virtual const char* getExportedSymbolName(const Symbol* sym) const; | |
65 | virtual uint32_t getExportedSymbolCount() const; | |
66 | virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const; | |
67 | virtual uint32_t getImportedSymbolCount() const; | |
68 | virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const; | |
69 | virtual ReferenceFlags getImportedSymbolInfo(const Symbol* sym) const; | |
70 | virtual const char* getImportedSymbolName(const Symbol* sym) const; | |
71 | virtual bool isBundle() const; | |
72 | virtual bool isDylib() const; | |
73 | virtual bool isExecutable() const; | |
74 | virtual bool isPositionIndependentExecutable() const; | |
75 | virtual bool forceFlat() const; | |
76 | virtual bool participatesInCoalescing() const; | |
77 | virtual const char* findClosestSymbol(const void* addr, const void** closestAddr) const = 0; | |
78 | virtual void initializeCoalIterator(CoalIterator&, unsigned int loadOrder, unsigned) = 0; | |
79 | virtual bool incrementCoalIterator(CoalIterator&) = 0; | |
80 | virtual uintptr_t getAddressCoalIterator(CoalIterator&, const LinkContext& contex) = 0; | |
81 | virtual void updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, unsigned targetIndex, const LinkContext& context) = 0; | |
82 | virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0; | |
83 | virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context, void (*lock)(), void (*unlock)()) = 0; | |
84 | virtual void doTermination(const LinkContext& context); | |
85 | virtual bool needsInitialization(); | |
86 | virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length); | |
87 | virtual void getUnwindInfo(dyld_unwind_sections* info); | |
88 | virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset); | |
89 | virtual bool usablePrebinding(const LinkContext& context) const; | |
90 | virtual unsigned int segmentCount() const; | |
91 | virtual const char* segName(unsigned int) const; | |
92 | virtual uintptr_t segSize(unsigned int) const; | |
93 | virtual uintptr_t segFileSize(unsigned int) const; | |
94 | virtual bool segHasTrailingZeroFill(unsigned int); | |
95 | virtual uintptr_t segFileOffset(unsigned int) const; | |
96 | virtual bool segReadable(unsigned int) const; | |
97 | virtual bool segWriteable(unsigned int) const; | |
98 | virtual bool segExecutable(unsigned int) const; | |
99 | virtual bool segUnaccessible(unsigned int) const; | |
100 | virtual bool segHasPreferredLoadAddress(unsigned int) const; | |
101 | virtual uintptr_t segActualLoadAddress(unsigned int) const; | |
102 | virtual uintptr_t segPreferredLoadAddress(unsigned int) const; | |
103 | virtual uintptr_t segActualEndAddress(unsigned int) const; | |
104 | virtual void registerInterposing(); | |
105 | virtual uint32_t sdkVersion() const; | |
106 | virtual uint32_t minOSVersion() const; | |
107 | virtual const char* libPath(unsigned int) const; | |
108 | virtual bool notifyObjC() const { return fNotifyObjC; } | |
109 | ||
110 | static void printStatisticsDetails(unsigned int imageCount, const InitializerTimingList&); | |
111 | static uint32_t minOSVersion(const mach_header*); | |
112 | static uint32_t sdkVersion(const mach_header* mh); | |
113 | static intptr_t computeSlide(const mach_header* mh); | |
114 | static bool findSection(const mach_header* mh, const char* segmentName, const char* sectionName, void** sectAddress, uintptr_t* sectSize); | |
115 | static const dyld_info_command* findDyldInfoLoadCommand(const mach_header* mh); | |
116 | static const char* findClosestSymbol(const mach_header* mh, const void* addr, const void** closestAddr); | |
117 | static bool getLazyBindingInfo(uint32_t& lazyBindingInfoOffset, const uint8_t* lazyInfoStart, const uint8_t* lazyInfoEnd, | |
118 | uint8_t* segIndex, uintptr_t* segOffset, int* ordinal, const char** symbolName, bool* doneAfterBind); | |
119 | static uintptr_t segPreferredAddress(const mach_header* mh, unsigned segIndex); | |
120 | static uintptr_t bindLocation(const LinkContext& context, uintptr_t location, uintptr_t value, | |
121 | uint8_t type, const char* symbolName, | |
122 | intptr_t addend, const char* inPath, const char* toPath, const char* msg); | |
123 | virtual void rebase(const LinkContext& context, uintptr_t slide) = 0; | |
124 | ||
125 | ||
126 | ||
127 | protected: | |
128 | ImageLoaderMachO(const ImageLoaderMachO&); | |
129 | ImageLoaderMachO(const macho_header* mh, const char* path, unsigned int segCount, | |
130 | uint32_t segOffsets[], unsigned int libCount); | |
131 | virtual ~ImageLoaderMachO() {} | |
132 | ||
133 | void operator=(const ImageLoaderMachO&); | |
134 | ||
135 | virtual void setDyldInfo(const struct dyld_info_command*) = 0; | |
136 | virtual void setSymbolTableInfo(const macho_nlist*, const char*, const dysymtab_command*) = 0; | |
137 | virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0; | |
138 | virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0; | |
139 | virtual uint32_t* segmentCommandOffsets() const = 0; | |
140 | virtual const ImageLoader::Symbol* findShallowExportedSymbol(const char* name, const ImageLoader** foundIn) const = 0; | |
141 | virtual bool containsSymbol(const void* addr) const = 0; | |
142 | virtual uintptr_t exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, const ImageLoader* requestor, bool runResolver) const = 0; | |
143 | virtual bool exportedSymbolIsWeakDefintion(const Symbol* symbol) const = 0; | |
144 | virtual const char* exportedSymbolName(const Symbol* symbol) const = 0; | |
145 | virtual unsigned int exportedSymbolCount() const = 0; | |
146 | virtual const ImageLoader::Symbol* exportedSymbolIndexed(unsigned int) const = 0; | |
147 | virtual unsigned int importedSymbolCount() const = 0; | |
148 | virtual const ImageLoader::Symbol* importedSymbolIndexed(unsigned int) const = 0; | |
149 | virtual const char* importedSymbolName(const Symbol* symbol) const = 0; | |
150 | #if PREBOUND_IMAGE_SUPPORT | |
151 | virtual void resetPreboundLazyPointers(const LinkContext& context) = 0; | |
152 | #endif | |
153 | ||
154 | ||
155 | virtual void doGetDependentLibraries(DependentLibraryInfo libs[]); | |
156 | virtual LibraryInfo doGetLibraryInfo(const LibraryInfo& requestorInfo); | |
157 | virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const; | |
158 | virtual bool getUUID(uuid_t) const; | |
159 | virtual void doRebase(const LinkContext& context); | |
160 | virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0; | |
161 | virtual void doBindJustLazies(const LinkContext& context) = 0; | |
162 | virtual bool doInitialization(const LinkContext& context); | |
163 | virtual void doGetDOFSections(const LinkContext& context, std::vector<ImageLoader::DOFInfo>& dofs); | |
164 | virtual bool needsTermination(); | |
165 | virtual bool segmentsMustSlideTogether() const; | |
166 | virtual bool segmentsCanSlide() const; | |
167 | virtual void setSlide(intptr_t slide); | |
168 | virtual bool usesTwoLevelNameSpace() const; | |
169 | virtual bool isPrebindable() const; | |
170 | ||
171 | protected: | |
172 | ||
173 | void destroy(); | |
174 | static void sniffLoadCommands(const macho_header* mh, const char* path, bool inCache, bool* compressed, | |
175 | unsigned int* segCount, unsigned int* libCount, const LinkContext& context, | |
176 | const linkedit_data_command** codeSigCmd, | |
177 | const encryption_info_command** encryptCmd); | |
178 | static bool needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh); | |
179 | void loadCodeSignature(const struct linkedit_data_command* codeSigCmd, int fd, uint64_t offsetInFatFile, const LinkContext& context); | |
180 | void validateFirstPages(const struct linkedit_data_command* codeSigCmd, int fd, const uint8_t *fileData, size_t lenFileData, off_t offsetInFat, const LinkContext& context); | |
181 | const struct macho_segment_command* segLoadCommand(unsigned int segIndex) const; | |
182 | void parseLoadCmds(const ImageLoader::LinkContext& context); | |
183 | int crashIfInvalidCodeSignature(); | |
184 | bool segHasRebaseFixUps(unsigned int) const; | |
185 | bool segHasBindFixUps(unsigned int) const; | |
186 | void segProtect(unsigned int segIndex, const ImageLoader::LinkContext& context); | |
187 | void segMakeWritable(unsigned int segIndex, const ImageLoader::LinkContext& context); | |
188 | #if __i386__ | |
189 | bool segIsReadOnlyImport(unsigned int) const; | |
190 | #endif | |
191 | intptr_t assignSegmentAddresses(const LinkContext& context); | |
192 | uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context); | |
193 | bool reserveAddressRange(uintptr_t start, size_t length); | |
194 | void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); | |
195 | void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context); | |
196 | void UnmapSegments(); | |
197 | void __attribute__((noreturn)) throwSymbolNotFound(const LinkContext& context, const char* symbol, | |
198 | const char* referencedFrom, const char* fromVersMismatch, | |
199 | const char* expectedIn); | |
200 | void doImageInit(const LinkContext& context); | |
201 | void doModInitFunctions(const LinkContext& context); | |
202 | void setupLazyPointerHandler(const LinkContext& context); | |
203 | void lookupProgramVars(const LinkContext& context) const; | |
204 | ||
205 | void makeTextSegmentWritable(const LinkContext& context, bool writeable); | |
206 | void preFetchDATA(int fd, uint64_t offsetInFat, const LinkContext& context); | |
207 | ||
208 | ||
209 | void doInterpose(const LinkContext& context) = 0; | |
210 | bool hasReferencesToWeakSymbols() const; | |
211 | uintptr_t getSymbolAddress(const Symbol* sym, const ImageLoader* requestor, | |
212 | const LinkContext& context, bool runResolver) const; | |
213 | ||
214 | static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer); | |
215 | protected: | |
216 | uint64_t fCoveredCodeLength; | |
217 | const uint8_t* fMachOData; | |
218 | const uint8_t* fLinkEditBase; // add any internal "offset" to this to get mapped address | |
219 | uintptr_t fSlide; | |
220 | uint32_t fEHFrameSectionOffset; | |
221 | uint32_t fUnwindInfoSectionOffset; | |
222 | uint32_t fDylibIDOffset; | |
223 | uint32_t fSegmentsCount : 8, | |
224 | fIsSplitSeg : 1, | |
225 | fInSharedCache : 1, | |
226 | #if TEXT_RELOC_SUPPORT | |
227 | fTextSegmentRebases : 1, | |
228 | fTextSegmentBinds : 1, | |
229 | #endif | |
230 | #if __i386__ | |
231 | fReadOnlyImportSegment : 1, | |
232 | #endif | |
233 | fHasSubLibraries : 1, | |
234 | fHasSubUmbrella : 1, | |
235 | fInUmbrella : 1, | |
236 | fHasDOFSections : 1, | |
237 | fHasDashInit : 1, | |
238 | fHasInitializers : 1, | |
239 | fHasTerminators : 1, | |
240 | fNotifyObjC : 1, | |
241 | fRetainForObjC : 1, | |
242 | fRegisteredAsRequiresCoalescing : 1; // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount | |
243 | ||
244 | ||
245 | static uint32_t fgSymbolTableBinarySearchs; | |
246 | }; | |
247 | ||
248 | ||
249 | #endif // __IMAGELOADERMACHO__ | |
250 | ||
251 | ||
252 | ||
253 |