summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp')
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp142
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 &sect,
+uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
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);
OpenPOWER on IntegriCloud