X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/c7f24d34adf9643c842ab6c44f8e530661cffcc7..d696c285d331ab577dcabd00419d8c30336673da:/src/Readers/ObjectFileDylibMachO.cpp diff --git a/src/Readers/ObjectFileDylibMachO.cpp b/src/Readers/ObjectFileDylibMachO.cpp deleted file mode 100644 index fad4dcb..0000000 --- a/src/Readers/ObjectFileDylibMachO.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- - * - * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - - -namespace ObjectFileDylibMachO { - -class Reader : public ObjectFile::Reader -{ -public: - Reader(const macho_header* header, const char* path, const ObjectFile::ReaderOptions& options); - virtual ~Reader(); - - virtual const char* getPath(); - virtual std::vector& getAtoms(); - virtual std::vector* getJustInTimeAtomsFor(const char* name); - virtual std::vector* getStabsDebugInfo(); - virtual const char* getInstallPath(); - virtual uint32_t getTimestamp(); - virtual uint32_t getCurrentVersion(); - virtual uint32_t getCompatibilityVersion(); - virtual std::vector* getDependentLibraryPaths(); - virtual bool reExports(ObjectFile::Reader*); - virtual bool isDefinitionWeak(const ObjectFile::Atom&); - -private: - struct CStringComparor - { - bool operator()(const char* left, const char* right) { return (strcmp(left, right) > 0); } - }; - typedef std::map Mapper; - - - void init(const macho_header* header,const char* path); - const macho_nlist* binarySearchWithToc(const char* key, const char stringPool[], const macho_nlist symbols[], const struct dylib_table_of_contents toc[], uint32_t symbolCount); - const macho_nlist* binarySearch(const char* key, const char stringPool[], const macho_nlist symbols[], uint32_t symbolCount); - bool hasExport(const char* name); - const macho_nlist* findExport(const char* name); - - const char* fPath; - const macho_header* fHeader; - const char* fStrings; - const macho_dysymtab_command* fDynamicInfo; - const macho_dylib_command* fDylibID; - const macho_nlist* fSymbols; - uint32_t fSymbolCount; - Mapper fAtoms; - std::vector fReExportedDylibs; - - static std::vector fEmptyAtomList; -}; - -std::vector Reader::fEmptyAtomList; - - -class Segment : public ObjectFile::Segment -{ -public: - Segment(const char* name) { fName = name; } - virtual const char* getName() const { return fName; } - virtual bool isContentReadable() const { return true; } - virtual bool isContentWritable() const { return false; } - virtual bool isContentExecutable() const { return false; } -private: - const char* fName; -}; - - -class ExportAtom : public ObjectFile::Atom -{ -public: - virtual ObjectFile::Reader* getFile() const { return &fOwner; } - virtual const char* getName() const { return fName; } - virtual const char* getDisplayName() const; - virtual Scope getScope() const { return ObjectFile::Atom::scopeGlobal; } - virtual bool isTentativeDefinition() const { return false; } - virtual bool isWeakDefinition() const { return false; } - virtual bool isCoalesableByName() const { return false; } - virtual bool isCoalesableByValue() const { return false; } - virtual bool isZeroFill() const { return false; } - virtual bool dontDeadStrip() const { return false; } - virtual bool dontStripName() const { return false; } - virtual bool isImportProxy() const { return true; } - virtual uint64_t getSize() const { return 0; } - virtual std::vector& getReferences() const { return fgEmptyReferenceList; } - virtual bool mustRemainInSection() const { return false; } - virtual const char* getSectionName() const { return "._imports"; } - virtual Segment& getSegment() const { return fgImportSegment; } - virtual bool requiresFollowOnAtom() const{ return false; } - virtual ObjectFile::Atom& getFollowOnAtom() const { return *((ObjectFile::Atom*)NULL); } - virtual std::vector* getStabsDebugInfo() const { return NULL; } - virtual uint8_t getAlignment() const { return 0; } - virtual WeakImportSetting getImportWeakness() const { return fWeakImportSetting; } - virtual void copyRawContent(uint8_t buffer[]) const {} - virtual void writeContent(bool finalLinkedImage, ObjectFile::ContentWriter&) const {} - - virtual void setScope(Scope) { } - virtual void setImportWeakness(bool weakImport) { fWeakImportSetting = weakImport ? kWeakImport : kNonWeakImport; } - -protected: - friend class Reader; - - ExportAtom(Reader& owner, const char* name) : fOwner(owner), fName(name), fWeakImportSetting(kWeakUnset) {} - virtual ~ExportAtom() {} - - Reader& fOwner; - const char* fName; - WeakImportSetting fWeakImportSetting; - - static std::vector fgEmptyReferenceList; - static Segment fgImportSegment; -}; - -Segment ExportAtom::fgImportSegment("__LINKEDIT"); -std::vector ExportAtom::fgEmptyReferenceList; - -const char* ExportAtom::getDisplayName() const -{ - static char temp[300]; - strcpy(temp, fName); - strcat(temp, "$import"); - return temp; -} - - - -Reader::Reader(const macho_header* header, const char* path, const ObjectFile::ReaderOptions& options) - : fHeader(header), fStrings(NULL), fDylibID(NULL), fSymbols(NULL), fSymbolCount(0) -{ - typedef std::pair DylibAndReExportFlag; - std::vector dependentDylibs; - - fPath = strdup(path); - const uint32_t cmd_count = header->ncmds(); - const macho_load_command* const cmds = (macho_load_command*)((char*)header + macho_header::size); - // get all dylib load commands - const macho_load_command* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - { - DylibAndReExportFlag info; - info.first = (struct macho_dylib_command*)cmd; - info.second = options.fFlatNamespace; - dependentDylibs.push_back(info); - } - break; - } - cmd = (const macho_load_command*)(((char*)cmd)+cmd->cmdsize()); - } - - // cache interesting pointers - cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_SYMTAB: - { - const macho_symtab_command* symtab = (macho_symtab_command*)cmd; - fSymbolCount = symtab->nsyms(); - fSymbols = (const macho_nlist*)((char*)header + symtab->symoff()); - fStrings = (char*)header + symtab->stroff(); - } - break; - case LC_DYSYMTAB: - fDynamicInfo = (macho_dysymtab_command*)cmd; - break; - case LC_ID_DYLIB: - fDylibID = (macho_dylib_command*)cmd; - break; - case LC_SUB_UMBRELLA: - if ( !options.fFlatNamespace ) { - const char* frameworkLeafName = ((macho_sub_umbrella_command*)cmd)->name(); - for (std::vector::iterator it = dependentDylibs.begin(); it != dependentDylibs.end(); it++) { - const char* dylibName = it->first->name(); - const char* lastSlash = strrchr(dylibName, '/'); - if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) ) - it->second = true; - } - } - break; - case LC_SUB_LIBRARY: - if ( !options.fFlatNamespace ) { - const char* dylibBaseName = ((macho_sub_library_command*)cmd)->name(); - for (std::vector::iterator it = dependentDylibs.begin(); it != dependentDylibs.end(); it++) { - const char* dylibName = it->first->name(); - const char* lastSlash = strrchr(dylibName, '/'); - const char* leafStart = &lastSlash[1]; - if ( lastSlash == NULL ) - leafStart = dylibName; - const char* firstDot = strchr(leafStart, '.'); - int len = strlen(leafStart); - if ( firstDot != NULL ) - len = firstDot - leafStart; - if ( strncmp(leafStart, dylibBaseName, len) == 0 ) - it->second = true; - } - } - break; - } - cmd = (const macho_load_command*)(((char*)cmd)+cmd->cmdsize()); - } - - // load dylibs we need to re-export - for (std::vector::iterator it = dependentDylibs.begin(); it != dependentDylibs.end(); it++) { - if ( it->second ) { - // printf("%s need to re-export %s\n", path, it->first->name()); - //fReExportedDylibs.push_back( - } - } -} - - -Reader::~Reader() -{ -} - -const char* Reader::getPath() -{ - return fPath; -} - - -std::vector& Reader::getAtoms() -{ - return fEmptyAtomList; -} - - - -const macho_nlist* Reader::binarySearchWithToc(const char* key, const char stringPool[], const macho_nlist symbols[], - const struct dylib_table_of_contents toc[], uint32_t symbolCount) -{ - int32_t high = symbolCount-1; - int32_t mid = symbolCount/2; - - for (int32_t low = 0; low <= high; mid = (low+high)/2) { - const uint32_t index = ENDIAN_READ32(toc[mid].symbol_index); - const macho_nlist* pivot = &symbols[index]; - const char* pivotStr = &stringPool[pivot->n_strx()]; - int cmp = strcmp(key, pivotStr); - if ( cmp == 0 ) - return pivot; - if ( cmp > 0 ) { - // key > pivot - low = mid + 1; - } - else { - // key < pivot - high = mid - 1; - } - } - return NULL; -} - - -const macho_nlist* Reader::binarySearch(const char* key, const char stringPool[], const macho_nlist symbols[], uint32_t symbolCount) -{ - const macho_nlist* base = symbols; - for (uint32_t n = symbolCount; n > 0; n /= 2) { - const macho_nlist* pivot = &base[n/2]; - const char* pivotStr = &stringPool[pivot->n_strx()]; - int cmp = strcmp(key, pivotStr); - if ( cmp == 0 ) - return pivot; - if ( cmp > 0 ) { - // key > pivot - // move base to symbol after pivot - base = &pivot[1]; - --n; - } - else { - // key < pivot - // keep same base - } - } - return NULL; -} - -const macho_nlist* Reader::findExport(const char* name) -{ - if ( fDynamicInfo->tocoff() == 0 ) - return binarySearch(name, fStrings, &fSymbols[fDynamicInfo->iextdefsym()], fDynamicInfo->nextdefsym()); - else { - return binarySearchWithToc(name, fStrings, fSymbols, (dylib_table_of_contents*)((char*)fHeader + fDynamicInfo->tocoff()), - fDynamicInfo->nextdefsym()); - } -} - -bool Reader::hasExport(const char* name) -{ - return ( findExport(name) != NULL ); -} - -std::vector* Reader::getJustInTimeAtomsFor(const char* name) -{ - std::vector* atoms = NULL; - // search exports - if ( this->hasExport(name) ) { - // see if this atom already synthesized - ObjectFile::Atom* atom = NULL; - Mapper::iterator pos = fAtoms.find(name); - if ( pos != fAtoms.end() ) { - atom = pos->second; - } - else { - atom = new ExportAtom(*this, name); - fAtoms[name] = atom; - } - // return a vector of one atom - atoms = new std::vector; - atoms->push_back(atom); - return atoms; - } - - // check re-exports - for (std::vector::iterator it = fReExportedDylibs.begin(); it != fReExportedDylibs.end(); it++) { - Reader* reExportedReader = *it; - atoms = reExportedReader->getJustInTimeAtomsFor(name); - if ( atoms != NULL ) - return atoms; - } - - return NULL; -} - - -std::vector* Reader::getStabsDebugInfo() -{ - return NULL; -} - -const char* Reader::getInstallPath() -{ - return fDylibID->name(); -} - -uint32_t Reader::getTimestamp() -{ - return fDylibID->timestamp(); -} - -uint32_t Reader::getCurrentVersion() -{ - return fDylibID->current_version(); -} - -uint32_t Reader::getCompatibilityVersion() -{ - return fDylibID->compatibility_version(); -} - -std::vector* Reader::getDependentLibraryPaths() -{ - std::vector* result = new std::vector; - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command* const cmds = (macho_load_command*)((char*)fHeader + macho_header::size); - const macho_load_command* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - { - result->push_back(((struct macho_dylib_command*)cmd)->name()); - } - break; - } - cmd = (const macho_load_command*)(((char*)cmd)+cmd->cmdsize()); - } - return result; -} - -bool Reader::reExports(ObjectFile::Reader* child) -{ - // A dependent dylib is re-exported under two conditions: - // 1) parent contains LC_SUB_UMBRELLA or LC_SUB_LIBRARY with child name - { - const uint32_t cmd_count = fHeader->ncmds(); - const macho_load_command* const cmds = (macho_load_command*)((char*)fHeader + macho_header::size); - const macho_load_command* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_SUB_UMBRELLA: - { - const char* frameworkLeafName = ((macho_sub_umbrella_command*)cmd)->name(); - const char* dylibName = child->getPath(); - const char* lastSlash = strrchr(dylibName, '/'); - if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) ) - return true; - } - break; - case LC_SUB_LIBRARY: - { - const char* dylibBaseName = ((macho_sub_library_command*)cmd)->name(); - const char* dylibName = child->getPath(); - const char* lastSlash = strrchr(dylibName, '/'); - const char* leafStart = &lastSlash[1]; - if ( lastSlash == NULL ) - leafStart = dylibName; - const char* firstDot = strchr(leafStart, '.'); - int len = strlen(leafStart); - if ( firstDot != NULL ) - len = firstDot - leafStart; - if ( strncmp(leafStart, dylibBaseName, len) == 0 ) - return true; - } - break; - } - cmd = (const macho_load_command*)(((char*)cmd)+cmd->cmdsize()); - } - } - - // 2) child contains LC_SUB_FRAMEWORK with parent name - { - const uint32_t cmd_count = ((Reader*)child)->fHeader->ncmds(); - const macho_load_command* const cmds = (macho_load_command*)((char*)(((Reader*)child)->fHeader) + macho_header::size); - const macho_load_command* cmd = cmds; - for (uint32_t i = 0; i < cmd_count; ++i) { - switch (cmd->cmd()) { - case LC_SUB_FRAMEWORK: - { - const char* frameworkLeafName = ((macho_sub_framework_command*)cmd)->name(); - const char* parentName = this->getPath(); - const char* lastSlash = strrchr(parentName, '/'); - if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) ) - return true; - } - break; - } - cmd = (const macho_load_command*)(((char*)cmd)+cmd->cmdsize()); - } - } - - - return false; -} - -bool Reader::isDefinitionWeak(const ObjectFile::Atom& atom) -{ - const macho_nlist* sym = findExport(atom.getName()); - if ( sym != NULL ) { - if ( (sym->n_desc() & N_WEAK_DEF) != 0 ) - return true; - } - return false; -} - - - -Reader* MakeReader(const macho_header* mh, const char* path, const ObjectFile::ReaderOptions& options) -{ - return new Reader(mh, path, options); -} - - - -}; - - - - - - -