X-Git-Url: https://git.saurik.com/apple/dyld.git/blobdiff_plain/d6f5f96dd73a9fc1307a46119d767ff3261f0f9c..04b5575d8fc9b95f96f2a621169e45d995ee8a41:/src/ImageLoaderMachO.h diff --git a/src/ImageLoaderMachO.h b/src/ImageLoaderMachO.h index b540479..72c90f1 100644 --- a/src/ImageLoaderMachO.h +++ b/src/ImageLoaderMachO.h @@ -1,6 +1,6 @@ /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * - * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2009 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -27,180 +27,211 @@ #define __IMAGELOADERMACHO__ #include +#include +#include #include "ImageLoader.h" +#include "mach-o/dyld_images.h" -struct sf_mapping; -struct _shared_region_mapping_np; // -// ImageLoaderMachO is the concrete subclass of ImageLoader which loads mach-o format files. -// The class is written to be 64-bit clean and support both 32-bit and 64-bit executables in -// mach-o. +// ImageLoaderMachO is a subclass of ImageLoader which loads mach-o format files. // // class ImageLoaderMachO : public ImageLoader { public: - ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offset, uint64_t len, const struct stat& info, const LinkContext& context); - ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context); - virtual ~ImageLoaderMachO() {} + static ImageLoader* instantiateMainExecutable(const macho_header* mh, uintptr_t slide, const char* path, const LinkContext& context); + static ImageLoader* instantiateFromFile(const char* path, int fd, const uint8_t firstPages[4096], uint64_t offsetInFat, + uint64_t lenInFat, const struct stat& info, const LinkContext& context); + static ImageLoader* instantiateFromCache(const macho_header* mh, const char* path, long slide, const struct stat& info, const LinkContext& context); + static ImageLoader* instantiateFromMemory(const char* moduleName, const macho_header* mh, uint64_t len, const LinkContext& context); + + + bool inSharedCache() const { return fInSharedCache; } + void disableCoverageCheck() { fCoveredCodeLength = UINT64_MAX; } const char* getInstallPath() const; virtual void* getMain() const; + virtual void* getThreadPC() const; virtual const struct mach_header* machHeader() const; virtual uintptr_t getSlide() const; - virtual const void* getBaseAddress() const; + virtual const void* getEnd() const; virtual bool hasCoalescedExports() const; - virtual const Symbol* findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const; - virtual uintptr_t getExportedSymbolAddress(const Symbol* sym) const; + virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const; + virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, + const ImageLoader* requestor, bool runResolver) const; virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const; virtual const char* getExportedSymbolName(const Symbol* sym) const; virtual uint32_t getExportedSymbolCount() const; virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const; virtual uint32_t getImportedSymbolCount() const; virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const; - virtual ReferenceFlags geImportedSymbolInfo(const Symbol* sym) const; + virtual ReferenceFlags getImportedSymbolInfo(const Symbol* sym) const; virtual const char* getImportedSymbolName(const Symbol* sym) const; virtual bool isBundle() const; virtual bool isDylib() const; + virtual bool isExecutable() const; + virtual bool isPositionIndependentExecutable() const; virtual bool forceFlat() const; - virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context); + virtual bool participatesInCoalescing() const; + virtual const char* findClosestSymbol(const void* addr, const void** closestAddr) const = 0; + virtual void initializeCoalIterator(CoalIterator&, unsigned int loadOrder) = 0; + virtual bool incrementCoalIterator(CoalIterator&) = 0; + virtual uintptr_t getAddressCoalIterator(CoalIterator&, const LinkContext& contex) = 0; + virtual void updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, const LinkContext& context) = 0; + virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0; + virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context, void (*lock)(), void (*unlock)()) = 0; virtual void doTermination(const LinkContext& context); - virtual void doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]); virtual bool needsInitialization(); - virtual bool hasImageNotification(); virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length); + virtual void getUnwindInfo(dyld_unwind_sections* info); virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset); virtual bool usablePrebinding(const LinkContext& context) const; + virtual unsigned int segmentCount() const; + virtual const char* segName(unsigned int) const; + virtual uintptr_t segSize(unsigned int) const; + virtual uintptr_t segFileSize(unsigned int) const; + virtual bool segHasTrailingZeroFill(unsigned int); + virtual uintptr_t segFileOffset(unsigned int) const; + virtual bool segReadable(unsigned int) const; + virtual bool segWriteable(unsigned int) const; + virtual bool segExecutable(unsigned int) const; + virtual bool segUnaccessible(unsigned int) const; + virtual bool segHasPreferredLoadAddress(unsigned int) const; + virtual uintptr_t segActualLoadAddress(unsigned int) const; + virtual uintptr_t segPreferredLoadAddress(unsigned int) const; + virtual uintptr_t segActualEndAddress(unsigned int) const; + virtual void registerInterposing(); + virtual uint32_t sdkVersion() const; + virtual uint32_t minOSVersion() const; - static void printStatistics(unsigned int imageCount); + static void printStatistics(unsigned int imageCount, const InitializerTimingList&); + static uint32_t minOSVersion(const mach_header*); protected: ImageLoaderMachO(const ImageLoaderMachO&); + ImageLoaderMachO(const macho_header* mh, const char* path, unsigned int segCount, + uint32_t segOffsets[], unsigned int libCount); + virtual ~ImageLoaderMachO() {} + void operator=(const ImageLoaderMachO&); - virtual uint32_t doGetDependentLibraryCount(); - virtual void doGetDependentLibraries(DependentLibrary libs[]); + virtual void setDyldInfo(const struct dyld_info_command*) = 0; + virtual void setSymbolTableInfo(const macho_nlist*, const char*, const dysymtab_command*) = 0; + virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0; + virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0; + virtual uint32_t* segmentCommandOffsets() const = 0; + virtual void rebase(const LinkContext& context) = 0; + virtual const ImageLoader::Symbol* findExportedSymbol(const char* name, const ImageLoader** foundIn) const = 0; + virtual bool containsSymbol(const void* addr) const = 0; + virtual uintptr_t exportedSymbolAddress(const LinkContext& context, const Symbol* symbol, const ImageLoader* requestor, bool runResolver) const = 0; + virtual bool exportedSymbolIsWeakDefintion(const Symbol* symbol) const = 0; + virtual const char* exportedSymbolName(const Symbol* symbol) const = 0; + virtual unsigned int exportedSymbolCount() const = 0; + virtual const ImageLoader::Symbol* exportedSymbolIndexed(unsigned int) const = 0; + virtual unsigned int importedSymbolCount() const = 0; + virtual const ImageLoader::Symbol* importedSymbolIndexed(unsigned int) const = 0; + virtual const char* importedSymbolName(const Symbol* symbol) const = 0; +#if PREBOUND_IMAGE_SUPPORT + virtual void resetPreboundLazyPointers(const LinkContext& context) = 0; +#endif + + + virtual void doGetDependentLibraries(DependentLibraryInfo libs[]); virtual LibraryInfo doGetLibraryInfo(); + virtual void getRPaths(const LinkContext& context, std::vector&) const; + virtual bool getUUID(uuid_t) const; virtual void doRebase(const LinkContext& context); - virtual void doBind(const LinkContext& context, BindingLaziness bindness); - virtual void doInitialization(const LinkContext& context); - virtual void doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind); + virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0; + virtual void doBindJustLazies(const LinkContext& context) = 0; + virtual bool doInitialization(const LinkContext& context); + virtual void doGetDOFSections(const LinkContext& context, std::vector& dofs); virtual bool needsTermination(); - virtual void instantiateSegments(const uint8_t* fileData); virtual bool segmentsMustSlideTogether() const; virtual bool segmentsCanSlide() const; virtual void setSlide(intptr_t slide); virtual bool usesTwoLevelNameSpace() const; - virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const; - virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const; virtual bool isPrebindable() const; - virtual void prebindUnmap(const LinkContext& context); -#if !__LP64__ // split segs not supported for 64-bits - virtual void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); -#endif -private: - friend class SegmentMachO; - - void init(); - void parseLoadCmds(); - void doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols); - void doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols); - uintptr_t resolveUndefined(const LinkContext& context, const struct macho_nlist* symbol, bool twoLevel, ImageLoader **foundIn); - uintptr_t getRelocBase(); +protected: + + void destroy(); + static void sniffLoadCommands(const macho_header* mh, const char* path, bool inCache, bool* compressed, + unsigned int* segCount, unsigned int* libCount, const LinkContext& context, + const linkedit_data_command** codeSigCmd, + const encryption_info_command** encryptCmd); + static bool needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh); + void loadCodeSignature(const struct linkedit_data_command* codeSigCmd, int fd, uint64_t offsetInFatFile, const LinkContext& context); + void validateFirstPages(const struct linkedit_data_command* codeSigCmd, int fd, const uint8_t *fileData, size_t lenFileData, off_t offsetInFat, const LinkContext& context); + const struct macho_segment_command* segLoadCommand(unsigned int segIndex) const; + void parseLoadCmds(const ImageLoader::LinkContext& context); + int crashIfInvalidCodeSignature(); + bool segHasRebaseFixUps(unsigned int) const; + bool segHasBindFixUps(unsigned int) const; + void segProtect(unsigned int segIndex, const ImageLoader::LinkContext& context); + void segMakeWritable(unsigned int segIndex, const ImageLoader::LinkContext& context); +#if __i386__ + bool segIsReadOnlyImport(unsigned int) const; +#endif + intptr_t assignSegmentAddresses(const LinkContext& context); + uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context); + bool reserveAddressRange(uintptr_t start, size_t length); + void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); + void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context); + void UnmapSegments(); + void __attribute__((noreturn)) throwSymbolNotFound(const LinkContext& context, const char* symbol, + const char* referencedFrom, const char* fromVersMismatch, + const char* expectedIn); void doImageInit(const LinkContext& context); void doModInitFunctions(const LinkContext& context); - void setupLazyPointerHandler(); - void applyPrebindingToDATA(uint8_t* fileToPrebind); - void applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp); - void applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind); -#if !__LP64__ // split segs not supported for 64-bits - unsigned int getExtraZeroFillEntriesCount(); - int sharedRegionLoadFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); - int sharedRegionMapFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); - int sharedRegionMakePrivate(const LinkContext& context); - int sharedRegionMapFilePrivate(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context, bool usemmap); - int sharedRegionMapFilePrivateOutside(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context); - void initMappingTable(uint64_t offsetInFat, sf_mapping *mappingTable, uintptr_t baseAddress); - void initMappingTable(uint64_t offsetInFat, _shared_region_mapping_np *mappingTable); -#endif - bool needsCoalescing() const; - bool isAddrInSection(uintptr_t addr, uint8_t sectionIndex); + void setupLazyPointerHandler(const LinkContext& context); + void lookupProgramVars(const LinkContext& context) const; + uintptr_t bindLocation(const LinkContext& context, uintptr_t location, uintptr_t value, + const ImageLoader* targetImage, uint8_t type, const char* symbolName, + intptr_t addend, const char* msg); - static bool symbolRequiresCoalescing(const struct macho_nlist* symbol); - static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer); - static const struct macho_nlist* binarySearch(const char* key, const char stringPool[], const struct macho_nlist symbols[], uint32_t symbolCount); - static const struct macho_nlist* binarySearchWithToc(const char* key, const char stringPool[], const struct macho_nlist symbols[], - const struct dylib_table_of_contents toc[], uint32_t symbolCount, uint32_t hintIndex); - - const uint8_t* fMachOData; - const uint8_t* fLinkEditBase; // add any internal "offset" to this to get actual address - const struct macho_nlist* fSymbolTable; - const char* fStrings; - const struct dysymtab_command* fDynamicInfo; - uintptr_t fSlide; - bool fIsSplitSeg; - bool fHasSubLibraries; - bool fHasSubUmbrella; - bool fTextSegmentHasFixups; - const struct macho_routines_command* fDashInit; - const struct macho_section* fModInitSection; - const struct macho_section* fModTermSection; - const struct macho_section* fDATAdyld; - const struct macho_section* fImageNotifySection; - const struct twolevel_hints_command* fTwoLevelHints; - const struct dylib_command* fDylibID; - const char* fReExportThruFramework; - class SegmentMachO* fTextSegmentWithFixups; // NULL unless __TEXT segment has fixups - - static uint32_t fgHintedBinaryTreeSearchs; - static uint32_t fgUnhintedBinaryTreeSearchs; -}; + void makeTextSegmentWritable(const LinkContext& context, bool writeable); + void preFetchDATA(int fd, uint64_t offsetInFat, const LinkContext& context); -class SegmentMachO : public Segment -{ -public: - SegmentMachO(const struct macho_segment_command* cmd, ImageLoaderMachO*, const uint8_t* fileData); - virtual ~SegmentMachO(); - - virtual const ImageLoader* getImage(); - virtual const char* getName(); - virtual uintptr_t getSize(); - virtual uintptr_t getFileSize(); - virtual uintptr_t getFileOffset(); - virtual bool readable(); - virtual bool writeable(); - virtual bool executable(); - virtual bool unaccessible(); - virtual bool hasFixUps(); - virtual uintptr_t getActualLoadAddress(); - virtual uintptr_t getPreferredLoadAddress(); - virtual void setUnMapWhenDestructed(bool unmap); - virtual uint32_t crc32(); - + void doInterpose(const LinkContext& context) = 0; + bool hasReferencesToWeakSymbols() const; + uintptr_t getSymbolAddress(const Symbol* sym, const ImageLoader* requestor, + const LinkContext& context, bool runResolver) const; + + static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer); protected: - virtual bool hasPreferredLoadAddress(); - -private: - SegmentMachO(const SegmentMachO&); - void operator=(const SegmentMachO&); - - friend class ImageLoaderMachO; - - - ImageLoaderMachO* const fImage; - char fName[18]; - const uintptr_t fSize; - const uintptr_t fFileSize; - const uintptr_t fFileOffset; - const uintptr_t fPreferredLoadAddress; - const uint16_t fVMProtection; - bool fHasFixUps; - bool fUnMapOnDestruction; + uint64_t fCoveredCodeLength; + const uint8_t* fMachOData; + const uint8_t* fLinkEditBase; // add any internal "offset" to this to get mapped address + uintptr_t fSlide; + uint32_t fEHFrameSectionOffset; + uint32_t fUnwindInfoSectionOffset; + uint32_t fDylibIDOffset; + uint32_t fSegmentsCount : 8, + fIsSplitSeg : 1, + fInSharedCache : 1, +#if TEXT_RELOC_SUPPORT + fTextSegmentRebases : 1, + fTextSegmentBinds : 1, +#endif +#if __i386__ + fReadOnlyImportSegment : 1, +#endif + fHasSubLibraries : 1, + fHasSubUmbrella : 1, + fInUmbrella : 1, + fHasDOFSections : 1, + fHasDashInit : 1, + fHasInitializers : 1, + fHasTerminators : 1, + fRegisteredAsRequiresCoalescing : 1; // Loading MH_DYLIB_STUB causing coalescable miscount + + + static uint32_t fgSymbolTableBinarySearchs; + static uint32_t fgSymbolTrieSearchs; };