diff options
Diffstat (limited to 'llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp index 56dd08df3b09..295098ed4118 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp @@ -16,9 +16,8 @@ #include "llvm/Support/ErrorHandling.h" #include <memory> -namespace llvm { -namespace objcopy { -namespace macho { +using namespace llvm; +using namespace llvm::objcopy::macho; size_t MachOWriter::headerSize() const { return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); @@ -108,6 +107,16 @@ size_t MachOWriter::totalSize() const { LinkEditDataCommand.datasize); } + if (O.LinkerOptimizationHintCommandIndex) { + const MachO::linkedit_data_command &LinkEditDataCommand = + O.LoadCommands[*O.LinkerOptimizationHintCommandIndex] + .MachOLoadCommand.linkedit_data_command_data; + + if (LinkEditDataCommand.dataoff) + Ends.push_back(LinkEditDataCommand.dataoff + + LinkEditDataCommand.datasize); + } + if (O.FunctionStartsCommandIndex) { const MachO::linkedit_data_command &LinkEditDataCommand = O.LoadCommands[*O.FunctionStartsCommandIndex] @@ -159,11 +168,12 @@ void MachOWriter::writeHeader() { auto HeaderSize = Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); - memcpy(B.getBufferStart(), &Header, HeaderSize); + memcpy(Buf->getBufferStart(), &Header, HeaderSize); } void MachOWriter::writeLoadCommands() { - uint8_t *Begin = B.getBufferStart() + headerSize(); + uint8_t *Begin = + reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + headerSize(); for (const LoadCommand &LC : O.LoadCommands) { // Construct a load command. MachO::macho_load_command MLC = LC.MachOLoadCommand; @@ -257,11 +267,11 @@ void MachOWriter::writeSections() { assert(Sec->Offset && "Section offset can not be zero"); assert((Sec->Size == Sec->Content.size()) && "Incorrect section size"); - memcpy(B.getBufferStart() + Sec->Offset, Sec->Content.data(), + memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(), Sec->Content.size()); for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) { RelocationInfo RelocInfo = Sec->Relocations[Index]; - if (!RelocInfo.Scattered) { + if (!RelocInfo.Scattered && !RelocInfo.IsAddend) { const uint32_t SymbolNum = RelocInfo.Extern ? (*RelocInfo.Symbol)->Index : (*RelocInfo.Sec)->Index; @@ -270,7 +280,7 @@ void MachOWriter::writeSections() { if (IsLittleEndian != sys::IsLittleEndianHost) MachO::swapStruct( reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info)); - memcpy(B.getBufferStart() + Sec->RelOff + + memcpy(Buf->getBufferStart() + Sec->RelOff + Index * sizeof(MachO::any_relocation_info), &RelocInfo.Info, sizeof(RelocInfo.Info)); } @@ -300,7 +310,7 @@ void MachOWriter::writeStringTable() { O.LoadCommands[*O.SymTabCommandIndex] .MachOLoadCommand.symtab_command_data; - uint8_t *StrTable = (uint8_t *)B.getBufferStart() + SymTabCommand.stroff; + uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.stroff; LayoutBuilder.getStringTableBuilder().write(StrTable); } @@ -311,7 +321,7 @@ void MachOWriter::writeSymbolTable() { O.LoadCommands[*O.SymTabCommandIndex] .MachOLoadCommand.symtab_command_data; - char *SymTable = (char *)B.getBufferStart() + SymTabCommand.symoff; + char *SymTable = (char *)Buf->getBufferStart() + SymTabCommand.symoff; for (auto Iter = O.SymTable.Symbols.begin(), End = O.SymTable.Symbols.end(); Iter != End; Iter++) { SymbolEntry *Sym = Iter->get(); @@ -330,7 +340,7 @@ void MachOWriter::writeRebaseInfo() { const MachO::dyld_info_command &DyLdInfoCommand = O.LoadCommands[*O.DyLdInfoCommandIndex] .MachOLoadCommand.dyld_info_command_data; - char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.rebase_off; + char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.rebase_off; assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) && "Incorrect rebase opcodes size"); memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size()); @@ -342,7 +352,7 @@ void MachOWriter::writeBindInfo() { const MachO::dyld_info_command &DyLdInfoCommand = O.LoadCommands[*O.DyLdInfoCommandIndex] .MachOLoadCommand.dyld_info_command_data; - char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.bind_off; + char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.bind_off; assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) && "Incorrect bind opcodes size"); memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size()); @@ -354,7 +364,7 @@ void MachOWriter::writeWeakBindInfo() { const MachO::dyld_info_command &DyLdInfoCommand = O.LoadCommands[*O.DyLdInfoCommandIndex] .MachOLoadCommand.dyld_info_command_data; - char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.weak_bind_off; + char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.weak_bind_off; assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) && "Incorrect weak bind opcodes size"); memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size()); @@ -366,7 +376,7 @@ void MachOWriter::writeLazyBindInfo() { const MachO::dyld_info_command &DyLdInfoCommand = O.LoadCommands[*O.DyLdInfoCommandIndex] .MachOLoadCommand.dyld_info_command_data; - char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.lazy_bind_off; + char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.lazy_bind_off; assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) && "Incorrect lazy bind opcodes size"); memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size()); @@ -378,7 +388,7 @@ void MachOWriter::writeExportInfo() { const MachO::dyld_info_command &DyLdInfoCommand = O.LoadCommands[*O.DyLdInfoCommandIndex] .MachOLoadCommand.dyld_info_command_data; - char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.export_off; + char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.export_off; assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) && "Incorrect export trie size"); memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size()); @@ -393,7 +403,7 @@ void MachOWriter::writeIndirectSymbolTable() { .MachOLoadCommand.dysymtab_command_data; uint32_t *Out = - (uint32_t *)(B.getBufferStart() + DySymTabCommand.indirectsymoff); + (uint32_t *)(Buf->getBufferStart() + DySymTabCommand.indirectsymoff); for (const IndirectSymbolEntry &Sym : O.IndirectSymTable.Symbols) { uint32_t Entry = (Sym.Symbol) ? (*Sym.Symbol)->Index : Sym.OriginalIndex; if (IsLittleEndian != sys::IsLittleEndianHost) @@ -407,7 +417,7 @@ void MachOWriter::writeLinkData(Optional<size_t> LCIndex, const LinkData &LD) { return; const MachO::linkedit_data_command &LinkEditDataCommand = O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data; - char *Out = (char *)B.getBufferStart() + LinkEditDataCommand.dataoff; + char *Out = (char *)Buf->getBufferStart() + LinkEditDataCommand.dataoff; assert((LinkEditDataCommand.datasize == LD.Data.size()) && "Incorrect data size"); memcpy(Out, LD.Data.data(), LD.Data.size()); @@ -421,6 +431,11 @@ void MachOWriter::writeDataInCodeData() { return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode); } +void MachOWriter::writeLinkerOptimizationHint() { + return writeLinkData(O.LinkerOptimizationHintCommandIndex, + O.LinkerOptimizationHint); +} + void MachOWriter::writeFunctionStartsData() { return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts); } @@ -490,6 +505,16 @@ void MachOWriter::writeTail() { &MachOWriter::writeDataInCodeData); } + if (O.LinkerOptimizationHintCommandIndex) { + const MachO::linkedit_data_command &LinkEditDataCommand = + O.LoadCommands[*O.LinkerOptimizationHintCommandIndex] + .MachOLoadCommand.linkedit_data_command_data; + + if (LinkEditDataCommand.dataoff) + Queue.emplace_back(LinkEditDataCommand.dataoff, + &MachOWriter::writeLinkerOptimizationHint); + } + if (O.FunctionStartsCommandIndex) { const MachO::linkedit_data_command &LinkEditDataCommand = O.LoadCommands[*O.FunctionStartsCommandIndex] @@ -511,16 +536,20 @@ void MachOWriter::writeTail() { Error MachOWriter::finalize() { return LayoutBuilder.layout(); } Error MachOWriter::write() { - if (Error E = B.allocate(totalSize())) - return E; - memset(B.getBufferStart(), 0, totalSize()); + size_t TotalSize = totalSize(); + Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); + if (!Buf) + return createStringError(errc::not_enough_memory, + "failed to allocate memory buffer of " + + Twine::utohexstr(TotalSize) + " bytes"); + memset(Buf->getBufferStart(), 0, totalSize()); writeHeader(); writeLoadCommands(); writeSections(); writeTail(); - return B.commit(); -} -} // end namespace macho -} // end namespace objcopy -} // end namespace llvm + // TODO: Implement direct writing to the output stream (without intermediate + // memory buffer Buf). + Out.write(Buf->getBufferStart(), Buf->getBufferSize()); + return Error::success(); +} |