]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306325, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / lib / ReaderWriter / MachO / MachONormalizedFileYAML.cpp
1 //===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp -----------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 ///
11 /// \file For mach-o object files, this implementation uses YAML I/O to
12 /// provide the convert between YAML and the normalized mach-o (NM).
13 ///
14 ///                  +------------+         +------+
15 ///                  | normalized |   <->   | yaml |
16 ///                  +------------+         +------+
17
18 #include "MachONormalizedFile.h"
19 #include "lld/Core/Error.h"
20 #include "lld/Core/LLVM.h"
21 #include "lld/ReaderWriter/YamlContext.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/BinaryFormat/MachO.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/Format.h"
30 #include "llvm/Support/MemoryBuffer.h"
31 #include "llvm/Support/SourceMgr.h"
32 #include "llvm/Support/YAMLTraits.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <system_error>
35
36 using llvm::StringRef;
37 using namespace llvm::yaml;
38 using namespace llvm::MachO;
39 using namespace lld::mach_o::normalized;
40 using lld::YamlContext;
41
42 LLVM_YAML_IS_SEQUENCE_VECTOR(Segment)
43 LLVM_YAML_IS_SEQUENCE_VECTOR(DependentDylib)
44 LLVM_YAML_IS_SEQUENCE_VECTOR(RebaseLocation)
45 LLVM_YAML_IS_SEQUENCE_VECTOR(BindLocation)
46 LLVM_YAML_IS_SEQUENCE_VECTOR(Export)
47 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
48 LLVM_YAML_IS_SEQUENCE_VECTOR(DataInCode)
49
50
51 // for compatibility with gcc-4.7 in C++11 mode, add extra namespace
52 namespace llvm {
53 namespace yaml {
54
55 // A vector of Sections is a sequence.
56 template<>
57 struct SequenceTraits< std::vector<Section> > {
58   static size_t size(IO &io, std::vector<Section> &seq) {
59     return seq.size();
60   }
61   static Section& element(IO &io, std::vector<Section> &seq, size_t index) {
62     if ( index >= seq.size() )
63       seq.resize(index+1);
64     return seq[index];
65   }
66 };
67
68 template<>
69 struct SequenceTraits< std::vector<Symbol> > {
70   static size_t size(IO &io, std::vector<Symbol> &seq) {
71     return seq.size();
72   }
73   static Symbol& element(IO &io, std::vector<Symbol> &seq, size_t index) {
74     if ( index >= seq.size() )
75       seq.resize(index+1);
76     return seq[index];
77   }
78 };
79
80 // A vector of Relocations is a sequence.
81 template<>
82 struct SequenceTraits< Relocations > {
83   static size_t size(IO &io, Relocations &seq) {
84     return seq.size();
85   }
86   static Relocation& element(IO &io, Relocations &seq, size_t index) {
87     if ( index >= seq.size() )
88       seq.resize(index+1);
89     return seq[index];
90   }
91 };
92
93 // The content for a section is represented as a flow sequence of hex bytes.
94 template<>
95 struct SequenceTraits< ContentBytes > {
96   static size_t size(IO &io, ContentBytes &seq) {
97     return seq.size();
98   }
99   static Hex8& element(IO &io, ContentBytes &seq, size_t index) {
100     if ( index >= seq.size() )
101       seq.resize(index+1);
102     return seq[index];
103   }
104   static const bool flow = true;
105 };
106
107 // The indirect symbols for a section is represented as a flow sequence
108 // of numbers (symbol table indexes).
109 template<>
110 struct SequenceTraits< IndirectSymbols > {
111   static size_t size(IO &io, IndirectSymbols &seq) {
112     return seq.size();
113   }
114   static uint32_t& element(IO &io, IndirectSymbols &seq, size_t index) {
115     if ( index >= seq.size() )
116       seq.resize(index+1);
117     return seq[index];
118   }
119   static const bool flow = true;
120 };
121
122 template <>
123 struct ScalarEnumerationTraits<lld::MachOLinkingContext::Arch> {
124   static void enumeration(IO &io, lld::MachOLinkingContext::Arch &value) {
125     io.enumCase(value, "unknown",lld::MachOLinkingContext::arch_unknown);
126     io.enumCase(value, "ppc",    lld::MachOLinkingContext::arch_ppc);
127     io.enumCase(value, "x86",    lld::MachOLinkingContext::arch_x86);
128     io.enumCase(value, "x86_64", lld::MachOLinkingContext::arch_x86_64);
129     io.enumCase(value, "armv6",  lld::MachOLinkingContext::arch_armv6);
130     io.enumCase(value, "armv7",  lld::MachOLinkingContext::arch_armv7);
131     io.enumCase(value, "armv7s", lld::MachOLinkingContext::arch_armv7s);
132     io.enumCase(value, "arm64",  lld::MachOLinkingContext::arch_arm64);
133   }
134 };
135
136 template <>
137 struct ScalarEnumerationTraits<lld::MachOLinkingContext::OS> {
138   static void enumeration(IO &io, lld::MachOLinkingContext::OS &value) {
139     io.enumCase(value, "unknown",
140                           lld::MachOLinkingContext::OS::unknown);
141     io.enumCase(value, "Mac OS X",
142                           lld::MachOLinkingContext::OS::macOSX);
143     io.enumCase(value, "iOS",
144                           lld::MachOLinkingContext::OS::iOS);
145     io.enumCase(value, "iOS Simulator",
146                           lld::MachOLinkingContext::OS::iOS_simulator);
147   }
148 };
149
150
151 template <>
152 struct ScalarEnumerationTraits<HeaderFileType> {
153   static void enumeration(IO &io, HeaderFileType &value) {
154     io.enumCase(value, "MH_OBJECT",   llvm::MachO::MH_OBJECT);
155     io.enumCase(value, "MH_DYLIB",    llvm::MachO::MH_DYLIB);
156     io.enumCase(value, "MH_EXECUTE",  llvm::MachO::MH_EXECUTE);
157     io.enumCase(value, "MH_BUNDLE",   llvm::MachO::MH_BUNDLE);
158   }
159 };
160
161
162 template <>
163 struct ScalarBitSetTraits<FileFlags> {
164   static void bitset(IO &io, FileFlags &value) {
165     io.bitSetCase(value, "MH_TWOLEVEL",
166                           llvm::MachO::MH_TWOLEVEL);
167     io.bitSetCase(value, "MH_SUBSECTIONS_VIA_SYMBOLS",
168                           llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
169   }
170 };
171
172
173 template <>
174 struct ScalarEnumerationTraits<SectionType> {
175   static void enumeration(IO &io, SectionType &value) {
176     io.enumCase(value, "S_REGULAR",
177                         llvm::MachO::S_REGULAR);
178     io.enumCase(value, "S_ZEROFILL",
179                         llvm::MachO::S_ZEROFILL);
180     io.enumCase(value, "S_CSTRING_LITERALS",
181                         llvm::MachO::S_CSTRING_LITERALS);
182     io.enumCase(value, "S_4BYTE_LITERALS",
183                         llvm::MachO::S_4BYTE_LITERALS);
184     io.enumCase(value, "S_8BYTE_LITERALS",
185                         llvm::MachO::S_8BYTE_LITERALS);
186     io.enumCase(value, "S_LITERAL_POINTERS",
187                         llvm::MachO::S_LITERAL_POINTERS);
188     io.enumCase(value, "S_NON_LAZY_SYMBOL_POINTERS",
189                         llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS);
190     io.enumCase(value, "S_LAZY_SYMBOL_POINTERS",
191                         llvm::MachO::S_LAZY_SYMBOL_POINTERS);
192     io.enumCase(value, "S_SYMBOL_STUBS",
193                         llvm::MachO::S_SYMBOL_STUBS);
194     io.enumCase(value, "S_MOD_INIT_FUNC_POINTERS",
195                         llvm::MachO::S_MOD_INIT_FUNC_POINTERS);
196     io.enumCase(value, "S_MOD_TERM_FUNC_POINTERS",
197                         llvm::MachO::S_MOD_TERM_FUNC_POINTERS);
198     io.enumCase(value, "S_COALESCED",
199                         llvm::MachO::S_COALESCED);
200     io.enumCase(value, "S_GB_ZEROFILL",
201                         llvm::MachO::S_GB_ZEROFILL);
202     io.enumCase(value, "S_INTERPOSING",
203                         llvm::MachO::S_INTERPOSING);
204     io.enumCase(value, "S_16BYTE_LITERALS",
205                         llvm::MachO::S_16BYTE_LITERALS);
206     io.enumCase(value, "S_DTRACE_DOF",
207                         llvm::MachO::S_DTRACE_DOF);
208     io.enumCase(value, "S_LAZY_DYLIB_SYMBOL_POINTERS",
209                         llvm::MachO::S_LAZY_DYLIB_SYMBOL_POINTERS);
210     io.enumCase(value, "S_THREAD_LOCAL_REGULAR",
211                         llvm::MachO::S_THREAD_LOCAL_REGULAR);
212     io.enumCase(value, "S_THREAD_LOCAL_ZEROFILL",
213                         llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
214     io.enumCase(value, "S_THREAD_LOCAL_VARIABLES",
215                         llvm::MachO::S_THREAD_LOCAL_VARIABLES);
216     io.enumCase(value, "S_THREAD_LOCAL_VARIABLE_POINTERS",
217                         llvm::MachO::S_THREAD_LOCAL_VARIABLE_POINTERS);
218     io.enumCase(value, "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS",
219                         llvm::MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
220   }
221 };
222
223 template <>
224 struct ScalarBitSetTraits<SectionAttr> {
225   static void bitset(IO &io, SectionAttr &value) {
226     io.bitSetCase(value, "S_ATTR_PURE_INSTRUCTIONS",
227                           llvm::MachO::S_ATTR_PURE_INSTRUCTIONS);
228     io.bitSetCase(value, "S_ATTR_SOME_INSTRUCTIONS",
229                           llvm::MachO::S_ATTR_SOME_INSTRUCTIONS);
230     io.bitSetCase(value, "S_ATTR_NO_DEAD_STRIP",
231                           llvm::MachO::S_ATTR_NO_DEAD_STRIP);
232     io.bitSetCase(value, "S_ATTR_EXT_RELOC",
233                           llvm::MachO::S_ATTR_EXT_RELOC);
234     io.bitSetCase(value, "S_ATTR_LOC_RELOC",
235                           llvm::MachO::S_ATTR_LOC_RELOC);
236     io.bitSetCase(value, "S_ATTR_DEBUG",
237                          llvm::MachO::S_ATTR_DEBUG);
238   }
239 };
240
241 /// This is a custom formatter for SectionAlignment.  Values are
242 /// the power to raise by, ie, the n in 2^n.
243 template <> struct ScalarTraits<SectionAlignment> {
244   static void output(const SectionAlignment &value, void *ctxt,
245                      raw_ostream &out) {
246     out << llvm::format("%d", (uint32_t)value);
247   }
248
249   static StringRef input(StringRef scalar, void *ctxt,
250                          SectionAlignment &value) {
251     uint32_t alignment;
252     if (scalar.getAsInteger(0, alignment)) {
253       return "malformed alignment value";
254     }
255     if (!llvm::isPowerOf2_32(alignment))
256       return "alignment must be a power of 2";
257     value = alignment;
258     return StringRef(); // returning empty string means success
259   }
260
261   static bool mustQuote(StringRef) { return false; }
262 };
263
264 template <>
265 struct ScalarEnumerationTraits<NListType> {
266   static void enumeration(IO &io, NListType &value) {
267     io.enumCase(value, "N_UNDF",  llvm::MachO::N_UNDF);
268     io.enumCase(value, "N_ABS",   llvm::MachO::N_ABS);
269     io.enumCase(value, "N_SECT",  llvm::MachO::N_SECT);
270     io.enumCase(value, "N_PBUD",  llvm::MachO::N_PBUD);
271     io.enumCase(value, "N_INDR",  llvm::MachO::N_INDR);
272   }
273 };
274
275 template <>
276 struct ScalarBitSetTraits<SymbolScope> {
277   static void bitset(IO &io, SymbolScope &value) {
278     io.bitSetCase(value, "N_EXT",   llvm::MachO::N_EXT);
279     io.bitSetCase(value, "N_PEXT",  llvm::MachO::N_PEXT);
280   }
281 };
282
283 template <>
284 struct ScalarBitSetTraits<SymbolDesc> {
285   static void bitset(IO &io, SymbolDesc &value) {
286     io.bitSetCase(value, "N_NO_DEAD_STRIP",   llvm::MachO::N_NO_DEAD_STRIP);
287     io.bitSetCase(value, "N_WEAK_REF",        llvm::MachO::N_WEAK_REF);
288     io.bitSetCase(value, "N_WEAK_DEF",        llvm::MachO::N_WEAK_DEF);
289     io.bitSetCase(value, "N_ARM_THUMB_DEF",   llvm::MachO::N_ARM_THUMB_DEF);
290     io.bitSetCase(value, "N_SYMBOL_RESOLVER", llvm::MachO::N_SYMBOL_RESOLVER);
291   }
292 };
293
294
295 template <>
296 struct MappingTraits<Section> {
297   struct NormalizedContentBytes;
298   static void mapping(IO &io, Section &sect) {
299     io.mapRequired("segment",         sect.segmentName);
300     io.mapRequired("section",         sect.sectionName);
301     io.mapRequired("type",            sect.type);
302     io.mapOptional("attributes",      sect.attributes);
303     io.mapOptional("alignment",       sect.alignment, (SectionAlignment)1);
304     io.mapRequired("address",         sect.address);
305     if (isZeroFillSection(sect.type)) {
306       // S_ZEROFILL sections use "size:" instead of "content:"
307       uint64_t size = sect.content.size();
308       io.mapOptional("size",          size);
309       if (!io.outputting()) {
310         uint8_t *bytes = nullptr;
311         sect.content = makeArrayRef(bytes, size);
312       }
313     } else {
314       MappingNormalization<NormalizedContent, ArrayRef<uint8_t>> content(
315         io, sect.content);
316       io.mapOptional("content",         content->_normalizedContent);
317     }
318     io.mapOptional("relocations",     sect.relocations);
319     io.mapOptional("indirect-syms",   sect.indirectSymbols);
320   }
321
322   struct NormalizedContent {
323     NormalizedContent(IO &io) : _io(io) {}
324     NormalizedContent(IO &io, ArrayRef<uint8_t> content) : _io(io) {
325       // When writing yaml, copy content byte array to Hex8 vector.
326       for (auto &c : content) {
327         _normalizedContent.push_back(c);
328       }
329     }
330     ArrayRef<uint8_t> denormalize(IO &io) {
331       // When reading yaml, allocate byte array owned by NormalizedFile and
332       // copy Hex8 vector to byte array.
333       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
334       assert(info != nullptr);
335       NormalizedFile *file = info->_normalizeMachOFile;
336       assert(file != nullptr);
337       size_t size = _normalizedContent.size();
338       if (!size)
339         return None;
340       uint8_t *bytes = file->ownedAllocations.Allocate<uint8_t>(size);
341       std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes);
342       return makeArrayRef(bytes, size);
343     }
344
345     IO                &_io;
346     ContentBytes       _normalizedContent;
347   };
348 };
349
350
351 template <>
352 struct MappingTraits<Relocation> {
353   static void mapping(IO &io, Relocation &reloc) {
354     io.mapRequired("offset",    reloc.offset);
355     io.mapOptional("scattered", reloc.scattered, false);
356     io.mapRequired("type",      reloc.type);
357     io.mapRequired("length",    reloc.length);
358     io.mapRequired("pc-rel",    reloc.pcRel);
359     if ( !reloc.scattered )
360      io.mapRequired("extern",   reloc.isExtern);
361     if ( reloc.scattered )
362      io.mapRequired("value",    reloc.value);
363     if ( !reloc.scattered )
364      io.mapRequired("symbol",   reloc.symbol);
365   }
366 };
367
368
369 template <>
370 struct ScalarEnumerationTraits<RelocationInfoType> {
371   static void enumeration(IO &io, RelocationInfoType &value) {
372     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
373     assert(info != nullptr);
374     NormalizedFile *file = info->_normalizeMachOFile;
375     assert(file != nullptr);
376     switch (file->arch) {
377     case lld::MachOLinkingContext::arch_x86_64:
378       io.enumCase(value, "X86_64_RELOC_UNSIGNED",
379                                   llvm::MachO::X86_64_RELOC_UNSIGNED);
380       io.enumCase(value, "X86_64_RELOC_SIGNED",
381                                   llvm::MachO::X86_64_RELOC_SIGNED);
382       io.enumCase(value, "X86_64_RELOC_BRANCH",
383                                   llvm::MachO::X86_64_RELOC_BRANCH);
384       io.enumCase(value, "X86_64_RELOC_GOT_LOAD",
385                                   llvm::MachO::X86_64_RELOC_GOT_LOAD);
386       io.enumCase(value, "X86_64_RELOC_GOT",
387                                   llvm::MachO::X86_64_RELOC_GOT);
388       io.enumCase(value, "X86_64_RELOC_SUBTRACTOR",
389                                   llvm::MachO::X86_64_RELOC_SUBTRACTOR);
390       io.enumCase(value, "X86_64_RELOC_SIGNED_1",
391                                   llvm::MachO::X86_64_RELOC_SIGNED_1);
392       io.enumCase(value, "X86_64_RELOC_SIGNED_2",
393                                   llvm::MachO::X86_64_RELOC_SIGNED_2);
394       io.enumCase(value, "X86_64_RELOC_SIGNED_4",
395                                   llvm::MachO::X86_64_RELOC_SIGNED_4);
396       io.enumCase(value, "X86_64_RELOC_TLV",
397                                   llvm::MachO::X86_64_RELOC_TLV);
398       break;
399     case lld::MachOLinkingContext::arch_x86:
400       io.enumCase(value, "GENERIC_RELOC_VANILLA",
401                                   llvm::MachO::GENERIC_RELOC_VANILLA);
402       io.enumCase(value, "GENERIC_RELOC_PAIR",
403                                   llvm::MachO::GENERIC_RELOC_PAIR);
404       io.enumCase(value, "GENERIC_RELOC_SECTDIFF",
405                                   llvm::MachO::GENERIC_RELOC_SECTDIFF);
406       io.enumCase(value, "GENERIC_RELOC_LOCAL_SECTDIFF",
407                                   llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
408       io.enumCase(value, "GENERIC_RELOC_TLV",
409                                   llvm::MachO::GENERIC_RELOC_TLV);
410       break;
411     case lld::MachOLinkingContext::arch_armv6:
412     case lld::MachOLinkingContext::arch_armv7:
413     case lld::MachOLinkingContext::arch_armv7s:
414        io.enumCase(value, "ARM_RELOC_VANILLA",
415                                   llvm::MachO::ARM_RELOC_VANILLA);
416       io.enumCase(value, "ARM_RELOC_PAIR",
417                                   llvm::MachO::ARM_RELOC_PAIR);
418       io.enumCase(value, "ARM_RELOC_SECTDIFF",
419                                   llvm::MachO::ARM_RELOC_SECTDIFF);
420       io.enumCase(value, "ARM_RELOC_LOCAL_SECTDIFF",
421                                   llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF);
422       io.enumCase(value, "ARM_RELOC_BR24",
423                                   llvm::MachO::ARM_RELOC_BR24);
424       io.enumCase(value, "ARM_THUMB_RELOC_BR22",
425                                   llvm::MachO::ARM_THUMB_RELOC_BR22);
426       io.enumCase(value, "ARM_RELOC_HALF",
427                                   llvm::MachO::ARM_RELOC_HALF);
428       io.enumCase(value, "ARM_RELOC_HALF_SECTDIFF",
429                                   llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
430       break;
431     case lld::MachOLinkingContext::arch_arm64:
432       io.enumCase(value, "ARM64_RELOC_UNSIGNED",
433                                   llvm::MachO::ARM64_RELOC_UNSIGNED);
434       io.enumCase(value, "ARM64_RELOC_SUBTRACTOR",
435                                   llvm::MachO::ARM64_RELOC_SUBTRACTOR);
436       io.enumCase(value, "ARM64_RELOC_BRANCH26",
437                                   llvm::MachO::ARM64_RELOC_BRANCH26);
438       io.enumCase(value, "ARM64_RELOC_PAGE21",
439                                   llvm::MachO::ARM64_RELOC_PAGE21);
440       io.enumCase(value, "ARM64_RELOC_PAGEOFF12",
441                                   llvm::MachO::ARM64_RELOC_PAGEOFF12);
442       io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGE21",
443                                   llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
444       io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
445                                   llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
446       io.enumCase(value, "ARM64_RELOC_POINTER_TO_GOT",
447                                   llvm::MachO::ARM64_RELOC_POINTER_TO_GOT);
448       io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGE21",
449                                   llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
450       io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
451                                   llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
452       io.enumCase(value, "ARM64_RELOC_ADDEND",
453                                   llvm::MachO::ARM64_RELOC_ADDEND);
454       break;
455     default:
456       llvm_unreachable("unknown architecture");
457     }
458  }
459 };
460
461
462 template <>
463 struct MappingTraits<Symbol> {
464   static void mapping(IO &io, Symbol& sym) {
465     io.mapRequired("name",    sym.name);
466     io.mapRequired("type",    sym.type);
467     io.mapOptional("scope",   sym.scope, SymbolScope(0));
468     io.mapOptional("sect",    sym.sect, (uint8_t)0);
469     if (sym.type == llvm::MachO::N_UNDF) {
470       // In undef symbols, desc field contains alignment/ordinal info
471       // which is better represented as a hex vaule.
472       uint16_t t1 = sym.desc;
473       Hex16 t2 = t1;
474       io.mapOptional("desc",  t2, Hex16(0));
475       sym.desc = t2;
476     } else {
477       // In defined symbols, desc fit is a set of option bits.
478       io.mapOptional("desc",    sym.desc, SymbolDesc(0));
479     }
480     io.mapRequired("value",  sym.value);
481   }
482 };
483
484 // Custom mapping for VMProtect (e.g. "r-x").
485 template <>
486 struct ScalarTraits<VMProtect> {
487   static void output(const VMProtect &value, void*, raw_ostream &out) {
488     out << ( (value & llvm::MachO::VM_PROT_READ)    ? 'r' : '-');
489     out << ( (value & llvm::MachO::VM_PROT_WRITE)   ? 'w' : '-');
490     out << ( (value & llvm::MachO::VM_PROT_EXECUTE) ? 'x' : '-');
491   }
492   static StringRef input(StringRef scalar, void*, VMProtect &value) {
493     value = 0;
494     if (scalar.size() != 3)
495       return "segment access protection must be three chars (e.g. \"r-x\")";
496     switch (scalar[0]) {
497     case 'r':
498       value = llvm::MachO::VM_PROT_READ;
499       break;
500     case '-':
501       break;
502     default:
503       return "segment access protection first char must be 'r' or '-'";
504     }
505     switch (scalar[1]) {
506     case 'w':
507       value = value | llvm::MachO::VM_PROT_WRITE;
508       break;
509     case '-':
510       break;
511     default:
512       return "segment access protection second char must be 'w' or '-'";
513     }
514     switch (scalar[2]) {
515     case 'x':
516       value = value | llvm::MachO::VM_PROT_EXECUTE;
517       break;
518     case '-':
519       break;
520     default:
521       return "segment access protection third char must be 'x' or '-'";
522     }
523     // Return the empty string on success,
524     return StringRef();
525   }
526   static bool mustQuote(StringRef) { return false; }
527 };
528
529
530 template <>
531 struct MappingTraits<Segment> {
532   static void mapping(IO &io, Segment& seg) {
533     io.mapRequired("name",            seg.name);
534     io.mapRequired("address",         seg.address);
535     io.mapRequired("size",            seg.size);
536     io.mapRequired("init-access",     seg.init_access);
537     io.mapRequired("max-access",      seg.max_access);
538   }
539 };
540
541 template <>
542 struct ScalarEnumerationTraits<LoadCommandType> {
543   static void enumeration(IO &io, LoadCommandType &value) {
544     io.enumCase(value, "LC_LOAD_DYLIB",
545                         llvm::MachO::LC_LOAD_DYLIB);
546     io.enumCase(value, "LC_LOAD_WEAK_DYLIB",
547                         llvm::MachO::LC_LOAD_WEAK_DYLIB);
548     io.enumCase(value, "LC_REEXPORT_DYLIB",
549                         llvm::MachO::LC_REEXPORT_DYLIB);
550     io.enumCase(value, "LC_LOAD_UPWARD_DYLIB",
551                         llvm::MachO::LC_LOAD_UPWARD_DYLIB);
552     io.enumCase(value, "LC_LAZY_LOAD_DYLIB",
553                         llvm::MachO::LC_LAZY_LOAD_DYLIB);
554     io.enumCase(value, "LC_VERSION_MIN_MACOSX",
555                         llvm::MachO::LC_VERSION_MIN_MACOSX);
556     io.enumCase(value, "LC_VERSION_MIN_IPHONEOS",
557                         llvm::MachO::LC_VERSION_MIN_IPHONEOS);
558     io.enumCase(value, "LC_VERSION_MIN_TVOS",
559                         llvm::MachO::LC_VERSION_MIN_TVOS);
560     io.enumCase(value, "LC_VERSION_MIN_WATCHOS",
561                         llvm::MachO::LC_VERSION_MIN_WATCHOS);
562   }
563 };
564
565 template <>
566 struct MappingTraits<DependentDylib> {
567   static void mapping(IO &io, DependentDylib& dylib) {
568     io.mapRequired("path",            dylib.path);
569     io.mapOptional("kind",            dylib.kind,
570                                       llvm::MachO::LC_LOAD_DYLIB);
571     io.mapOptional("compat-version",  dylib.compatVersion,
572                                       PackedVersion(0x10000));
573     io.mapOptional("current-version", dylib.currentVersion,
574                                       PackedVersion(0x10000));
575   }
576 };
577
578 template <>
579 struct ScalarEnumerationTraits<RebaseType> {
580   static void enumeration(IO &io, RebaseType &value) {
581     io.enumCase(value, "REBASE_TYPE_POINTER",
582                         llvm::MachO::REBASE_TYPE_POINTER);
583     io.enumCase(value, "REBASE_TYPE_TEXT_PCREL32",
584                         llvm::MachO::REBASE_TYPE_TEXT_PCREL32);
585     io.enumCase(value, "REBASE_TYPE_TEXT_ABSOLUTE32",
586                         llvm::MachO::REBASE_TYPE_TEXT_ABSOLUTE32);
587   }
588 };
589
590
591 template <>
592 struct MappingTraits<RebaseLocation> {
593   static void mapping(IO &io, RebaseLocation& rebase) {
594     io.mapRequired("segment-index",   rebase.segIndex);
595     io.mapRequired("segment-offset",  rebase.segOffset);
596     io.mapOptional("kind",            rebase.kind,
597                                       llvm::MachO::REBASE_TYPE_POINTER);
598   }
599 };
600
601
602
603 template <>
604 struct ScalarEnumerationTraits<BindType> {
605   static void enumeration(IO &io, BindType &value) {
606     io.enumCase(value, "BIND_TYPE_POINTER",
607                         llvm::MachO::BIND_TYPE_POINTER);
608     io.enumCase(value, "BIND_TYPE_TEXT_ABSOLUTE32",
609                         llvm::MachO::BIND_TYPE_TEXT_ABSOLUTE32);
610     io.enumCase(value, "BIND_TYPE_TEXT_PCREL32",
611                         llvm::MachO::BIND_TYPE_TEXT_PCREL32);
612   }
613 };
614
615 template <>
616 struct MappingTraits<BindLocation> {
617   static void mapping(IO &io, BindLocation &bind) {
618     io.mapRequired("segment-index",   bind.segIndex);
619     io.mapRequired("segment-offset",  bind.segOffset);
620     io.mapOptional("kind",            bind.kind,
621                                       llvm::MachO::BIND_TYPE_POINTER);
622     io.mapOptional("can-be-null",     bind.canBeNull, false);
623     io.mapRequired("ordinal",         bind.ordinal);
624     io.mapRequired("symbol-name",     bind.symbolName);
625     io.mapOptional("addend",          bind.addend, Hex64(0));
626   }
627 };
628
629
630 template <>
631 struct ScalarEnumerationTraits<ExportSymbolKind> {
632   static void enumeration(IO &io, ExportSymbolKind &value) {
633     io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_REGULAR",
634                         llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
635     io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL",
636                         llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
637     io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE",
638                         llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
639   }
640 };
641
642 template <>
643 struct ScalarBitSetTraits<ExportFlags> {
644   static void bitset(IO &io, ExportFlags &value) {
645     io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION",
646                           llvm::MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
647     io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_REEXPORT",
648                           llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
649     io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER",
650                           llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
651   }
652 };
653
654
655 template <>
656 struct MappingTraits<Export> {
657   static void mapping(IO &io, Export &exp) {
658     io.mapRequired("name",         exp.name);
659     io.mapOptional("offset",       exp.offset);
660     io.mapOptional("kind",         exp.kind,
661                                 llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
662     if (!io.outputting() || exp.flags)
663       io.mapOptional("flags",      exp.flags);
664     io.mapOptional("other",        exp.otherOffset, Hex32(0));
665     io.mapOptional("other-name",   exp.otherName, StringRef());
666   }
667 };
668
669 template <>
670 struct ScalarEnumerationTraits<DataRegionType> {
671   static void enumeration(IO &io, DataRegionType &value) {
672     io.enumCase(value, "DICE_KIND_DATA",
673                         llvm::MachO::DICE_KIND_DATA);
674     io.enumCase(value, "DICE_KIND_JUMP_TABLE8",
675                         llvm::MachO::DICE_KIND_JUMP_TABLE8);
676     io.enumCase(value, "DICE_KIND_JUMP_TABLE16",
677                         llvm::MachO::DICE_KIND_JUMP_TABLE16);
678     io.enumCase(value, "DICE_KIND_JUMP_TABLE32",
679                         llvm::MachO::DICE_KIND_JUMP_TABLE32);
680     io.enumCase(value, "DICE_KIND_ABS_JUMP_TABLE32",
681                         llvm::MachO::DICE_KIND_ABS_JUMP_TABLE32);
682   }
683 };
684
685 template <>
686 struct MappingTraits<DataInCode> {
687   static void mapping(IO &io, DataInCode &entry) {
688     io.mapRequired("offset",       entry.offset);
689     io.mapRequired("length",       entry.length);
690     io.mapRequired("kind",         entry.kind);
691   }
692 };
693
694 template <>
695 struct ScalarTraits<PackedVersion> {
696   static void output(const PackedVersion &value, void*, raw_ostream &out) {
697     out << llvm::format("%d.%d", (value >> 16), (value >> 8) & 0xFF);
698     if (value & 0xFF) {
699       out << llvm::format(".%d", (value & 0xFF));
700     }
701   }
702   static StringRef input(StringRef scalar, void*, PackedVersion &result) {
703     uint32_t value;
704     if (lld::MachOLinkingContext::parsePackedVersion(scalar, value))
705       return "malformed version number";
706     result = value;
707     // Return the empty string on success,
708     return StringRef();
709   }
710   static bool mustQuote(StringRef) { return false; }
711 };
712
713 template <>
714 struct MappingTraits<NormalizedFile> {
715   static void mapping(IO &io, NormalizedFile &file) {
716     io.mapRequired("arch",             file.arch);
717     io.mapRequired("file-type",        file.fileType);
718     io.mapOptional("flags",            file.flags);
719     io.mapOptional("dependents",       file.dependentDylibs);
720     io.mapOptional("install-name",     file.installName,    StringRef());
721     io.mapOptional("compat-version",   file.compatVersion,  PackedVersion(0x10000));
722     io.mapOptional("current-version",  file.currentVersion, PackedVersion(0x10000));
723     io.mapOptional("has-UUID",         file.hasUUID,        true);
724     io.mapOptional("rpaths",           file.rpaths);
725     io.mapOptional("entry-point",      file.entryAddress,   Hex64(0));
726     io.mapOptional("stack-size",       file.stackSize,      Hex64(0));
727     io.mapOptional("source-version",   file.sourceVersion,  Hex64(0));
728     io.mapOptional("OS",               file.os);
729     io.mapOptional("min-os-version",   file.minOSverson,    PackedVersion(0));
730     io.mapOptional("min-os-version-kind",   file.minOSVersionKind, (LoadCommandType)0);
731     io.mapOptional("sdk-version",      file.sdkVersion,     PackedVersion(0));
732     io.mapOptional("segments",         file.segments);
733     io.mapOptional("sections",         file.sections);
734     io.mapOptional("local-symbols",    file.localSymbols);
735     io.mapOptional("global-symbols",   file.globalSymbols);
736     io.mapOptional("undefined-symbols",file.undefinedSymbols);
737     io.mapOptional("page-size",        file.pageSize,       Hex32(4096));
738     io.mapOptional("rebasings",        file.rebasingInfo);
739     io.mapOptional("bindings",         file.bindingInfo);
740     io.mapOptional("weak-bindings",    file.weakBindingInfo);
741     io.mapOptional("lazy-bindings",    file.lazyBindingInfo);
742     io.mapOptional("exports",          file.exportInfo);
743     io.mapOptional("dataInCode",       file.dataInCode);
744   }
745   static StringRef validate(IO &io, NormalizedFile &file) {
746     return StringRef();
747   }
748 };
749
750 } // namespace llvm
751 } // namespace yaml
752
753
754 namespace lld {
755 namespace mach_o {
756
757 /// Handles !mach-o tagged yaml documents.
758 bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
759                                                  const lld::File *&file) const {
760   if (!io.mapTag("!mach-o"))
761     return false;
762   // Step 1: parse yaml into normalized mach-o struct.
763   NormalizedFile nf;
764   YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
765   assert(info != nullptr);
766   assert(info->_normalizeMachOFile == nullptr);
767   info->_normalizeMachOFile = &nf;
768   MappingTraits<NormalizedFile>::mapping(io, nf);
769   // Step 2: parse normalized mach-o struct into atoms.
770   auto fileOrError = normalizedToAtoms(nf, info->_path, true);
771
772   // Check that we parsed successfully.
773   if (!fileOrError) {
774     std::string buffer;
775     llvm::raw_string_ostream stream(buffer);
776     handleAllErrors(fileOrError.takeError(),
777                     [&](const llvm::ErrorInfoBase &EI) {
778       EI.log(stream);
779       stream << "\n";
780     });
781     io.setError(stream.str());
782     return false;
783   }
784
785   if (nf.arch != _arch) {
786     io.setError(Twine("file is wrong architecture. Expected ("
787                       + MachOLinkingContext::nameFromArch(_arch)
788                       + ") found ("
789                       + MachOLinkingContext::nameFromArch(nf.arch)
790                       + ")"));
791     return false;
792   }
793   info->_normalizeMachOFile = nullptr;
794   file = fileOrError->release();
795   return true;
796 }
797
798
799
800 namespace normalized {
801
802 /// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
803 llvm::Expected<std::unique_ptr<NormalizedFile>>
804 readYaml(std::unique_ptr<MemoryBuffer> &mb) {
805   // Make empty NormalizedFile.
806   std::unique_ptr<NormalizedFile> f(new NormalizedFile());
807
808   // Create YAML Input parser.
809   YamlContext yamlContext;
810   yamlContext._normalizeMachOFile = f.get();
811   llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
812
813   // Fill NormalizedFile by parsing yaml.
814   yin >> *f;
815
816   // Return error if there were parsing problems.
817   if (auto ec = yin.error())
818     return llvm::make_error<GenericError>(Twine("YAML parsing error: ")
819                                           + ec.message());
820
821   // Hand ownership of instantiated NormalizedFile to caller.
822   return std::move(f);
823 }
824
825
826 /// Writes a yaml encoded mach-o files from an in-memory normalized view.
827 std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out) {
828   // YAML I/O is not const aware, so need to cast away ;-(
829   NormalizedFile *f = const_cast<NormalizedFile*>(&file);
830
831   // Create yaml Output writer, using yaml options for context.
832   YamlContext yamlContext;
833   yamlContext._normalizeMachOFile = f;
834   llvm::yaml::Output yout(out, &yamlContext);
835
836   // Stream out yaml.
837   yout << *f;
838
839   return std::error_code();
840 }
841
842 } // namespace normalized
843 } // namespace mach_o
844 } // namespace lld