]>
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[4096], 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 ImageLoader** foundIn) const; | |
61 | virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, | |
62 | const ImageLoader* requestor, bool runResolver) 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) = 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, 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 | ||
108 | ||
109 | static void printStatistics(unsigned int imageCount, const InitializerTimingList&); | |
110 | static uint32_t minOSVersion(const mach_header*); | |
111 | ||
112 | protected: | |
113 | ImageLoaderMachO(const ImageLoaderMachO&); | |
114 | ImageLoaderMachO(const macho_header* mh, const char* path, unsigned int segCount, | |
115 | uint32_t segOffsets[], unsigned int libCount); | |
116 | virtual ~ImageLoaderMachO() {} | |
117 | ||
118 | void operator=(const ImageLoaderMachO&); | |
119 | ||
120 | virtual void setDyldInfo(const struct dyld_info_command*) = 0; | |
121 | virtual void setSymbolTableInfo(const macho_nlist*, const char*, const dysymtab_command*) = 0; | |
122 | virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0; | |
123 | virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0; | |
124 | virtual uint32_t* segmentCommandOffsets() const = 0; | |
125 | virtual void rebase(const LinkContext& context) = 0; | |
126 | virtual const ImageLoader::Symbol* findExportedSymbol(const char* name, const ImageLoader** foundIn) const = 0; | |
127 | virtual bool containsSymbol(const void* addr) const = 0; | |
128 | virtual uintptr_t exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, const ImageLoader* requestor, bool runResolver) const = 0; | |
129 | virtual bool exportedSymbolIsWeakDefintion(const Symbol* symbol) const = 0; | |
130 | virtual const char* exportedSymbolName(const Symbol* symbol) const = 0; | |
131 | virtual unsigned int exportedSymbolCount() const = 0; | |
132 | virtual const ImageLoader::Symbol* exportedSymbolIndexed(unsigned int) const = 0; | |
133 | virtual unsigned int importedSymbolCount() const = 0; | |
134 | virtual const ImageLoader::Symbol* importedSymbolIndexed(unsigned int) const = 0; | |
135 | virtual const char* importedSymbolName(const Symbol* symbol) const = 0; | |
136 | #if PREBOUND_IMAGE_SUPPORT | |
137 | virtual void resetPreboundLazyPointers(const LinkContext& context) = 0; | |
138 | #endif | |
139 | ||
140 | ||
141 | virtual void doGetDependentLibraries(DependentLibraryInfo libs[]); | |
142 | virtual LibraryInfo doGetLibraryInfo(); | |
143 | virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const; | |
144 | virtual bool getUUID(uuid_t) const; | |
145 | virtual void doRebase(const LinkContext& context); | |
146 | virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0; | |
147 | virtual void doBindJustLazies(const LinkContext& context) = 0; | |
148 | virtual bool doInitialization(const LinkContext& context); | |
149 | virtual void doGetDOFSections(const LinkContext& context, std::vector<ImageLoader::DOFInfo>& dofs); | |
150 | virtual bool needsTermination(); | |
151 | virtual bool segmentsMustSlideTogether() const; | |
152 | virtual bool segmentsCanSlide() const; | |
153 | virtual void setSlide(intptr_t slide); | |
154 | virtual bool usesTwoLevelNameSpace() const; | |
155 | virtual bool isPrebindable() const; | |
156 | ||
157 | ||
158 | protected: | |
159 | ||
160 | void destroy(); | |
161 | static void sniffLoadCommands(const macho_header* mh, const char* path, bool inCache, bool* compressed, | |
162 | unsigned int* segCount, unsigned int* libCount, const LinkContext& context, | |
163 | const linkedit_data_command** codeSigCmd, | |
164 | const encryption_info_command** encryptCmd); | |
165 | static bool needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh); | |
166 | void loadCodeSignature(const struct linkedit_data_command* codeSigCmd, int fd, uint64_t offsetInFatFile, const LinkContext& context); | |
167 | void validateFirstPages(const struct linkedit_data_command* codeSigCmd, int fd, const uint8_t *fileData, size_t lenFileData, off_t offsetInFat, const LinkContext& context); | |
168 | const struct macho_segment_command* segLoadCommand(unsigned int segIndex) const; | |
169 | void parseLoadCmds(const ImageLoader::LinkContext& context); | |
170 | int crashIfInvalidCodeSignature(); | |
171 | bool segHasRebaseFixUps(unsigned int) const; | |
172 | bool segHasBindFixUps(unsigned int) const; | |
173 | void segProtect(unsigned int segIndex, const ImageLoader::LinkContext& context); | |
174 | void segMakeWritable(unsigned int segIndex, const ImageLoader::LinkContext& context); | |
175 | #if __i386__ | |
176 | bool segIsReadOnlyImport(unsigned int) const; | |
177 | #endif | |
178 | intptr_t assignSegmentAddresses(const LinkContext& context); | |
179 | uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context); | |
180 | bool reserveAddressRange(uintptr_t start, size_t length); | |
181 | void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); | |
182 | void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context); | |
183 | void UnmapSegments(); | |
184 | void __attribute__((noreturn)) throwSymbolNotFound(const LinkContext& context, const char* symbol, | |
185 | const char* referencedFrom, const char* fromVersMismatch, | |
186 | const char* expectedIn); | |
187 | void doImageInit(const LinkContext& context); | |
188 | void doModInitFunctions(const LinkContext& context); | |
189 | void setupLazyPointerHandler(const LinkContext& context); | |
190 | void lookupProgramVars(const LinkContext& context) const; | |
191 | uintptr_t bindLocation(const LinkContext& context, uintptr_t location, uintptr_t value, | |
192 | const ImageLoader* targetImage, uint8_t type, const char* symbolName, | |
193 | intptr_t addend, const char* msg); | |
194 | ||
195 | void makeTextSegmentWritable(const LinkContext& context, bool writeable); | |
196 | void preFetchDATA(int fd, uint64_t offsetInFat, const LinkContext& context); | |
197 | ||
198 | ||
199 | void doInterpose(const LinkContext& context) = 0; | |
200 | bool hasReferencesToWeakSymbols() const; | |
201 | uintptr_t getSymbolAddress(const Symbol* sym, const ImageLoader* requestor, | |
202 | const LinkContext& context, bool runResolver) const; | |
203 | ||
204 | static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer); | |
205 | protected: | |
206 | uint64_t fCoveredCodeLength; | |
207 | const uint8_t* fMachOData; | |
208 | const uint8_t* fLinkEditBase; // add any internal "offset" to this to get mapped address | |
209 | uintptr_t fSlide; | |
210 | uint32_t fEHFrameSectionOffset; | |
211 | uint32_t fUnwindInfoSectionOffset; | |
212 | uint32_t fDylibIDOffset; | |
213 | uint32_t fSegmentsCount : 8, | |
214 | fIsSplitSeg : 1, | |
215 | fInSharedCache : 1, | |
216 | #if TEXT_RELOC_SUPPORT | |
217 | fTextSegmentRebases : 1, | |
218 | fTextSegmentBinds : 1, | |
219 | #endif | |
220 | #if __i386__ | |
221 | fReadOnlyImportSegment : 1, | |
222 | #endif | |
223 | fHasSubLibraries : 1, | |
224 | fHasSubUmbrella : 1, | |
225 | fInUmbrella : 1, | |
226 | fHasDOFSections : 1, | |
227 | fHasDashInit : 1, | |
228 | fHasInitializers : 1, | |
229 | fHasTerminators : 1, | |
230 | fRegisteredAsRequiresCoalescing : 1; // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount | |
231 | ||
232 | ||
233 | static uint32_t fgSymbolTableBinarySearchs; | |
234 | static uint32_t fgSymbolTrieSearchs; | |
235 | }; | |
236 | ||
237 | ||
238 | #endif // __IMAGELOADERMACHO__ | |
239 | ||
240 | ||
241 | ||
242 |