summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorChris Bieneman <beanz@apple.com>2016-06-24 20:42:28 +0000
committerChris Bieneman <beanz@apple.com>2016-06-24 20:42:28 +0000
commit93e711938050e35f5275a1b36fae25226c25fc63 (patch)
tree92e6e7e0739f0c986b8d7c821aa0b374ce1a0f0c /llvm/tools
parent2e6d2d48205f272c39a50ae93ae4c700888e11e3 (diff)
downloadbcm5719-llvm-93e711938050e35f5275a1b36fae25226c25fc63.tar.gz
bcm5719-llvm-93e711938050e35f5275a1b36fae25226c25fc63.zip
[obj2yaml] [yaml2obj] Support for MachO Universal binaries
This patch adds round-trip support for MachO Universal binaries to obj2yaml and yaml2obj. Universal binaries have a header and list of architecture structures, followed by a the individual object files at specified offsets. llvm-svn: 273719
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/obj2yaml/macho2yaml.cpp39
-rw-r--r--llvm/tools/obj2yaml/obj2yaml.cpp6
-rw-r--r--llvm/tools/obj2yaml/obj2yaml.h2
-rw-r--r--llvm/tools/yaml2obj/yaml2macho.cpp107
4 files changed, 144 insertions, 10 deletions
diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index 24bd6a60da4..060a2b82726 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -473,23 +473,52 @@ Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) {
}
Error macho2yaml(raw_ostream &Out, const object::MachOUniversalBinary &Obj) {
- return make_error<Obj2YamlError>(obj2yaml_error::not_implemented);
+ MachOYAML::MachFile YAMLFile;
+ YAMLFile.isFat = true;
+ MachOYAML::UniversalBinary &YAML = YAMLFile.FatFile;
+ YAML.Header.magic = Obj.getMagic();
+ YAML.Header.nfat_arch = Obj.getNumberOfObjects();
+
+ for (auto Slice : Obj.objects()) {
+ MachOYAML::FatArch arch;
+ arch.cputype = Slice.getCPUType();
+ arch.cpusubtype = Slice.getCPUSubType();
+ arch.offset = Slice.getOffset();
+ arch.size = Slice.getSize();
+ arch.align = Slice.getAlign();
+ arch.reserved = Slice.getReserved();
+ YAML.FatArchs.push_back(arch);
+
+ auto SliceObj = Slice.getAsObjectFile();
+ if (!SliceObj)
+ return SliceObj.takeError();
+
+ MachODumper Dumper(*SliceObj.get());
+ Expected<std::unique_ptr<MachOYAML::Object>> YAMLObj = Dumper.dump();
+ if (!YAMLObj)
+ return YAMLObj.takeError();
+ YAML.Slices.push_back(*YAMLObj.get());
+ }
+
+ yaml::Output Yout(Out);
+ Yout << YAML;
+ return Error::success();
}
-std::error_code macho2yaml(raw_ostream &Out, const object::ObjectFile &Obj) {
- if (const auto *MachOObj = dyn_cast<object::MachOUniversalBinary>(&Obj)) {
+std::error_code macho2yaml(raw_ostream &Out, const object::Binary &Binary) {
+ if (const auto *MachOObj = dyn_cast<object::MachOUniversalBinary>(&Binary)) {
if (auto Err = macho2yaml(Out, *MachOObj)) {
return errorToErrorCode(std::move(Err));
}
return obj2yaml_error::success;
}
- if (const auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj)) {
+ if (const auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Binary)) {
if (auto Err = macho2yaml(Out, *MachOObj)) {
return errorToErrorCode(std::move(Err));
}
return obj2yaml_error::success;
}
-
+
return obj2yaml_error::unsupported_obj_file_format;
}
diff --git a/llvm/tools/obj2yaml/obj2yaml.cpp b/llvm/tools/obj2yaml/obj2yaml.cpp
index e243f2d843a..3f9373ee17e 100644
--- a/llvm/tools/obj2yaml/obj2yaml.cpp
+++ b/llvm/tools/obj2yaml/obj2yaml.cpp
@@ -24,8 +24,6 @@ static std::error_code dumpObject(const ObjectFile &Obj) {
return coff2yaml(outs(), cast<COFFObjectFile>(Obj));
if (Obj.isELF())
return elf2yaml(outs(), Obj);
- if (Obj.isMachO() || Obj.isMachOUniversalBinary())
- return macho2yaml(outs(), Obj);
return obj2yaml_error::unsupported_obj_file_format;
}
@@ -36,6 +34,10 @@ static std::error_code dumpInput(StringRef File) {
return errorToErrorCode(BinaryOrErr.takeError());
Binary &Binary = *BinaryOrErr.get().getBinary();
+ // Universal MachO is not a subclass of ObjectFile, so it needs to be handled
+ // here with the other binary types.
+ if (Binary.isMachO() || Binary.isMachOUniversalBinary())
+ return macho2yaml(outs(), Binary);
// TODO: If this is an archive, then burst it and dump each entry
if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
return dumpObject(*Obj);
diff --git a/llvm/tools/obj2yaml/obj2yaml.h b/llvm/tools/obj2yaml/obj2yaml.h
index c17b7d1642c..28c74751c0d 100644
--- a/llvm/tools/obj2yaml/obj2yaml.h
+++ b/llvm/tools/obj2yaml/obj2yaml.h
@@ -22,6 +22,6 @@ std::error_code coff2yaml(llvm::raw_ostream &Out,
std::error_code elf2yaml(llvm::raw_ostream &Out,
const llvm::object::ObjectFile &Obj);
std::error_code macho2yaml(llvm::raw_ostream &Out,
- const llvm::object::ObjectFile &Obj);
+ const llvm::object::Binary &Obj);
#endif
diff --git a/llvm/tools/yaml2obj/yaml2macho.cpp b/llvm/tools/yaml2obj/yaml2macho.cpp
index 7821e63cf88..3d8be965209 100644
--- a/llvm/tools/yaml2obj/yaml2macho.cpp
+++ b/llvm/tools/yaml2obj/yaml2macho.cpp
@@ -424,17 +424,120 @@ Error MachOWriter::writeStringTable(raw_ostream &OS) {
return Error::success();
}
+class UniversalWriter {
+public:
+ UniversalWriter(MachOYAML::MachFile &MachFile)
+ : MachFile(MachFile), fileStart(0) {}
+
+ Error writeMachO(raw_ostream &OS);
+
+private:
+ Error writeFatHeader(raw_ostream &OS);
+ Error writeFatArchs(raw_ostream &OS);
+
+ void ZeroToOffset(raw_ostream &OS, size_t offset);
+
+ MachOYAML::MachFile &MachFile;
+ uint64_t fileStart;
+};
+
+Error UniversalWriter::writeMachO(raw_ostream &OS) {
+ fileStart = OS.tell();
+ if (!MachFile.isFat) {
+ MachOWriter Writer(MachFile.ThinFile);
+ return Writer.writeMachO(OS);
+ }
+ if (auto Err = writeFatHeader(OS))
+ return Err;
+ if (auto Err = writeFatArchs(OS))
+ return Err;
+ auto &FatFile = MachFile.FatFile;
+ assert(FatFile.FatArchs.size() == FatFile.Slices.size());
+ for (size_t i = 0; i < FatFile.Slices.size(); i++) {
+ ZeroToOffset(OS, FatFile.FatArchs[i].offset);
+ MachOWriter Writer(FatFile.Slices[i]);
+ if (auto Err = Writer.writeMachO(OS))
+ return Err;
+ auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
+ ZeroToOffset(OS, SliceEnd);
+ }
+ return Error::success();
+}
+
+Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
+ auto &FatFile = MachFile.FatFile;
+ MachO::fat_header header;
+ header.magic = FatFile.Header.magic;
+ header.nfat_arch = FatFile.Header.nfat_arch;
+ if (sys::IsLittleEndianHost)
+ swapStruct(header);
+ OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
+ return Error::success();
+}
+
+template <typename FatArchType>
+FatArchType constructFatArch(MachOYAML::FatArch &Arch) {
+ FatArchType FatArch;
+ FatArch.cputype = Arch.cputype;
+ FatArch.cpusubtype = Arch.cpusubtype;
+ FatArch.offset = Arch.offset;
+ FatArch.size = Arch.size;
+ FatArch.align = Arch.align;
+ return FatArch;
+}
+
+template <typename StructType>
+void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {}
+
+template <>
+void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) {
+ auto FatArch = constructFatArch<MachO::fat_arch>(Arch);
+ if (sys::IsLittleEndianHost)
+ swapStruct(FatArch);
+ OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch));
+}
+
+template <>
+void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
+ raw_ostream &OS) {
+ auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch);
+ FatArch.reserved = Arch.reserved;
+ if (sys::IsLittleEndianHost)
+ swapStruct(FatArch);
+ OS.write(reinterpret_cast<const char *>(&FatArch),
+ sizeof(MachO::fat_arch_64));
+}
+
+Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
+ auto &FatFile = MachFile.FatFile;
+ bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
+ for (auto Arch : FatFile.FatArchs) {
+ if (is64Bit)
+ writeFatArch<MachO::fat_arch_64>(Arch, OS);
+ else
+ writeFatArch<MachO::fat_arch>(Arch, OS);
+ }
+
+ return Error::success();
+}
+
+void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
+ auto currOffset = OS.tell() - fileStart;
+ if (currOffset < Offset)
+ ZeroFillBytes(OS, Offset - currOffset);
+}
+
} // end anonymous namespace
int yaml2macho(yaml::Input &YIn, raw_ostream &Out) {
- MachOYAML::Object Doc;
+ MachOYAML::MachFile Doc;
YIn >> Doc;
if (YIn.error()) {
errs() << "yaml2obj: Failed to parse YAML file!\n";
return 1;
}
- MachOWriter Writer(Doc);
+ UniversalWriter Writer(Doc);
if (auto Err = Writer.writeMachO(Out)) {
errs() << toString(std::move(Err));
return 1;
OpenPOWER on IntegriCloud