diff options
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp')
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp | 142 |
1 files changed, 71 insertions, 71 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index beecd331594..7b0b501c3b0 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -8,18 +8,18 @@ //===----------------------------------------------------------------------===// /// -/// \file For mach-o object files, this implementation converts normalized +/// \file For mach-o object files, this implementation converts normalized /// mach-o in memory to mach-o binary on disk. /// -/// +---------------+ -/// | binary mach-o | -/// +---------------+ +/// +---------------+ +/// | binary mach-o | +/// +---------------+ /// ^ /// | /// | -/// +------------+ -/// | normalized | -/// +------------+ +/// +------------+ +/// | normalized | +/// +------------+ #include "MachONormalizedFile.h" #include "MachONormalizedFileBinaryUtils.h" @@ -51,7 +51,7 @@ namespace mach_o { namespace normalized { /// Utility class for writing a mach-o binary file given an in-memory -/// normalized file. +/// normalized file. class MachOFileLayout { public: /// All layout computation is done in the constructor. @@ -60,11 +60,11 @@ public: /// Returns the final file size as computed in the constructor. size_t size() const; - /// Writes the normalized file as a binary mach-o file to the specified + /// Writes the normalized file as a binary mach-o file to the specified /// path. This does not have a stream interface because the generated /// file may need the 'x' bit set. error_code writeBinary(StringRef path); - + private: uint32_t loadCommandsSize(uint32_t &count); void buildFileOffsets(); @@ -101,7 +101,7 @@ private: typedef llvm::MachO::section section; enum { LC = llvm::MachO::LC_SEGMENT }; }; - + template <typename T> error_code writeSingleSegmentLoadCommand(uint8_t *&lc); template <typename T> @@ -109,7 +109,7 @@ private: uint32_t pointerAlign(uint32_t value); static StringRef dyldPath(); - + class ByteBuffer { public: ByteBuffer() : _ostream(_bytes) { } @@ -141,7 +141,7 @@ private: // Stream ivar must be after SmallVector ivar to construct properly. llvm::raw_svector_ostream _ostream; }; - + struct SegExtraInfo { uint32_t fileOffset; @@ -152,7 +152,7 @@ private: uint32_t fileOffset; }; typedef std::map<const Section*, SectionExtraInfo> SectionMap; - + const NormalizedFile &_file; error_code _ec; uint8_t *_buffer; @@ -207,19 +207,19 @@ StringRef MachOFileLayout::dyldPath() { uint32_t MachOFileLayout::pointerAlign(uint32_t value) { return llvm::RoundUpToAlignment(value, _is64 ? 8 : 4); -} +} - -MachOFileLayout::MachOFileLayout(const NormalizedFile &file) + +MachOFileLayout::MachOFileLayout(const NormalizedFile &file) : _file(file), _is64(MachOLinkingContext::is64Bit(file.arch)), _swap(!MachOLinkingContext::isHostEndian(file.arch)), _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)), _seg1addr(INT64_MAX) { _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header); - const size_t segCommandBaseSize = + const size_t segCommandBaseSize = (_is64 ? sizeof(segment_command_64) : sizeof(segment_command)); const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section)); if (file.fileType == llvm::MachO::MH_OBJECT) { @@ -229,7 +229,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) + file.sections.size() * sectsSize + sizeof(symtab_command); _countOfLoadCommands = 2; - + // Accumulate size of each section. _startOfSectionsContent = _endOfLoadCommands; _endOfSectionsContent = _startOfSectionsContent; @@ -239,21 +239,21 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) _endOfSectionsContent += sect.content.size(); relocCount += sect.relocations.size(); } - + computeSymbolTableSizes(); - + // Align start of relocations. - _startOfRelocations = pointerAlign(_endOfSectionsContent); + _startOfRelocations = pointerAlign(_endOfSectionsContent); _startOfSymbols = _startOfRelocations + relocCount * 8; // Add Indirect symbol table. _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize; // Align start of symbol table and symbol strings. - _startOfSymbolStrings = _startOfIndirectSymbols + _startOfSymbolStrings = _startOfIndirectSymbols + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t)); - _endOfSymbolStrings = _startOfSymbolStrings + _endOfSymbolStrings = _startOfSymbolStrings + pointerAlign(_symbolStringPoolSize); _endOfLinkEdit = _endOfSymbolStrings; - DEBUG_WITH_TYPE("MachOFileLayout", + DEBUG_WITH_TYPE("MachOFileLayout", llvm::dbgs() << "MachOFileLayout()\n" << " startOfLoadCommands=" << _startOfLoadCommands << "\n" << " countOfLoadCommands=" << _countOfLoadCommands << "\n" @@ -266,13 +266,13 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) << " endOfSectionsContent=" << _endOfSectionsContent << "\n"); } else { // Final linked images have one load command per segment. - _endOfLoadCommands = _startOfLoadCommands + _endOfLoadCommands = _startOfLoadCommands + loadCommandsSize(_countOfLoadCommands); // Assign section file offsets. buildFileOffsets(); buildLinkEditInfo(); - + // LINKEDIT of final linked images has in order: // rebase info, binding info, lazy binding info, weak binding info, // indirect symbol table, symbol table, symbol table strings. @@ -285,12 +285,12 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) _startOfSymbols = _endOfLazyBindingInfo; _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize; - _startOfSymbolStrings = _startOfIndirectSymbols + _startOfSymbolStrings = _startOfIndirectSymbols + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t)); - _endOfSymbolStrings = _startOfSymbolStrings + _endOfSymbolStrings = _startOfSymbolStrings + pointerAlign(_symbolStringPoolSize); _endOfLinkEdit = _endOfSymbolStrings; - DEBUG_WITH_TYPE("MachOFileLayout", + DEBUG_WITH_TYPE("MachOFileLayout", llvm::dbgs() << "MachOFileLayout()\n" << " startOfLoadCommands=" << _startOfLoadCommands << "\n" << " countOfLoadCommands=" << _countOfLoadCommands << "\n" @@ -312,8 +312,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) { uint32_t size = 0; count = 0; - - const size_t segCommandSize = + + const size_t segCommandSize = (_is64 ? sizeof(segment_command_64) : sizeof(segment_command)); const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section)); @@ -325,21 +325,21 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) { // Add one LC_SEGMENT for implicit __LINKEDIT segment size += segCommandSize; ++count; - + // Add LC_DYLD_INFO size += sizeof(dyld_info_command); ++count; - + // Add LC_SYMTAB size += sizeof(symtab_command); ++count; - + // Add LC_DYSYMTAB if (_file.fileType != llvm::MachO::MH_PRELOAD) { size += sizeof(dysymtab_command); ++count; } - + // If main executable add LC_LOAD_DYLINKER and LC_MAIN if (_file.fileType == llvm::MachO::MH_EXECUTE) { size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1); @@ -347,13 +347,13 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) { size += sizeof(entry_point_command); ++count; } - + // Add LC_LOAD_DYLIB for each dependent dylib. for (const DependentDylib &dep : _file.dependentDylibs) { size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1); ++count; } - + return size; } @@ -385,8 +385,8 @@ void MachOFileLayout::buildFileOffsets() { } } } - - // Verify no sections overlap + + // Verify no sections overlap for (const Section &s1 : _file.sections) { for (const Section &s2 : _file.sections) { if (&s1 == &s2) @@ -397,7 +397,7 @@ void MachOFileLayout::buildFileOffsets() { } } } - + // Build side table of extra info about segments and sections. SegExtraInfo t; t.fileOffset = 0; @@ -410,7 +410,7 @@ void MachOFileLayout::buildFileOffsets() { for (const Section &s : _file.sections) { _sectInfo[&s] = t2; for (const Segment &sg : _file.segments) { - if ((s.address >= sg.address) + if ((s.address >= sg.address) && (s.address+s.content.size() <= sg.address+sg.size)) { if (!sg.name.equals(s.segmentName)) { _ec = llvm::make_error_code(llvm::errc::executable_format_error); @@ -420,23 +420,23 @@ void MachOFileLayout::buildFileOffsets() { } } } - + // Assign file offsets. uint32_t fileOffset = 0; - DEBUG_WITH_TYPE("MachOFileLayout", + DEBUG_WITH_TYPE("MachOFileLayout", llvm::dbgs() << "buildFileOffsets()\n"); for (const Segment &sg : _file.segments) { // FIXME: 4096 should be inferred from segments in normalized file. _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096); if ((_seg1addr == INT64_MAX) && sg.access) _seg1addr = sg.address; - DEBUG_WITH_TYPE("MachOFileLayout", + DEBUG_WITH_TYPE("MachOFileLayout", llvm::dbgs() << " segment=" << sg.name << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n"); for (const Section *s : _segInfo[&sg].sections) { fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset; _sectInfo[s].fileOffset = fileOffset; - DEBUG_WITH_TYPE("MachOFileLayout", + DEBUG_WITH_TYPE("MachOFileLayout", llvm::dbgs() << " section=" << s->sectionName << ", fileOffset=" << fileOffset << "\n"); } @@ -463,7 +463,7 @@ void MachOFileLayout::writeMachHeader() { swapStruct(*mh); } -uint32_t MachOFileLayout::indirectSymbolIndex(const Section §, +uint32_t MachOFileLayout::indirectSymbolIndex(const Section §, uint32_t &index) { if (sect.indirectSymbols.empty()) return 0; @@ -486,7 +486,7 @@ template <typename T> error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) { typename T::command* seg = reinterpret_cast<typename T::command*>(lc); seg->cmd = T::LC; - seg->cmdsize = sizeof(typename T::command) + seg->cmdsize = sizeof(typename T::command) + _file.sections.size() * sizeof(typename T::section); uint8_t *next = lc + seg->cmdsize; memset(seg->segname, 0, 16); @@ -536,7 +536,7 @@ error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) { SegExtraInfo &segInfo = _segInfo[&seg]; typename T::command* cmd = reinterpret_cast<typename T::command*>(lc); cmd->cmd = T::LC; - cmd->cmdsize = sizeof(typename T::command) + cmd->cmdsize = sizeof(typename T::command) + segInfo.sections.size() * sizeof(typename T::section); uint8_t *next = lc + cmd->cmdsize; setString16(seg.name, cmd->segname); @@ -567,7 +567,7 @@ error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) { if (_swap) swapStruct(*sect); ++sect; - } + } lc = reinterpret_cast<uint8_t*>(next); } // Add implicit __LINKEDIT segment @@ -605,7 +605,7 @@ error_code MachOFileLayout::writeLoadCommands() { st->cmd = LC_SYMTAB; st->cmdsize = sizeof(symtab_command); st->symoff = _startOfSymbols; - st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size() + st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size() + _file.undefinedSymbols.size(); st->stroff = _startOfSymbolStrings; st->strsize = _endOfSymbolStrings - _startOfSymbolStrings; @@ -617,7 +617,7 @@ error_code MachOFileLayout::writeLoadCommands() { ec = writeSegmentLoadCommands<MachO64Trait>(lc); else ec = writeSegmentLoadCommands<MachO32Trait>(lc); - + // Add LC_DYLD_INFO_ONLY. dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc); di->cmd = LC_DYLD_INFO_ONLY; @@ -641,14 +641,14 @@ error_code MachOFileLayout::writeLoadCommands() { st->cmd = LC_SYMTAB; st->cmdsize = sizeof(symtab_command); st->symoff = _startOfSymbols; - st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size() + st->nsyms = _file.localSymbols.size() + _file.globalSymbols.size() + _file.undefinedSymbols.size(); st->stroff = _startOfSymbolStrings; st->strsize = _endOfSymbolStrings - _startOfSymbolStrings; if (_swap) swapStruct(*st); lc += sizeof(symtab_command); - + // Add LC_DYSYMTAB if (_file.fileType != llvm::MachO::MH_PRELOAD) { dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc); @@ -666,7 +666,7 @@ error_code MachOFileLayout::writeLoadCommands() { dst->nmodtab = 0; dst->extrefsymoff = 0; dst->nextrefsyms = 0; - dst->indirectsymoff = _startOfIndirectSymbols; + dst->indirectsymoff = _startOfIndirectSymbols; dst->nindirectsyms = _indirectSymbolTableCount; dst->extreloff = 0; dst->nextrel = 0; @@ -676,7 +676,7 @@ error_code MachOFileLayout::writeLoadCommands() { swapStruct(*dst); lc += sizeof(dysymtab_command); } - + // If main executable, add LC_LOAD_DYLINKER and LC_MAIN. if (_file.fileType == llvm::MachO::MH_EXECUTE) { // Build LC_LOAD_DYLINKER load command. @@ -700,7 +700,7 @@ error_code MachOFileLayout::writeLoadCommands() { swapStruct(*ep); lc += sizeof(entry_point_command); } - + // Add LC_LOAD_DYLIB commands for (const DependentDylib &dep : _file.dependentDylibs) { dylib_command* dc = reinterpret_cast<dylib_command*>(lc); @@ -717,7 +717,7 @@ error_code MachOFileLayout::writeLoadCommands() { lc[sizeof(dylib_command)+dep.path.size()] = '\0'; lc += size; } - + } return ec; } @@ -818,12 +818,12 @@ void MachOFileLayout::writeRebaseInfo() { } void MachOFileLayout::writeBindingInfo() { - memcpy(&_buffer[_startOfBindingInfo], + memcpy(&_buffer[_startOfBindingInfo], _bindingInfo.bytes(), _bindingInfo.size()); } void MachOFileLayout::writeLazyBindingInfo() { - memcpy(&_buffer[_startOfLazyBindingInfo], + memcpy(&_buffer[_startOfLazyBindingInfo], _lazyBindingInfo.bytes(), _lazyBindingInfo.size()); } @@ -842,12 +842,12 @@ void MachOFileLayout::buildRebaseInfo() { // TODO: compress rebasing info. for (const RebaseLocation& entry : _file.rebasingInfo) { _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind); - _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | entry.segIndex); _rebaseInfo.append_uleb128(entry.segOffset); _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1); } - _rebaseInfo.append_byte(REBASE_OPCODE_DONE); + _rebaseInfo.append_byte(REBASE_OPCODE_DONE); _rebaseInfo.align(_is64 ? 8 : 4); } @@ -855,7 +855,7 @@ void MachOFileLayout::buildBindInfo() { // TODO: compress bind info. for (const BindLocation& entry : _file.bindingInfo) { _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind); - _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | entry.segIndex); _bindingInfo.append_uleb128(entry.segOffset); _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal); @@ -867,14 +867,14 @@ void MachOFileLayout::buildBindInfo() { } _bindingInfo.append_byte(BIND_OPCODE_DO_BIND); } - _bindingInfo.append_byte(BIND_OPCODE_DONE); + _bindingInfo.append_byte(BIND_OPCODE_DONE); _bindingInfo.align(_is64 ? 8 : 4); } void MachOFileLayout::buildLazyBindInfo() { for (const BindLocation& entry : _file.lazyBindingInfo) { _lazyBindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind); - _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | entry.segIndex); _lazyBindingInfo.append_uleb128(entry.segOffset); _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal); @@ -882,17 +882,17 @@ void MachOFileLayout::buildLazyBindInfo() { _lazyBindingInfo.append_string(entry.symbolName); _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND); } - _lazyBindingInfo.append_byte(BIND_OPCODE_DONE); + _lazyBindingInfo.append_byte(BIND_OPCODE_DONE); _lazyBindingInfo.align(_is64 ? 8 : 4); } void MachOFileLayout::computeSymbolTableSizes() { // MachO symbol tables have three ranges: locals, globals, and undefines const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist)); - _symbolTableSize = nlistSize * (_file.localSymbols.size() + _symbolTableSize = nlistSize * (_file.localSymbols.size() + _file.globalSymbols.size() + _file.undefinedSymbols.size()); - _symbolStringPoolSize = 0; + _symbolStringPoolSize = 0; for (const Symbol &sym : _file.localSymbols) { _symbolStringPoolSize += (sym.name.size()+1); } @@ -904,7 +904,7 @@ void MachOFileLayout::computeSymbolTableSizes() { } _symbolTableLocalsStartIndex = 0; _symbolTableGlobalsStartIndex = _file.localSymbols.size(); - _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex + _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex + _file.globalSymbols.size(); _indirectSymbolTableCount = 0; @@ -941,7 +941,7 @@ error_code MachOFileLayout::writeBinary(StringRef path) { ec = llvm::FileOutputBuffer::create(path, size(), fob, flags); if (ec) return ec; - + // Write content. _buffer = fob->getBufferStart(); writeMachHeader(); @@ -958,7 +958,7 @@ error_code MachOFileLayout::writeBinary(StringRef path) { /// Takes in-memory normalized view and writes a mach-o object file. -error_code +error_code writeBinary(const NormalizedFile &file, StringRef path) { MachOFileLayout layout(file); return layout.writeBinary(path); |