diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h index 00d7ab2d377..bfc6dcb4028 100644 --- a/include/llvm/ObjectYAML/MachOYAML.h +++ b/include/llvm/ObjectYAML/MachOYAML.h @@ -33,12 +33,23 @@ struct FileHeader { llvm::yaml::Hex32 reserved; }; +struct LoadCommand { + virtual ~LoadCommand(); + MachO::LoadCommandType cmd; + uint32_t cmdsize; +}; + struct Object { FileHeader Header; + std::vector> LoadCommands; }; } // namespace llvm::MachOYAML +} // namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) + +namespace llvm { namespace yaml { template <> struct MappingTraits { @@ -49,6 +60,22 @@ template <> struct MappingTraits { static void mapping(IO &IO, MachOYAML::Object &Object); }; +template <> struct MappingTraits> { + static void mapping(IO &IO, + std::unique_ptr &LoadCommand); +}; + +#define HANDLE_LOAD_COMMAND(LoadCommandName, LoadCommandValue) \ + io.enumCase(value, #LoadCommandName, MachO::LoadCommandName); + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, MachO::LoadCommandType &value) { +#include "llvm/Support/MachO.def" + } +}; + +#undef HANDLE_LOAD_COMMAND + } // namespace llvm::yaml } // namespace llvm diff --git a/lib/ObjectYAML/MachOYAML.cpp b/lib/ObjectYAML/MachOYAML.cpp index d54140b6794..af80c1645a6 100644 --- a/lib/ObjectYAML/MachOYAML.cpp +++ b/lib/ObjectYAML/MachOYAML.cpp @@ -16,6 +16,8 @@ namespace llvm { +MachOYAML::LoadCommand::~LoadCommand() {} + namespace yaml { void MappingTraits::mapping( @@ -40,9 +42,18 @@ void MappingTraits::mapping(IO &IO, IO.mapTag("!mach-o", true); } IO.mapRequired("FileHeader", Object.Header); + IO.mapOptional("LoadCommands", Object.LoadCommands); IO.setContext(nullptr); } +void MappingTraits>::mapping( + IO &IO, std::unique_ptr &LoadCommand) { + if (!IO.outputting()) + LoadCommand.reset(new MachOYAML::LoadCommand()); + IO.mapRequired("cmd", LoadCommand->cmd); + IO.mapRequired("cmdsize", LoadCommand->cmdsize); +} + } // namespace llvm::yaml } // namespace llvm diff --git a/test/ObjectYAML/MachO/load_commands.yaml b/test/ObjectYAML/MachO/load_commands.yaml new file mode 100644 index 00000000000..246759da2cc --- /dev/null +++ b/test/ObjectYAML/MachO/load_commands.yaml @@ -0,0 +1,81 @@ +# RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x80000003 + filetype: 0x00000002 + ncmds: 16 + sizeofcmds: 1408 + flags: 0x00218085 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 72 + - cmd: LC_SEGMENT_64 + cmdsize: 552 + - cmd: LC_SEGMENT_64 + cmdsize: 312 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + - cmd: LC_DYSYMTAB + cmdsize: 80 + - cmd: LC_LOAD_DYLINKER + cmdsize: 32 + - cmd: LC_UUID + cmdsize: 24 + - cmd: LC_VERSION_MIN_MACOSX + cmdsize: 16 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + - cmd: LC_MAIN + cmdsize: 24 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 +... + + +# CHECK: LoadCommands: +# CHECK: - cmd: LC_SEGMENT_64 +# CHECK: cmdsize: 72 +# CHECK: - cmd: LC_SEGMENT_64 +# CHECK: cmdsize: 552 +# CHECK: - cmd: LC_SEGMENT_64 +# CHECK: cmdsize: 312 +# CHECK: - cmd: LC_SEGMENT_64 +# CHECK: cmdsize: 72 +# CHECK: - cmd: LC_DYLD_INFO_ONLY +# CHECK: cmdsize: 48 +# CHECK: - cmd: LC_SYMTAB +# CHECK: cmdsize: 24 +# CHECK: - cmd: LC_DYSYMTAB +# CHECK: cmdsize: 80 +# CHECK: - cmd: LC_LOAD_DYLINKER +# CHECK: cmdsize: 32 +# CHECK: - cmd: LC_UUID +# CHECK: cmdsize: 24 +# CHECK: - cmd: LC_VERSION_MIN_MACOSX +# CHECK: cmdsize: 16 +# CHECK: - cmd: LC_SOURCE_VERSION +# CHECK: cmdsize: 16 +# CHECK: - cmd: LC_MAIN +# CHECK: cmdsize: 24 +# CHECK: - cmd: LC_LOAD_DYLIB +# CHECK: cmdsize: 48 +# CHECK: - cmd: LC_LOAD_DYLIB +# CHECK: cmdsize: 56 +# CHECK: - cmd: LC_FUNCTION_STARTS +# CHECK: cmdsize: 16 +# CHECK: - cmd: LC_DATA_IN_CODE +# CHECK: cmdsize: 16 diff --git a/tools/obj2yaml/macho2yaml.cpp b/tools/obj2yaml/macho2yaml.cpp index b787a3e0c24..e71f467e794 100644 --- a/tools/obj2yaml/macho2yaml.cpp +++ b/tools/obj2yaml/macho2yaml.cpp @@ -21,10 +21,10 @@ class MachODumper { public: MachODumper(const object::MachOObjectFile &O) : Obj(O) {} - Expected > dump(); + Expected> dump(); }; -Expected > MachODumper::dump() { +Expected> MachODumper::dump() { auto Y = make_unique(); Y->Header.magic = Obj.getHeader().magic; Y->Header.cputype = Obj.getHeader().cputype; @@ -34,12 +34,19 @@ Expected > MachODumper::dump() { Y->Header.sizeofcmds = Obj.getHeader().sizeofcmds; Y->Header.flags = Obj.getHeader().flags; + for (auto load_command : Obj.load_commands()) { + auto LC = make_unique(); + LC->cmd = static_cast(load_command.C.cmd); + LC->cmdsize = load_command.C.cmdsize; + Y->LoadCommands.push_back(std::move(LC)); + } + return std::move(Y); } Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) { MachODumper Dumper(Obj); - Expected > YAML = Dumper.dump(); + Expected> YAML = Dumper.dump(); if (!YAML) return YAML.takeError(); diff --git a/tools/yaml2obj/yaml2macho.cpp b/tools/yaml2obj/yaml2macho.cpp index 8437475a411..ed243a2cdd9 100644 --- a/tools/yaml2obj/yaml2macho.cpp +++ b/tools/yaml2obj/yaml2macho.cpp @@ -40,8 +40,9 @@ public: private: Error writeHeader(raw_ostream &OS); + Error writeLoadCommands(raw_ostream &OS); - MachOYAML::Object Obj; + MachOYAML::Object &Obj; bool is64Bit; union { @@ -53,6 +54,8 @@ private: Error MachOWriter::writeMachO(raw_ostream &OS) { if (auto Err = writeHeader(OS)) return Err; + if (auto Err = writeLoadCommands(OS)) + return Err; return Error::success(); } @@ -66,15 +69,32 @@ Error MachOWriter::writeHeader(raw_ostream &OS) { Header.flags = Obj.Header.flags; Header64.reserved = Obj.Header.reserved; - if (is64Bit) { + if (is64Bit) OS.write((const char *)&Header64, sizeof(MachO::mach_header_64)); - } else OS.write((const char *)&Header, sizeof(MachO::mach_header)); return Error::success(); } +Error MachOWriter::writeLoadCommands(raw_ostream &OS) { + for (auto &LC : Obj.LoadCommands) { + MachO::load_command LCTemp; + LCTemp.cmd = LC->cmd; + LCTemp.cmdsize = LC->cmdsize; + OS.write(reinterpret_cast(&LCTemp), + sizeof(MachO::load_command)); + auto remaining_size = LC->cmdsize - sizeof(MachO::load_command); + if (remaining_size > 0) { + // TODO: Replace all this once the load command data is present in yaml. + std::vector fill_data; + fill_data.insert(fill_data.begin(), remaining_size, 0); + OS.write(fill_data.data(), remaining_size); + } + } + return Error::success(); +} + } // end anonymous namespace int yaml2macho(yaml::Input &YIn, raw_ostream &Out) {