summaryrefslogtreecommitdiffstats
path: root/llvm/tools/yaml2obj/yaml2macho.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/yaml2obj/yaml2macho.cpp')
-rw-r--r--llvm/tools/yaml2obj/yaml2macho.cpp126
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();
}
OpenPOWER on IntegriCloud