mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-14 07:09:08 +00:00
[obj2yaml] [yaml2obj] Basic support for MachO::load_command
This patch adds basic support for MachO::load_command. Load command types and sizes are encoded in the YAML and expanded back into MachO. The YAML doesn't yet support load command structs, that is coming next. In the meantime as a temporary measure when writing MachO files the load commands are padded with zeros so that the generated binary is valid. llvm-svn: 269442
This commit is contained in:
parent
e6e6eb6572
commit
58dc349826
@ -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<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> {
|
||||
@ -49,6 +60,22 @@ template <> struct MappingTraits<MachOYAML::Object> {
|
||||
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
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
MachOYAML::LoadCommand::~LoadCommand() {}
|
||||
|
||||
namespace yaml {
|
||||
|
||||
void MappingTraits<MachOYAML::FileHeader>::mapping(
|
||||
@ -40,9 +42,18 @@ void MappingTraits<MachOYAML::Object>::mapping(IO &IO,
|
||||
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
|
||||
|
81
test/ObjectYAML/MachO/load_commands.yaml
Normal file
81
test/ObjectYAML/MachO/load_commands.yaml
Normal file
@ -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
|
@ -21,10 +21,10 @@ class MachODumper {
|
||||
|
||||
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;
|
||||
@ -34,12 +34,19 @@ Expected<std::unique_ptr<MachOYAML::Object> > 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<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();
|
||||
|
||||
|
@ -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<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) {
|
||||
|
Loading…
Reference in New Issue
Block a user