Coverage Report

Created: 2019-05-22 02:55

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