Coverage Report

Created: 2017-10-03 07:32

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