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