llvm.org GIT mirror llvm / 062cef5
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269442 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Bieneman 3 years ago
5 changed file(s) with 152 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
3232 llvm::yaml::Hex32 reserved;
3333 };
3434
35 struct LoadCommand {
36 virtual ~LoadCommand();
37 MachO::LoadCommandType cmd;
38 uint32_t cmdsize;
39 };
40
3541 struct Object {
3642 FileHeader Header;
43 std::vector> LoadCommands;
3744 };
3845
3946 } // namespace llvm::MachOYAML
47 } // namespace llvm
4048
49 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr)
50
51 namespace llvm {
4152 namespace yaml {
4253
4354 template <> struct MappingTraits {
4859 static void mapping(IO &IO, MachOYAML::Object &Object);
4960 };
5061
62 template <> struct MappingTraits> {
63 static void mapping(IO &IO,
64 std::unique_ptr &LoadCommand);
65 };
66
67 #define HANDLE_LOAD_COMMAND(LoadCommandName, LoadCommandValue) \
68 io.enumCase(value, #LoadCommandName, MachO::LoadCommandName);
69
70 template <> struct ScalarEnumerationTraits {
71 static void enumeration(IO &io, MachO::LoadCommandType &value) {
72 #include "llvm/Support/MachO.def"
73 }
74 };
75
76 #undef HANDLE_LOAD_COMMAND
77
5178 } // namespace llvm::yaml
5279
5380 } // namespace llvm
1414 #include "llvm/Support/Casting.h"
1515
1616 namespace llvm {
17
18 MachOYAML::LoadCommand::~LoadCommand() {}
1719
1820 namespace yaml {
1921
3941 IO.mapTag("!mach-o", true);
4042 }
4143 IO.mapRequired("FileHeader", Object.Header);
44 IO.mapOptional("LoadCommands", Object.LoadCommands);
4245 IO.setContext(nullptr);
46 }
47
48 void MappingTraits>::mapping(
49 IO &IO, std::unique_ptr &LoadCommand) {
50 if (!IO.outputting())
51 LoadCommand.reset(new MachOYAML::LoadCommand());
52 IO.mapRequired("cmd", LoadCommand->cmd);
53 IO.mapRequired("cmdsize", LoadCommand->cmdsize);
4354 }
4455
4556 } // namespace llvm::yaml
0 # RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
1
2 --- !mach-o
3 FileHeader:
4 magic: 0xFEEDFACF
5 cputype: 0x01000007
6 cpusubtype: 0x80000003
7 filetype: 0x00000002
8 ncmds: 16
9 sizeofcmds: 1408
10 flags: 0x00218085
11 reserved: 0x00000000
12 LoadCommands:
13 - cmd: LC_SEGMENT_64
14 cmdsize: 72
15 - cmd: LC_SEGMENT_64
16 cmdsize: 552
17 - cmd: LC_SEGMENT_64
18 cmdsize: 312
19 - cmd: LC_SEGMENT_64
20 cmdsize: 72
21 - cmd: LC_DYLD_INFO_ONLY
22 cmdsize: 48
23 - cmd: LC_SYMTAB
24 cmdsize: 24
25 - cmd: LC_DYSYMTAB
26 cmdsize: 80
27 - cmd: LC_LOAD_DYLINKER
28 cmdsize: 32
29 - cmd: LC_UUID
30 cmdsize: 24
31 - cmd: LC_VERSION_MIN_MACOSX
32 cmdsize: 16
33 - cmd: LC_SOURCE_VERSION
34 cmdsize: 16
35 - cmd: LC_MAIN
36 cmdsize: 24
37 - cmd: LC_LOAD_DYLIB
38 cmdsize: 48
39 - cmd: LC_LOAD_DYLIB
40 cmdsize: 56
41 - cmd: LC_FUNCTION_STARTS
42 cmdsize: 16
43 - cmd: LC_DATA_IN_CODE
44 cmdsize: 16
45 ...
46
47
48 # CHECK: LoadCommands:
49 # CHECK: - cmd: LC_SEGMENT_64
50 # CHECK: cmdsize: 72
51 # CHECK: - cmd: LC_SEGMENT_64
52 # CHECK: cmdsize: 552
53 # CHECK: - cmd: LC_SEGMENT_64
54 # CHECK: cmdsize: 312
55 # CHECK: - cmd: LC_SEGMENT_64
56 # CHECK: cmdsize: 72
57 # CHECK: - cmd: LC_DYLD_INFO_ONLY
58 # CHECK: cmdsize: 48
59 # CHECK: - cmd: LC_SYMTAB
60 # CHECK: cmdsize: 24
61 # CHECK: - cmd: LC_DYSYMTAB
62 # CHECK: cmdsize: 80
63 # CHECK: - cmd: LC_LOAD_DYLINKER
64 # CHECK: cmdsize: 32
65 # CHECK: - cmd: LC_UUID
66 # CHECK: cmdsize: 24
67 # CHECK: - cmd: LC_VERSION_MIN_MACOSX
68 # CHECK: cmdsize: 16
69 # CHECK: - cmd: LC_SOURCE_VERSION
70 # CHECK: cmdsize: 16
71 # CHECK: - cmd: LC_MAIN
72 # CHECK: cmdsize: 24
73 # CHECK: - cmd: LC_LOAD_DYLIB
74 # CHECK: cmdsize: 48
75 # CHECK: - cmd: LC_LOAD_DYLIB
76 # CHECK: cmdsize: 56
77 # CHECK: - cmd: LC_FUNCTION_STARTS
78 # CHECK: cmdsize: 16
79 # CHECK: - cmd: LC_DATA_IN_CODE
80 # CHECK: cmdsize: 16
2020
2121 public:
2222 MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
23 Expected > dump();
23 Expected> dump();
2424 };
2525
26 Expected > MachODumper::dump() {
26 Expected> MachODumper::dump() {
2727 auto Y = make_unique();
2828 Y->Header.magic = Obj.getHeader().magic;
2929 Y->Header.cputype = Obj.getHeader().cputype;
3333 Y->Header.sizeofcmds = Obj.getHeader().sizeofcmds;
3434 Y->Header.flags = Obj.getHeader().flags;
3535
36 for (auto load_command : Obj.load_commands()) {
37 auto LC = make_unique();
38 LC->cmd = static_cast(load_command.C.cmd);
39 LC->cmdsize = load_command.C.cmdsize;
40 Y->LoadCommands.push_back(std::move(LC));
41 }
42
3643 return std::move(Y);
3744 }
3845
3946 Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) {
4047 MachODumper Dumper(Obj);
41 Expected > YAML = Dumper.dump();
48 Expected> YAML = Dumper.dump();
4249 if (!YAML)
4350 return YAML.takeError();
4451
3939
4040 private:
4141 Error writeHeader(raw_ostream &OS);
42 Error writeLoadCommands(raw_ostream &OS);
4243
43 MachOYAML::Object Obj;
44 MachOYAML::Object &Obj;
4445 bool is64Bit;
4546
4647 union {
5152
5253 Error MachOWriter::writeMachO(raw_ostream &OS) {
5354 if (auto Err = writeHeader(OS))
55 return Err;
56 if (auto Err = writeLoadCommands(OS))
5457 return Err;
5558 return Error::success();
5659 }
6568 Header.flags = Obj.Header.flags;
6669 Header64.reserved = Obj.Header.reserved;
6770
68 if (is64Bit) {
71 if (is64Bit)
6972 OS.write((const char *)&Header64, sizeof(MachO::mach_header_64));
70 }
7173 else
7274 OS.write((const char *)&Header, sizeof(MachO::mach_header));
7375
76 return Error::success();
77 }
78
79 Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
80 for (auto &LC : Obj.LoadCommands) {
81 MachO::load_command LCTemp;
82 LCTemp.cmd = LC->cmd;
83 LCTemp.cmdsize = LC->cmdsize;
84 OS.write(reinterpret_cast(&LCTemp),
85 sizeof(MachO::load_command));
86 auto remaining_size = LC->cmdsize - sizeof(MachO::load_command);
87 if (remaining_size > 0) {
88 // TODO: Replace all this once the load command data is present in yaml.
89 std::vector fill_data;
90 fill_data.insert(fill_data.begin(), remaining_size, 0);
91 OS.write(fill_data.data(), remaining_size);
92 }
93 }
7494 return Error::success();
7595 }
7696