Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lib/ReaderWriter/YAML/ReaderWriterYAML.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
#include "lld/Core/AbsoluteAtom.h"
10
#include "lld/Core/ArchiveLibraryFile.h"
11
#include "lld/Core/Atom.h"
12
#include "lld/Core/DefinedAtom.h"
13
#include "lld/Core/Error.h"
14
#include "lld/Core/File.h"
15
#include "lld/Core/LinkingContext.h"
16
#include "lld/Core/Reader.h"
17
#include "lld/Core/Reference.h"
18
#include "lld/Core/SharedLibraryAtom.h"
19
#include "lld/Core/Simple.h"
20
#include "lld/Core/UndefinedAtom.h"
21
#include "lld/Core/Writer.h"
22
#include "lld/ReaderWriter/YamlContext.h"
23
#include "llvm/ADT/ArrayRef.h"
24
#include "llvm/ADT/DenseMap.h"
25
#include "llvm/ADT/StringMap.h"
26
#include "llvm/ADT/StringRef.h"
27
#include "llvm/ADT/Twine.h"
28
#include "llvm/BinaryFormat/Magic.h"
29
#include "llvm/Support/Allocator.h"
30
#include "llvm/Support/Debug.h"
31
#include "llvm/Support/Error.h"
32
#include "llvm/Support/ErrorOr.h"
33
#include "llvm/Support/FileSystem.h"
34
#include "llvm/Support/Format.h"
35
#include "llvm/Support/MemoryBuffer.h"
36
#include "llvm/Support/YAMLTraits.h"
37
#include "llvm/Support/raw_ostream.h"
38
#include <cassert>
39
#include <cstdint>
40
#include <cstring>
41
#include <memory>
42
#include <string>
43
#include <system_error>
44
#include <vector>
45
46
using llvm::file_magic;
47
using llvm::yaml::MappingTraits;
48
using llvm::yaml::ScalarEnumerationTraits;
49
using llvm::yaml::ScalarTraits;
50
using llvm::yaml::IO;
51
using llvm::yaml::SequenceTraits;
52
using llvm::yaml::DocumentListTraits;
53
54
using namespace lld;
55
56
/// The conversion of Atoms to and from YAML uses LLVM's YAML I/O.  This
57
/// file just defines template specializations on the lld types which control
58
/// how the mapping is done to and from YAML.
59
60
namespace {
61
62
/// Used when writing yaml files.
63
/// In most cases, atoms names are unambiguous, so references can just
64
/// use the atom name as the target (e.g. target: foo).  But in a few
65
/// cases that does not work, so ref-names are added.  These are labels
66
/// used only in yaml.  The labels do not exist in the Atom model.
67
///
68
/// One need for ref-names are when atoms have no user supplied name
69
/// (e.g. c-string literal).  Another case is when two object files with
70
/// identically named static functions are merged (ld -r) into one object file.
71
/// In that case referencing the function by name is ambiguous, so a unique
72
/// ref-name is added.
73
class RefNameBuilder {
74
public:
75
  RefNameBuilder(const lld::File &file)
76
60
      : _collisionCount(0), _unnamedCounter(0) {
77
60
    // visit all atoms
78
272
    for (const lld::DefinedAtom *atom : file.defined()) {
79
272
      // Build map of atoms names to detect duplicates
80
272
      if (!atom->name().empty())
81
176
        buildDuplicateNameMap(*atom);
82
272
83
272
      // Find references to unnamed atoms and create ref-names for them.
84
442
      for (const lld::Reference *ref : *atom) {
85
442
        // create refname for any unnamed reference target
86
442
        const lld::Atom *target = ref->target();
87
442
        if ((target != nullptr) && target->name().empty()) {
88
48
          std::string storage;
89
48
          llvm::raw_string_ostream buffer(storage);
90
48
          buffer << llvm::format("L%03d", _unnamedCounter++);
91
48
          StringRef newName = copyString(buffer.str());
92
48
          _refNames[target] = newName;
93
48
          DEBUG_WITH_TYPE("WriterYAML",
94
48
                          llvm::dbgs() << "unnamed atom: creating ref-name: '"
95
48
                                       << newName << "' ("
96
48
                                       << (const void *)newName.data() << ", "
97
48
                                       << newName.size() << ")\n");
98
48
        }
99
442
      }
100
272
    }
101
60
    for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
102
41
      buildDuplicateNameMap(*undefAtom);
103
41
    }
104
60
    for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
105
11
      buildDuplicateNameMap(*shlibAtom);
106
11
    }
107
60
    for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
108
0
      if (!absAtom->name().empty())
109
0
        buildDuplicateNameMap(*absAtom);
110
0
    }
111
60
  }
112
113
228
  void buildDuplicateNameMap(const lld::Atom &atom) {
114
228
    assert(!atom.name().empty());
115
228
    NameToAtom::iterator pos = _nameMap.find(atom.name());
116
228
    if (pos != _nameMap.end()) {
117
0
      // Found name collision, give each a unique ref-name.
118
0
      std::string Storage;
119
0
      llvm::raw_string_ostream buffer(Storage);
120
0
      buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
121
0
      StringRef newName = copyString(buffer.str());
122
0
      _refNames[&atom] = newName;
123
0
      DEBUG_WITH_TYPE("WriterYAML",
124
0
                      llvm::dbgs() << "name collsion: creating ref-name: '"
125
0
                                   << newName << "' ("
126
0
                                   << (const void *)newName.data()
127
0
                                   << ", " << newName.size() << ")\n");
128
0
      const lld::Atom *prevAtom = pos->second;
129
0
      AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
130
0
      if (pos2 == _refNames.end()) {
131
0
        // Only create ref-name for previous if none already created.
132
0
        std::string Storage2;
133
0
        llvm::raw_string_ostream buffer2(Storage2);
134
0
        buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
135
0
        StringRef newName2 = copyString(buffer2.str());
136
0
        _refNames[prevAtom] = newName2;
137
0
        DEBUG_WITH_TYPE("WriterYAML",
138
0
                        llvm::dbgs() << "name collsion: creating ref-name: '"
139
0
                                     << newName2 << "' ("
140
0
                                     << (const void *)newName2.data() << ", "
141
0
                                     << newName2.size() << ")\n");
142
0
      }
143
228
    } else {
144
228
      // First time we've seen this name, just add it to map.
145
228
      _nameMap[atom.name()] = &atom;
146
228
      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
147
228
                                        << "atom name seen for first time: '"
148
228
                                        << atom.name() << "' ("
149
228
                                        << (const void *)atom.name().data()
150
228
                                        << ", " << atom.name().size() << ")\n");
151
228
    }
152
228
  }
153
154
714
  bool hasRefName(const lld::Atom *atom) { return _refNames.count(atom); }
155
156
78
  StringRef refName(const lld::Atom *atom) {
157
78
    return _refNames.find(atom)->second;
158
78
  }
159
160
private:
161
  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
162
  typedef llvm::DenseMap<const lld::Atom *, std::string> AtomToRefName;
163
164
  // Allocate a new copy of this string in _storage, so the strings
165
  // can be freed when RefNameBuilder is destroyed.
166
48
  StringRef copyString(StringRef str) {
167
48
    char *s = _storage.Allocate<char>(str.size());
168
48
    memcpy(s, str.data(), str.size());
169
48
    return StringRef(s, str.size());
170
48
  }
171
172
  unsigned int                         _collisionCount;
173
  unsigned int                         _unnamedCounter;
174
  NameToAtom                           _nameMap;
175
  AtomToRefName                        _refNames;
176
  llvm::BumpPtrAllocator               _storage;
177
};
178
179
/// Used when reading yaml files to find the target of a reference
180
/// that could be a name or ref-name.
181
class RefNameResolver {
182
public:
183
  RefNameResolver(const lld::File *file, IO &io);
184
185
18
  const lld::Atom *lookup(StringRef name) const {
186
18
    NameToAtom::const_iterator pos = _nameMap.find(name);
187
18
    if (pos != _nameMap.end())
188
18
      return pos->second;
189
0
    _io.setError(Twine("no such atom name: ") + name);
190
0
    return nullptr;
191
0
  }
192
193
private:
194
  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
195
196
53
  void add(StringRef name, const lld::Atom *atom) {
197
53
    if (_nameMap.count(name)) {
198
0
      _io.setError(Twine("duplicate atom name: ") + name);
199
53
    } else {
200
53
      _nameMap[name] = atom;
201
53
    }
202
53
  }
203
204
  IO &_io;
205
  NameToAtom _nameMap;
206
};
207
208
/// Mapping of Atoms.
209
template <typename T> class AtomList {
210
  using Ty = std::vector<OwningAtomPtr<T>>;
211
212
public:
213
0
  typename Ty::iterator begin() { return _atoms.begin(); }
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::DefinedAtom>::begin()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::UndefinedAtom>::begin()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::SharedLibraryAtom>::begin()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::AbsoluteAtom>::begin()
214
0
  typename Ty::iterator end() { return _atoms.end(); }
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::DefinedAtom>::end()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::UndefinedAtom>::end()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::SharedLibraryAtom>::end()
Unexecuted instantiation: ReaderWriterYAML.cpp:(anonymous namespace)::AtomList<lld::AbsoluteAtom>::end()
215
  Ty _atoms;
216
};
217
218
/// Mapping of kind: field in yaml files.
219
enum FileKinds {
220
  fileKindObjectAtoms, // atom based object file encoded in yaml
221
  fileKindArchive,     // static archive library encoded in yaml
222
  fileKindObjectMachO  // mach-o object files encoded in yaml
223
};
224
225
struct ArchMember {
226
  FileKinds         _kind;
227
  StringRef         _name;
228
  const lld::File  *_content;
229
};
230
231
// The content bytes in a DefinedAtom are just uint8_t but we want
232
// special formatting, so define a strong type.
233
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8)
234
235
// SharedLibraryAtoms have a bool canBeNull() method which we'd like to be
236
// more readable than just true/false.
237
LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull)
238
239
// lld::Reference::Kind is a tuple of <namespace, arch, value>.
240
// For yaml, we just want one string that encapsulates the tuple.
241
struct RefKind {
242
  Reference::KindNamespace  ns;
243
  Reference::KindArch       arch;
244
  Reference::KindValue      value;
245
};
246
247
} // end anonymous namespace
248
249
LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
250
LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
251
// Always write DefinedAtoms content bytes as a flow sequence.
252
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8)
253
254
// for compatibility with gcc-4.7 in C++11 mode, add extra namespace
255
namespace llvm {
256
namespace yaml {
257
258
// This is a custom formatter for RefKind
259
template <> struct ScalarTraits<RefKind> {
260
442
  static void output(const RefKind &kind, void *ctxt, raw_ostream &out) {
261
442
    assert(ctxt != nullptr);
262
442
    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
263
442
    assert(info->_registry);
264
442
    StringRef str;
265
442
    if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value,
266
442
                                               str))
267
442
      out << str;
268
0
    else
269
0
      out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value;
270
442
  }
271
272
18
  static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) {
273
18
    assert(ctxt != nullptr);
274
18
    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
275
18
    assert(info->_registry);
276
18
    if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch,
277
18
                                                 kind.value))
278
18
      return StringRef();
279
0
    return StringRef("unknown reference kind");
280
0
  }
281
282
460
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
283
};
284
285
template <> struct ScalarEnumerationTraits<lld::File::Kind> {
286
0
  static void enumeration(IO &io, lld::File::Kind &value) {
287
0
    io.enumCase(value, "error-object",   lld::File::kindErrorObject);
288
0
    io.enumCase(value, "object",         lld::File::kindMachObject);
289
0
    io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
290
0
    io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
291
0
  }
292
};
293
294
template <> struct ScalarEnumerationTraits<lld::Atom::Scope> {
295
169
  static void enumeration(IO &io, lld::Atom::Scope &value) {
296
169
    io.enumCase(value, "global", lld::Atom::scopeGlobal);
297
169
    io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
298
169
    io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
299
169
  }
300
};
301
302
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
303
17
  static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
304
17
    io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
305
17
    io.enumCase(value, "custom",  lld::DefinedAtom::sectionCustomPreferred);
306
17
    io.enumCase(value, "custom-required",
307
17
                                 lld::DefinedAtom::sectionCustomRequired);
308
17
  }
309
};
310
311
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
312
0
  static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
313
0
    io.enumCase(value, "no",           DefinedAtom::interposeNo);
314
0
    io.enumCase(value, "yes",          DefinedAtom::interposeYes);
315
0
    io.enumCase(value, "yes-and-weak", DefinedAtom::interposeYesAndRuntimeWeak);
316
0
  }
317
};
318
319
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> {
320
47
  static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
321
47
    io.enumCase(value, "no",           lld::DefinedAtom::mergeNo);
322
47
    io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
323
47
    io.enumCase(value, "as-weak",      lld::DefinedAtom::mergeAsWeak);
324
47
    io.enumCase(value, "as-addressed-weak",
325
47
                                   lld::DefinedAtom::mergeAsWeakAndAddressUsed);
326
47
    io.enumCase(value, "by-content",   lld::DefinedAtom::mergeByContent);
327
47
    io.enumCase(value, "same-name-and-size",
328
47
                lld::DefinedAtom::mergeSameNameAndSize);
329
47
    io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
330
47
  }
331
};
332
333
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
334
47
  static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
335
47
    io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
336
47
    io.enumCase(value, "never",  lld::DefinedAtom::deadStripNever);
337
47
    io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
338
47
  }
339
};
340
341
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DynamicExport> {
342
0
  static void enumeration(IO &io, lld::DefinedAtom::DynamicExport &value) {
343
0
    io.enumCase(value, "normal", lld::DefinedAtom::dynamicExportNormal);
344
0
    io.enumCase(value, "always", lld::DefinedAtom::dynamicExportAlways);
345
0
  }
346
};
347
348
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
349
0
  static void enumeration(IO &io, lld::DefinedAtom::CodeModel &value) {
350
0
    io.enumCase(value, "none", lld::DefinedAtom::codeNA);
351
0
    io.enumCase(value, "mips-pic", lld::DefinedAtom::codeMipsPIC);
352
0
    io.enumCase(value, "mips-micro", lld::DefinedAtom::codeMipsMicro);
353
0
    io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
354
0
    io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
355
0
    io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb);
356
0
    io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a);
357
0
    io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d);
358
0
    io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t);
359
0
  }
360
};
361
362
template <>
363
struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
364
1
  static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
365
1
    io.enumCase(value, "---",     lld::DefinedAtom::perm___);
366
1
    io.enumCase(value, "r--",     lld::DefinedAtom::permR__);
367
1
    io.enumCase(value, "r-x",     lld::DefinedAtom::permR_X);
368
1
    io.enumCase(value, "rw-",     lld::DefinedAtom::permRW_);
369
1
    io.enumCase(value, "rwx",     lld::DefinedAtom::permRWX);
370
1
    io.enumCase(value, "rw-l",    lld::DefinedAtom::permRW_L);
371
1
    io.enumCase(value, "unknown", lld::DefinedAtom::permUnknown);
372
1
  }
373
};
374
375
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
376
186
  static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
377
186
    io.enumCase(value, "unknown",         DefinedAtom::typeUnknown);
378
186
    io.enumCase(value, "code",            DefinedAtom::typeCode);
379
186
    io.enumCase(value, "stub",            DefinedAtom::typeStub);
380
186
    io.enumCase(value, "constant",        DefinedAtom::typeConstant);
381
186
    io.enumCase(value, "data",            DefinedAtom::typeData);
382
186
    io.enumCase(value, "quick-data",      DefinedAtom::typeDataFast);
383
186
    io.enumCase(value, "zero-fill",       DefinedAtom::typeZeroFill);
384
186
    io.enumCase(value, "zero-fill-quick", DefinedAtom::typeZeroFillFast);
385
186
    io.enumCase(value, "const-data",      DefinedAtom::typeConstData);
386
186
    io.enumCase(value, "got",             DefinedAtom::typeGOT);
387
186
    io.enumCase(value, "resolver",        DefinedAtom::typeResolver);
388
186
    io.enumCase(value, "branch-island",   DefinedAtom::typeBranchIsland);
389
186
    io.enumCase(value, "branch-shim",     DefinedAtom::typeBranchShim);
390
186
    io.enumCase(value, "stub-helper",     DefinedAtom::typeStubHelper);
391
186
    io.enumCase(value, "c-string",        DefinedAtom::typeCString);
392
186
    io.enumCase(value, "utf16-string",    DefinedAtom::typeUTF16String);
393
186
    io.enumCase(value, "unwind-cfi",      DefinedAtom::typeCFI);
394
186
    io.enumCase(value, "unwind-lsda",     DefinedAtom::typeLSDA);
395
186
    io.enumCase(value, "const-4-byte",    DefinedAtom::typeLiteral4);
396
186
    io.enumCase(value, "const-8-byte",    DefinedAtom::typeLiteral8);
397
186
    io.enumCase(value, "const-16-byte",   DefinedAtom::typeLiteral16);
398
186
    io.enumCase(value, "lazy-pointer",    DefinedAtom::typeLazyPointer);
399
186
    io.enumCase(value, "lazy-dylib-pointer",
400
186
                                          DefinedAtom::typeLazyDylibPointer);
401
186
    io.enumCase(value, "cfstring",        DefinedAtom::typeCFString);
402
186
    io.enumCase(value, "initializer-pointer",
403
186
                                          DefinedAtom::typeInitializerPtr);
404
186
    io.enumCase(value, "terminator-pointer",
405
186
                                          DefinedAtom::typeTerminatorPtr);
406
186
    io.enumCase(value, "c-string-pointer",DefinedAtom::typeCStringPtr);
407
186
    io.enumCase(value, "objc-class-pointer",
408
186
                                          DefinedAtom::typeObjCClassPtr);
409
186
    io.enumCase(value, "objc-category-list",
410
186
                                          DefinedAtom::typeObjC2CategoryList);
411
186
    io.enumCase(value, "objc-image-info",
412
186
                                          DefinedAtom::typeObjCImageInfo);
413
186
    io.enumCase(value, "objc-method-list",
414
186
                                          DefinedAtom::typeObjCMethodList);
415
186
    io.enumCase(value, "objc-class1",     DefinedAtom::typeObjC1Class);
416
186
    io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);
417
186
    io.enumCase(value, "interposing-tuples",
418
186
                                          DefinedAtom::typeInterposingTuples);
419
186
    io.enumCase(value, "lto-temp",        DefinedAtom::typeTempLTO);
420
186
    io.enumCase(value, "compact-unwind",  DefinedAtom::typeCompactUnwindInfo);
421
186
    io.enumCase(value, "unwind-info",     DefinedAtom::typeProcessedUnwindInfo);
422
186
    io.enumCase(value, "tlv-thunk",       DefinedAtom::typeThunkTLV);
423
186
    io.enumCase(value, "tlv-data",        DefinedAtom::typeTLVInitialData);
424
186
    io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);
425
186
    io.enumCase(value, "tlv-initializer-ptr",
426
186
                                          DefinedAtom::typeTLVInitializerPtr);
427
186
    io.enumCase(value, "mach_header",     DefinedAtom::typeMachHeader);
428
186
    io.enumCase(value, "dso_handle",      DefinedAtom::typeDSOHandle);
429
186
    io.enumCase(value, "sectcreate",      DefinedAtom::typeSectCreate);
430
186
  }
431
};
432
433
template <> struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> {
434
0
  static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) {
435
0
    io.enumCase(value, "never",       lld::UndefinedAtom::canBeNullNever);
436
0
    io.enumCase(value, "at-runtime",  lld::UndefinedAtom::canBeNullAtRuntime);
437
0
    io.enumCase(value, "at-buildtime",lld::UndefinedAtom::canBeNullAtBuildtime);
438
0
  }
439
};
440
441
template <> struct ScalarEnumerationTraits<ShlibCanBeNull> {
442
0
  static void enumeration(IO &io, ShlibCanBeNull &value) {
443
0
    io.enumCase(value, "never",      false);
444
0
    io.enumCase(value, "at-runtime", true);
445
0
  }
446
};
447
448
template <>
449
struct ScalarEnumerationTraits<lld::SharedLibraryAtom::Type> {
450
17
  static void enumeration(IO &io, lld::SharedLibraryAtom::Type &value) {
451
17
    io.enumCase(value, "code",    lld::SharedLibraryAtom::Type::Code);
452
17
    io.enumCase(value, "data",    lld::SharedLibraryAtom::Type::Data);
453
17
    io.enumCase(value, "unknown", lld::SharedLibraryAtom::Type::Unknown);
454
17
  }
455
};
456
457
/// This is a custom formatter for lld::DefinedAtom::Alignment.  Values look
458
/// like:
459
///     8           # 8-byte aligned
460
///     7 mod 16    # 16-byte aligned plus 7 bytes
461
template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
462
  static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
463
170
                     raw_ostream &out) {
464
170
    if (value.modulus == 0) {
465
140
      out << llvm::format("%d", value.value);
466
140
    } else {
467
30
      out << llvm::format("%d mod %d", value.modulus, value.value);
468
30
    }
469
170
  }
470
471
  static StringRef input(StringRef scalar, void *ctxt,
472
7
                         lld::DefinedAtom::Alignment &value) {
473
7
    value.modulus = 0;
474
7
    size_t modStart = scalar.find("mod");
475
7
    if (modStart != StringRef::npos) {
476
0
      StringRef modStr = scalar.slice(0, modStart);
477
0
      modStr = modStr.rtrim();
478
0
      unsigned int modulus;
479
0
      if (modStr.getAsInteger(0, modulus)) {
480
0
        return "malformed alignment modulus";
481
0
      }
482
0
      value.modulus = modulus;
483
0
      scalar = scalar.drop_front(modStart + 3);
484
0
      scalar = scalar.ltrim();
485
0
    }
486
7
    unsigned int power;
487
7
    if (scalar.getAsInteger(0, power)) {
488
0
      return "malformed alignment power";
489
0
    }
490
7
    value.value = power;
491
7
    if (value.modulus >= power) {
492
0
      return "malformed alignment, modulus too large for power";
493
0
    }
494
7
    return StringRef(); // returning empty string means success
495
7
  }
496
497
177
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
498
};
499
500
template <> struct ScalarEnumerationTraits<FileKinds> {
501
0
  static void enumeration(IO &io, FileKinds &value) {
502
0
    io.enumCase(value, "object",        fileKindObjectAtoms);
503
0
    io.enumCase(value, "archive",       fileKindArchive);
504
0
    io.enumCase(value, "object-mach-o", fileKindObjectMachO);
505
0
  }
506
};
507
508
template <> struct MappingTraits<ArchMember> {
509
0
  static void mapping(IO &io, ArchMember &member) {
510
0
    io.mapOptional("kind",    member._kind, fileKindObjectAtoms);
511
0
    io.mapOptional("name",    member._name);
512
0
    io.mapRequired("content", member._content);
513
0
  }
514
};
515
516
// Declare that an AtomList is a yaml sequence.
517
template <typename T> struct SequenceTraits<AtomList<T> > {
518
0
  static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
Unexecuted instantiation: ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::DefinedAtom>, void>::size(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::DefinedAtom>&)
Unexecuted instantiation: ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::UndefinedAtom>, void>::size(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::UndefinedAtom>&)
Unexecuted instantiation: ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::SharedLibraryAtom>, void>::size(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::SharedLibraryAtom>&)
Unexecuted instantiation: ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::AbsoluteAtom>, void>::size(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::AbsoluteAtom>&)
519
73
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
73
    if (index >= seq._atoms.size())
521
73
      seq._atoms.resize(index + 1);
522
73
    return seq._atoms[index].get();
523
73
  }
ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::DefinedAtom>, void>::element(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::DefinedAtom>&, unsigned long)
Line
Count
Source
519
60
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
60
    if (index >= seq._atoms.size())
521
60
      seq._atoms.resize(index + 1);
522
60
    return seq._atoms[index].get();
523
60
  }
ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::UndefinedAtom>, void>::element(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::UndefinedAtom>&, unsigned long)
Line
Count
Source
519
7
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
7
    if (index >= seq._atoms.size())
521
7
      seq._atoms.resize(index + 1);
522
7
    return seq._atoms[index].get();
523
7
  }
ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::SharedLibraryAtom>, void>::element(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::SharedLibraryAtom>&, unsigned long)
Line
Count
Source
519
6
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
6
    if (index >= seq._atoms.size())
521
6
      seq._atoms.resize(index + 1);
522
6
    return seq._atoms[index].get();
523
6
  }
Unexecuted instantiation: ReaderWriterYAML.cpp:llvm::yaml::SequenceTraits<(anonymous namespace)::AtomList<lld::AbsoluteAtom>, void>::element(llvm::yaml::IO&, (anonymous namespace)::AtomList<lld::AbsoluteAtom>&, unsigned long)
524
};
525
526
// Declare that an AtomRange is a yaml sequence.
527
template <typename T> struct SequenceTraits<File::AtomRange<T> > {
528
90
  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::DefinedAtom>, void>::size(llvm::yaml::IO&, lld::File::AtomRange<lld::DefinedAtom>&)
Line
Count
Source
528
60
  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::UndefinedAtom>, void>::size(llvm::yaml::IO&, lld::File::AtomRange<lld::UndefinedAtom>&)
Line
Count
Source
528
23
  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::SharedLibraryAtom>, void>::size(llvm::yaml::IO&, lld::File::AtomRange<lld::SharedLibraryAtom>&)
Line
Count
Source
528
7
  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
Unexecuted instantiation: llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::AbsoluteAtom>, void>::size(llvm::yaml::IO&, lld::File::AtomRange<lld::AbsoluteAtom>&)
529
324
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
324
    assert(io.outputting() && "AtomRange only used when outputting");
531
324
    assert(index < seq.size() && "Out of range access");
532
324
    return seq[index].get();
533
324
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::DefinedAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::DefinedAtom>&, unsigned long)
Line
Count
Source
529
272
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
272
    assert(io.outputting() && "AtomRange only used when outputting");
531
272
    assert(index < seq.size() && "Out of range access");
532
272
    return seq[index].get();
533
272
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::UndefinedAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::UndefinedAtom>&, unsigned long)
Line
Count
Source
529
41
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
41
    assert(io.outputting() && "AtomRange only used when outputting");
531
41
    assert(index < seq.size() && "Out of range access");
532
41
    return seq[index].get();
533
41
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::SharedLibraryAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::SharedLibraryAtom>&, unsigned long)
Line
Count
Source
529
11
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
11
    assert(io.outputting() && "AtomRange only used when outputting");
531
11
    assert(index < seq.size() && "Out of range access");
532
11
    return seq[index].get();
533
11
  }
Unexecuted instantiation: llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::AbsoluteAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::AbsoluteAtom>&, unsigned long)
534
};
535
536
// Used to allow DefinedAtom content bytes to be a flow sequence of
537
// two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A)
538
template <> struct ScalarTraits<ImplicitHex8> {
539
4.26k
  static void output(const ImplicitHex8 &val, void *, raw_ostream &out) {
540
4.26k
    uint8_t num = val;
541
4.26k
    out << llvm::format("%02X", num);
542
4.26k
  }
543
544
4.10k
  static StringRef input(StringRef str, void *, ImplicitHex8 &val) {
545
4.10k
    unsigned long long n;
546
4.10k
    if (getAsUnsignedInteger(str, 16, n))
547
0
      return "invalid two-digit-hex number";
548
4.10k
    if (n > 0xFF)
549
0
      return "out of range two-digit-hex number";
550
4.10k
    val = n;
551
4.10k
    return StringRef(); // returning empty string means success
552
4.10k
  }
553
554
8.36k
  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
555
};
556
557
// YAML conversion for std::vector<const lld::File*>
558
template <> struct DocumentListTraits<std::vector<const lld::File *> > {
559
0
  static size_t size(IO &io, std::vector<const lld::File *> &seq) {
560
0
    return seq.size();
561
0
  }
562
  static const lld::File *&element(IO &io, std::vector<const lld::File *> &seq,
563
284
                                   size_t index) {
564
284
    if (index >= seq.size())
565
284
      seq.resize(index + 1);
566
284
    return seq[index];
567
284
  }
568
};
569
570
// YAML conversion for const lld::File*
571
template <> struct MappingTraits<const lld::File *> {
572
  class NormArchiveFile : public lld::ArchiveLibraryFile {
573
  public:
574
0
    NormArchiveFile(IO &io) : ArchiveLibraryFile("") {}
575
576
    NormArchiveFile(IO &io, const lld::File *file)
577
0
        : ArchiveLibraryFile(file->path()), _path(file->path()) {
578
0
      // If we want to support writing archives, this constructor would
579
0
      // need to populate _members.
580
0
    }
581
582
0
    const lld::File *denormalize(IO &io) { return this; }
583
584
0
    const AtomRange<lld::DefinedAtom> defined() const override {
585
0
      return _noDefinedAtoms;
586
0
    }
587
588
0
    const AtomRange<lld::UndefinedAtom> undefined() const override {
589
0
      return _noUndefinedAtoms;
590
0
    }
591
592
0
    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
593
0
      return _noSharedLibraryAtoms;
594
0
    }
595
596
0
    const AtomRange<lld::AbsoluteAtom> absolute() const override {
597
0
      return _noAbsoluteAtoms;
598
0
    }
599
600
0
    void clearAtoms() override {
601
0
      _noDefinedAtoms.clear();
602
0
      _noUndefinedAtoms.clear();
603
0
      _noSharedLibraryAtoms.clear();
604
0
      _noAbsoluteAtoms.clear();
605
0
    }
606
607
0
    File *find(StringRef name) override {
608
0
      for (const ArchMember &member : _members)
609
0
        for (const lld::DefinedAtom *atom : member._content->defined())
610
0
          if (name == atom->name())
611
0
            return const_cast<File *>(member._content);
612
0
      return nullptr;
613
0
    }
614
615
    std::error_code
616
0
    parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
617
0
      return std::error_code();
618
0
    }
619
620
    StringRef               _path;
621
    std::vector<ArchMember> _members;
622
  };
623
624
  class NormalizedFile : public lld::File {
625
  public:
626
    NormalizedFile(IO &io)
627
      : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
628
        _definedAtomsRef(_definedAtoms._atoms),
629
        _undefinedAtomsRef(_undefinedAtoms._atoms),
630
        _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
631
19
        _absoluteAtomsRef(_absoluteAtoms._atoms) {}
632
633
    NormalizedFile(IO &io, const lld::File *file)
634
        : File(file->path(), kindNormalizedObject), _io(io),
635
          _rnb(new RefNameBuilder(*file)), _path(file->path()),
636
        _definedAtomsRef(file->defined()),
637
        _undefinedAtomsRef(file->undefined()),
638
        _sharedLibraryAtomsRef(file->sharedLibrary()),
639
60
        _absoluteAtomsRef(file->absolute()) {
640
60
    }
641
642
79
    ~NormalizedFile() override {
643
79
    }
644
645
    const lld::File *denormalize(IO &io);
646
647
57
    const AtomRange<lld::DefinedAtom> defined() const override {
648
57
      return _definedAtomsRef;
649
57
    }
650
651
38
    const AtomRange<lld::UndefinedAtom> undefined() const override {
652
38
      return _undefinedAtomsRef;
653
38
    }
654
655
38
    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
656
38
      return _sharedLibraryAtomsRef;
657
38
    }
658
659
38
    const AtomRange<lld::AbsoluteAtom> absolute() const override {
660
38
      return _absoluteAtomsRef;
661
38
    }
662
663
19
    void clearAtoms() override {
664
19
      _definedAtoms._atoms.clear();
665
19
      _undefinedAtoms._atoms.clear();
666
19
      _sharedLibraryAtoms._atoms.clear();
667
19
      _absoluteAtoms._atoms.clear();
668
19
    }
669
670
    // Allocate a new copy of this string in _storage, so the strings
671
    // can be freed when File is destroyed.
672
79
    StringRef copyString(StringRef str) {
673
79
      char *s = _storage.Allocate<char>(str.size());
674
79
      memcpy(s, str.data(), str.size());
675
79
      return StringRef(s, str.size());
676
79
    }
677
678
    IO                                  &_io;
679
    std::unique_ptr<RefNameBuilder>      _rnb;
680
    StringRef                            _path;
681
    AtomList<lld::DefinedAtom>           _definedAtoms;
682
    AtomList<lld::UndefinedAtom>         _undefinedAtoms;
683
    AtomList<lld::SharedLibraryAtom>     _sharedLibraryAtoms;
684
    AtomList<lld::AbsoluteAtom>          _absoluteAtoms;
685
    AtomRange<lld::DefinedAtom>          _definedAtomsRef;
686
    AtomRange<lld::UndefinedAtom>        _undefinedAtomsRef;
687
    AtomRange<lld::SharedLibraryAtom>    _sharedLibraryAtomsRef;
688
    AtomRange<lld::AbsoluteAtom>         _absoluteAtomsRef;
689
    llvm::BumpPtrAllocator               _storage;
690
  };
691
692
344
  static void mapping(IO &io, const lld::File *&file) {
693
344
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
694
344
    assert(info != nullptr);
695
344
    // Let any register tag handler process this.
696
344
    if (info->_registry && info->_registry->handleTaggedDoc(io, file))
697
275
      return;
698
69
    // If no registered handler claims this tag and there is no tag,
699
69
    // grandfather in as "!native".
700
69
    if (io.mapTag("!native", true) || 
io.mapTag("tag:yaml.org,2002:map")9
)
701
64
      mappingAtoms(io, file);
702
69
  }
703
704
79
  static void mappingAtoms(IO &io, const lld::File *&file) {
705
79
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
706
79
    MappingNormalizationHeap<NormalizedFile, const lld::File *>
707
79
      keys(io, file, nullptr);
708
79
    assert(info != nullptr);
709
79
    info->_file = keys.operator->();
710
79
711
79
    io.mapOptional("path",                 keys->_path);
712
79
713
79
    if (io.outputting()) {
714
60
      io.mapOptional("defined-atoms",        keys->_definedAtomsRef);
715
60
      io.mapOptional("undefined-atoms",      keys->_undefinedAtomsRef);
716
60
      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
717
60
      io.mapOptional("absolute-atoms",       keys->_absoluteAtomsRef);
718
60
    } else {
719
19
      io.mapOptional("defined-atoms",        keys->_definedAtoms);
720
19
      io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
721
19
      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
722
19
      io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
723
19
    }
724
79
  }
725
726
0
  static void mappingArchive(IO &io, const lld::File *&file) {
727
0
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
728
0
    MappingNormalizationHeap<NormArchiveFile, const lld::File *>
729
0
      keys(io, file, &info->_file->allocator());
730
0
731
0
    io.mapOptional("path",    keys->_path);
732
0
    io.mapOptional("members", keys->_members);
733
0
  }
734
};
735
736
// YAML conversion for const lld::Reference*
737
template <> struct MappingTraits<const lld::Reference *> {
738
  class NormalizedReference : public lld::Reference {
739
  public:
740
    NormalizedReference(IO &io)
741
        : lld::Reference(lld::Reference::KindNamespace::all,
742
                         lld::Reference::KindArch::all, 0),
743
18
          _target(nullptr), _offset(0), _addend(0), _tag(0) {}
744
745
    NormalizedReference(IO &io, const lld::Reference *ref)
746
        : lld::Reference(ref->kindNamespace(), ref->kindArch(),
747
                         ref->kindValue()),
748
          _target(nullptr), _targetName(targetName(io, ref)),
749
          _offset(ref->offsetInAtom()), _addend(ref->addend()),
750
442
          _tag(ref->tag()) {
751
442
      _mappedKind.ns = ref->kindNamespace();
752
442
      _mappedKind.arch = ref->kindArch();
753
442
      _mappedKind.value = ref->kindValue();
754
442
    }
755
756
18
    const lld::Reference *denormalize(IO &io) {
757
18
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
758
18
      assert(info != nullptr);
759
18
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
760
18
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
761
18
      if (!_targetName.empty())
762
18
        _targetName = f->copyString(_targetName);
763
18
      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
764
18
                                        << "created Reference to name: '"
765
18
                                        << _targetName << "' ("
766
18
                                        << (const void *)_targetName.data()
767
18
                                        << ", " << _targetName.size() << ")\n");
768
18
      setKindNamespace(_mappedKind.ns);
769
18
      setKindArch(_mappedKind.arch);
770
18
      setKindValue(_mappedKind.value);
771
18
      return this;
772
18
    }
773
774
    void bind(const RefNameResolver &);
775
    static StringRef targetName(IO &io, const lld::Reference *ref);
776
777
25
    uint64_t offsetInAtom() const override { return _offset; }
778
61
    const lld::Atom *target() const override { return _target; }
779
10
    Addend addend() const override { return _addend; }
780
0
    void setAddend(Addend a) override { _addend = a; }
781
21
    void setTarget(const lld::Atom *a) override { _target = a; }
782
783
    const lld::Atom *_target;
784
    StringRef        _targetName;
785
    uint32_t         _offset;
786
    Addend           _addend;
787
    RefKind          _mappedKind;
788
    uint32_t         _tag;
789
  };
790
791
460
  static void mapping(IO &io, const lld::Reference *&ref) {
792
460
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
793
460
    MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
794
460
        io, ref, &info->_file->allocator());
795
460
796
460
    io.mapRequired("kind",   keys->_mappedKind);
797
460
    io.mapOptional("offset", keys->_offset);
798
460
    io.mapOptional("target", keys->_targetName);
799
460
    io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
800
460
    io.mapOptional("tag",    keys->_tag, 0u);
801
460
  }
802
};
803
804
// YAML conversion for const lld::DefinedAtom*
805
template <> struct MappingTraits<const lld::DefinedAtom *> {
806
807
  class NormalizedAtom : public lld::DefinedAtom {
808
  public:
809
    NormalizedAtom(IO &io)
810
60
        : _file(fileFromContext(io)), _contentType(), _alignment(1) {
811
60
      static uint32_t ordinalCounter = 1;
812
60
      _ordinal = ordinalCounter++;
813
60
    }
814
815
    NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
816
        : _file(fileFromContext(io)), _name(atom->name()),
817
          _scope(atom->scope()), _interpose(atom->interposable()),
818
          _merge(atom->merge()), _contentType(atom->contentType()),
819
          _alignment(atom->alignment()), _sectionChoice(atom->sectionChoice()),
820
          _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
821
          _codeModel(atom->codeModel()),
822
          _permissions(atom->permissions()), _size(atom->size()),
823
          _sectionName(atom->customSectionName()),
824
272
          _sectionSize(atom->sectionSize()) {
825
272
      for (const lld::Reference *r : *atom)
826
442
        _references.push_back(r);
827
272
      if (!atom->occupiesDiskSpace())
828
7
        return;
829
265
      ArrayRef<uint8_t> cont = atom->rawContent();
830
265
      _content.reserve(cont.size());
831
265
      for (uint8_t x : cont)
832
4.26k
        _content.push_back(x);
833
265
    }
834
835
332
    ~NormalizedAtom() override = default;
836
837
60
    const lld::DefinedAtom *denormalize(IO &io) {
838
60
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
839
60
      assert(info != nullptr);
840
60
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
841
60
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
842
60
      if (!_name.empty())
843
40
        _name = f->copyString(_name);
844
60
      if (!_refName.empty())
845
0
        _refName = f->copyString(_refName);
846
60
      if (!_sectionName.empty())
847
2
        _sectionName = f->copyString(_sectionName);
848
60
      DEBUG_WITH_TYPE("WriterYAML",
849
60
                      llvm::dbgs() << "created DefinedAtom named: '" << _name
850
60
                                   << "' (" << (const void *)_name.data()
851
60
                                   << ", " << _name.size() << ")\n");
852
60
      return this;
853
60
    }
854
855
    void bind(const RefNameResolver &);
856
857
    // Extract current File object from YAML I/O parsing context
858
332
    const lld::File &fileFromContext(IO &io) {
859
332
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
860
332
      assert(info != nullptr);
861
332
      assert(info->_file != nullptr);
862
332
      return *info->_file;
863
332
    }
864
865
190
    const lld::File &file() const override { return _file; }
866
265
    StringRef name() const override { return _name; }
867
189
    uint64_t size() const override { return _size; }
868
139
    Scope scope() const override { return _scope; }
869
6
    Interposable interposable() const override { return _interpose; }
870
99
    Merge merge() const override { return _merge; }
871
943
    ContentType contentType() const override { return _contentType; }
872
58
    Alignment alignment() const override { return _alignment; }
873
58
    SectionChoice sectionChoice() const override { return _sectionChoice; }
874
7
    StringRef customSectionName() const override { return _sectionName; }
875
5
    uint64_t sectionSize() const override { return _sectionSize; }
876
49
    DeadStripKind deadStrip() const override { return _deadStrip; }
877
5
    DynamicExport dynamicExport() const override { return _dynamicExport; }
878
5
    CodeModel codeModel() const override { return _codeModel; }
879
298
    ContentPermissions permissions() const override { return _permissions; }
880
114
    ArrayRef<uint8_t> rawContent() const override {
881
114
      if (!occupiesDiskSpace())
882
0
        return ArrayRef<uint8_t>();
883
114
      return ArrayRef<uint8_t>(
884
114
          reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
885
114
    }
886
887
42
    uint64_t ordinal() const override { return _ordinal; }
888
889
464
    reference_iterator begin() const override {
890
464
      uintptr_t index = 0;
891
464
      const void *it = reinterpret_cast<const void *>(index);
892
464
      return reference_iterator(*this, it);
893
464
    }
894
464
    reference_iterator end() const override {
895
464
      uintptr_t index = _references.size();
896
464
      const void *it = reinterpret_cast<const void *>(index);
897
464
      return reference_iterator(*this, it);
898
464
    }
899
121
    const lld::Reference *derefIterator(const void *it) const override {
900
121
      uintptr_t index = reinterpret_cast<uintptr_t>(it);
901
121
      assert(index < _references.size());
902
121
      return _references[index];
903
121
    }
904
117
    void incrementIterator(const void *&it) const override {
905
117
      uintptr_t index = reinterpret_cast<uintptr_t>(it);
906
117
      ++index;
907
117
      it = reinterpret_cast<const void *>(index);
908
117
    }
909
910
    void addReference(Reference::KindNamespace ns,
911
                      Reference::KindArch arch,
912
                      Reference::KindValue kindValue, uint64_t off,
913
0
                      const Atom *target, Reference::Addend a) override {
914
0
      assert(target && "trying to create reference to nothing");
915
0
      auto node = new (file().allocator()) SimpleReference(ns, arch, kindValue,
916
0
                                                           off, target, a);
917
0
      _references.push_back(node);
918
0
    }
919
920
    const lld::File                    &_file;
921
    StringRef                           _name;
922
    StringRef                           _refName;
923
    Scope                               _scope;
924
    Interposable                        _interpose;
925
    Merge                               _merge;
926
    ContentType                         _contentType;
927
    Alignment                           _alignment;
928
    SectionChoice                       _sectionChoice;
929
    DeadStripKind                       _deadStrip;
930
    DynamicExport                       _dynamicExport;
931
    CodeModel                           _codeModel;
932
    ContentPermissions                  _permissions;
933
    uint32_t                            _ordinal;
934
    std::vector<ImplicitHex8>           _content;
935
    uint64_t                            _size;
936
    StringRef                           _sectionName;
937
    uint64_t                            _sectionSize;
938
    std::vector<const lld::Reference *> _references;
939
  };
940
941
332
  static void mapping(IO &io, const lld::DefinedAtom *&atom) {
942
332
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
943
332
    MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
944
332
        io, atom, &info->_file->allocator());
945
332
    if (io.outputting()) {
946
272
      // If writing YAML, check if atom needs a ref-name.
947
272
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
948
272
      assert(info != nullptr);
949
272
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
950
272
      assert(f);
951
272
      assert(f->_rnb);
952
272
      if (f->_rnb->hasRefName(atom)) {
953
30
        keys->_refName = f->_rnb->refName(atom);
954
30
      }
955
272
    }
956
332
957
332
    io.mapOptional("name",             keys->_name,    StringRef());
958
332
    io.mapOptional("ref-name",         keys->_refName, StringRef());
959
332
    io.mapOptional("scope",            keys->_scope,
960
332
                                         DefinedAtom::scopeTranslationUnit);
961
332
    io.mapOptional("type",             keys->_contentType,
962
332
                                         DefinedAtom::typeCode);
963
332
    io.mapOptional("content",          keys->_content);
964
332
    io.mapOptional("size",             keys->_size, (uint64_t)keys->_content.size());
965
332
    io.mapOptional("interposable",     keys->_interpose,
966
332
                                         DefinedAtom::interposeNo);
967
332
    io.mapOptional("merge",            keys->_merge, DefinedAtom::mergeNo);
968
332
    io.mapOptional("alignment",        keys->_alignment,
969
332
                                         DefinedAtom::Alignment(1));
970
332
    io.mapOptional("section-choice",   keys->_sectionChoice,
971
332
                                         DefinedAtom::sectionBasedOnContent);
972
332
    io.mapOptional("section-name",     keys->_sectionName, StringRef());
973
332
    io.mapOptional("section-size",     keys->_sectionSize, (uint64_t)0);
974
332
    io.mapOptional("dead-strip",       keys->_deadStrip,
975
332
                                         DefinedAtom::deadStripNormal);
976
332
    io.mapOptional("dynamic-export",   keys->_dynamicExport,
977
332
                                         DefinedAtom::dynamicExportNormal);
978
332
    io.mapOptional("code-model",       keys->_codeModel, DefinedAtom::codeNA);
979
332
    // default permissions based on content type
980
332
    io.mapOptional("permissions",      keys->_permissions,
981
332
                                         DefinedAtom::permissions(
982
332
                                                          keys->_contentType));
983
332
    io.mapOptional("references",       keys->_references);
984
332
  }
985
};
986
987
template <> struct MappingTraits<lld::DefinedAtom *> {
988
332
  static void mapping(IO &io, lld::DefinedAtom *&atom) {
989
332
    const lld::DefinedAtom *atomPtr = atom;
990
332
    MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
991
332
    atom = const_cast<lld::DefinedAtom *>(atomPtr);
992
332
  }
993
};
994
995
// YAML conversion for const lld::UndefinedAtom*
996
template <> struct MappingTraits<const lld::UndefinedAtom *> {
997
  class NormalizedAtom : public lld::UndefinedAtom {
998
  public:
999
    NormalizedAtom(IO &io)
1000
7
        : _file(fileFromContext(io)), _canBeNull(canBeNullNever) {}
1001
1002
    NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
1003
        : _file(fileFromContext(io)), _name(atom->name()),
1004
41
          _canBeNull(atom->canBeNull()) {}
1005
1006
48
    ~NormalizedAtom() override = default;
1007
1008
7
    const lld::UndefinedAtom *denormalize(IO &io) {
1009
7
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1010
7
      assert(info != nullptr);
1011
7
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1012
7
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1013
7
      if (!_name.empty())
1014
7
        _name = f->copyString(_name);
1015
7
1016
7
      DEBUG_WITH_TYPE("WriterYAML",
1017
7
                      llvm::dbgs() << "created UndefinedAtom named: '" << _name
1018
7
                      << "' (" << (const void *)_name.data() << ", "
1019
7
                      << _name.size() << ")\n");
1020
7
      return this;
1021
7
    }
1022
1023
    // Extract current File object from YAML I/O parsing context
1024
48
    const lld::File &fileFromContext(IO &io) {
1025
48
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1026
48
      assert(info != nullptr);
1027
48
      assert(info->_file != nullptr);
1028
48
      return *info->_file;
1029
48
    }
1030
1031
2
    const lld::File &file() const override { return _file; }
1032
22
    StringRef name() const override { return _name; }
1033
1
    CanBeNull canBeNull() const override { return _canBeNull; }
1034
1035
    const lld::File     &_file;
1036
    StringRef            _name;
1037
    CanBeNull            _canBeNull;
1038
  };
1039
1040
48
  static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
1041
48
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1042
48
    MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
1043
48
        io, atom, &info->_file->allocator());
1044
48
1045
48
    io.mapRequired("name",        keys->_name);
1046
48
    io.mapOptional("can-be-null", keys->_canBeNull,
1047
48
                                  lld::UndefinedAtom::canBeNullNever);
1048
48
  }
1049
};
1050
1051
template <> struct MappingTraits<lld::UndefinedAtom *> {
1052
48
  static void mapping(IO &io, lld::UndefinedAtom *&atom) {
1053
48
    const lld::UndefinedAtom *atomPtr = atom;
1054
48
    MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
1055
48
    atom = const_cast<lld::UndefinedAtom *>(atomPtr);
1056
48
  }
1057
};
1058
1059
// YAML conversion for const lld::SharedLibraryAtom*
1060
template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
1061
  class NormalizedAtom : public lld::SharedLibraryAtom {
1062
  public:
1063
    NormalizedAtom(IO &io)
1064
        : _file(fileFromContext(io)), _canBeNull(false),
1065
6
          _type(Type::Unknown), _size(0) {}
1066
1067
    NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom)
1068
        : _file(fileFromContext(io)), _name(atom->name()),
1069
          _loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
1070
11
          _type(atom->type()), _size(atom->size()) {}
1071
1072
17
    ~NormalizedAtom() override = default;
1073
1074
6
    const lld::SharedLibraryAtom *denormalize(IO &io) {
1075
6
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1076
6
      assert(info != nullptr);
1077
6
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1078
6
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1079
6
      if (!_name.empty())
1080
6
        _name = f->copyString(_name);
1081
6
      if (!_loadName.empty())
1082
6
        _loadName = f->copyString(_loadName);
1083
6
1084
6
      DEBUG_WITH_TYPE("WriterYAML",
1085
6
                      llvm::dbgs() << "created SharedLibraryAtom named: '"
1086
6
                                   << _name << "' ("
1087
6
                                   << (const void *)_name.data()
1088
6
                                   << ", " << _name.size() << ")\n");
1089
6
      return this;
1090
6
    }
1091
1092
    // Extract current File object from YAML I/O parsing context
1093
17
    const lld::File &fileFromContext(IO &io) {
1094
17
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1095
17
      assert(info != nullptr);
1096
17
      assert(info->_file != nullptr);
1097
17
      return *info->_file;
1098
17
    }
1099
1100
0
    const lld::File &file() const override { return _file; }
1101
30
    StringRef name() const override { return _name; }
1102
10
    StringRef loadName() const override { return _loadName; }
1103
4
    bool canBeNullAtRuntime() const override { return _canBeNull; }
1104
3
    Type type() const override { return _type; }
1105
3
    uint64_t size() const override { return _size; }
1106
1107
    const lld::File &_file;
1108
    StringRef        _name;
1109
    StringRef        _loadName;
1110
    ShlibCanBeNull   _canBeNull;
1111
    Type             _type;
1112
    uint64_t         _size;
1113
  };
1114
1115
17
  static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
1116
17
1117
17
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1118
17
    MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
1119
17
    keys(io, atom, &info->_file->allocator());
1120
17
1121
17
    io.mapRequired("name",        keys->_name);
1122
17
    io.mapOptional("load-name",   keys->_loadName);
1123
17
    io.mapOptional("can-be-null", keys->_canBeNull, (ShlibCanBeNull) false);
1124
17
    io.mapOptional("type",        keys->_type, SharedLibraryAtom::Type::Code);
1125
17
    io.mapOptional("size",        keys->_size, uint64_t(0));
1126
17
  }
1127
};
1128
1129
template <> struct MappingTraits<lld::SharedLibraryAtom *> {
1130
17
  static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
1131
17
    const lld::SharedLibraryAtom *atomPtr = atom;
1132
17
    MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
1133
17
    atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
1134
17
  }
1135
};
1136
1137
// YAML conversion for const lld::AbsoluteAtom*
1138
template <> struct MappingTraits<const lld::AbsoluteAtom *> {
1139
  class NormalizedAtom : public lld::AbsoluteAtom {
1140
  public:
1141
    NormalizedAtom(IO &io)
1142
0
        : _file(fileFromContext(io)), _scope(), _value(0) {}
1143
1144
    NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
1145
        : _file(fileFromContext(io)), _name(atom->name()),
1146
0
          _scope(atom->scope()), _value(atom->value()) {}
1147
1148
0
    ~NormalizedAtom() override = default;
1149
1150
0
    const lld::AbsoluteAtom *denormalize(IO &io) {
1151
0
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1152
0
      assert(info != nullptr);
1153
0
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1154
0
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1155
0
      if (!_name.empty())
1156
0
        _name = f->copyString(_name);
1157
0
1158
0
      DEBUG_WITH_TYPE("WriterYAML",
1159
0
                      llvm::dbgs() << "created AbsoluteAtom named: '" << _name
1160
0
                                   << "' (" << (const void *)_name.data()
1161
0
                                   << ", " << _name.size() << ")\n");
1162
0
      return this;
1163
0
    }
1164
1165
    // Extract current File object from YAML I/O parsing context
1166
0
    const lld::File &fileFromContext(IO &io) {
1167
0
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1168
0
      assert(info != nullptr);
1169
0
      assert(info->_file != nullptr);
1170
0
      return *info->_file;
1171
0
    }
1172
1173
0
    const lld::File &file() const override { return _file; }
1174
0
    StringRef name() const override { return _name; }
1175
0
    uint64_t value() const override { return _value; }
1176
0
    Scope scope() const override { return _scope; }
1177
1178
    const lld::File &_file;
1179
    StringRef        _name;
1180
    StringRef        _refName;
1181
    Scope            _scope;
1182
    Hex64            _value;
1183
  };
1184
1185
0
  static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
1186
0
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1187
0
    MappingNormalizationHeap<NormalizedAtom, const lld::AbsoluteAtom *> keys(
1188
0
        io, atom, &info->_file->allocator());
1189
0
1190
0
    if (io.outputting()) {
1191
0
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1192
0
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1193
0
      assert(info != nullptr);
1194
0
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1195
0
      assert(f);
1196
0
      assert(f->_rnb);
1197
0
      if (f->_rnb->hasRefName(atom)) {
1198
0
        keys->_refName = f->_rnb->refName(atom);
1199
0
      }
1200
0
    }
1201
0
1202
0
    io.mapRequired("name",     keys->_name);
1203
0
    io.mapOptional("ref-name", keys->_refName, StringRef());
1204
0
    io.mapOptional("scope",    keys->_scope);
1205
0
    io.mapRequired("value",    keys->_value);
1206
0
  }
1207
};
1208
1209
template <> struct MappingTraits<lld::AbsoluteAtom *> {
1210
0
  static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
1211
0
    const lld::AbsoluteAtom *atomPtr = atom;
1212
0
    MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
1213
0
    atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
1214
0
  }
1215
};
1216
1217
} // end namespace llvm
1218
} // end namespace yaml
1219
1220
19
RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
1221
19
  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1222
19
  NormalizedAtom;
1223
60
  for (const lld::DefinedAtom *a : file->defined()) {
1224
60
    const auto *na = (const NormalizedAtom *)a;
1225
60
    if (!na->_refName.empty())
1226
0
      add(na->_refName, a);
1227
60
    else if (!na->_name.empty())
1228
40
      add(na->_name, a);
1229
60
  }
1230
19
1231
19
  for (const lld::UndefinedAtom *a : file->undefined())
1232
7
    add(a->name(), a);
1233
19
1234
19
  for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
1235
6
    add(a->name(), a);
1236
19
1237
19
  typedef MappingTraits<const lld::AbsoluteAtom *>::NormalizedAtom NormAbsAtom;
1238
19
  for (const lld::AbsoluteAtom *a : file->absolute()) {
1239
0
    const auto *na = (const NormAbsAtom *)a;
1240
0
    if (na->_refName.empty())
1241
0
      add(na->_name, a);
1242
0
    else
1243
0
      add(na->_refName, a);
1244
0
  }
1245
19
}
1246
1247
inline const lld::File *
1248
19
MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
1249
19
  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1250
19
  NormalizedAtom;
1251
19
1252
19
  RefNameResolver nameResolver(this, io);
1253
19
  // Now that all atoms are parsed, references can be bound.
1254
60
  for (const lld::DefinedAtom *a : this->defined()) {
1255
60
    auto *normAtom = (NormalizedAtom *)const_cast<DefinedAtom *>(a);
1256
60
    normAtom->bind(nameResolver);
1257
60
  }
1258
19
1259
19
  return this;
1260
19
}
1261
1262
inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
1263
60
    const RefNameResolver &resolver) {
1264
60
  typedef MappingTraits<const lld::Reference *>::NormalizedReference
1265
60
  NormalizedReference;
1266
60
  for (const lld::Reference *ref : _references) {
1267
18
    auto *normRef = (NormalizedReference *)const_cast<Reference *>(ref);
1268
18
    normRef->bind(resolver);
1269
18
  }
1270
60
}
1271
1272
inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
1273
18
    const RefNameResolver &resolver) {
1274
18
  _target = resolver.lookup(_targetName);
1275
18
}
1276
1277
inline StringRef
1278
MappingTraits<const lld::Reference *>::NormalizedReference::targetName(
1279
442
    IO &io, const lld::Reference *ref) {
1280
442
  if (ref->target() == nullptr)
1281
0
    return StringRef();
1282
442
  YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1283
442
  assert(info != nullptr);
1284
442
  typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1285
442
  NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1286
442
  RefNameBuilder &rnb = *f->_rnb;
1287
442
  if (rnb.hasRefName(ref->target()))
1288
48
    return rnb.refName(ref->target());
1289
394
  return ref->target()->name();
1290
394
}
1291
1292
namespace lld {
1293
namespace yaml {
1294
1295
class Writer : public lld::Writer {
1296
public:
1297
60
  Writer(const LinkingContext &context) : _ctx(context) {}
1298
1299
60
  llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
1300
60
    // Create stream to path.
1301
60
    std::error_code ec;
1302
60
    llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_Text);
1303
60
    if (ec)
1304
0
      return llvm::errorCodeToError(ec);
1305
60
1306
60
    // Create yaml Output writer, using yaml options for context.
1307
60
    YamlContext yamlContext;
1308
60
    yamlContext._ctx = &_ctx;
1309
60
    yamlContext._registry = &_ctx.registry();
1310
60
    llvm::yaml::Output yout(out, &yamlContext);
1311
60
1312
60
    // Write yaml output.
1313
60
    const lld::File *fileRef = &file;
1314
60
    yout << fileRef;
1315
60
1316
60
    return llvm::Error::success();
1317
60
  }
1318
1319
private:
1320
  const LinkingContext &_ctx;
1321
};
1322
1323
} // end namespace yaml
1324
1325
namespace {
1326
1327
/// Handles !native tagged yaml documents.
1328
class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
1329
84
  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1330
84
    if (io.mapTag("!native")) {
1331
15
      MappingTraits<const lld::File *>::mappingAtoms(io, file);
1332
15
      return true;
1333
15
    }
1334
69
    return false;
1335
69
  }
1336
};
1337
1338
/// Handles !archive tagged yaml documents.
1339
class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
1340
69
  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1341
69
    if (io.mapTag("!archive")) {
1342
0
      MappingTraits<const lld::File *>::mappingArchive(io, file);
1343
0
      return true;
1344
0
    }
1345
69
    return false;
1346
69
  }
1347
};
1348
1349
class YAMLReader : public Reader {
1350
public:
1351
225
  YAMLReader(const Registry &registry) : _registry(registry) {}
1352
1353
284
  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
1354
284
    StringRef name = mb.getBufferIdentifier();
1355
284
    return name.endswith(".objtxt") || 
name.endswith(".yaml")280
;
1356
284
  }
1357
1358
  ErrorOr<std::unique_ptr<File>>
1359
  loadFile(std::unique_ptr<MemoryBuffer> mb,
1360
284
           const class Registry &) const override {
1361
284
    // Create YAML Input Reader.
1362
284
    YamlContext yamlContext;
1363
284
    yamlContext._registry = &_registry;
1364
284
    yamlContext._path = mb->getBufferIdentifier();
1365
284
    llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
1366
284
1367
284
    // Fill vector with File objects created by parsing yaml.
1368
284
    std::vector<const lld::File *> createdFiles;
1369
284
    yin >> createdFiles;
1370
284
    assert(createdFiles.size() == 1);
1371
284
1372
284
    // Error out now if there were parsing errors.
1373
284
    if (yin.error())
1374
6
      return make_error_code(lld::YamlReaderError::illegal_value);
1375
278
1376
278
    std::shared_ptr<MemoryBuffer> smb(mb.release());
1377
278
    const File *file = createdFiles[0];
1378
278
    // Note: loadFile() should return vector of *const* File
1379
278
    File *f = const_cast<File *>(file);
1380
278
    f->setLastError(std::error_code());
1381
278
    f->setSharedMemoryBuffer(smb);
1382
278
    return std::unique_ptr<File>(f);
1383
278
  }
1384
1385
private:
1386
  const Registry &_registry;
1387
};
1388
1389
} // end anonymous namespace
1390
1391
225
void Registry::addSupportYamlFiles() {
1392
225
  add(std::unique_ptr<Reader>(new YAMLReader(*this)));
1393
225
  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1394
225
                                    new NativeYamlIOTaggedDocumentHandler()));
1395
225
  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1396
225
                                    new ArchiveYamlIOTaggedDocumentHandler()));
1397
225
}
1398
1399
60
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
1400
60
  return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
1401
60
}
1402
1403
} // end namespace lld