X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/07feaf2cb00322d025073eb8ec22189ada5e4180..a645023da60d22e86be13f7b4d97adeff8bc6665:/src/ld/OutputFile.h diff --git a/src/ld/OutputFile.h b/src/ld/OutputFile.h new file mode 100644 index 0000000..9b49289 --- /dev/null +++ b/src/ld/OutputFile.h @@ -0,0 +1,289 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-* + * + * Copyright (c) 2009 Apple 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@ + */ + +#ifndef __OUTPUT_FILE_H__ +#define __OUTPUT_FILE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Options.h" +#include "ld.hpp" + +namespace ld { +namespace tool { + +class OutputFile +{ +public: + OutputFile(const Options& opts); + + + // iterates all atoms in initial files + void write(ld::Internal&); + bool findSegment(ld::Internal& state, uint64_t addr, uint64_t* start, uint64_t* end, uint32_t* index); + void setLazyBindingInfoOffset(uint64_t lpAddress, uint32_t lpInfoOffset); + uint32_t dylibCount(); + const ld::dylib::File* dylibByOrdinal(unsigned int ordinal); + uint32_t dylibToOrdinal(const ld::dylib::File*); + uint32_t encryptedTextStartOffset() { return _encryptedTEXTstartOffset; } + uint32_t encryptedTextEndOffset() { return _encryptedTEXTendOffset; } + int compressedOrdinalForAtom(const ld::Atom* target); + + + + bool hasWeakExternalSymbols; + bool usesWeakExternalSymbols; + bool overridesWeakExternalSymbols; + bool _noReExportedDylibs; + bool hasThreadLocalVariableDefinitions; + bool pieDisabled; + ld::Internal::FinalSection* headerAndLoadCommandsSection; + ld::Internal::FinalSection* rebaseSection; + ld::Internal::FinalSection* bindingSection; + ld::Internal::FinalSection* weakBindingSection; + ld::Internal::FinalSection* lazyBindingSection; + ld::Internal::FinalSection* exportSection; + ld::Internal::FinalSection* splitSegInfoSection; + ld::Internal::FinalSection* functionStartsSection; + ld::Internal::FinalSection* symbolTableSection; + ld::Internal::FinalSection* stringPoolSection; + ld::Internal::FinalSection* localRelocationsSection; + ld::Internal::FinalSection* externalRelocationsSection; + ld::Internal::FinalSection* sectionRelocationsSection; + ld::Internal::FinalSection* indirectSymbolTableSection; + + struct RebaseInfo { + RebaseInfo(uint8_t t, uint64_t addr) : _type(t), _address(addr) {} + uint8_t _type; + uint64_t _address; + // for sorting + int operator<(const RebaseInfo& rhs) const { + // sort by type, then address + if ( this->_type != rhs._type ) + return (this->_type < rhs._type ); + return (this->_address < rhs._address ); + } + }; + + struct BindingInfo { + BindingInfo(uint8_t t, int ord, const char* sym, bool weak_import, uint64_t addr, int64_t add) + : _type(t), _flags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ), _libraryOrdinal(ord), + _symbolName(sym), _address(addr), _addend(add) {} + BindingInfo(uint8_t t, const char* sym, bool non_weak_definition, uint64_t addr, int64_t add) + : _type(t), _flags(non_weak_definition ? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION : 0 ), + _libraryOrdinal(0), _symbolName(sym), _address(addr), _addend(add) {} + uint8_t _type; + uint8_t _flags; + int _libraryOrdinal; + const char* _symbolName; + uint64_t _address; + int64_t _addend; + + // for sorting + int operator<(const BindingInfo& rhs) const { + // sort by library, symbol, type, then address + if ( this->_libraryOrdinal != rhs._libraryOrdinal ) + return (this->_libraryOrdinal < rhs._libraryOrdinal ); + if ( this->_symbolName != rhs._symbolName ) + return ( strcmp(this->_symbolName, rhs._symbolName) < 0 ); + if ( this->_type != rhs._type ) + return (this->_type < rhs._type ); + return (this->_address < rhs._address ); + } + }; + + struct SplitSegInfoEntry { + SplitSegInfoEntry(uint64_t a, ld::Fixup::Kind k) : address(a), kind(k) {} + uint64_t address; + ld::Fixup::Kind kind; + }; + +private: + void buildDylibOrdinalMapping(ld::Internal&); + bool hasOrdinalForInstallPath(const char* path, int* ordinal); + void addLoadCommands(ld::Internal& state); + void addLinkEdit(ld::Internal& state); + void addPreloadLinkEdit(ld::Internal& state); + void generateLinkEditInfo(ld::Internal& state); + void buildSymbolTable(ld::Internal& state); + void writeOutputFile(ld::Internal& state); + void assignFileOffsets(ld::Internal& state); + void setSectionSizesAndAlignments(ld::Internal& state); + void addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend); + void addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend); + void addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, + const ld::Atom* atom, ld::Fixup* fixupWithTarget, + ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore, + const ld::Atom* target, const ld::Atom* minusTarget, + uint64_t targetAddend, uint64_t minusTargetAddend); + bool useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target, + ld::Fixup* fixupWithTarget); + uint64_t pageAlign(uint64_t addr); + uint64_t pageAlign(uint64_t addr, uint64_t pageSize); + void setLoadCommandsPadding(ld::Internal& state); + void assignAtomAddresses(ld::Internal& state); + void addRebaseInfo(const ld::Atom* atom, const ld::Fixup* fixup, const ld::Atom* target); + void makeRebasingInfo(ld::Internal& state); + void makeBindingInfo(ld::Internal& state); + void updateLINKEDITAddresses(ld::Internal& state); + void applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer); + uint64_t addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target); + bool targetIsThumb(ld::Internal& state, const ld::Fixup* fixup); + uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress); + void copyNoOps(uint8_t* from, uint8_t* to); + bool isPointerToTarget(ld::Fixup::Kind kind); + bool isPointerFromTarget(ld::Fixup::Kind kind); + bool isPcRelStore(ld::Fixup::Kind kind); + bool isStore(ld::Fixup::Kind kind); + bool storeAddendOnly(const ld::Atom* inAtom, const ld::Atom* target, bool pcRel=false); + bool setsTarget(ld::Fixup::Kind kind); + void addFixupOutInfo(ld::Internal& state); + void makeRelocations(ld::Internal& state); + void makeSectionRelocations(ld::Internal& state); + void makeDyldInfo(ld::Internal& state); + void makeSplitSegInfo(ld::Internal& state); + void writeMapFile(ld::Internal& state); + uint64_t lookBackAddend(ld::Fixup::iterator fit); + bool takesNoDiskSpace(const ld::Section* sect); + bool hasZeroForFileOffset(const ld::Section* sect); + + void printSectionLayout(ld::Internal& state); + void rangeCheck8(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheck16(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckBranch32(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckRIP32(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckARM12(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckARMBranch24(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckThumbBranch22(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckPPCBranch24(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + void rangeCheckPPCBranch14(int64_t delta, ld::Internal& state, const ld::Atom* atom, + const ld::Fixup* fixup); + uint64_t sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup); + uint64_t tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup); + void dumpAtomsBySection(ld::Internal& state, bool); + void synthesizeDebugNotes(ld::Internal& state); + const char* assureFullPath(const char* path); + void noteTextReloc(const ld::Atom* atom, const ld::Atom* target); + + + static uint16_t get16LE(uint8_t* loc); + static void set16LE(uint8_t* loc, uint16_t value); + static uint32_t get32LE(uint8_t* loc); + static void set32LE(uint8_t* loc, uint32_t value); + static uint64_t get64LE(uint8_t* loc); + static void set64LE(uint8_t* loc, uint64_t value); + + static uint16_t get16BE(uint8_t* loc); + static void set16BE(uint8_t* loc, uint16_t value); + static uint32_t get32BE(uint8_t* loc); + static void set32BE(uint8_t* loc, uint32_t value); + static uint64_t get64BE(uint8_t* loc); + static void set64BE(uint8_t* loc, uint64_t value); + + + + const Options& _options; + std::map _dylibToOrdinal; + std::vector _dylibsToLoad; + std::vector _dylibOrdinalPaths; + const bool _hasDyldInfo; + const bool _hasSymbolTable; + const bool _hasSectionRelocations; + const bool _hasSplitSegInfo; + const bool _hasFunctionStartsInfo; + bool _hasDynamicSymbolTable; + bool _hasLocalRelocations; + bool _hasExternalRelocations; + uint64_t _fileSize; + std::map _lazyPointerAddressToInfoOffset; + uint32_t _encryptedTEXTstartOffset; + uint32_t _encryptedTEXTendOffset; +public: + std::vector _localAtoms; + std::vector _exportedAtoms; + std::vector _importedAtoms; + uint32_t _localSymbolsStartIndex; + uint32_t _localSymbolsCount; + uint32_t _globalSymbolsStartIndex; + uint32_t _globalSymbolsCount; + uint32_t _importSymbolsStartIndex; + uint32_t _importSymbolsCount; + std::map _atomToSymbolIndex; + std::vector _rebaseInfo; + std::vector _bindingInfo; + std::vector _lazyBindingInfo; + std::vector _weakBindingInfo; + std::vector _splitSegInfos; + class HeaderAndLoadCommandsAbtract* _headersAndLoadCommandAtom; + class RelocationsAtomAbstract* _sectionsRelocationsAtom; + class RelocationsAtomAbstract* _localRelocsAtom; + class RelocationsAtomAbstract* _externalRelocsAtom; + class ClassicLinkEditAtom* _symbolTableAtom; + class ClassicLinkEditAtom* _indirectSymbolTableAtom; + class StringPoolAtom* _stringPoolAtom; + class LinkEditAtom* _rebasingInfoAtom; + class LinkEditAtom* _bindingInfoAtom; + class LinkEditAtom* _lazyBindingInfoAtom; + class LinkEditAtom* _weakBindingInfoAtom; + class LinkEditAtom* _exportInfoAtom; + class LinkEditAtom* _splitSegInfoAtom; + class LinkEditAtom* _functionStartsAtom; +}; + +} // namespace tool +} // namespace ld + +#endif // __OUTPUT_FILE_H__