llvm::yaml::Hex32 reserved;
};
+struct LoadCommand {
+ virtual ~LoadCommand();
+ MachO::LoadCommandType cmd;
+ uint32_t cmdsize;
+};
+
struct Object {
FileHeader Header;
+ std::vector<std::unique_ptr<LoadCommand>> LoadCommands;
};
} // namespace llvm::MachOYAML
+} // namespace llvm
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MachOYAML::LoadCommand>)
+
+namespace llvm {
namespace yaml {
template <> struct MappingTraits<MachOYAML::FileHeader> {
static void mapping(IO &IO, MachOYAML::Object &Object);
};
+template <> struct MappingTraits<std::unique_ptr<MachOYAML::LoadCommand>> {
+ static void mapping(IO &IO,
+ std::unique_ptr<MachOYAML::LoadCommand> &LoadCommand);
+};
+
+#define HANDLE_LOAD_COMMAND(LoadCommandName, LoadCommandValue) \
+ io.enumCase(value, #LoadCommandName, MachO::LoadCommandName);
+
+template <> struct ScalarEnumerationTraits<MachO::LoadCommandType> {
+ static void enumeration(IO &io, MachO::LoadCommandType &value) {
+#include "llvm/Support/MachO.def"
+ }
+};
+
+#undef HANDLE_LOAD_COMMAND
+
} // namespace llvm::yaml
} // namespace llvm
namespace llvm {
+MachOYAML::LoadCommand::~LoadCommand() {}
+
namespace yaml {
void MappingTraits<MachOYAML::FileHeader>::mapping(
IO.mapTag("!mach-o", true);
}
IO.mapRequired("FileHeader", Object.Header);
+ IO.mapOptional("LoadCommands", Object.LoadCommands);
IO.setContext(nullptr);
}
+void MappingTraits<std::unique_ptr<MachOYAML::LoadCommand>>::mapping(
+ IO &IO, std::unique_ptr<MachOYAML::LoadCommand> &LoadCommand) {
+ if (!IO.outputting())
+ LoadCommand.reset(new MachOYAML::LoadCommand());
+ IO.mapRequired("cmd", LoadCommand->cmd);
+ IO.mapRequired("cmdsize", LoadCommand->cmdsize);
+}
+
} // namespace llvm::yaml
} // namespace llvm
--- /dev/null
+# 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
public:
MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
- Expected<std::unique_ptr<MachOYAML::Object> > dump();
+ Expected<std::unique_ptr<MachOYAML::Object>> dump();
};
-Expected<std::unique_ptr<MachOYAML::Object> > MachODumper::dump() {
+Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
auto Y = make_unique<MachOYAML::Object>();
Y->Header.magic = Obj.getHeader().magic;
Y->Header.cputype = Obj.getHeader().cputype;
Y->Header.sizeofcmds = Obj.getHeader().sizeofcmds;
Y->Header.flags = Obj.getHeader().flags;
+ for (auto load_command : Obj.load_commands()) {
+ auto LC = make_unique<MachOYAML::LoadCommand>();
+ LC->cmd = static_cast<MachO::LoadCommandType>(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<std::unique_ptr<MachOYAML::Object> > YAML = Dumper.dump();
+ Expected<std::unique_ptr<MachOYAML::Object>> YAML = Dumper.dump();
if (!YAML)
return YAML.takeError();
private:
Error writeHeader(raw_ostream &OS);
+ Error writeLoadCommands(raw_ostream &OS);
- MachOYAML::Object Obj;
+ MachOYAML::Object &Obj;
bool is64Bit;
union {
Error MachOWriter::writeMachO(raw_ostream &OS) {
if (auto Err = writeHeader(OS))
return Err;
+ if (auto Err = writeLoadCommands(OS))
+ return Err;
return Error::success();
}
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<const char *>(&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<char> 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) {