Coverage Report

Created: 2019-05-22 02:55

/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
33
      : _collisionCount(0), _unnamedCounter(0) {
77
33
    // visit all atoms
78
145
    for (const lld::DefinedAtom *atom : file.defined()) {
79
145
      // Build map of atoms names to detect duplicates
80
145
      if (!atom->name().empty())
81
95
        buildDuplicateNameMap(*atom);
82
145
83
145
      // Find references to unnamed atoms and create ref-names for them.
84
273
      for (const lld::Reference *ref : *atom) {
85
273
        // create refname for any unnamed reference target
86
273
        const lld::Atom *target = ref->target();
87
273
        if ((target != nullptr) && target->name().empty()) {
88
22
          std::string storage;
89
22
          llvm::raw_string_ostream buffer(storage);
90
22
          buffer << llvm::format("L%03d", _unnamedCounter++);
91
22
          StringRef newName = copyString(buffer.str());
92
22
          _refNames[target] = newName;
93
22
          DEBUG_WITH_TYPE("WriterYAML",
94
22
                          llvm::dbgs() << "unnamed atom: creating ref-name: '"
95
22
                                       << newName << "' ("
96
22
                                       << (const void *)newName.data() << ", "
97
22
                                       << newName.size() << ")\n");
98
22
        }
99
273
      }
100
145
    }
101
33
    for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
102
28
      buildDuplicateNameMap(*undefAtom);
103
28
    }
104
33
    for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
105
9
      buildDuplicateNameMap(*shlibAtom);
106
9
    }
107
33
    for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
108
0
      if (!absAtom->name().empty())
109
0
        buildDuplicateNameMap(*absAtom);
110
0
    }
111
33
  }
112
113
132
  void buildDuplicateNameMap(const lld::Atom &atom) {
114
132
    assert(!atom.name().empty());
115
132
    NameToAtom::iterator pos = _nameMap.find(atom.name());
116
132
    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
132
    } else {
144
132
      // First time we've seen this name, just add it to map.
145
132
      _nameMap[atom.name()] = &atom;
146
132
      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
147
132
                                        << "atom name seen for first time: '"
148
132
                                        << atom.name() << "' ("
149
132
                                        << (const void *)atom.name().data()
150
132
                                        << ", " << atom.name().size() << ")\n");
151
132
    }
152
132
  }
153
154
418
  bool hasRefName(const lld::Atom *atom) { return _refNames.count(atom); }
155
156
37
  StringRef refName(const lld::Atom *atom) {
157
37
    return _refNames.find(atom)->second;
158
37
  }
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
22
  StringRef copyString(StringRef str) {
167
22
    char *s = _storage.Allocate<char>(str.size());
168
22
    memcpy(s, str.data(), str.size());
169
22
    return StringRef(s, str.size());
170
22
  }
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
16
  const lld::Atom *lookup(StringRef name) const {
186
16
    NameToAtom::const_iterator pos = _nameMap.find(name);
187
16
    if (pos != _nameMap.end())
188
16
      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
37
  void add(StringRef name, const lld::Atom *atom) {
197
37
    if (_nameMap.count(name)) {
198
0
      _io.setError(Twine("duplicate atom name: ") + name);
199
37
    } else {
200
37
      _nameMap[name] = atom;
201
37
    }
202
37
  }
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
273
  static void output(const RefKind &kind, void *ctxt, raw_ostream &out) {
261
273
    assert(ctxt != nullptr);
262
273
    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
263
273
    assert(info->_registry);
264
273
    StringRef str;
265
273
    if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value,
266
273
                                               str))
267
273
      out << str;
268
0
    else
269
0
      out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value;
270
273
  }
271
272
16
  static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) {
273
16
    assert(ctxt != nullptr);
274
16
    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
275
16
    assert(info->_registry);
276
16
    if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch,
277
16
                                                 kind.value))
278
16
      return StringRef();
279
0
    return StringRef("unknown reference kind");
280
0
  }
281
282
289
  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
97
  static void enumeration(IO &io, lld::Atom::Scope &value) {
296
97
    io.enumCase(value, "global", lld::Atom::scopeGlobal);
297
97
    io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
298
97
    io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
299
97
  }
300
};
301
302
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
303
10
  static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
304
10
    io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
305
10
    io.enumCase(value, "custom",  lld::DefinedAtom::sectionCustomPreferred);
306
10
    io.enumCase(value, "custom-required",
307
10
                                 lld::DefinedAtom::sectionCustomRequired);
308
10
  }
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
32
  static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
321
32
    io.enumCase(value, "no",           lld::DefinedAtom::mergeNo);
322
32
    io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
323
32
    io.enumCase(value, "as-weak",      lld::DefinedAtom::mergeAsWeak);
324
32
    io.enumCase(value, "as-addressed-weak",
325
32
                                   lld::DefinedAtom::mergeAsWeakAndAddressUsed);
326
32
    io.enumCase(value, "by-content",   lld::DefinedAtom::mergeByContent);
327
32
    io.enumCase(value, "same-name-and-size",
328
32
                lld::DefinedAtom::mergeSameNameAndSize);
329
32
    io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
330
32
  }
331
};
332
333
template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
334
17
  static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
335
17
    io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
336
17
    io.enumCase(value, "never",  lld::DefinedAtom::deadStripNever);
337
17
    io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
338
17
  }
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
110
  static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
377
110
    io.enumCase(value, "unknown",         DefinedAtom::typeUnknown);
378
110
    io.enumCase(value, "code",            DefinedAtom::typeCode);
379
110
    io.enumCase(value, "stub",            DefinedAtom::typeStub);
380
110
    io.enumCase(value, "constant",        DefinedAtom::typeConstant);
381
110
    io.enumCase(value, "data",            DefinedAtom::typeData);
382
110
    io.enumCase(value, "quick-data",      DefinedAtom::typeDataFast);
383
110
    io.enumCase(value, "zero-fill",       DefinedAtom::typeZeroFill);
384
110
    io.enumCase(value, "zero-fill-quick", DefinedAtom::typeZeroFillFast);
385
110
    io.enumCase(value, "const-data",      DefinedAtom::typeConstData);
386
110
    io.enumCase(value, "got",             DefinedAtom::typeGOT);
387
110
    io.enumCase(value, "resolver",        DefinedAtom::typeResolver);
388
110
    io.enumCase(value, "branch-island",   DefinedAtom::typeBranchIsland);
389
110
    io.enumCase(value, "branch-shim",     DefinedAtom::typeBranchShim);
390
110
    io.enumCase(value, "stub-helper",     DefinedAtom::typeStubHelper);
391
110
    io.enumCase(value, "c-string",        DefinedAtom::typeCString);
392
110
    io.enumCase(value, "utf16-string",    DefinedAtom::typeUTF16String);
393
110
    io.enumCase(value, "unwind-cfi",      DefinedAtom::typeCFI);
394
110
    io.enumCase(value, "unwind-lsda",     DefinedAtom::typeLSDA);
395
110
    io.enumCase(value, "const-4-byte",    DefinedAtom::typeLiteral4);
396
110
    io.enumCase(value, "const-8-byte",    DefinedAtom::typeLiteral8);
397
110
    io.enumCase(value, "const-16-byte",   DefinedAtom::typeLiteral16);
398
110
    io.enumCase(value, "lazy-pointer",    DefinedAtom::typeLazyPointer);
399
110
    io.enumCase(value, "lazy-dylib-pointer",
400
110
                                          DefinedAtom::typeLazyDylibPointer);
401
110
    io.enumCase(value, "cfstring",        DefinedAtom::typeCFString);
402
110
    io.enumCase(value, "initializer-pointer",
403
110
                                          DefinedAtom::typeInitializerPtr);
404
110
    io.enumCase(value, "terminator-pointer",
405
110
                                          DefinedAtom::typeTerminatorPtr);
406
110
    io.enumCase(value, "c-string-pointer",DefinedAtom::typeCStringPtr);
407
110
    io.enumCase(value, "objc-class-pointer",
408
110
                                          DefinedAtom::typeObjCClassPtr);
409
110
    io.enumCase(value, "objc-category-list",
410
110
                                          DefinedAtom::typeObjC2CategoryList);
411
110
    io.enumCase(value, "objc-image-info",
412
110
                                          DefinedAtom::typeObjCImageInfo);
413
110
    io.enumCase(value, "objc-method-list",
414
110
                                          DefinedAtom::typeObjCMethodList);
415
110
    io.enumCase(value, "objc-class1",     DefinedAtom::typeObjC1Class);
416
110
    io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);
417
110
    io.enumCase(value, "interposing-tuples",
418
110
                                          DefinedAtom::typeInterposingTuples);
419
110
    io.enumCase(value, "lto-temp",        DefinedAtom::typeTempLTO);
420
110
    io.enumCase(value, "compact-unwind",  DefinedAtom::typeCompactUnwindInfo);
421
110
    io.enumCase(value, "unwind-info",     DefinedAtom::typeProcessedUnwindInfo);
422
110
    io.enumCase(value, "tlv-thunk",       DefinedAtom::typeThunkTLV);
423
110
    io.enumCase(value, "tlv-data",        DefinedAtom::typeTLVInitialData);
424
110
    io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);
425
110
    io.enumCase(value, "tlv-initializer-ptr",
426
110
                                          DefinedAtom::typeTLVInitializerPtr);
427
110
    io.enumCase(value, "mach_header",     DefinedAtom::typeMachHeader);
428
110
    io.enumCase(value, "dso_handle",      DefinedAtom::typeDSOHandle);
429
110
    io.enumCase(value, "sectcreate",      DefinedAtom::typeSectCreate);
430
110
  }
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
12
  static void enumeration(IO &io, lld::SharedLibraryAtom::Type &value) {
451
12
    io.enumCase(value, "code",    lld::SharedLibraryAtom::Type::Code);
452
12
    io.enumCase(value, "data",    lld::SharedLibraryAtom::Type::Data);
453
12
    io.enumCase(value, "unknown", lld::SharedLibraryAtom::Type::Unknown);
454
12
  }
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
91
                     raw_ostream &out) {
464
91
    if (value.modulus == 0) {
465
71
      out << llvm::format("%d", value.value);
466
71
    } else {
467
20
      out << llvm::format("%d mod %d", value.modulus, value.value);
468
20
    }
469
91
  }
470
471
  static StringRef input(StringRef scalar, void *ctxt,
472
4
                         lld::DefinedAtom::Alignment &value) {
473
4
    value.modulus = 0;
474
4
    size_t modStart = scalar.find("mod");
475
4
    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
4
    unsigned int power;
487
4
    if (scalar.getAsInteger(0, power)) {
488
0
      return "malformed alignment power";
489
0
    }
490
4
    value.value = power;
491
4
    if (value.modulus >= power) {
492
0
      return "malformed alignment, modulus too large for power";
493
0
    }
494
4
    return StringRef(); // returning empty string means success
495
4
  }
496
497
95
  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
57
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
57
    if (index >= seq._atoms.size())
521
57
      seq._atoms.resize(index + 1);
522
57
    return seq._atoms[index].get();
523
57
  }
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
49
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
49
    if (index >= seq._atoms.size())
521
49
      seq._atoms.resize(index + 1);
522
49
    return seq._atoms[index].get();
523
49
  }
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
5
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
5
    if (index >= seq._atoms.size())
521
5
      seq._atoms.resize(index + 1);
522
5
    return seq._atoms[index].get();
523
5
  }
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
3
  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
520
3
    if (index >= seq._atoms.size())
521
3
      seq._atoms.resize(index + 1);
522
3
    return seq._atoms[index].get();
523
3
  }
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
53
  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
33
  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
15
  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
5
  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
182
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
182
    assert(io.outputting() && "AtomRange only used when outputting");
531
182
    assert(index < seq.size() && "Out of range access");
532
182
    return seq[index].get();
533
182
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::DefinedAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::DefinedAtom>&, unsigned long)
Line
Count
Source
529
145
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
145
    assert(io.outputting() && "AtomRange only used when outputting");
531
145
    assert(index < seq.size() && "Out of range access");
532
145
    return seq[index].get();
533
145
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::UndefinedAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::UndefinedAtom>&, unsigned long)
Line
Count
Source
529
28
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
28
    assert(io.outputting() && "AtomRange only used when outputting");
531
28
    assert(index < seq.size() && "Out of range access");
532
28
    return seq[index].get();
533
28
  }
llvm::yaml::SequenceTraits<lld::File::AtomRange<lld::SharedLibraryAtom>, void>::element(llvm::yaml::IO&, lld::File::AtomRange<lld::SharedLibraryAtom>&, unsigned long)
Line
Count
Source
529
9
  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
530
9
    assert(io.outputting() && "AtomRange only used when outputting");
531
9
    assert(index < seq.size() && "Out of range access");
532
9
    return seq[index].get();
533
9
  }
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
2.31k
  static void output(const ImplicitHex8 &val, void *, raw_ostream &out) {
540
2.31k
    uint8_t num = val;
541
2.31k
    out << llvm::format("%02X", num);
542
2.31k
  }
543
544
647
  static StringRef input(StringRef str, void *, ImplicitHex8 &val) {
545
647
    unsigned long long n;
546
647
    if (getAsUnsignedInteger(str, 16, n))
547
0
      return "invalid two-digit-hex number";
548
647
    if (n > 0xFF)
549
0
      return "out of range two-digit-hex number";
550
647
    val = n;
551
647
    return StringRef(); // returning empty string means success
552
647
  }
553
554
2.96k
  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
128
                                   size_t index) {
564
128
    if (index >= seq.size())
565
128
      seq.resize(index + 1);
566
128
    return seq[index];
567
128
  }
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
11
        _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
33
        _absoluteAtomsRef(file->absolute()) {
640
33
    }
641
642
44
    ~NormalizedFile() override {
643
44
    }
644
645
    const lld::File *denormalize(IO &io);
646
647
33
    const AtomRange<lld::DefinedAtom> defined() const override {
648
33
      return _definedAtomsRef;
649
33
    }
650
651
22
    const AtomRange<lld::UndefinedAtom> undefined() const override {
652
22
      return _undefinedAtomsRef;
653
22
    }
654
655
22
    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
656
22
      return _sharedLibraryAtomsRef;
657
22
    }
658
659
22
    const AtomRange<lld::AbsoluteAtom> absolute() const override {
660
22
      return _absoluteAtomsRef;
661
22
    }
662
663
11
    void clearAtoms() override {
664
11
      _definedAtoms._atoms.clear();
665
11
      _undefinedAtoms._atoms.clear();
666
11
      _sharedLibraryAtoms._atoms.clear();
667
11
      _absoluteAtoms._atoms.clear();
668
11
    }
669
670
    // Allocate a new copy of this string in _storage, so the strings
671
    // can be freed when File is destroyed.
672
57
    StringRef copyString(StringRef str) {
673
57
      char *s = _storage.Allocate<char>(str.size());
674
57
      memcpy(s, str.data(), str.size());
675
57
      return StringRef(s, str.size());
676
57
    }
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
161
  static void mapping(IO &io, const lld::File *&file) {
693
161
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
694
161
    assert(info != nullptr);
695
161
    // Let any register tag handler process this.
696
161
    if (info->_registry && info->_registry->handleTaggedDoc(io, file))
697
126
      return;
698
35
    // If no registered handler claims this tag and there is no tag,
699
35
    // grandfather in as "!native".
700
35
    if (io.mapTag("!native", true) || 
io.mapTag("tag:yaml.org,2002:map")2
)
701
34
      mappingAtoms(io, file);
702
35
  }
703
704
44
  static void mappingAtoms(IO &io, const lld::File *&file) {
705
44
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
706
44
    MappingNormalizationHeap<NormalizedFile, const lld::File *>
707
44
      keys(io, file, nullptr);
708
44
    assert(info != nullptr);
709
44
    info->_file = keys.operator->();
710
44
711
44
    io.mapOptional("path",                 keys->_path);
712
44
713
44
    if (io.outputting()) {
714
33
      io.mapOptional("defined-atoms",        keys->_definedAtomsRef);
715
33
      io.mapOptional("undefined-atoms",      keys->_undefinedAtomsRef);
716
33
      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
717
33
      io.mapOptional("absolute-atoms",       keys->_absoluteAtomsRef);
718
33
    } else {
719
11
      io.mapOptional("defined-atoms",        keys->_definedAtoms);
720
11
      io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
721
11
      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
722
11
      io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
723
11
    }
724
44
  }
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
16
          _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
273
          _tag(ref->tag()) {
751
273
      _mappedKind.ns = ref->kindNamespace();
752
273
      _mappedKind.arch = ref->kindArch();
753
273
      _mappedKind.value = ref->kindValue();
754
273
    }
755
756
16
    const lld::Reference *denormalize(IO &io) {
757
16
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
758
16
      assert(info != nullptr);
759
16
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
760
16
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
761
16
      if (!_targetName.empty())
762
16
        _targetName = f->copyString(_targetName);
763
16
      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
764
16
                                        << "created Reference to name: '"
765
16
                                        << _targetName << "' ("
766
16
                                        << (const void *)_targetName.data()
767
16
                                        << ", " << _targetName.size() << ")\n");
768
16
      setKindNamespace(_mappedKind.ns);
769
16
      setKindArch(_mappedKind.arch);
770
16
      setKindValue(_mappedKind.value);
771
16
      return this;
772
16
    }
773
774
    void bind(const RefNameResolver &);
775
    static StringRef targetName(IO &io, const lld::Reference *ref);
776
777
23
    uint64_t offsetInAtom() const override { return _offset; }
778
56
    const lld::Atom *target() const override { return _target; }
779
9
    Addend addend() const override { return _addend; }
780
0
    void setAddend(Addend a) override { _addend = a; }
781
18
    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
289
  static void mapping(IO &io, const lld::Reference *&ref) {
792
289
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
793
289
    MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
794
289
        io, ref, &info->_file->allocator());
795
289
796
289
    io.mapRequired("kind",   keys->_mappedKind);
797
289
    io.mapOptional("offset", keys->_offset);
798
289
    io.mapOptional("target", keys->_targetName);
799
289
    io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
800
289
    io.mapOptional("tag",    keys->_tag, 0u);
801
289
  }
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
49
        : _file(fileFromContext(io)), _contentType(), _alignment(1) {
811
49
      static uint32_t ordinalCounter = 1;
812
49
      _ordinal = ordinalCounter++;
813
49
    }
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
145
          _sectionSize(atom->sectionSize()) {
825
145
      for (const lld::Reference *r : *atom)
826
273
        _references.push_back(r);
827
145
      if (!atom->occupiesDiskSpace())
828
1
        return;
829
144
      ArrayRef<uint8_t> cont = atom->rawContent();
830
144
      _content.reserve(cont.size());
831
144
      for (uint8_t x : cont)
832
2.31k
        _content.push_back(x);
833
144
    }
834
835
194
    ~NormalizedAtom() override = default;
836
837
49
    const lld::DefinedAtom *denormalize(IO &io) {
838
49
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
839
49
      assert(info != nullptr);
840
49
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
841
49
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
842
49
      if (!_name.empty())
843
29
        _name = f->copyString(_name);
844
49
      if (!_refName.empty())
845
0
        _refName = f->copyString(_refName);
846
49
      if (!_sectionName.empty())
847
1
        _sectionName = f->copyString(_sectionName);
848
49
      DEBUG_WITH_TYPE("WriterYAML",
849
49
                      llvm::dbgs() << "created DefinedAtom named: '" << _name
850
49
                                   << "' (" << (const void *)_name.data()
851
49
                                   << ", " << _name.size() << ")\n");
852
49
      return this;
853
49
    }
854
855
    void bind(const RefNameResolver &);
856
857
    // Extract current File object from YAML I/O parsing context
858
194
    const lld::File &fileFromContext(IO &io) {
859
194
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
860
194
      assert(info != nullptr);
861
194
      assert(info->_file != nullptr);
862
194
      return *info->_file;
863
194
    }
864
865
159
    const lld::File &file() const override { return _file; }
866
199
    StringRef name() const override { return _name; }
867
157
    uint64_t size() const override { return _size; }
868
106
    Scope scope() const override { return _scope; }
869
3
    Interposable interposable() const override { return _interpose; }
870
78
    Merge merge() const override { return _merge; }
871
832
    ContentType contentType() const override { return _contentType; }
872
46
    Alignment alignment() const override { return _alignment; }
873
46
    SectionChoice sectionChoice() const override { return _sectionChoice; }
874
3
    StringRef customSectionName() const override { return _sectionName; }
875
2
    uint64_t sectionSize() const override { return _sectionSize; }
876
33
    DeadStripKind deadStrip() const override { return _deadStrip; }
877
2
    DynamicExport dynamicExport() const override { return _dynamicExport; }
878
2
    CodeModel codeModel() const override { return _codeModel; }
879
277
    ContentPermissions permissions() const override { return _permissions; }
880
107
    ArrayRef<uint8_t> rawContent() const override {
881
107
      if (!occupiesDiskSpace())
882
0
        return ArrayRef<uint8_t>();
883
107
      return ArrayRef<uint8_t>(
884
107
          reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
885
107
    }
886
887
38
    uint64_t ordinal() const override { return _ordinal; }
888
889
387
    reference_iterator begin() const override {
890
387
      uintptr_t index = 0;
891
387
      const void *it = reinterpret_cast<const void *>(index);
892
387
      return reference_iterator(*this, it);
893
387
    }
894
387
    reference_iterator end() const override {
895
387
      uintptr_t index = _references.size();
896
387
      const void *it = reinterpret_cast<const void *>(index);
897
387
      return reference_iterator(*this, it);
898
387
    }
899
112
    const lld::Reference *derefIterator(const void *it) const override {
900
112
      uintptr_t index = reinterpret_cast<uintptr_t>(it);
901
112
      assert(index < _references.size());
902
112
      return _references[index];
903
112
    }
904
108
    void incrementIterator(const void *&it) const override {
905
108
      uintptr_t index = reinterpret_cast<uintptr_t>(it);
906
108
      ++index;
907
108
      it = reinterpret_cast<const void *>(index);
908
108
    }
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
194
  static void mapping(IO &io, const lld::DefinedAtom *&atom) {
942
194
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
943
194
    MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
944
194
        io, atom, &info->_file->allocator());
945
194
    if (io.outputting()) {
946
145
      // If writing YAML, check if atom needs a ref-name.
947
145
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
948
145
      assert(info != nullptr);
949
145
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
950
145
      assert(f);
951
145
      assert(f->_rnb);
952
145
      if (f->_rnb->hasRefName(atom)) {
953
15
        keys->_refName = f->_rnb->refName(atom);
954
15
      }
955
145
    }
956
194
957
194
    io.mapOptional("name",             keys->_name,    StringRef());
958
194
    io.mapOptional("ref-name",         keys->_refName, StringRef());
959
194
    io.mapOptional("scope",            keys->_scope,
960
194
                                         DefinedAtom::scopeTranslationUnit);
961
194
    io.mapOptional("type",             keys->_contentType,
962
194
                                         DefinedAtom::typeCode);
963
194
    io.mapOptional("content",          keys->_content);
964
194
    io.mapOptional("size",             keys->_size, (uint64_t)keys->_content.size());
965
194
    io.mapOptional("interposable",     keys->_interpose,
966
194
                                         DefinedAtom::interposeNo);
967
194
    io.mapOptional("merge",            keys->_merge, DefinedAtom::mergeNo);
968
194
    io.mapOptional("alignment",        keys->_alignment,
969
194
                                         DefinedAtom::Alignment(1));
970
194
    io.mapOptional("section-choice",   keys->_sectionChoice,
971
194
                                         DefinedAtom::sectionBasedOnContent);
972
194
    io.mapOptional("section-name",     keys->_sectionName, StringRef());
973
194
    io.mapOptional("section-size",     keys->_sectionSize, (uint64_t)0);
974
194
    io.mapOptional("dead-strip",       keys->_deadStrip,
975
194
                                         DefinedAtom::deadStripNormal);
976
194
    io.mapOptional("dynamic-export",   keys->_dynamicExport,
977
194
                                         DefinedAtom::dynamicExportNormal);
978
194
    io.mapOptional("code-model",       keys->_codeModel, DefinedAtom::codeNA);
979
194
    // default permissions based on content type
980
194
    io.mapOptional("permissions",      keys->_permissions,
981
194
                                         DefinedAtom::permissions(
982
194
                                                          keys->_contentType));
983
194
    io.mapOptional("references",       keys->_references);
984
194
  }
985
};
986
987
template <> struct MappingTraits<lld::DefinedAtom *> {
988
194
  static void mapping(IO &io, lld::DefinedAtom *&atom) {
989
194
    const lld::DefinedAtom *atomPtr = atom;
990
194
    MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
991
194
    atom = const_cast<lld::DefinedAtom *>(atomPtr);
992
194
  }
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
5
        : _file(fileFromContext(io)), _canBeNull(canBeNullNever) {}
1001
1002
    NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
1003
        : _file(fileFromContext(io)), _name(atom->name()),
1004
28
          _canBeNull(atom->canBeNull()) {}
1005
1006
33
    ~NormalizedAtom() override = default;
1007
1008
5
    const lld::UndefinedAtom *denormalize(IO &io) {
1009
5
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1010
5
      assert(info != nullptr);
1011
5
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1012
5
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1013
5
      if (!_name.empty())
1014
5
        _name = f->copyString(_name);
1015
5
1016
5
      DEBUG_WITH_TYPE("WriterYAML",
1017
5
                      llvm::dbgs() << "created UndefinedAtom named: '" << _name
1018
5
                      << "' (" << (const void *)_name.data() << ", "
1019
5
                      << _name.size() << ")\n");
1020
5
      return this;
1021
5
    }
1022
1023
    // Extract current File object from YAML I/O parsing context
1024
33
    const lld::File &fileFromContext(IO &io) {
1025
33
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1026
33
      assert(info != nullptr);
1027
33
      assert(info->_file != nullptr);
1028
33
      return *info->_file;
1029
33
    }
1030
1031
0
    const lld::File &file() const override { return _file; }
1032
15
    StringRef name() const override { return _name; }
1033
0
    CanBeNull canBeNull() const override { return _canBeNull; }
1034
1035
    const lld::File     &_file;
1036
    StringRef            _name;
1037
    CanBeNull            _canBeNull;
1038
  };
1039
1040
33
  static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
1041
33
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1042
33
    MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
1043
33
        io, atom, &info->_file->allocator());
1044
33
1045
33
    io.mapRequired("name",        keys->_name);
1046
33
    io.mapOptional("can-be-null", keys->_canBeNull,
1047
33
                                  lld::UndefinedAtom::canBeNullNever);
1048
33
  }
1049
};
1050
1051
template <> struct MappingTraits<lld::UndefinedAtom *> {
1052
33
  static void mapping(IO &io, lld::UndefinedAtom *&atom) {
1053
33
    const lld::UndefinedAtom *atomPtr = atom;
1054
33
    MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
1055
33
    atom = const_cast<lld::UndefinedAtom *>(atomPtr);
1056
33
  }
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
3
          _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
9
          _type(atom->type()), _size(atom->size()) {}
1071
1072
12
    ~NormalizedAtom() override = default;
1073
1074
3
    const lld::SharedLibraryAtom *denormalize(IO &io) {
1075
3
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1076
3
      assert(info != nullptr);
1077
3
      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1078
3
      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1079
3
      if (!_name.empty())
1080
3
        _name = f->copyString(_name);
1081
3
      if (!_loadName.empty())
1082
3
        _loadName = f->copyString(_loadName);
1083
3
1084
3
      DEBUG_WITH_TYPE("WriterYAML",
1085
3
                      llvm::dbgs() << "created SharedLibraryAtom named: '"
1086
3
                                   << _name << "' ("
1087
3
                                   << (const void *)_name.data()
1088
3
                                   << ", " << _name.size() << ")\n");
1089
3
      return this;
1090
3
    }
1091
1092
    // Extract current File object from YAML I/O parsing context
1093
12
    const lld::File &fileFromContext(IO &io) {
1094
12
      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1095
12
      assert(info != nullptr);
1096
12
      assert(info->_file != nullptr);
1097
12
      return *info->_file;
1098
12
    }
1099
1100
0
    const lld::File &file() const override { return _file; }
1101
15
    StringRef name() const override { return _name; }
1102
5
    StringRef loadName() const override { return _loadName; }
1103
2
    bool canBeNullAtRuntime() const override { return _canBeNull; }
1104
1
    Type type() const override { return _type; }
1105
1
    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
12
  static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
1116
12
1117
12
    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1118
12
    MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
1119
12
    keys(io, atom, &info->_file->allocator());
1120
12
1121
12
    io.mapRequired("name",        keys->_name);
1122
12
    io.mapOptional("load-name",   keys->_loadName);
1123
12
    io.mapOptional("can-be-null", keys->_canBeNull, (ShlibCanBeNull) false);
1124
12
    io.mapOptional("type",        keys->_type, SharedLibraryAtom::Type::Code);
1125
12
    io.mapOptional("size",        keys->_size, uint64_t(0));
1126
12
  }
1127
};
1128
1129
template <> struct MappingTraits<lld::SharedLibraryAtom *> {
1130
12
  static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
1131
12
    const lld::SharedLibraryAtom *atomPtr = atom;
1132
12
    MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
1133
12
    atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
1134
12
  }
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
11
RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
1221
11
  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1222
11
  NormalizedAtom;
1223
49
  for (const lld::DefinedAtom *a : file->defined()) {
1224
49
    const auto *na = (const NormalizedAtom *)a;
1225
49
    if (!na->_refName.empty())
1226
0
      add(na->_refName, a);
1227
49
    else if (!na->_name.empty())
1228
29
      add(na->_name, a);
1229
49
  }
1230
11
1231
11
  for (const lld::UndefinedAtom *a : file->undefined())
1232
5
    add(a->name(), a);
1233
11
1234
11
  for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
1235
3
    add(a->name(), a);
1236
11
1237
11
  typedef MappingTraits<const lld::AbsoluteAtom *>::NormalizedAtom NormAbsAtom;
1238
11
  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
11
}
1246
1247
inline const lld::File *
1248
11
MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
1249
11
  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1250
11
  NormalizedAtom;
1251
11
1252
11
  RefNameResolver nameResolver(this, io);
1253
11
  // Now that all atoms are parsed, references can be bound.
1254
49
  for (const lld::DefinedAtom *a : this->defined()) {
1255
49
    auto *normAtom = (NormalizedAtom *)const_cast<DefinedAtom *>(a);
1256
49
    normAtom->bind(nameResolver);
1257
49
  }
1258
11
1259
11
  return this;
1260
11
}
1261
1262
inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
1263
49
    const RefNameResolver &resolver) {
1264
49
  typedef MappingTraits<const lld::Reference *>::NormalizedReference
1265
49
  NormalizedReference;
1266
49
  for (const lld::Reference *ref : _references) {
1267
16
    auto *normRef = (NormalizedReference *)const_cast<Reference *>(ref);
1268
16
    normRef->bind(resolver);
1269
16
  }
1270
49
}
1271
1272
inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
1273
16
    const RefNameResolver &resolver) {
1274
16
  _target = resolver.lookup(_targetName);
1275
16
}
1276
1277
inline StringRef
1278
MappingTraits<const lld::Reference *>::NormalizedReference::targetName(
1279
273
    IO &io, const lld::Reference *ref) {
1280
273
  if (ref->target() == nullptr)
1281
0
    return StringRef();
1282
273
  YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1283
273
  assert(info != nullptr);
1284
273
  typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1285
273
  NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1286
273
  RefNameBuilder &rnb = *f->_rnb;
1287
273
  if (rnb.hasRefName(ref->target()))
1288
22
    return rnb.refName(ref->target());
1289
251
  return ref->target()->name();
1290
251
}
1291
1292
namespace lld {
1293
namespace yaml {
1294
1295
class Writer : public lld::Writer {
1296
public:
1297
33
  Writer(const LinkingContext &context) : _ctx(context) {}
1298
1299
33
  llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
1300
33
    // Create stream to path.
1301
33
    std::error_code ec;
1302
33
    llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_Text);
1303
33
    if (ec)
1304
0
      return llvm::errorCodeToError(ec);
1305
33
1306
33
    // Create yaml Output writer, using yaml options for context.
1307
33
    YamlContext yamlContext;
1308
33
    yamlContext._ctx = &_ctx;
1309
33
    yamlContext._registry = &_ctx.registry();
1310
33
    llvm::yaml::Output yout(out, &yamlContext);
1311
33
1312
33
    // Write yaml output.
1313
33
    const lld::File *fileRef = &file;
1314
33
    yout << fileRef;
1315
33
1316
33
    return llvm::Error::success();
1317
33
  }
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
45
  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1330
45
    if (io.mapTag("!native")) {
1331
10
      MappingTraits<const lld::File *>::mappingAtoms(io, file);
1332
10
      return true;
1333
10
    }
1334
35
    return false;
1335
35
  }
1336
};
1337
1338
/// Handles !archive tagged yaml documents.
1339
class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
1340
35
  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1341
35
    if (io.mapTag("!archive")) {
1342
0
      MappingTraits<const lld::File *>::mappingArchive(io, file);
1343
0
      return true;
1344
0
    }
1345
35
    return false;
1346
35
  }
1347
};
1348
1349
class YAMLReader : public Reader {
1350
public:
1351
106
  YAMLReader(const Registry &registry) : _registry(registry) {}
1352
1353
128
  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
1354
128
    StringRef name = mb.getBufferIdentifier();
1355
128
    return name.endswith(".objtxt") || 
name.endswith(".yaml")125
;
1356
128
  }
1357
1358
  ErrorOr<std::unique_ptr<File>>
1359
  loadFile(std::unique_ptr<MemoryBuffer> mb,
1360
128
           const class Registry &) const override {
1361
128
    // Create YAML Input Reader.
1362
128
    YamlContext yamlContext;
1363
128
    yamlContext._registry = &_registry;
1364
128
    yamlContext._path = mb->getBufferIdentifier();
1365
128
    llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
1366
128
1367
128
    // Fill vector with File objects created by parsing yaml.
1368
128
    std::vector<const lld::File *> createdFiles;
1369
128
    yin >> createdFiles;
1370
128
    assert(createdFiles.size() == 1);
1371
128
1372
128
    // Error out now if there were parsing errors.
1373
128
    if (yin.error())
1374
1
      return make_error_code(lld::YamlReaderError::illegal_value);
1375
127
1376
127
    std::shared_ptr<MemoryBuffer> smb(mb.release());
1377
127
    const File *file = createdFiles[0];
1378
127
    // Note: loadFile() should return vector of *const* File
1379
127
    File *f = const_cast<File *>(file);
1380
127
    f->setLastError(std::error_code());
1381
127
    f->setSharedMemoryBuffer(smb);
1382
127
    return std::unique_ptr<File>(f);
1383
127
  }
1384
1385
private:
1386
  const Registry &_registry;
1387
};
1388
1389
} // end anonymous namespace
1390
1391
106
void Registry::addSupportYamlFiles() {
1392
106
  add(std::unique_ptr<Reader>(new YAMLReader(*this)));
1393
106
  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1394
106
                                    new NativeYamlIOTaggedDocumentHandler()));
1395
106
  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1396
106
                                    new ArchiveYamlIOTaggedDocumentHandler()));
1397
106
}
1398
1399
33
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
1400
33
  return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
1401
33
}
1402
1403
} // end namespace lld