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