diff options
Diffstat (limited to 'llvm/tools/yaml2obj/yaml2macho.cpp')
-rw-r--r-- | llvm/tools/yaml2obj/yaml2macho.cpp | 87 |
1 files changed, 67 insertions, 20 deletions
diff --git a/llvm/tools/yaml2obj/yaml2macho.cpp b/llvm/tools/yaml2obj/yaml2macho.cpp index 749090e7cfa..d24a08c6e54 100644 --- a/llvm/tools/yaml2obj/yaml2macho.cpp +++ b/llvm/tools/yaml2obj/yaml2macho.cpp @@ -15,10 +15,13 @@ #include "yaml2obj.h" #include "llvm/ObjectYAML/MachOYAML.h" #include "llvm/Support/Error.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MachO.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" + using namespace llvm; namespace { @@ -42,6 +45,9 @@ private: Error writeHeader(raw_ostream &OS); Error writeLoadCommands(raw_ostream &OS); Error writeSectionData(raw_ostream &OS); + Error writeLinkEditData(raw_ostream &OS); + + void ZeroToOffset(raw_ostream &OS, size_t offset); MachOYAML::Object &Obj; bool is64Bit; @@ -165,6 +171,12 @@ void Fill(raw_ostream &OS, size_t Size, uint32_t Data) { OS.write(reinterpret_cast<char *>(FillData.data()), Size); } +void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) { + auto currOffset = OS.tell() - fileStart; + if (currOffset < Offset) + ZeroFillBytes(OS, Offset - currOffset); +} + Error MachOWriter::writeLoadCommands(raw_ostream &OS) { for (auto &LC : Obj.LoadCommands) { size_t BytesWritten = 0; @@ -212,42 +224,77 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) { switch (LC.Data.load_command_data.cmd) { case MachO::LC_SEGMENT: case MachO::LC_SEGMENT_64: + auto currOffset = OS.tell() - fileStart; + auto segname = LC.Data.segment_command_data.segname; uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff : LC.Data.segment_command_data.fileoff; - // Zero Fill any data between the end of the last thing we wrote and the - // start of this section. - auto currOffset = OS.tell() - fileStart; - if (currOffset < segOff) { - ZeroFillBytes(OS, segOff - currOffset); - } - - for (auto &Sec : LC.Sections) { + if (0 == strncmp(&segname[0], "__LINKEDIT", 16)) { + if (auto Err = writeLinkEditData(OS)) + return Err; + } else { // Zero Fill any data between the end of the last thing we wrote and the // start of this section. - assert(OS.tell() - fileStart <= Sec.offset && - "Wrote too much data somewhere, section offsets don't line up."); - currOffset = OS.tell() - fileStart; - if (currOffset < Sec.offset) { - ZeroFillBytes(OS, Sec.offset - currOffset); + if (currOffset < segOff) { + ZeroFillBytes(OS, segOff - currOffset); } - // Fills section data with 0xDEADBEEF - Fill(OS, Sec.size, 0xDEADBEEFu); + for (auto &Sec : LC.Sections) { + // Zero Fill any data between the end of the last thing we wrote and + // the + // start of this section. + assert( + OS.tell() - fileStart <= Sec.offset && + "Wrote too much data somewhere, section offsets don't line up."); + currOffset = OS.tell() - fileStart; + if (currOffset < Sec.offset) { + ZeroFillBytes(OS, Sec.offset - currOffset); + } + + // Fills section data with 0xDEADBEEF + Fill(OS, Sec.size, 0xDEADBEEFu); + } } uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize : LC.Data.segment_command_data.filesize; - currOffset = OS.tell() - fileStart; - if (currOffset < segOff + segSize) { - // Fills segment data not covered by a section with 0xBAADDA7A - Fill(OS, (segOff + segSize) - currOffset, 0xBAADDA7Au); - } + ZeroToOffset(OS, segOff + segSize); break; } } return Error::success(); } +Error MachOWriter::writeLinkEditData(raw_ostream &OS) { + MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit; + MachO::dyld_info_command *DyldInfoOnlyCmd = 0; + MachO::symtab_command *SymtabCmd = 0; + for (auto &LC : Obj.LoadCommands) { + switch (LC.Data.load_command_data.cmd) { + case MachO::LC_SYMTAB: + SymtabCmd = &LC.Data.symtab_command_data; + break; + case MachO::LC_DYLD_INFO_ONLY: + DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data; + break; + } + } + + ZeroToOffset(OS, DyldInfoOnlyCmd->rebase_off); + + for (auto Opcode : LinkEdit.RebaseOpcodes) { + uint8_t OpByte = Opcode.Opcode | Opcode.Imm; + OS.write(reinterpret_cast<char *>(&OpByte), 1); + for (auto Data : Opcode.ExtraData) { + encodeULEB128(Data, OS); + } + } + + // Fill to the end of the string table + ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize); + + return Error::success(); +} + } // end anonymous namespace int yaml2macho(yaml::Input &YIn, raw_ostream &Out) { |