1 //===- MachOYAML.cpp - MachO YAMLIO implementation ------------------------===//
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 // This file defines classes for handling the YAML representation of MachO.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ObjectYAML/MachOYAML.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/Format.h"
17 
18 #include <string.h> // For memcpy, memset and strnlen.
19 
20 namespace llvm {
21 
22 MachOYAML::LoadCommand::~LoadCommand() {}
23 
24 namespace yaml {
25 
26 void ScalarTraits<char_16>::output(const char_16 &Val, void *,
27                                    llvm::raw_ostream &Out) {
28   auto Len = strnlen(&Val[0], 16);
29   Out << StringRef(&Val[0], Len);
30 }
31 
32 StringRef ScalarTraits<char_16>::input(StringRef Scalar, void *, char_16 &Val) {
33   size_t CopySize = 16 >= Scalar.size() ? 16 : Scalar.size();
34   memcpy((void *)Val, Scalar.data(), CopySize);
35 
36   if (Scalar.size() < 16) {
37     memset((void *)&Val[Scalar.size()], 0, 16 - Scalar.size());
38   }
39 
40   return StringRef();
41 }
42 
43 bool ScalarTraits<char_16>::mustQuote(StringRef S) { return needsQuotes(S); }
44 
45 void ScalarTraits<uuid_t>::output(const uuid_t &Val, void *,
46                                   llvm::raw_ostream &Out) {
47   for (int Idx = 0; Idx < 16; ++Idx) {
48     Out << format("%02" PRIX32, Val[Idx]);
49     if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
50       Out << "-";
51   }
52 }
53 
54 StringRef ScalarTraits<uuid_t>::input(StringRef Scalar, void *, uuid_t &Val) {
55   size_t OutIdx = 0;
56   for (size_t Idx = 0; Idx < Scalar.size(); ++Idx) {
57     if (Scalar[Idx] == '-' || OutIdx >= 16)
58       continue;
59     unsigned long long TempInt;
60     if (getAsUnsignedInteger(Scalar.slice(Idx, Idx + 2), 16, TempInt))
61       return "invalid number";
62     if (TempInt > 0xFF)
63       return "out of range number";
64     Val[OutIdx] = static_cast<uint8_t>(TempInt);
65     ++Idx; // increment idx an extra time because we're consuming 2 chars
66     ++OutIdx;
67   }
68   return StringRef();
69 }
70 
71 bool ScalarTraits<uuid_t>::mustQuote(StringRef S) { return needsQuotes(S); }
72 
73 void MappingTraits<MachOYAML::FileHeader>::mapping(
74     IO &IO, MachOYAML::FileHeader &FileHdr) {
75   IO.mapRequired("magic", FileHdr.magic);
76   IO.mapRequired("cputype", FileHdr.cputype);
77   IO.mapRequired("cpusubtype", FileHdr.cpusubtype);
78   IO.mapRequired("filetype", FileHdr.filetype);
79   IO.mapRequired("ncmds", FileHdr.ncmds);
80   IO.mapRequired("sizeofcmds", FileHdr.sizeofcmds);
81   IO.mapRequired("flags", FileHdr.flags);
82   IO.mapOptional("reserved", FileHdr.reserved,
83                  static_cast<llvm::yaml::Hex32>(0xDEADBEEFu));
84 }
85 
86 void MappingTraits<MachOYAML::Object>::mapping(IO &IO,
87                                                MachOYAML::Object &Object) {
88   // If the context isn't already set, tag the document as !mach-o.
89   // For Fat files there will be a different tag so they can be differentiated.
90   if (!IO.getContext()) {
91     IO.setContext(&Object);
92     IO.mapTag("!mach-o", true);
93   }
94   IO.mapRequired("FileHeader", Object.Header);
95   IO.mapOptional("LoadCommands", Object.LoadCommands);
96   IO.mapOptional("LinkEditData", Object.LinkEdit);
97   IO.setContext(nullptr);
98 }
99 
100 void MappingTraits<MachOYAML::LinkEditData>::mapping(
101     IO &IO, MachOYAML::LinkEditData &LinkEditData) {
102   IO.mapOptional("RebaseOpcodes", LinkEditData.RebaseOpcodes);
103   IO.mapOptional("BindOpcodes", LinkEditData.BindOpcodes);
104   IO.mapOptional("WeakBindOpcodes", LinkEditData.WeakBindOpcodes);
105   IO.mapOptional("LazyBindOpcodes", LinkEditData.LazyBindOpcodes);
106 }
107 
108 void MappingTraits<MachOYAML::RebaseOpcode>::mapping(
109     IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode) {
110   IO.mapRequired("Opcode", RebaseOpcode.Opcode);
111   IO.mapRequired("Imm", RebaseOpcode.Imm);
112   IO.mapOptional("ExtraData", RebaseOpcode.ExtraData);
113 }
114 
115 void MappingTraits<MachOYAML::BindOpcode>::mapping(
116     IO &IO, MachOYAML::BindOpcode &BindOpcode) {
117   IO.mapRequired("Opcode", BindOpcode.Opcode);
118   IO.mapRequired("Imm", BindOpcode.Imm);
119   IO.mapOptional("ULEBExtraData", BindOpcode.ULEBExtraData);
120   IO.mapOptional("SLEBExtraData", BindOpcode.SLEBExtraData);
121   IO.mapOptional("Symbol", BindOpcode.Symbol);
122 }
123 
124 template <typename StructType>
125 void mapLoadCommandData(IO &IO, MachOYAML::LoadCommand &LoadCommand) {}
126 
127 template <>
128 void mapLoadCommandData<MachO::segment_command>(
129     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
130   IO.mapOptional("Sections", LoadCommand.Sections);
131 }
132 
133 template <>
134 void mapLoadCommandData<MachO::segment_command_64>(
135     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
136   IO.mapOptional("Sections", LoadCommand.Sections);
137 }
138 
139 template <>
140 void mapLoadCommandData<MachO::dylib_command>(
141     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
142   IO.mapOptional("PayloadString", LoadCommand.PayloadString);
143 }
144 
145 template <>
146 void mapLoadCommandData<MachO::dylinker_command>(
147     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
148   IO.mapOptional("PayloadString", LoadCommand.PayloadString);
149 }
150 
151 void MappingTraits<MachOYAML::LoadCommand>::mapping(
152     IO &IO, MachOYAML::LoadCommand &LoadCommand) {
153   IO.mapRequired(
154       "cmd", (MachO::LoadCommandType &)LoadCommand.Data.load_command_data.cmd);
155   IO.mapRequired("cmdsize", LoadCommand.Data.load_command_data.cmdsize);
156 
157 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \
158   case MachO::LCName:                                                          \
159     MappingTraits<MachO::LCStruct>::mapping(IO,                                \
160                                             LoadCommand.Data.LCStruct##_data); \
161     mapLoadCommandData<MachO::LCStruct>(IO, LoadCommand);                      \
162     break;
163 
164   switch (LoadCommand.Data.load_command_data.cmd) {
165 #include "llvm/Support/MachO.def"
166   }
167   IO.mapOptional("PayloadBytes", LoadCommand.PayloadBytes);
168   IO.mapOptional("ZeroPadBytes", LoadCommand.ZeroPadBytes, (uint64_t)0ull);
169 }
170 
171 void MappingTraits<MachO::dyld_info_command>::mapping(
172     IO &IO, MachO::dyld_info_command &LoadCommand) {
173   IO.mapRequired("rebase_off", LoadCommand.rebase_off);
174   IO.mapRequired("rebase_size", LoadCommand.rebase_size);
175   IO.mapRequired("bind_off", LoadCommand.bind_off);
176   IO.mapRequired("bind_size", LoadCommand.bind_size);
177   IO.mapRequired("weak_bind_off", LoadCommand.weak_bind_off);
178   IO.mapRequired("weak_bind_size", LoadCommand.weak_bind_size);
179   IO.mapRequired("lazy_bind_off", LoadCommand.lazy_bind_off);
180   IO.mapRequired("lazy_bind_size", LoadCommand.lazy_bind_size);
181   IO.mapRequired("export_off", LoadCommand.export_off);
182   IO.mapRequired("export_size", LoadCommand.export_size);
183 }
184 
185 void MappingTraits<MachOYAML::Section>::mapping(IO &IO,
186                                                 MachOYAML::Section &Section) {
187   IO.mapRequired("sectname", Section.sectname);
188   IO.mapRequired("segname", Section.segname);
189   IO.mapRequired("addr", Section.addr);
190   IO.mapRequired("size", Section.size);
191   IO.mapRequired("offset", Section.offset);
192   IO.mapRequired("align", Section.align);
193   IO.mapRequired("reloff", Section.reloff);
194   IO.mapRequired("nreloc", Section.nreloc);
195   IO.mapRequired("flags", Section.flags);
196   IO.mapRequired("reserved1", Section.reserved1);
197   IO.mapRequired("reserved2", Section.reserved2);
198   IO.mapOptional("reserved3", Section.reserved3);
199 }
200 
201 void MappingTraits<MachO::dylib>::mapping(IO &IO, MachO::dylib &DylibStruct) {
202   IO.mapRequired("name", DylibStruct.name);
203   IO.mapRequired("timestamp", DylibStruct.timestamp);
204   IO.mapRequired("current_version", DylibStruct.current_version);
205   IO.mapRequired("compatibility_version", DylibStruct.compatibility_version);
206 }
207 
208 void MappingTraits<MachO::dylib_command>::mapping(
209     IO &IO, MachO::dylib_command &LoadCommand) {
210   IO.mapRequired("dylib", LoadCommand.dylib);
211 }
212 
213 void MappingTraits<MachO::dylinker_command>::mapping(
214     IO &IO, MachO::dylinker_command &LoadCommand) {
215 
216   IO.mapRequired("name", LoadCommand.name);
217 }
218 
219 void MappingTraits<MachO::dysymtab_command>::mapping(
220     IO &IO, MachO::dysymtab_command &LoadCommand) {
221 
222   IO.mapRequired("ilocalsym", LoadCommand.ilocalsym);
223   IO.mapRequired("nlocalsym", LoadCommand.nlocalsym);
224   IO.mapRequired("iextdefsym", LoadCommand.iextdefsym);
225   IO.mapRequired("nextdefsym", LoadCommand.nextdefsym);
226   IO.mapRequired("iundefsym", LoadCommand.iundefsym);
227   IO.mapRequired("nundefsym", LoadCommand.nundefsym);
228   IO.mapRequired("tocoff", LoadCommand.tocoff);
229   IO.mapRequired("ntoc", LoadCommand.ntoc);
230   IO.mapRequired("modtaboff", LoadCommand.modtaboff);
231   IO.mapRequired("nmodtab", LoadCommand.nmodtab);
232   IO.mapRequired("extrefsymoff", LoadCommand.extrefsymoff);
233   IO.mapRequired("nextrefsyms", LoadCommand.nextrefsyms);
234   IO.mapRequired("indirectsymoff", LoadCommand.indirectsymoff);
235   IO.mapRequired("nindirectsyms", LoadCommand.nindirectsyms);
236   IO.mapRequired("extreloff", LoadCommand.extreloff);
237   IO.mapRequired("nextrel", LoadCommand.nextrel);
238   IO.mapRequired("locreloff", LoadCommand.locreloff);
239   IO.mapRequired("nlocrel", LoadCommand.nlocrel);
240 }
241 
242 void MappingTraits<MachO::encryption_info_command>::mapping(
243     IO &IO, MachO::encryption_info_command &LoadCommand) {
244 
245   IO.mapRequired("cryptoff", LoadCommand.cryptoff);
246   IO.mapRequired("cryptsize", LoadCommand.cryptsize);
247   IO.mapRequired("cryptid", LoadCommand.cryptid);
248 }
249 
250 void MappingTraits<MachO::encryption_info_command_64>::mapping(
251     IO &IO, MachO::encryption_info_command_64 &LoadCommand) {
252 
253   IO.mapRequired("cryptoff", LoadCommand.cryptoff);
254   IO.mapRequired("cryptsize", LoadCommand.cryptsize);
255   IO.mapRequired("cryptid", LoadCommand.cryptid);
256   IO.mapRequired("pad", LoadCommand.pad);
257 }
258 
259 void MappingTraits<MachO::entry_point_command>::mapping(
260     IO &IO, MachO::entry_point_command &LoadCommand) {
261 
262   IO.mapRequired("entryoff", LoadCommand.entryoff);
263   IO.mapRequired("stacksize", LoadCommand.stacksize);
264 }
265 
266 void MappingTraits<MachO::fvmfile_command>::mapping(
267     IO &IO, MachO::fvmfile_command &LoadCommand) {
268 
269   IO.mapRequired("name", LoadCommand.name);
270   IO.mapRequired("header_addr", LoadCommand.header_addr);
271 }
272 
273 void MappingTraits<MachO::fvmlib>::mapping(IO &IO, MachO::fvmlib &FVMLib) {
274   IO.mapRequired("name", FVMLib.name);
275   IO.mapRequired("minor_version", FVMLib.minor_version);
276   IO.mapRequired("header_addr", FVMLib.header_addr);
277 }
278 
279 void MappingTraits<MachO::fvmlib_command>::mapping(
280     IO &IO, MachO::fvmlib_command &LoadCommand) {
281 
282   IO.mapRequired("fvmlib", LoadCommand.fvmlib);
283 }
284 
285 void MappingTraits<MachO::ident_command>::mapping(
286     IO &IO, MachO::ident_command &LoadCommand) {}
287 
288 void MappingTraits<MachO::linkedit_data_command>::mapping(
289     IO &IO, MachO::linkedit_data_command &LoadCommand) {
290 
291   IO.mapRequired("dataoff", LoadCommand.dataoff);
292   IO.mapRequired("datasize", LoadCommand.datasize);
293 }
294 
295 void MappingTraits<MachO::linker_option_command>::mapping(
296     IO &IO, MachO::linker_option_command &LoadCommand) {
297 
298   IO.mapRequired("count", LoadCommand.count);
299 }
300 
301 void MappingTraits<MachO::prebind_cksum_command>::mapping(
302     IO &IO, MachO::prebind_cksum_command &LoadCommand) {
303 
304   IO.mapRequired("cksum", LoadCommand.cksum);
305 }
306 
307 void MappingTraits<MachO::load_command>::mapping(
308     IO &IO, MachO::load_command &LoadCommand) {}
309 
310 void MappingTraits<MachO::prebound_dylib_command>::mapping(
311     IO &IO, MachO::prebound_dylib_command &LoadCommand) {
312 
313   IO.mapRequired("name", LoadCommand.name);
314   IO.mapRequired("nmodules", LoadCommand.nmodules);
315   IO.mapRequired("linked_modules", LoadCommand.linked_modules);
316 }
317 
318 void MappingTraits<MachO::routines_command>::mapping(
319     IO &IO, MachO::routines_command &LoadCommand) {
320 
321   IO.mapRequired("init_address", LoadCommand.init_address);
322   IO.mapRequired("init_module", LoadCommand.init_module);
323   IO.mapRequired("reserved1", LoadCommand.reserved1);
324   IO.mapRequired("reserved2", LoadCommand.reserved2);
325   IO.mapRequired("reserved3", LoadCommand.reserved3);
326   IO.mapRequired("reserved4", LoadCommand.reserved4);
327   IO.mapRequired("reserved5", LoadCommand.reserved5);
328   IO.mapRequired("reserved6", LoadCommand.reserved6);
329 }
330 
331 void MappingTraits<MachO::routines_command_64>::mapping(
332     IO &IO, MachO::routines_command_64 &LoadCommand) {
333 
334   IO.mapRequired("init_address", LoadCommand.init_address);
335   IO.mapRequired("init_module", LoadCommand.init_module);
336   IO.mapRequired("reserved1", LoadCommand.reserved1);
337   IO.mapRequired("reserved2", LoadCommand.reserved2);
338   IO.mapRequired("reserved3", LoadCommand.reserved3);
339   IO.mapRequired("reserved4", LoadCommand.reserved4);
340   IO.mapRequired("reserved5", LoadCommand.reserved5);
341   IO.mapRequired("reserved6", LoadCommand.reserved6);
342 }
343 
344 void MappingTraits<MachO::rpath_command>::mapping(
345     IO &IO, MachO::rpath_command &LoadCommand) {
346 
347   IO.mapRequired("path", LoadCommand.path);
348 }
349 
350 void MappingTraits<MachO::section>::mapping(IO &IO, MachO::section &Section) {
351   IO.mapRequired("sectname", Section.sectname);
352   IO.mapRequired("segname", Section.segname);
353   IO.mapRequired("addr", Section.addr);
354   IO.mapRequired("size", Section.size);
355   IO.mapRequired("offset", Section.offset);
356   IO.mapRequired("align", Section.align);
357   IO.mapRequired("reloff", Section.reloff);
358   IO.mapRequired("nreloc", Section.nreloc);
359   IO.mapRequired("flags", Section.flags);
360   IO.mapRequired("reserved1", Section.reserved1);
361   IO.mapRequired("reserved2", Section.reserved2);
362 }
363 
364 void MappingTraits<MachO::section_64>::mapping(IO &IO,
365                                                MachO::section_64 &Section) {
366   IO.mapRequired("sectname", Section.sectname);
367   IO.mapRequired("segname", Section.segname);
368   IO.mapRequired("addr", Section.addr);
369   IO.mapRequired("size", Section.size);
370   IO.mapRequired("offset", Section.offset);
371   IO.mapRequired("align", Section.align);
372   IO.mapRequired("reloff", Section.reloff);
373   IO.mapRequired("nreloc", Section.nreloc);
374   IO.mapRequired("flags", Section.flags);
375   IO.mapRequired("reserved1", Section.reserved1);
376   IO.mapRequired("reserved2", Section.reserved2);
377   IO.mapRequired("reserved3", Section.reserved3);
378 }
379 
380 void MappingTraits<MachO::segment_command>::mapping(
381     IO &IO, MachO::segment_command &LoadCommand) {
382 
383   IO.mapRequired("segname", LoadCommand.segname);
384   IO.mapRequired("vmaddr", LoadCommand.vmaddr);
385   IO.mapRequired("vmsize", LoadCommand.vmsize);
386   IO.mapRequired("fileoff", LoadCommand.fileoff);
387   IO.mapRequired("filesize", LoadCommand.filesize);
388   IO.mapRequired("maxprot", LoadCommand.maxprot);
389   IO.mapRequired("initprot", LoadCommand.initprot);
390   IO.mapRequired("nsects", LoadCommand.nsects);
391   IO.mapRequired("flags", LoadCommand.flags);
392 }
393 
394 void MappingTraits<MachO::segment_command_64>::mapping(
395     IO &IO, MachO::segment_command_64 &LoadCommand) {
396 
397   IO.mapRequired("segname", LoadCommand.segname);
398   IO.mapRequired("vmaddr", LoadCommand.vmaddr);
399   IO.mapRequired("vmsize", LoadCommand.vmsize);
400   IO.mapRequired("fileoff", LoadCommand.fileoff);
401   IO.mapRequired("filesize", LoadCommand.filesize);
402   IO.mapRequired("maxprot", LoadCommand.maxprot);
403   IO.mapRequired("initprot", LoadCommand.initprot);
404   IO.mapRequired("nsects", LoadCommand.nsects);
405   IO.mapRequired("flags", LoadCommand.flags);
406 }
407 
408 void MappingTraits<MachO::source_version_command>::mapping(
409     IO &IO, MachO::source_version_command &LoadCommand) {
410 
411   IO.mapRequired("version", LoadCommand.version);
412 }
413 
414 void MappingTraits<MachO::sub_client_command>::mapping(
415     IO &IO, MachO::sub_client_command &LoadCommand) {
416 
417   IO.mapRequired("client", LoadCommand.client);
418 }
419 
420 void MappingTraits<MachO::sub_framework_command>::mapping(
421     IO &IO, MachO::sub_framework_command &LoadCommand) {
422 
423   IO.mapRequired("umbrella", LoadCommand.umbrella);
424 }
425 
426 void MappingTraits<MachO::sub_library_command>::mapping(
427     IO &IO, MachO::sub_library_command &LoadCommand) {
428 
429   IO.mapRequired("sub_library", LoadCommand.sub_library);
430 }
431 
432 void MappingTraits<MachO::sub_umbrella_command>::mapping(
433     IO &IO, MachO::sub_umbrella_command &LoadCommand) {
434 
435   IO.mapRequired("sub_umbrella", LoadCommand.sub_umbrella);
436 }
437 
438 void MappingTraits<MachO::symseg_command>::mapping(
439     IO &IO, MachO::symseg_command &LoadCommand) {
440 
441   IO.mapRequired("offset", LoadCommand.offset);
442   IO.mapRequired("size", LoadCommand.size);
443 }
444 
445 void MappingTraits<MachO::symtab_command>::mapping(
446     IO &IO, MachO::symtab_command &LoadCommand) {
447 
448   IO.mapRequired("symoff", LoadCommand.symoff);
449   IO.mapRequired("nsyms", LoadCommand.nsyms);
450   IO.mapRequired("stroff", LoadCommand.stroff);
451   IO.mapRequired("strsize", LoadCommand.strsize);
452 }
453 
454 void MappingTraits<MachO::thread_command>::mapping(
455     IO &IO, MachO::thread_command &LoadCommand) {}
456 
457 void MappingTraits<MachO::twolevel_hints_command>::mapping(
458     IO &IO, MachO::twolevel_hints_command &LoadCommand) {
459 
460   IO.mapRequired("offset", LoadCommand.offset);
461   IO.mapRequired("nhints", LoadCommand.nhints);
462 }
463 
464 void MappingTraits<MachO::uuid_command>::mapping(
465     IO &IO, MachO::uuid_command &LoadCommand) {
466 
467   IO.mapRequired("uuid", LoadCommand.uuid);
468 }
469 
470 void MappingTraits<MachO::version_min_command>::mapping(
471     IO &IO, MachO::version_min_command &LoadCommand) {
472 
473   IO.mapRequired("version", LoadCommand.version);
474   IO.mapRequired("sdk", LoadCommand.sdk);
475 }
476 
477 } // namespace llvm::yaml
478 
479 } // namespace llvm
480