1 //===- MachOYAML.h - Mach-O YAMLIO implementation ---------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file declares classes for handling the YAML representation
12 /// of Mach-O.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_OBJECTYAML_MACHOYAML_H
17 #define LLVM_OBJECTYAML_MACHOYAML_H
18
19 #include "llvm/ObjectYAML/YAML.h"
20 #include "llvm/Support/MachO.h"
21
22 namespace llvm {
23 namespace MachOYAML {
24
25 struct Section {
26 char sectname[16];
27 char segname[16];
28 llvm::yaml::Hex64 addr;
29 uint64_t size;
30 llvm::yaml::Hex32 offset;
31 uint32_t align;
32 llvm::yaml::Hex32 reloff;
33 uint32_t nreloc;
34 llvm::yaml::Hex32 flags;
35 llvm::yaml::Hex32 reserved1;
36 llvm::yaml::Hex32 reserved2;
37 llvm::yaml::Hex32 reserved3;
38 };
39
40 struct FileHeader {
41 llvm::yaml::Hex32 magic;
42 llvm::yaml::Hex32 cputype;
43 llvm::yaml::Hex32 cpusubtype;
44 llvm::yaml::Hex32 filetype;
45 uint32_t ncmds;
46 uint32_t sizeofcmds;
47 llvm::yaml::Hex32 flags;
48 llvm::yaml::Hex32 reserved;
49 };
50
51 struct LoadCommand {
52 virtual ~LoadCommand();
53 llvm::MachO::macho_load_command Data;
54 std::vector<Section> Sections;
55 std::vector<llvm::yaml::Hex8> PayloadBytes;
56 std::string PayloadString;
57 uint64_t ZeroPadBytes;
58 };
59
60 struct NListEntry {
61 uint32_t n_strx;
62 uint8_t n_type;
63 uint8_t n_sect;
64 uint16_t n_desc;
65 uint64_t n_value;
66 };
67 struct RebaseOpcode {
68 MachO::RebaseOpcode Opcode;
69 uint8_t Imm;
70 std::vector<yaml::Hex64> ExtraData;
71 };
72
73 struct BindOpcode {
74 MachO::BindOpcode Opcode;
75 uint8_t Imm;
76 std::vector<yaml::Hex64> ULEBExtraData;
77 std::vector<int64_t> SLEBExtraData;
78 StringRef Symbol;
79 };
80
81 struct ExportEntry {
ExportEntryExportEntry82 ExportEntry()
83 : TerminalSize(0), NodeOffset(0), Name(), Flags(0), Address(0), Other(0),
84 ImportName(), Children() {}
85 uint64_t TerminalSize;
86 uint64_t NodeOffset;
87 std::string Name;
88 llvm::yaml::Hex64 Flags;
89 llvm::yaml::Hex64 Address;
90 llvm::yaml::Hex64 Other;
91 std::string ImportName;
92 std::vector<MachOYAML::ExportEntry> Children;
93 };
94
95 struct LinkEditData {
96 std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes;
97 std::vector<MachOYAML::BindOpcode> BindOpcodes;
98 std::vector<MachOYAML::BindOpcode> WeakBindOpcodes;
99 std::vector<MachOYAML::BindOpcode> LazyBindOpcodes;
100 MachOYAML::ExportEntry ExportTrie;
101 std::vector<NListEntry> NameList;
102 std::vector<StringRef> StringTable;
103 };
104
105 struct Object {
106 FileHeader Header;
107 std::vector<LoadCommand> LoadCommands;
108 std::vector<Section> Sections;
109 LinkEditData LinkEdit;
110 };
111
112 struct FatHeader {
113 llvm::yaml::Hex32 magic;
114 uint32_t nfat_arch;
115 };
116
117 struct FatArch {
118 llvm::yaml::Hex32 cputype;
119 llvm::yaml::Hex32 cpusubtype;
120 llvm::yaml::Hex64 offset;
121 uint64_t size;
122 uint32_t align;
123 llvm::yaml::Hex32 reserved;
124 };
125
126 struct UniversalBinary {
127 FatHeader Header;
128 std::vector<FatArch> FatArchs;
129 std::vector<Object> Slices;
130 };
131
132 } // namespace llvm::MachOYAML
133 } // namespace llvm
134
135 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)136 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)
137 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8)
138 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64)
139 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
140 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode)
141 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode)
142 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::ExportEntry)
143 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::NListEntry)
144 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
145 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Object)
146 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::FatArch)
147
148 namespace llvm {
149 namespace yaml {
150
151 template <> struct MappingTraits<MachOYAML::FileHeader> {
152 static void mapping(IO &IO, MachOYAML::FileHeader &FileHeader);
153 };
154
155 template <> struct MappingTraits<MachOYAML::Object> {
156 static void mapping(IO &IO, MachOYAML::Object &Object);
157 };
158
159 template <> struct MappingTraits<MachOYAML::FatHeader> {
160 static void mapping(IO &IO, MachOYAML::FatHeader &FatHeader);
161 };
162
163 template <> struct MappingTraits<MachOYAML::FatArch> {
164 static void mapping(IO &IO, MachOYAML::FatArch &FatArch);
165 };
166
167 template <> struct MappingTraits<MachOYAML::UniversalBinary> {
168 static void mapping(IO &IO, MachOYAML::UniversalBinary &UniversalBinary);
169 };
170
171 template <> struct MappingTraits<MachOYAML::LoadCommand> {
172 static void mapping(IO &IO, MachOYAML::LoadCommand &LoadCommand);
173 };
174
175 template <> struct MappingTraits<MachOYAML::LinkEditData> {
176 static void mapping(IO &IO, MachOYAML::LinkEditData &LinkEditData);
177 };
178
179 template <> struct MappingTraits<MachOYAML::RebaseOpcode> {
180 static void mapping(IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode);
181 };
182
183 template <> struct MappingTraits<MachOYAML::BindOpcode> {
184 static void mapping(IO &IO, MachOYAML::BindOpcode &BindOpcode);
185 };
186
187 template <> struct MappingTraits<MachOYAML::ExportEntry> {
188 static void mapping(IO &IO, MachOYAML::ExportEntry &ExportEntry);
189 };
190
191 template <> struct MappingTraits<MachOYAML::Section> {
192 static void mapping(IO &IO, MachOYAML::Section &Section);
193 };
194
195 template <> struct MappingTraits<MachOYAML::NListEntry> {
196 static void mapping(IO &IO, MachOYAML::NListEntry &NListEntry);
197 };
198
199 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
200 io.enumCase(value, #LCName, MachO::LCName);
201
202 template <> struct ScalarEnumerationTraits<MachO::LoadCommandType> {
203 static void enumeration(IO &io, MachO::LoadCommandType &value) {
204 #include "llvm/Support/MachO.def"
205 io.enumFallback<Hex32>(value);
206 }
207 };
208
209 #define ENUM_CASE(Enum) io.enumCase(value, #Enum, MachO::Enum);
210
211 template <> struct ScalarEnumerationTraits<MachO::RebaseOpcode> {
212 static void enumeration(IO &io, MachO::RebaseOpcode &value) {
213 ENUM_CASE(REBASE_OPCODE_DONE)
214 ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM)
215 ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
216 ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB)
217 ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED)
218 ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES)
219 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
220 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
221 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB)
222 io.enumFallback<Hex8>(value);
223 }
224 };
225
226 template <> struct ScalarEnumerationTraits<MachO::BindOpcode> {
227 static void enumeration(IO &io, MachO::BindOpcode &value) {
228 ENUM_CASE(BIND_OPCODE_DONE)
229 ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM)
230 ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB)
231 ENUM_CASE(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM)
232 ENUM_CASE(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
233 ENUM_CASE(BIND_OPCODE_SET_TYPE_IMM)
234 ENUM_CASE(BIND_OPCODE_SET_ADDEND_SLEB)
235 ENUM_CASE(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
236 ENUM_CASE(BIND_OPCODE_ADD_ADDR_ULEB)
237 ENUM_CASE(BIND_OPCODE_DO_BIND)
238 ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
239 ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED)
240 ENUM_CASE(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB)
241 io.enumFallback<Hex8>(value);
242 }
243 };
244
245 // This trait is used for 16-byte chars in Mach structures used for strings
246 typedef char char_16[16];
247
248 template <> struct ScalarTraits<char_16> {
249 static void output(const char_16 &Val, void *, llvm::raw_ostream &Out);
250
251 static StringRef input(StringRef Scalar, void *, char_16 &Val);
252 static bool mustQuote(StringRef S);
253 };
254
255 // This trait is used for UUIDs. It reads and writes them matching otool's
256 // formatting style.
257 typedef uint8_t uuid_t[16];
258
259 template <> struct ScalarTraits<uuid_t> {
260 static void output(const uuid_t &Val, void *, llvm::raw_ostream &Out);
261
262 static StringRef input(StringRef Scalar, void *, uuid_t &Val);
263 static bool mustQuote(StringRef S);
264 };
265
266 // Load Command struct mapping traits
267
268 #define LOAD_COMMAND_STRUCT(LCStruct) \
269 template <> struct MappingTraits<MachO::LCStruct> { \
270 static void mapping(IO &IO, MachO::LCStruct &LoadCommand); \
271 };
272
273 #include "llvm/Support/MachO.def"
274
275 // Extra structures used by load commands
276 template <> struct MappingTraits<MachO::dylib> {
277 static void mapping(IO &IO, MachO::dylib &LoadCommand);
278 };
279
280 template <> struct MappingTraits<MachO::fvmlib> {
281 static void mapping(IO &IO, MachO::fvmlib &LoadCommand);
282 };
283
284 template <> struct MappingTraits<MachO::section> {
285 static void mapping(IO &IO, MachO::section &LoadCommand);
286 };
287
288 template <> struct MappingTraits<MachO::section_64> {
289 static void mapping(IO &IO, MachO::section_64 &LoadCommand);
290 };
291
292 } // namespace llvm::yaml
293
294 } // namespace llvm
295
296 #endif
297