| //===- Core/YamlWriter.cpp - Writes YAML ----------------------------------===// |
| // |
| // The LLVM Linker |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "YamlKeyValues.h" |
| |
| #include "lld/Core/YamlWriter.h" |
| #include "lld/Core/Atom.h" |
| #include "lld/Core/File.h" |
| #include "lld/Core/Reference.h" |
| |
| #include "llvm/ADT/OwningPtr.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Support/DataTypes.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/system_error.h" |
| |
| #include <vector> |
| |
| namespace lld { |
| namespace yaml { |
| |
| class Handler : public File::AtomHandler { |
| public: |
| Handler(llvm::raw_ostream &out) : _out(out), _firstAtom(true) { } |
| |
| virtual void doFile(const class File &) { _firstAtom = true; } |
| |
| virtual void doDefinedAtom(const class DefinedAtom &atom) { |
| // add blank line between atoms for readability |
| if ( !_firstAtom ) |
| _out << "\n"; |
| _firstAtom = false; |
| |
| _out << " - " |
| << KeyValues::nameKeyword |
| << ":" |
| << spacePadding(KeyValues::nameKeyword) |
| << atom.name() |
| << "\n"; |
| |
| if ( atom.internalName() != KeyValues::internalNameDefault ) { |
| _out << " " |
| << KeyValues::internalNameKeyword |
| << ":" |
| << spacePadding(KeyValues::internalNameKeyword) |
| << KeyValues::internalName(atom.internalName()) |
| << "\n"; |
| } |
| |
| if ( atom.definition() != KeyValues::definitionDefault ) { |
| _out << " " |
| << KeyValues::definitionKeyword |
| << ":" |
| << spacePadding(KeyValues::definitionKeyword) |
| << KeyValues::definition(atom.definition()) |
| << "\n"; |
| } |
| |
| if ( atom.scope() != KeyValues::scopeDefault ) { |
| _out << " " |
| << KeyValues::scopeKeyword |
| << ":" |
| << spacePadding(KeyValues::scopeKeyword) |
| << KeyValues::scope(atom.scope()) |
| << "\n"; |
| } |
| |
| if ( atom.interposable() != KeyValues::interposableDefault ) { |
| _out << " " |
| << KeyValues::interposableKeyword |
| << ":" |
| << spacePadding(KeyValues::interposableKeyword) |
| << KeyValues::interposable(atom.interposable()) |
| << "\n"; |
| } |
| |
| if ( atom.merge() != KeyValues::mergeDefault ) { |
| _out << " " |
| << KeyValues::mergeKeyword |
| << ":" |
| << spacePadding(KeyValues::mergeKeyword) |
| << KeyValues::merge(atom.merge()) |
| << "\n"; |
| } |
| |
| if ( atom.contentType() != KeyValues::contentTypeDefault ) { |
| _out << " " |
| << KeyValues::contentTypeKeyword |
| << ":" |
| << spacePadding(KeyValues::contentTypeKeyword) |
| << KeyValues::contentType(atom.contentType()) |
| << "\n"; |
| } |
| |
| if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) { |
| _out << " " |
| << KeyValues::deadStripKindKeyword |
| << ":" |
| << spacePadding(KeyValues::deadStripKindKeyword) |
| << KeyValues::deadStripKind(atom.deadStrip()) |
| << "\n"; |
| } |
| |
| if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) { |
| _out << " " |
| << KeyValues::sectionChoiceKeyword |
| << ":" |
| << spacePadding(KeyValues::sectionChoiceKeyword) |
| << KeyValues::sectionChoice(atom.sectionChoice()) |
| << "\n"; |
| assert( ! atom.customSectionName().empty() ); |
| _out << " " |
| << KeyValues::sectionNameKeyword |
| << ":" |
| << spacePadding(KeyValues::sectionNameKeyword) |
| << atom.customSectionName() |
| << "\n"; |
| } |
| |
| if ( atom.isThumb() != KeyValues::isThumbDefault ) { |
| _out << " " |
| << KeyValues::isThumbKeyword |
| << ":" |
| << spacePadding(KeyValues::isThumbKeyword) |
| << KeyValues::isThumb(atom.isThumb()) |
| << "\n"; |
| } |
| |
| if ( atom.isAlias() != KeyValues::isAliasDefault ) { |
| _out << " " |
| << KeyValues::isAliasKeyword |
| << ":" |
| << spacePadding(KeyValues::isAliasKeyword) |
| << KeyValues::isAlias(atom.isAlias()) |
| << "\n"; |
| } |
| |
| if ( atom.contentType() != DefinedAtom::typeZeroFill ) { |
| _out << " " |
| << KeyValues::contentKeyword |
| << ":" |
| << spacePadding(KeyValues::contentKeyword) |
| << "[ "; |
| llvm::ArrayRef<uint8_t> arr = atom.rawContent(); |
| bool needComma = false; |
| for (unsigned int i=0; i < arr.size(); ++i) { |
| if ( needComma ) |
| _out << ", "; |
| _out << hexdigit(arr[i] >> 4); |
| _out << hexdigit(arr[i] & 0x0F); |
| needComma = true; |
| } |
| _out << " ]\n"; |
| } |
| |
| if (atom.referencesBegin() != atom.referencesEnd()) { |
| _out << " fixups:\n"; |
| for (Reference::iterator it = atom.referencesBegin(), |
| end = atom.referencesEnd(); it != end; ++it) { |
| _out << " - kind: " << it->kind << "\n"; |
| _out << " offset: " << it->offsetInAtom << "\n"; |
| } |
| } |
| |
| } |
| |
| virtual void doUndefinedAtom(const class UndefinedAtom &atom) { |
| |
| } |
| |
| |
| private: |
| // return a string of the correct number of spaces to align value |
| const char* spacePadding(const char* key) { |
| const char* spaces = " "; |
| assert(strlen(spaces) > strlen(key)); |
| return &spaces[strlen(key)]; |
| } |
| |
| char hexdigit(uint8_t nibble) { |
| if ( nibble < 0x0A ) |
| return '0' + nibble; |
| else |
| return 'A' + nibble - 0x0A; |
| } |
| |
| llvm::raw_ostream& _out; |
| bool _firstAtom; |
| }; |
| |
| void writeObjectText(File &file, llvm::raw_ostream &out) { |
| Handler h(out); |
| out << "---\n"; |
| out << "atoms:\n"; |
| file.forEachAtom(h); |
| out << "...\n"; |
| } |
| |
| } // namespace yaml |
| } // namespace lld |