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