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