diff options
Diffstat (limited to 'llvm/tools/yaml2obj/yaml2macho.cpp')
-rw-r--r-- | llvm/tools/yaml2obj/yaml2macho.cpp | 126 |
1 files changed, 66 insertions, 60 deletions
diff --git a/llvm/tools/yaml2obj/yaml2macho.cpp b/llvm/tools/yaml2obj/yaml2macho.cpp index 3fdf3cf43bd..a68d8803772 100644 --- a/llvm/tools/yaml2obj/yaml2macho.cpp +++ b/llvm/tools/yaml2obj/yaml2macho.cpp @@ -41,8 +41,7 @@ private: Error writeLoadCommands(raw_ostream &OS); Error writeSectionData(raw_ostream &OS); Error writeLinkEditData(raw_ostream &OS); - Error writeDWARFData(raw_ostream &OS, - std::vector<MachOYAML::Section> &Sections); + void writeBindOpcodes(raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes); // LinkEdit writers @@ -85,6 +84,9 @@ Error MachOWriter::writeHeader(raw_ostream &OS) { Header.flags = Obj.Header.flags; Header.reserved = Obj.Header.reserved; + if (Obj.IsLittleEndian != sys::IsLittleEndianHost) + MachO::swapStruct(Header); + auto header_size = is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); OS.write((const char *)&Header, header_size); @@ -110,16 +112,20 @@ SectionType constructSection(MachOYAML::Section Sec) { } template <typename StructType> -size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS) { +size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS, + bool IsLittleEndian) { return 0; } template <> size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC, - raw_ostream &OS) { + raw_ostream &OS, + bool IsLittleEndian) { size_t BytesWritten = 0; for (const auto &Sec : LC.Sections) { auto TempSec = constructSection<MachO::section>(Sec); + if (IsLittleEndian != sys::IsLittleEndianHost) + MachO::swapStruct(TempSec); OS.write(reinterpret_cast<const char *>(&(TempSec)), sizeof(MachO::section)); BytesWritten += sizeof(MachO::section); @@ -128,13 +134,14 @@ size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC, } template <> -size_t -writeLoadCommandData<MachO::segment_command_64>(MachOYAML::LoadCommand &LC, - raw_ostream &OS) { +size_t writeLoadCommandData<MachO::segment_command_64>( + MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) { size_t BytesWritten = 0; for (const auto &Sec : LC.Sections) { auto TempSec = constructSection<MachO::section_64>(Sec); TempSec.reserved3 = Sec.reserved3; + if (IsLittleEndian != sys::IsLittleEndianHost) + MachO::swapStruct(TempSec); OS.write(reinterpret_cast<const char *>(&(TempSec)), sizeof(MachO::section_64)); BytesWritten += sizeof(MachO::section_64); @@ -153,19 +160,22 @@ size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) { template <> size_t writeLoadCommandData<MachO::dylib_command>(MachOYAML::LoadCommand &LC, - raw_ostream &OS) { + raw_ostream &OS, + bool IsLittleEndian) { return writePayloadString(LC, OS); } template <> size_t writeLoadCommandData<MachO::dylinker_command>(MachOYAML::LoadCommand &LC, - raw_ostream &OS) { + raw_ostream &OS, + bool IsLittleEndian) { return writePayloadString(LC, OS); } template <> size_t writeLoadCommandData<MachO::rpath_command>(MachOYAML::LoadCommand &LC, - raw_ostream &OS) { + raw_ostream &OS, + bool IsLittleEndian) { return writePayloadString(LC, OS); } @@ -190,20 +200,28 @@ void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) { Error MachOWriter::writeLoadCommands(raw_ostream &OS) { for (auto &LC : Obj.LoadCommands) { size_t BytesWritten = 0; + llvm::MachO::macho_load_command Data = LC.Data; + #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ case MachO::LCName: \ - OS.write(reinterpret_cast<const char *>(&(LC.Data.LCStruct##_data)), \ + if (Obj.IsLittleEndian != sys::IsLittleEndianHost) \ + MachO::swapStruct(Data.LCStruct##_data); \ + OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)), \ sizeof(MachO::LCStruct)); \ BytesWritten = sizeof(MachO::LCStruct); \ - BytesWritten += writeLoadCommandData<MachO::LCStruct>(LC, OS); \ + BytesWritten += \ + writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian); \ break; switch (LC.Data.load_command_data.cmd) { default: - OS.write(reinterpret_cast<const char *>(&(LC.Data.load_command_data)), + if (Obj.IsLittleEndian != sys::IsLittleEndianHost) + MachO::swapStruct(Data.load_command_data); + OS.write(reinterpret_cast<const char *>(&(Data.load_command_data)), sizeof(MachO::load_command)); BytesWritten = sizeof(MachO::load_command); - BytesWritten += writeLoadCommandData<MachO::load_command>(LC, OS); + BytesWritten += + writeLoadCommandData<MachO::load_command>(LC, OS, Obj.IsLittleEndian); break; #include "llvm/Support/MachO.def" } @@ -230,41 +248,38 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) { } Error MachOWriter::writeSectionData(raw_ostream &OS) { + bool FoundLinkEditSeg = false; for (auto &LC : Obj.LoadCommands) { 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; - - if (0 == strncmp(&segname[0], "__LINKEDIT", 16)) { + if (0 == strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) { + FoundLinkEditSeg = true; if (auto Err = writeLinkEditData(OS)) return Err; - } else if (0 == strncmp(&segname[0], "__DWARF", 16)) { - if (auto Err = writeDWARFData(OS, LC.Sections)) - return Err; - } else { + } + for (auto &Sec : LC.Sections) { + ZeroToOffset(OS, Sec.offset); // Zero Fill any data between the end of the last thing we wrote and the // start of this section. - if (currOffset < segOff) { - ZeroFillBytes(OS, segOff - currOffset); - } - - 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 || - Sec.offset == (uint32_t)0) && - "Wrote too much data somewhere, section offsets don't line up."); - currOffset = OS.tell() - fileStart; - if (currOffset < Sec.offset) { - ZeroFillBytes(OS, Sec.offset - currOffset); + assert((OS.tell() - fileStart <= Sec.offset || + Sec.offset == (uint32_t)0) && + "Wrote too much data somewhere, section offsets don't line up."); + if (0 == strncmp(&Sec.segname[0], "__DWARF", 16)) { + if (0 == strncmp(&Sec.sectname[0], "__debug_str", 16)) { + yaml2debug_str(OS, Obj.DWARF); + } else if (0 == strncmp(&Sec.sectname[0], "__debug_abbrev", 16)) { + yaml2debug_abbrev(OS, Obj.DWARF); + } else if (0 == strncmp(&Sec.sectname[0], "__debug_aranges", 16)) { + yaml2debug_aranges(OS, Obj.DWARF); + } else if (0 == strncmp(&Sec.sectname[0], "__debug_pubnames", 16)) { + yaml2pubsection(OS, Obj.DWARF.PubNames, Obj.IsLittleEndian); + } else if (0 == strncmp(&Sec.sectname[0], "__debug_pubtypes", 16)) { + yaml2pubsection(OS, Obj.DWARF.PubTypes, Obj.IsLittleEndian); } - + } else { // Fills section data with 0xDEADBEEF Fill(OS, Sec.size, 0xDEADBEEFu); } @@ -275,6 +290,12 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) { break; } } + // Old PPC Object Files didn't have __LINKEDIT segments, the data was just + // stuck at the end of the file. + if (!FoundLinkEditSeg) { + if (auto Err = writeLinkEditData(OS)) + return Err; + } return Error::success(); } @@ -328,13 +349,17 @@ Error MachOWriter::writeExportTrie(raw_ostream &OS) { } template <typename NListType> -void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS) { +void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS, + bool IsLittleEndian) { NListType ListEntry; ListEntry.n_strx = NLE.n_strx; ListEntry.n_type = NLE.n_type; ListEntry.n_sect = NLE.n_sect; ListEntry.n_desc = NLE.n_desc; ListEntry.n_value = NLE.n_value; + + if (sys::IsBigEndianHost) + MachO::swapStruct(ListEntry); OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType)); } @@ -384,25 +409,6 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) { return Error::success(); } -Error MachOWriter::writeDWARFData(raw_ostream &OS, - std::vector<MachOYAML::Section> &Sections) { - for (auto Section : Sections) { - ZeroToOffset(OS, Section.offset); - if (0 == strncmp(&Section.sectname[0], "__debug_str", 16)) { - yaml2debug_str(OS, Obj.DWARF); - } else if (0 == strncmp(&Section.sectname[0], "__debug_abbrev", 16)) { - yaml2debug_abbrev(OS, Obj.DWARF); - } else if (0 == strncmp(&Section.sectname[0], "__debug_aranges", 16)) { - yaml2debug_aranges(OS, Obj.DWARF); - } else if (0 == strncmp(&Section.sectname[0], "__debug_pubnames", 16)) { - yaml2pubsection(OS, Obj.DWARF.PubNames); - } else if (0 == strncmp(&Section.sectname[0], "__debug_pubtypes", 16)) { - yaml2pubsection(OS, Obj.DWARF.PubTypes); - } - } - return Error::success(); -} - Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) { MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit; @@ -434,9 +440,9 @@ Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) { Error MachOWriter::writeNameList(raw_ostream &OS) { for (auto NLE : Obj.LinkEdit.NameList) { if (is64Bit) - writeNListEntry<MachO::nlist_64>(NLE, OS); + writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian); else - writeNListEntry<MachO::nlist>(NLE, OS); + writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian); } return Error::success(); } |