diff options
52 files changed, 1667 insertions, 2693 deletions
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h index ab5f691c34a..e6747b85fff 100644 --- a/lld/include/lld/Core/DefinedAtom.h +++ b/lld/include/lld/Core/DefinedAtom.h @@ -173,6 +173,10 @@ public: uint16_t powerOf2; uint16_t modulus; + + bool operator==(const Alignment &rhs) const { + return (powerOf2 == rhs.powerOf2) && (modulus == rhs.modulus); + } }; /// \brief returns a value for the order of this Atom within its file. diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h index 4042da42367..46d3e1b034e 100644 --- a/lld/include/lld/Core/File.h +++ b/lld/include/lld/Core/File.h @@ -16,6 +16,7 @@ #include "lld/Core/UndefinedAtom.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" #include <vector> @@ -66,9 +67,8 @@ public: return true; } -protected: - template <typename T> class atom_iterator; // forward reference public: + template <typename T> class atom_iterator; // forward reference /// For use interating over DefinedAtoms in this File. typedef atom_iterator<DefinedAtom> defined_iterator; @@ -91,10 +91,6 @@ public: /// call this method when no longer iterating over the File's Atoms. virtual void addAtom(const Atom&) = 0; -protected: - /// only subclasses of File can be instantiated - File(StringRef p) : _path(p) {} - /// Different object file readers may instantiate and manage atoms with /// different data structures. This class is a collection abstraction. /// Each concrete File instance must implement these atom_collection @@ -105,8 +101,8 @@ protected: virtual ~atom_collection() { } virtual atom_iterator<T> begin() const = 0; virtual atom_iterator<T> end() const = 0; - virtual const T* deref(const void* it) const = 0; - virtual void next(const void*& it) const = 0; + virtual const T *deref(const void *it) const = 0; + virtual void next(const void *&it) const = 0; }; /// The class is the iterator type used to iterate through a File's Atoms. @@ -140,7 +136,7 @@ protected: const void* _it; }; -public: + /// Must be implemented to return the atom_collection object for /// all DefinedAtoms in this File. virtual const atom_collection<DefinedAtom>& defined() const = 0; @@ -158,6 +154,10 @@ public: virtual const atom_collection<AbsoluteAtom>& absolute() const = 0; protected: + /// only subclasses of File can be instantiated + File(StringRef p) : _path(p) {} + + /// This is a convenience class for File subclasses which manage their /// atoms as a simple std::vector<>. template <typename T> @@ -182,6 +182,32 @@ protected: std::vector<const T*> _atoms; }; + /// This is a convenience class for File subclasses which need to return + /// an empty collection + template <typename T> + class atom_collection_empty : public atom_collection<T> { + public: + virtual atom_iterator<T> begin() const { + return atom_iterator<T>(*this, nullptr); + } + virtual atom_iterator<T> end() const{ + return atom_iterator<T>(*this, nullptr); + } + virtual const T *deref(const void *it) const { + llvm_unreachable("empty collection should never be accessed"); + } + virtual void next(const void *&it) const { + } + virtual void push_back(const T *element) { + llvm_unreachable("empty collection should never be grown"); + } + }; + + static atom_collection_empty<DefinedAtom> _noDefinedAtoms; + static atom_collection_empty<UndefinedAtom> _noUndefinedAtoms; + static atom_collection_empty<SharedLibraryAtom> _noSharedLibaryAtoms; + static atom_collection_empty<AbsoluteAtom> _noAbsoluteAtoms; + StringRef _path; }; } // namespace lld diff --git a/lld/include/lld/ReaderWriter/ReaderArchive.h b/lld/include/lld/ReaderWriter/ReaderArchive.h index abe868b2ff4..bf98d844429 100644 --- a/lld/include/lld/ReaderWriter/ReaderArchive.h +++ b/lld/include/lld/ReaderWriter/ReaderArchive.h @@ -56,7 +56,7 @@ private: }; /// \brief ReaderArchive is a class for reading archive libraries -class ReaderArchive { +class ReaderArchive : public Reader { public: ReaderArchive(const ReaderOptionsArchive &options) : _options(options) diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp index 768f1d26282..be0b74d685c 100644 --- a/lld/lib/Core/File.cpp +++ b/lld/lib/Core/File.cpp @@ -18,4 +18,10 @@ StringRef File::translationUnitSource() const { return StringRef(); } + +File::atom_collection_empty<DefinedAtom> File::_noDefinedAtoms; +File::atom_collection_empty<UndefinedAtom> File::_noUndefinedAtoms; +File::atom_collection_empty<SharedLibraryAtom> File::_noSharedLibaryAtoms; +File::atom_collection_empty<AbsoluteAtom> File::_noAbsoluteAtoms; + } diff --git a/lld/lib/ReaderWriter/YAML/CMakeLists.txt b/lld/lib/ReaderWriter/YAML/CMakeLists.txt index 72e5d2afe2e..b76246d015b 100644 --- a/lld/lib/ReaderWriter/YAML/CMakeLists.txt +++ b/lld/lib/ReaderWriter/YAML/CMakeLists.txt @@ -1,7 +1,5 @@ add_lld_library(lldYAML - YamlKeyValues.cpp - ReaderYAML.cpp - WriterYAML.cpp + ReaderWriterYAML.cpp ) target_link_libraries(lldYAML diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp new file mode 100644 index 00000000000..cadd2637e08 --- /dev/null +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -0,0 +1,1357 @@ +//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "lld/Core/ArchiveLibraryFile.h" +#include "lld/Core/DefinedAtom.h" +#include "lld/Core/Error.h" +#include "lld/Core/File.h" +#include "lld/Core/LLVM.h" +#include "lld/Core/Reference.h" +#include "lld/ReaderWriter/ReaderYAML.h" +#include "lld/ReaderWriter/WriterYAML.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/YAMLTraits.h" + +#include <string> + +using llvm::yaml::MappingTraits; +using llvm::yaml::ScalarEnumerationTraits; +using llvm::yaml::ScalarTraits; +using llvm::yaml::IO; +using llvm::yaml::SequenceTraits; +using llvm::yaml::DocumentListTraits; + + +/// The conversion of Atoms to and from YAML uses LLVM's YAML I/O. This +/// file just defines template specializations on the lld types which control +/// how the mapping is done to and from YAML. + + +namespace { +/// Most of the traits are context-free and always do the same transformation. +/// But, there are some traits that need some contextual information to properly +/// do their transform. This struct is available via io.getContext() and +/// supplies contextual information. +class ContextInfo { +public: + ContextInfo(const lld::ReaderOptionsYAML &ro) + : _currentFile(nullptr), _readerOptions(&ro), _writerOptions(nullptr) { } + ContextInfo(const lld::WriterOptionsYAML &wo) + : _currentFile(nullptr), _readerOptions(nullptr), _writerOptions(&wo) { } + + lld::File *_currentFile; + const lld::ReaderOptionsYAML *_readerOptions; + const lld::WriterOptionsYAML *_writerOptions; +}; + + +/// Used when writing yaml files. +/// In most cases, atoms names are unambiguous, so references can just +/// use the atom name as the target (e.g. target: foo). But in a few +/// cases that does not work, so ref-names are added. These are labels +/// used only in yaml. The labels do not exist in the Atom model. +/// +/// One need for ref-names are when atoms have no user supplied name +/// (e.g. c-string literal). Another case is when two object files with +/// identically named static functions are merged (ld -r) into one object file. +/// In that case referencing the function by name is ambiguous, so a unique +/// ref-name is added. +class RefNameBuilder { +public: + RefNameBuilder(const lld::File &file) + : _collisionCount(0), _unnamedCounter(0) { + if (&file == nullptr) + return; + // visit all atoms + for (const lld::DefinedAtom *atom : file.defined()) { + // Build map of atoms names to detect duplicates + if (!atom->name().empty()) + buildDuplicateNameMap(*atom); + + // Find references to unnamed atoms and create ref-names for them. + for (const lld::Reference *ref : *atom) { + // create refname for any unnamed reference target + const lld::Atom *target = ref->target(); + if ((target != nullptr) && target->name().empty()) { + std::string storage; + llvm::raw_string_ostream buffer(storage); + buffer << llvm::format("L%03d", _unnamedCounter++); + llvm::StringRef newName = copyString(buffer.str()); + _refNames[target] = newName; + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "unnamed atom: creating ref-name: '" << newName + << "' (" << (void*)newName.data() << ", " + << newName.size() << ")\n"); + } + } + } + for (const lld::UndefinedAtom *undefAtom : file.undefined()) { + buildDuplicateNameMap(*undefAtom); + } + for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) { + buildDuplicateNameMap(*shlibAtom); + } + for (const lld::AbsoluteAtom *absAtom : file.absolute()) { + buildDuplicateNameMap(*absAtom); + } + } + + void buildDuplicateNameMap(const lld::Atom &atom) { + assert(!atom.name().empty()); + NameToAtom::iterator pos = _nameMap.find(atom.name()); + if ( pos != _nameMap.end() ) { + // Found name collision, give each a unique ref-name. + std::string Storage; + llvm::raw_string_ostream buffer(Storage); + buffer << atom.name() << llvm::format(".%03d", ++_collisionCount); + llvm::StringRef newName = copyString(buffer.str()); + _refNames[&atom] = newName; + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "name collsion: creating ref-name: '" << newName + << "' (" << (void*)newName.data() << ", " + << newName.size() << ")\n"); + const lld::Atom *prevAtom = pos->second; + AtomToRefName::iterator pos2 = _refNames.find(prevAtom); + if ( pos2 == _refNames.end() ) { + // Only create ref-name for previous if none already created. + std::string Storage2; + llvm::raw_string_ostream buffer2(Storage2); + buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount); + llvm::StringRef newName2 = copyString(buffer2.str()); + _refNames[prevAtom] = newName2; + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "name collsion: creating ref-name: '" << newName2 + << "' (" << (void*)newName2.data() << ", " + << newName2.size() << ")\n"); + } + } + else { + // First time we've seen this name, just add it to map. + _nameMap[atom.name()] = &atom; + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "atom name seen for first time: '" << atom.name() + << "' (" << (void*)atom.name().data() << ", " + << atom.name().size() << ")\n"); + } + } + + bool hasRefName(const lld::Atom *atom) { + return _refNames.count(atom); + } + + llvm::StringRef refName(const lld::Atom *atom) { + return _refNames.find(atom)->second; + } + +private: + typedef llvm::StringMap<const lld::Atom*> NameToAtom; + typedef llvm::DenseMap<const lld::Atom*, std::string> AtomToRefName; + + // Allocate a new copy of this string and keep track of allocations + // in _stringCopies, so they can be freed when RefNameBuilder is destroyed. + llvm::StringRef copyString(llvm::StringRef str) { + // We want _stringCopies to own the string memory so it is deallocated + // when the File object is destroyed. But we need a StringRef that + // points into that memory. + std::unique_ptr<char> s = std::unique_ptr<char>(new char[str.size()]); + memcpy(s.get(), str.data(), str.size()); + llvm::StringRef r = llvm::StringRef(s.get(), str.size()); + _stringCopies.push_back(std::move(s)); + return r; + } + + unsigned int _collisionCount; + unsigned int _unnamedCounter; + NameToAtom _nameMap; + AtomToRefName _refNames; + std::vector<std::unique_ptr<char>> _stringCopies; +}; + + +/// Used when reading yaml files to find the target of a reference +/// that could be a name or ref-name. +class RefNameResolver { +public: + RefNameResolver(const lld::File *file, IO &io); + + const lld::Atom *lookup(llvm::StringRef name) const { + NameToAtom::const_iterator pos = _nameMap.find(name); + if (pos != _nameMap.end()) { + return pos->second; + } + else { + _io.setError(llvm::Twine("no such atom name: ") + name); + return nullptr; + } + } + +private: + typedef llvm::StringMap<const lld::Atom*> NameToAtom; + + void add(llvm::StringRef name, const lld::Atom *atom) { + if (_nameMap.count(name)) { + _io.setError(llvm::Twine("duplicate atom name: ") + name); + } + else { + _nameMap[name] = atom; + } + } + + IO &_io; + NameToAtom _nameMap; +}; + + +// Used in NormalizedFile to hold the atoms lists. +template <typename T> +class AtomList : public lld::File::atom_collection<T> { +public: + virtual lld::File::atom_iterator<T> begin() const { + return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*> + (_atoms.data())); + } + virtual lld::File::atom_iterator<T> end() const{ + return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*> + (_atoms.data() + _atoms.size())); + } + virtual const T *deref(const void *it) const { + return *reinterpret_cast<const T *const*>(it); + } + virtual void next(const void *&it) const { + const T *const *p = reinterpret_cast<const T *const *>(it); + ++p; + it = reinterpret_cast<const void*>(p); + } + virtual void push_back(const T *element) { + _atoms.push_back(element); + } + std::vector<const T*> _atoms; +}; + +/// Mapping of kind: field in yaml files. +enum FileKinds { + fileKindObjectAtoms, // atom based object file encoded in yaml + fileKindArchive, // static archive library encoded in yaml + fileKindObjectELF, // ELF object files encoded in yaml + fileKindObjectMachO // mach-o object files encoded in yaml +}; + +struct ArchMember { + FileKinds _kind; + llvm::StringRef _name; + const lld::File *_content; +}; + +// The content bytes in a DefinedAtom are just uint8_t but we want +// special formatting, so define a strong type. +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8); + +// SharedLibraryAtoms have a bool canBeNull() method which we'd like to be +// more readable than just true/false. +LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull); + +// lld::Reference::Kind is a typedef of int32. We need a stronger +// type to make template matching work, so invent RefKind. +LLVM_YAML_STRONG_TYPEDEF(lld::Reference::Kind, RefKind); + + +} // namespace anon + + +// This is a custom formatter for RefKind +template<> +struct ScalarTraits<RefKind> { + static void output(const RefKind &value, void *ctxt, + llvm::raw_ostream &out) { + assert(ctxt != nullptr); + ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt); + out << info->_writerOptions->kindToString(value); + } + + static StringRef input(StringRef scalar, void *ctxt, RefKind &value) { + assert(ctxt != nullptr); + ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt); + value = info->_readerOptions->kindFromString(scalar); + return StringRef(); + } +}; + + +template <> +struct ScalarEnumerationTraits<lld::File::Kind> { + static void enumeration(IO &io, lld::File::Kind &value) { + io.enumCase(value, "object", lld::File::kindObject); + io.enumCase(value, "shared-library", lld::File::kindSharedLibrary); + io.enumCase(value, "static-library", lld::File::kindArchiveLibrary); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::Atom::Scope> { + static void enumeration(IO &io, lld::Atom::Scope &value) { + io.enumCase(value, "global", lld::Atom::scopeGlobal); + io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit); + io.enumCase(value, "static", lld::Atom::scopeTranslationUnit); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> { + static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) { + io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent); + io.enumCase(value, "custom", lld::DefinedAtom::sectionCustomPreferred); + io.enumCase(value, "custom-required", + lld::DefinedAtom::sectionCustomRequired); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> { + static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) { + io.enumCase(value, "no", lld::DefinedAtom::interposeNo); + io.enumCase(value, "yes", lld::DefinedAtom::interposeYes); + io.enumCase(value, "yes-and-weak", + lld::DefinedAtom::interposeYesAndRuntimeWeak); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> { + static void enumeration(IO &io, lld::DefinedAtom::Merge &value) { + io.enumCase(value, "no", lld::DefinedAtom::mergeNo); + io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative); + io.enumCase(value, "as-weak", lld::DefinedAtom::mergeAsWeak); + io.enumCase(value, "as-addressed-weak", + lld::DefinedAtom::mergeAsWeakAndAddressUsed); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> { + static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) { + io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal); + io.enumCase(value, "never", lld::DefinedAtom::deadStripNever); + io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> { + static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) { + io.enumCase(value, "---", lld::DefinedAtom::perm___); + io.enumCase(value, "r--", lld::DefinedAtom::permR__); + io.enumCase(value, "r-x", lld::DefinedAtom::permR_X); + io.enumCase(value, "rw-", lld::DefinedAtom::permRW_); + io.enumCase(value, "rwx", lld::DefinedAtom::permRWX); + io.enumCase(value, "rw-l", lld::DefinedAtom::permRW_L); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> { + static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) { + io.enumCase(value, "unknown", + lld::DefinedAtom::typeUnknown); + io.enumCase(value, "code", + lld::DefinedAtom::typeCode); + io.enumCase(value, "stub", + lld::DefinedAtom::typeStub); + io.enumCase(value, "constant", + lld::DefinedAtom::typeConstant); + io.enumCase(value, "data", + lld::DefinedAtom::typeData); + io.enumCase(value, "zero-fill", + lld::DefinedAtom::typeZeroFill); + io.enumCase(value, "got", + lld::DefinedAtom::typeGOT); + io.enumCase(value, "resolver", + lld::DefinedAtom::typeResolver); + io.enumCase(value, "branch-island", + lld::DefinedAtom::typeBranchIsland); + io.enumCase(value, "branch-shim", + lld::DefinedAtom::typeBranchShim); + io.enumCase(value, "stub-helper", + lld::DefinedAtom::typeStubHelper); + io.enumCase(value, "c-string", + lld::DefinedAtom::typeCString); + io.enumCase(value, "utf16-string", + lld::DefinedAtom::typeUTF16String); + io.enumCase(value, "unwind-cfi", + lld::DefinedAtom::typeCFI); + io.enumCase(value, "unwind-lsda", + lld::DefinedAtom::typeLSDA); + io.enumCase(value, "const-4-byte", + lld::DefinedAtom::typeLiteral4); + io.enumCase(value, "const-8-byte", + lld::DefinedAtom::typeLiteral8); + io.enumCase(value, "const-16-byte", + lld::DefinedAtom::typeLiteral16); + io.enumCase(value, "lazy-pointer", + lld::DefinedAtom::typeLazyPointer); + io.enumCase(value, "lazy-dylib-pointer", + lld::DefinedAtom::typeLazyDylibPointer); + io.enumCase(value, "cfstring", + lld::DefinedAtom::typeCFString); + io.enumCase(value, "initializer-pointer", + lld::DefinedAtom::typeInitializerPtr); + io.enumCase(value, "terminator-pointer", + lld::DefinedAtom::typeTerminatorPtr); + io.enumCase(value, "c-string-pointer", + lld::DefinedAtom::typeCStringPtr); + io.enumCase(value, "objc-class-pointer", + lld::DefinedAtom::typeObjCClassPtr); + io.enumCase(value, "objc-category-list", + lld::DefinedAtom::typeObjC2CategoryList); + io.enumCase(value, "objc-class1", + lld::DefinedAtom::typeObjC1Class); + io.enumCase(value, "dtraceDOF", + lld::DefinedAtom::typeDTraceDOF); + io.enumCase(value, "lto-temp", + lld::DefinedAtom::typeTempLTO); + io.enumCase(value, "compact-unwind", + lld::DefinedAtom::typeCompactUnwindInfo); + io.enumCase(value, "tlv-thunk", + lld::DefinedAtom::typeThunkTLV); + io.enumCase(value, "tlv-data", + lld::DefinedAtom::typeTLVInitialData); + io.enumCase(value, "tlv-zero-fill", + lld::DefinedAtom::typeTLVInitialZeroFill); + io.enumCase(value, "tlv-initializer-ptr", + lld::DefinedAtom::typeTLVInitializerPtr); + io.enumCase(value, "first-in-section", + lld::DefinedAtom::typeFirstInSection); + io.enumCase(value, "last-in-section", + lld::DefinedAtom::typeLastInSection); + } +}; + +template <> +struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> { + static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) { + io.enumCase(value, "never", lld::UndefinedAtom::canBeNullNever); + io.enumCase(value, "at-runtime", lld::UndefinedAtom::canBeNullAtRuntime); + io.enumCase(value, "at-buildtime", lld::UndefinedAtom::canBeNullAtBuildtime); + } +}; + + +template <> +struct ScalarEnumerationTraits<ShlibCanBeNull> { + static void enumeration(IO &io, ShlibCanBeNull &value) { + io.enumCase(value, "never", false); + io.enumCase(value, "at-runtime", true); + } +}; + + + +/// This is a custom formatter for lld::DefinedAtom::Alignment. Values look +/// like: +/// 2^3 # 8-byte aligned +/// 7 mod 2^4 # 16-byte aligned plus 7 bytes +template<> +struct ScalarTraits<lld::DefinedAtom::Alignment> { + static void output(const lld::DefinedAtom::Alignment &value, void *ctxt, + llvm::raw_ostream &out) { + if (value.modulus == 0) { + out << llvm::format("2^%d", value.powerOf2); + } + else { + out << llvm::format("%d mod 2^%d", value.modulus, value.powerOf2); + } + } + + static StringRef input(StringRef scalar, void *ctxt, + lld::DefinedAtom::Alignment &value) { + value.modulus = 0; + size_t modStart = scalar.find("mod"); + if (modStart != StringRef::npos) { + StringRef modStr = scalar.slice(0, modStart); + modStr = modStr.rtrim(); + unsigned int modulus; + if (modStr.getAsInteger(0, modulus)) { + return "malformed alignment modulus"; + } + value.modulus = modulus; + scalar = scalar.drop_front(modStart+3); + scalar = scalar.ltrim(); + } + if (!scalar.startswith("2^")) { + return "malformed alignment"; + } + StringRef powerStr = scalar.drop_front(2); + unsigned int power; + if (powerStr.getAsInteger(0, power)) { + return "malformed alignment power"; + } + value.powerOf2 = power; + if (value.modulus > (1<<value.powerOf2)) { + return "malformed alignment, modulus too large for power"; + } + return StringRef(); // returning empty string means success + } +}; + + + + +template <> +struct ScalarEnumerationTraits<FileKinds> { + static void enumeration(IO &io, FileKinds &value) { + io.enumCase(value, "object", fileKindObjectAtoms); + io.enumCase(value, "archive", fileKindArchive); + io.enumCase(value, "object-elf", fileKindObjectELF); + io.enumCase(value, "object-mach-o", fileKindObjectMachO); + } +}; + +template <> +struct MappingTraits<ArchMember> { + static void mapping(IO &io, ArchMember &member) { + io.mapOptional("kind", member._kind, fileKindObjectAtoms); + io.mapOptional("name", member._name); + io.mapRequired("content", member._content); + } +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember); + + +// Declare that an AtomList is a yaml sequence. +template<typename T> +struct SequenceTraits<AtomList<T>> { + static size_t size(IO &io, AtomList<T> &seq) { + return seq._atoms.size(); + } + static const T *&element(IO &io, AtomList<T> &seq, size_t index) { + if (index >= seq._atoms.size()) + seq._atoms.resize(index+1); + return seq._atoms[index]; + } +}; + +// Used to allow DefinedAtom content bytes to be a flow sequence of +// two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A) +template<> +struct ScalarTraits<ImplicitHex8> { + static void output(const ImplicitHex8 &val, void*, llvm::raw_ostream &out) { + uint8_t num = val; + out << llvm::format("%02X", num); + } + + static llvm::StringRef input(llvm::StringRef str, void*, ImplicitHex8 &val) { + unsigned long long n; + if (getAsUnsignedInteger(str, 16, n)) + return "invalid two-digit-hex number"; + if (n > 0xFF) + return "out of range two-digit-hex number"; + val = n; + return StringRef(); // returning empty string means success + } +}; + +// Always write DefinedAtoms content bytes as a flow sequence. +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8); + + +// YAML conversion for std::vector<const lld::File*> +template<> +struct DocumentListTraits< std::vector<const lld::File*> > { + static size_t size(IO &io, std::vector<const lld::File*> &seq) { + return seq.size(); + } + static const lld::File *&element(IO &io, std::vector<const lld::File*> &seq, + size_t index) { + if (index >= seq.size()) + seq.resize(index+1); + return seq[index]; + } +}; + + +// YAML conversion for const lld::File* +template <> +struct MappingTraits<const lld::File*> { + + class NormArchiveFile : public lld::ArchiveLibraryFile { + public: + NormArchiveFile(IO &io) : ArchiveLibraryFile(""), _path() { + } + NormArchiveFile(IO &io, const lld::File *file) + : ArchiveLibraryFile(file->path()), + _path(file->path()) { + // If we want to support writing archives, this constructor would + // need to populate _members. + } + + const lld::File *denormalize(IO &io) { + return this; + } + + virtual void addAtom(const lld::Atom&) { + llvm_unreachable("cannot add atoms to yaml .o files"); + } + virtual const atom_collection<lld::DefinedAtom> &defined() const { + return _noDefinedAtoms; + } + virtual const atom_collection<lld::UndefinedAtom> &undefined() const { + return _noUndefinedAtoms; + } + virtual const atom_collection<lld::SharedLibraryAtom> &sharedLibrary()const{ + return _noSharedLibaryAtoms; + } + virtual const atom_collection<lld::AbsoluteAtom> &absolute() const { + return _noAbsoluteAtoms; + } + virtual const File *find(StringRef name, bool dataSymbolOnly) const { + for (const ArchMember &member : _members) { + for (const lld::DefinedAtom *atom : member._content->defined() ) { + if (name == atom->name()) { + if (!dataSymbolOnly) + return member._content; + switch (atom->contentType()) { + case lld::DefinedAtom::typeData: + case lld::DefinedAtom::typeZeroFill: + return member._content; + default: + break; + } + } + } + } + return nullptr; + } + + StringRef _path; + std::vector<ArchMember> _members; + }; + + + class NormalizedFile : public lld::File { + public: + NormalizedFile(IO &io) : File(""), _rnb(nullptr) { + } + NormalizedFile(IO &io, const lld::File *file) + : File(file->path()), + _rnb(new RefNameBuilder(*file)), + _path(file->path()) { + for (const lld::DefinedAtom *a : file->defined()) + _definedAtoms.push_back(a); + for (const lld::UndefinedAtom *a : file->undefined()) + _undefinedAtoms.push_back(a); + for (const lld::SharedLibraryAtom *a : file->sharedLibrary()) + _sharedLibraryAtoms.push_back(a); + for (const lld::AbsoluteAtom *a : file->absolute()) + _absoluteAtoms.push_back(a); + } + const lld::File *denormalize(IO &io); + + + virtual void addAtom(const lld::Atom&) { + llvm_unreachable("cannot add atoms to yaml .o files"); + } + virtual const atom_collection<lld::DefinedAtom> &defined() const { + return _definedAtoms; + } + virtual const atom_collection<lld::UndefinedAtom> &undefined() const { + return _undefinedAtoms; + } + virtual const atom_collection<lld::SharedLibraryAtom> &sharedLibrary()const{ + return _sharedLibraryAtoms; + } + virtual const atom_collection<lld::AbsoluteAtom> &absolute() const { + return _absoluteAtoms; + } + + // Allocate a new copy of this string and keep track of allocations + // in _stringCopies, so they can be freed when File is destroyed. + StringRef copyString(StringRef str) { + // We want _stringCopies to own the string memory so it is deallocated + // when the File object is destroyed. But we need a StringRef that + // points into that memory. + std::unique_ptr<char> s = std::unique_ptr<char>(new char[str.size()]); + memcpy(s.get(), str.data(), str.size()); + llvm::StringRef r = llvm::StringRef(s.get(), str.size()); + _stringCopies.push_back(std::move(s)); + return r; + } + + RefNameBuilder *_rnb; + StringRef _path; + AtomList<lld::DefinedAtom> _definedAtoms; + AtomList<lld::UndefinedAtom> _undefinedAtoms; + AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms; + AtomList<lld::AbsoluteAtom> _absoluteAtoms; + std::vector<std::unique_ptr<char>> _stringCopies; + }; + + + static void mapping(IO &io, const lld::File *&file) { + // We only support writing atom based YAML + FileKinds kind = fileKindObjectAtoms; + // If reading, peek ahead to see what kind of file this is. + io.mapOptional("kind", kind, fileKindObjectAtoms); + // + switch (kind) { + case fileKindObjectAtoms: + mappingAtoms(io, file); + break; + case fileKindArchive: + mappingArchive(io, file); + break; + case fileKindObjectELF: + case fileKindObjectMachO: + // Eventually we will have an external function to call, similar + // to mappingAtoms() and mappingArchive() but implememented + // with coresponding file format code. + default: + llvm_unreachable("section based YAML not supported yet"); + } + } + + static void mappingAtoms(IO &io, const lld::File *&file) { + MappingNormalizationHeap<NormalizedFile, const lld::File*> keys(io, file); + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + info->_currentFile = keys.operator->(); + + io.mapOptional("path", keys->_path); + io.mapOptional("defined-atoms", keys->_definedAtoms); + io.mapOptional("undefined-atoms", keys->_undefinedAtoms); + io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms); + io.mapOptional("absolute-atoms", keys->_absoluteAtoms); + } + + static void mappingArchive(IO &io, const lld::File *&file) { + MappingNormalizationHeap<NormArchiveFile, const lld::File*> keys(io, file); + + io.mapOptional("path", keys->_path); + io.mapOptional("members", keys->_members); + } + +}; + + + +// YAML conversion for const lld::Reference* +template <> +struct MappingTraits<const lld::Reference*> { + + class NormalizedReference : public lld::Reference { + public: + NormalizedReference(IO &io) + : _target(nullptr), _targetName(), _offset(0), _addend(0) , _kind(0) { + } + NormalizedReference(IO &io, const lld::Reference *ref) + : _target(nullptr), + _targetName(targetName(io, ref)), + _offset(ref->offsetInAtom()), + _addend(ref->addend()), + _kind(ref->kind()) { + } + const lld::Reference *denormalize(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + if (!_targetName.empty()) + _targetName = f->copyString(_targetName); + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "created Reference to name: '" << _targetName + << "' (" << (void*)_targetName.data() << ", " + << _targetName.size() << ")\n"); + return this; + } + void bind(const RefNameResolver&); + static StringRef targetName(IO &io, const lld::Reference *ref); + + virtual uint64_t offsetInAtom() const { return _offset; } + virtual Kind kind() const { return _kind; } + virtual const lld::Atom *target() const { return _target; } + virtual Addend addend() const { return _addend; } + virtual void setKind(Kind k) { _kind = k; } + virtual void setAddend(Addend a) { _addend = a; } + virtual void setTarget(const lld::Atom *a) { _target = a; } + + const lld::Atom *_target; + StringRef _targetName; + uint32_t _offset; + Addend _addend; + RefKind _kind; + }; + + + static void mapping(IO &io, const lld::Reference *&ref) { + MappingNormalizationHeap<NormalizedReference, + const lld::Reference*> keys(io, ref); + + io.mapRequired("kind", keys->_kind); + io.mapOptional("offset", keys->_offset); + io.mapOptional("target", keys->_targetName); + io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0); + } +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference*) + + +// YAML conversion for const lld::DefinedAtom* +template <> +struct MappingTraits<const lld::DefinedAtom*> { + + class NormalizedAtom : public lld::DefinedAtom { + public: + NormalizedAtom(IO &io) + : _file(fileFromContext(io)), _name(), _refName(), + _alignment(0), _content(), _references() { + } + NormalizedAtom(IO &io, const lld::DefinedAtom *atom) + : _file(fileFromContext(io)), + _name(atom->name()), + _refName(), + _scope(atom->scope()), + _interpose(atom->interposable()), + _merge(atom->merge()), + _contentType(atom->contentType()), + _alignment(atom->alignment()), + _sectionChoice(atom->sectionChoice()), + _deadStrip(atom->deadStrip()), + _permissions(atom->permissions()), + _size(atom->size()), + _sectionName(atom->customSectionName()) { + for ( const lld::Reference *r : *atom ) + _references.push_back(r); + ArrayRef<uint8_t> cont = atom->rawContent(); + _content.reserve(cont.size()); + for (uint8_t x : cont) + _content.push_back(x); + } + const lld::DefinedAtom *denormalize(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + if ( !_name.empty() ) + _name = f->copyString(_name); + if ( !_refName.empty() ) + _refName = f->copyString(_refName); + if ( !_sectionName.empty() ) + _sectionName = f->copyString(_sectionName); + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "created DefinedAtom named: '" << _name + << "' (" << (void*)_name.data() << ", " + << _name.size() << ")\n"); + return this; + } + void bind(const RefNameResolver&); + // Extract current File object from YAML I/O parsing context + const lld::File &fileFromContext(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + assert(info->_currentFile != nullptr); + return *info->_currentFile; + } + + virtual const lld::File &file() const { return _file; } + virtual StringRef name() const { return _name; } + virtual uint64_t size() const { return _size; } + virtual Scope scope() const { return _scope; } + virtual Interposable interposable() const { return _interpose; } + virtual Merge merge() const { return _merge; } + virtual ContentType contentType() const { return _contentType; } + virtual Alignment alignment() const { return _alignment; } + virtual SectionChoice sectionChoice() const { return _sectionChoice; } + virtual StringRef customSectionName() const { return _sectionName;} + virtual DeadStripKind deadStrip() const { return _deadStrip; } + virtual ContentPermissions permissions() const { return _permissions; } + virtual bool isThumb() const { return false; } + virtual bool isAlias() const { return false; } + ArrayRef<uint8_t> rawContent() const { + return ArrayRef<uint8_t>((uint8_t*)&_content.operator[](0), + _content.size()); } + virtual uint64_t ordinal() const { return 0; } + + reference_iterator begin() const { + uintptr_t index = 0; + const void *it = reinterpret_cast<const void*>(index); + return reference_iterator(*this, it); + } + reference_iterator end() const { + uintptr_t index = _references.size(); + const void *it = reinterpret_cast<const void*>(index); + return reference_iterator(*this, it); + } + const lld::Reference *derefIterator(const void *it) const { + uintptr_t index = reinterpret_cast<uintptr_t>(it); + assert(index < _references.size()); + return _references[index]; + } + void incrementIterator(const void *&it) const { + uintptr_t index = reinterpret_cast<uintptr_t>(it); + ++index; + it = reinterpret_cast<const void*>(index); + } + + const lld::File &_file; + StringRef _name; + StringRef _refName; + Scope _scope; + Interposable _interpose; + Merge _merge; + ContentType _contentType; + Alignment _alignment; + SectionChoice _sectionChoice; + DeadStripKind _deadStrip; + ContentPermissions _permissions; + std::vector<ImplicitHex8> _content; + uint64_t _size; + StringRef _sectionName; + std::vector<const lld::Reference*> _references; + }; + + static void mapping(IO &io, const lld::DefinedAtom *&atom) { + MappingNormalizationHeap<NormalizedAtom, + const lld::DefinedAtom*> keys(io, atom); + if ( io.outputting() ) { + // If writing YAML, check if atom needs a ref-name. + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + assert(f); + assert(f->_rnb); + if ( f->_rnb->hasRefName(atom) ) { + keys->_refName = f->_rnb->refName(atom); + } + } + + io.mapOptional("name", keys->_name, + StringRef()); + io.mapOptional("ref-name", keys->_refName, + StringRef()); + io.mapOptional("scope", keys->_scope, + lld::DefinedAtom::scopeTranslationUnit); + io.mapOptional("type", keys->_contentType, + lld::DefinedAtom::typeCode); + io.mapOptional("content", keys->_content); + io.mapOptional("size", keys->_size, + (uint64_t)keys->_content.size()); + io.mapOptional("interposable", keys->_interpose, + lld::DefinedAtom::interposeNo); + io.mapOptional("merge", keys->_merge, + lld::DefinedAtom::mergeNo); + io.mapOptional("alignment", keys->_alignment, + lld::DefinedAtom::Alignment(0)); + io.mapOptional("section-choice", keys->_sectionChoice, + lld::DefinedAtom::sectionBasedOnContent); + io.mapOptional("section-name", keys->_sectionName, + StringRef()); + io.mapOptional("dead-strip", keys->_deadStrip, + lld::DefinedAtom::deadStripNormal); + io.mapOptional("permissions", keys->_permissions, + lld::DefinedAtom::permR_X); + io.mapOptional("fixups", keys->_references); + } +}; + + + + +inline +const lld::File* +MappingTraits<const lld::File*>::NormalizedFile::denormalize(IO &io) { + typedef MappingTraits<const lld::DefinedAtom*>::NormalizedAtom NormalizedAtom; + + RefNameResolver nameResolver(this, io); + // Now that all atoms are parsed, references can be bound. + for (const lld::DefinedAtom *a : this->defined() ) { + NormalizedAtom *normAtom = (NormalizedAtom*)a; + normAtom->bind(nameResolver); + } + return this; +} + +inline +void MappingTraits<const lld::DefinedAtom*>:: + NormalizedAtom::bind(const RefNameResolver &resolver) { + typedef MappingTraits<const lld::Reference*>::NormalizedReference + NormalizedReference; + for (const lld::Reference *ref : _references) { + NormalizedReference *normRef = (NormalizedReference*)ref; + normRef->bind(resolver); + } +} + +inline +void MappingTraits<const lld::Reference*>:: + NormalizedReference::bind(const RefNameResolver &resolver) { + _target = resolver.lookup(_targetName); +} + + + +// YAML conversion for const lld::UndefinedAtom* +template <> +struct MappingTraits<const lld::UndefinedAtom*> { + + class NormalizedAtom : public lld::UndefinedAtom { + public: + NormalizedAtom(IO &io) + : _file(fileFromContext(io)), _name(), _canBeNull(canBeNullNever) { + } + NormalizedAtom(IO &io, const lld::UndefinedAtom *atom) + : _file(fileFromContext(io)), + _name(atom->name()), + _canBeNull(atom->canBeNull()) { + } + const lld::UndefinedAtom *denormalize(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + if ( !_name.empty() ) + _name = f->copyString(_name); + + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "created UndefinedAtom named: '" << _name + << "' (" << (void*)_name.data() << ", " + << _name.size() << ")\n"); + return this; + } + // Extract current File object from YAML I/O parsing context + const lld::File &fileFromContext(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + assert(info->_currentFile != nullptr); + return *info->_currentFile; + } + + virtual const lld::File &file() const { return _file; } + virtual StringRef name() const { return _name; } + virtual CanBeNull canBeNull() const { return _canBeNull; } + + const lld::File &_file; + StringRef _name; + CanBeNull _canBeNull; + }; + + + static void mapping(IO &io, const lld::UndefinedAtom* &atom) { + MappingNormalizationHeap<NormalizedAtom, + const lld::UndefinedAtom*> keys(io, atom); + + io.mapRequired("name", keys->_name); + io.mapOptional("can-be-null", keys->_canBeNull, + lld::UndefinedAtom::canBeNullNever); + } +}; + + +// YAML conversion for const lld::SharedLibraryAtom* +template <> +struct MappingTraits<const lld::SharedLibraryAtom*> { + + class NormalizedAtom : public lld::SharedLibraryAtom { + public: + NormalizedAtom(IO &io) + : _file(fileFromContext(io)), _name(), _loadName(), _canBeNull(false) { + } + NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom) + : _file(fileFromContext(io)), + _name(atom->name()), + _loadName(atom->loadName()), + _canBeNull(atom->canBeNullAtRuntime()) { + } + const lld::SharedLibraryAtom *denormalize(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + if ( !_name.empty() ) + _name = f->copyString(_name); + if ( !_loadName.empty() ) + _loadName = f->copyString(_loadName); + + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "created SharedLibraryAtom named: '" << _name + << "' (" << (void*)_name.data() << ", " + << _name.size() << ")\n"); + return this; + } + // Extract current File object from YAML I/O parsing context + const lld::File &fileFromContext(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + assert(info->_currentFile != nullptr); + return *info->_currentFile; + } + + virtual const lld::File &file() const { return _file; } + virtual StringRef name() const { return _name; } + virtual StringRef loadName() const { return _loadName;} + virtual bool canBeNullAtRuntime() const { return _canBeNull; } + + const lld::File &_file; + StringRef _name; + StringRef _loadName; + ShlibCanBeNull _canBeNull; + }; + + + static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) { + + MappingNormalizationHeap<NormalizedAtom, + const lld::SharedLibraryAtom*> keys(io, atom); + + io.mapRequired("name", keys->_name); + io.mapOptional("load-name", keys->_loadName); + io.mapOptional("can-be-null", keys->_canBeNull, + (ShlibCanBeNull)false); + } +}; + + +// YAML conversion for const lld::AbsoluteAtom* +template <> +struct MappingTraits<const lld::AbsoluteAtom*> { + + class NormalizedAtom : public lld::AbsoluteAtom { + public: + NormalizedAtom(IO &io) + : _file(fileFromContext(io)), _name(), _scope(), _value(0) { + } + NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom) + : _file(fileFromContext(io)), + _name(atom->name()), + _scope(atom->scope()), + _value(atom->value()) { + } + const lld::AbsoluteAtom *denormalize(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + if ( !_name.empty() ) + _name = f->copyString(_name); + + DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() + << "created AbsoluteAtom named: '" << _name + << "' (" << (void*)_name.data() << ", " + << _name.size() << ")\n"); + return this; + } + // Extract current File object from YAML I/O parsing context + const lld::File &fileFromContext(IO &io) { + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + assert(info->_currentFile != nullptr); + return *info->_currentFile; + } + + virtual const lld::File &file() const { return _file; } + virtual StringRef name() const { return _name; } + virtual uint64_t value() const { return _value; } + virtual Scope scope() const { return _scope; } + + const lld::File &_file; + StringRef _name; + StringRef _refName; + Scope _scope; + Hex64 _value; + }; + + + static void mapping(IO &io, const lld::AbsoluteAtom *&atom) { + MappingNormalizationHeap<NormalizedAtom, + const lld::AbsoluteAtom*> keys(io, atom); + + if ( io.outputting() ) { + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + assert(f); + assert(f->_rnb); + if ( f->_rnb->hasRefName(atom) ) { + keys->_refName = f->_rnb->refName(atom); + } + } + + io.mapRequired("name", keys->_name); + io.mapOptional("ref-name", keys->_refName, StringRef()); + io.mapOptional("scope", keys->_scope); + io.mapRequired("value", keys->_value); + } +}; + + +RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) { + typedef MappingTraits<const lld::DefinedAtom*>::NormalizedAtom NormalizedAtom; + for (const lld::DefinedAtom *a : file->defined() ) { + NormalizedAtom *na = (NormalizedAtom*)a; + if ( na->_refName.empty() ) + add(na->_name, a); + else + add(na->_refName, a); + } + + for (const lld::UndefinedAtom *a : file->undefined() ) + add(a->name(), a); + + for (const lld::SharedLibraryAtom *a : file->sharedLibrary() ) + add(a->name(), a); + + typedef MappingTraits<const lld::AbsoluteAtom*>::NormalizedAtom NormAbsAtom; + for (const lld::AbsoluteAtom *a : file->absolute() ) { + NormAbsAtom *na = (NormAbsAtom*)a; + if ( na->_refName.empty() ) + add(na->_name, a); + else + add(na->_refName, a); + } +} + + +inline +llvm::StringRef MappingTraits<const lld::Reference*>::NormalizedReference:: + targetName(IO &io, const lld::Reference *ref) { + if ( ref->target() == nullptr ) + return llvm::StringRef(); + ContextInfo *info = reinterpret_cast<ContextInfo*>(io.getContext()); + assert(info != nullptr); + typedef MappingTraits<const lld::File*>::NormalizedFile NormalizedFile; + NormalizedFile *f = reinterpret_cast<NormalizedFile*>(info->_currentFile); + RefNameBuilder *rnb = f->_rnb; + if ( rnb->hasRefName(ref->target()) ) + return rnb->refName(ref->target()); + return ref->target()->name(); +} + + + +namespace lld { +namespace yaml { + +class Writer : public lld::Writer { +public: + Writer(const WriterOptionsYAML &options) : _options(options) { + } + + virtual error_code writeFile(const lld::File &file, StringRef outPath) { + // Create stream to path. + std::string errorInfo; + llvm::raw_fd_ostream out(outPath.data(), errorInfo); + if (!errorInfo.empty()) + return llvm::make_error_code(llvm::errc::no_such_file_or_directory); + + // Create yaml Output writer, using yaml options for context. + ContextInfo context(_options); + llvm::yaml::Output yout(out, &context); + + // Write yaml output. + const lld::File *fileRef = &file; + yout << fileRef; + + return error_code::success(); + } + + virtual StubsPass *stubPass() { + return _options.stubPass(); + } + + virtual GOTPass *gotPass() { + return _options.gotPass(); + } + + +private: + const WriterOptionsYAML &_options; +}; + + + +class ReaderYAML : public Reader { +public: + ReaderYAML(const ReaderOptionsYAML &options) : _options(options) { + } + + error_code parseFile(std::unique_ptr<MemoryBuffer> mb, + std::vector<std::unique_ptr<File>> &result) { + // Note: we do not take ownership of the MemoryBuffer. That is + // because yaml may produce multiple File objects, so there is no + // *one* File to take ownership. Therefore, the yaml File objects + // produced must make copies of all strings that come from YAML I/O. + // Otherwise the strings will become invalid when this MemoryBuffer + // is deallocated. + + // Create YAML Input parser. + ContextInfo context(_options); + llvm::yaml::Input yin(mb->getBuffer(), &context); + + // Fill vector with File objects created by parsing yaml. + std::vector<const lld::File*> createdFiles; + yin >> createdFiles; + + // Quit now if there were parsing errors. + if ( yin.error() ) + return make_error_code(lld::yaml_reader_error::illegal_value); + + for (const File *file : createdFiles) { + // Note: parseFile() should return vector of *const* File + File *f = const_cast<File*>(file); + result.emplace_back(f); + } + return make_error_code(lld::yaml_reader_error::success); + } + +private: + const ReaderOptionsYAML &_options; +}; + + + +} // namespace yaml + + +Writer *createWriterYAML(const WriterOptionsYAML &options) { + return new lld::yaml::Writer(options); +} + +WriterOptionsYAML::WriterOptionsYAML() { +} + +WriterOptionsYAML::~WriterOptionsYAML() { +} + + + +Reader *createReaderYAML(const ReaderOptionsYAML &options) { + return new lld::yaml::ReaderYAML(options); +} + +ReaderOptionsYAML::ReaderOptionsYAML() { +} + +ReaderOptionsYAML::~ReaderOptionsYAML() { +} + + +} // namespace lld + diff --git a/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp deleted file mode 100644 index bb0a2726f89..00000000000 --- a/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp +++ /dev/null @@ -1,1264 +0,0 @@ -//===- lib/ReaderWriter/YAML/ReaderYAML.cpp - Reads YAML object files -----===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/ReaderWriter/ReaderYAML.h" - -#include "lld/Core/AbsoluteAtom.h" -#include "lld/Core/ArchiveLibraryFile.h" -#include "lld/Core/Atom.h" -#include "lld/Core/Error.h" -#include "lld/Core/File.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Reference.h" -#include "lld/Core/SharedLibraryAtom.h" -#include "lld/Core/UndefinedAtom.h" - -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/YAMLParser.h" - -#include <cstring> -#include <vector> - -#include "YamlKeyValues.h" - - -namespace lld { -namespace yaml { - - -/// -/// Concrete instance of lld::Reference created parsing YAML object files -/// -class YAMLReference : public Reference { -public: - YAMLReference() - : _target(nullptr) - , _targetNameNode(nullptr) - , _offsetInAtom(0) - , _addend(0) - , _kind(0) - {} - - virtual uint64_t offsetInAtom() const { - return _offsetInAtom; - } - - virtual Kind kind() const { - return _kind; - } - - virtual void setKind(Kind k) { - _kind = k; - } - - virtual const Atom *target() const { - return _target; - } - - virtual Addend addend() const { - return _addend; - } - - virtual void setAddend(Addend a) { - _addend = a; - } - - virtual void setTarget(const Atom *newAtom) { - _target = newAtom; - } - - typedef llvm::yaml::ScalarNode ScalarNode; - - const Atom *_target; - ScalarNode * _targetNameNode; - uint64_t _offsetInAtom; - Addend _addend; - Kind _kind; -}; - - -/// -/// Concrete instance of lld::File created parsing YAML object files. -/// -class YAMLFile : public ArchiveLibraryFile { -public: - YAMLFile() - : ArchiveLibraryFile("<anonymous>") - , _lastRefIndex(0) - , _kind(File::kindObject) { - } - - ~YAMLFile(); - - // Depending on the YAML description, this file can be either an - // lld::ArchiveLibraryFile or lld::File. - virtual File::Kind kind() const { - return _kind; - } - - virtual const atom_collection<DefinedAtom> &defined() const { - return _definedAtoms; - } - virtual const atom_collection<UndefinedAtom> &undefined() const { - return _undefinedAtoms; - } - virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const { - return _sharedLibraryAtoms; - } - virtual const atom_collection<AbsoluteAtom> &absolute() const { - return _absoluteAtoms; - } - - virtual void addAtom(const Atom&) { - assert(0 && "cannot add atoms to YAML files"); - } - - // Standard way that archives are searched. - virtual const File *find(StringRef name, bool dataSymbolOnly) const; - - error_code bindTargetReferences(llvm::yaml::Stream &stream); - - void addDefinedAtom(class YAMLDefinedAtom *atom, StringRef refName); - void addUndefinedAtom(UndefinedAtom *atom); - void addSharedLibraryAtom(SharedLibraryAtom *atom); - void addAbsoluteAtom(AbsoluteAtom *atom); - Atom *findAtom(StringRef name); - void addMember(StringRef); - void setName(StringRef); - - StringRef copyString(StringRef); - - struct NameAtomPair { - NameAtomPair(StringRef n, Atom *a) : name(n), atom(a) {} - StringRef name; - Atom *atom; - }; - - atom_collection_vector<DefinedAtom> _definedAtoms; - atom_collection_vector<UndefinedAtom> _undefinedAtoms; - atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; - atom_collection_vector<AbsoluteAtom> _absoluteAtoms; - std::vector<YAMLReference> _references; - std::vector<NameAtomPair> _nameToAtomMapping; - std::vector<std::unique_ptr<YAMLFile>> _memberFiles; - std::vector<char*> _stringCopies; - unsigned int _lastRefIndex; - File::Kind _kind; -}; - - - -/// -/// Concrete instance of lld::DefinedAtom created parsing YAML object files. -/// -class YAMLDefinedAtom : public DefinedAtom { -public: - YAMLDefinedAtom( uint32_t ord - , YAMLFile &file - , DefinedAtom::Scope scope - , DefinedAtom::ContentType type - , DefinedAtom::SectionChoice sectionChoice - , DefinedAtom::Interposable interpose - , DefinedAtom::Merge merge - , DefinedAtom::DeadStripKind deadStrip - , DefinedAtom::ContentPermissions perms - , bool isThumb - , bool isAlias - , DefinedAtom::Alignment alignment - , StringRef name - , StringRef sectionName - , uint64_t size - , std::vector<uint8_t>& content) - : _file(file) - , _name(name) - , _sectionName(sectionName) - , _size(size) - , _ord(ord) - , _content(content) - , _alignment(alignment) - , _scope(scope) - , _type(type) - , _sectionChoice(sectionChoice) - , _interpose(interpose) - , _merge(merge) - , _deadStrip(deadStrip) - , _permissions(perms) - , _isThumb(isThumb) - , _isAlias(isAlias) - , _refStartIndex(file._lastRefIndex) - , _refEndIndex(file._references.size()) { - file._lastRefIndex = _refEndIndex; - } - - virtual const class File &file() const { - return _file; - } - - virtual StringRef name() const { - return _name; - } - - virtual uint64_t size() const { - return _content.empty() ? _size : _content.size(); - } - - virtual DefinedAtom::Scope scope() const { - return _scope; - } - - virtual DefinedAtom::Interposable interposable() const { - return _interpose; - } - - virtual DefinedAtom::Merge merge() const { - return _merge; - } - - virtual DefinedAtom::ContentType contentType() const { - return _type; - } - - virtual DefinedAtom::Alignment alignment() const { - return _alignment; - } - - virtual DefinedAtom::SectionChoice sectionChoice() const { - return _sectionChoice; - } - - virtual StringRef customSectionName() const { - return _sectionName; - } - - virtual DefinedAtom::DeadStripKind deadStrip() const { - return _deadStrip; - } - - virtual DefinedAtom::ContentPermissions permissions() const { - return _permissions; - } - - virtual bool isThumb() const { - return _isThumb; - } - - virtual bool isAlias() const { - return _isAlias; - } - - ArrayRef<uint8_t> rawContent() const { - return ArrayRef<uint8_t>(_content); - } - - virtual uint64_t ordinal() const { - return _ord; - } - - DefinedAtom::reference_iterator begin() const { - uintptr_t index = _refStartIndex; - const void* it = reinterpret_cast<const void*>(index); - return reference_iterator(*this, it); - } - - DefinedAtom::reference_iterator end() const { - uintptr_t index = _refEndIndex; - const void* it = reinterpret_cast<const void*>(index); - return reference_iterator(*this, it); - } - - const Reference* derefIterator(const void* it) const { - uintptr_t index = reinterpret_cast<uintptr_t>(it); - assert(index >= _refStartIndex); - assert(index < _refEndIndex); - assert(index < _file._references.size()); - return &_file._references[index]; - } - - void incrementIterator(const void*& it) const { - uintptr_t index = reinterpret_cast<uintptr_t>(it); - ++index; - it = reinterpret_cast<const void*>(index); - } - - // Convert each target name to a pointer to an atom object - error_code bindTargetReferences(llvm::yaml::Stream &stream) const { - for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) { - llvm::SmallString<32> storage; - llvm::yaml::ScalarNode *node = _file._references[i]._targetNameNode; - StringRef name = node->getValue(storage); - Atom *targetAtom = _file.findAtom(name); - if ( targetAtom ) { - _file._references[i]._target = targetAtom; - } - else { - stream.printError(node, "Fixup has target '" + name - + "' which does not exist"); - return make_error_code(yaml_reader_error::illegal_value); - } - } - return make_error_code(yaml_reader_error::success); - } - -private: - YAMLFile &_file; - StringRef _name; - StringRef _sectionName; - unsigned long _size; - uint32_t _ord; - std::vector<uint8_t> _content; - DefinedAtom::Alignment _alignment; - DefinedAtom::Scope _scope; - DefinedAtom::ContentType _type; - DefinedAtom::SectionChoice _sectionChoice; - DefinedAtom::Interposable _interpose; - DefinedAtom::Merge _merge; - DefinedAtom::DeadStripKind _deadStrip; - DefinedAtom::ContentPermissions _permissions; - bool _isThumb; - bool _isAlias; - unsigned int _refStartIndex; - unsigned int _refEndIndex; -}; - - - -/// -/// Concrete instance of lld::UndefinedAtom created parsing YAML object files. -/// -class YAMLUndefinedAtom : public UndefinedAtom { -public: - YAMLUndefinedAtom( YAMLFile &f - , int32_t - , StringRef name - , UndefinedAtom::CanBeNull cbn) - : _file(f) - , _name(name) - , _canBeNull(cbn) { - } - - virtual const class File &file() const { - return _file; - } - - virtual StringRef name() const { - return _name; - } - - virtual CanBeNull canBeNull() const { - return _canBeNull; - } - -private: - YAMLFile &_file; - StringRef _name; - UndefinedAtom::CanBeNull _canBeNull; -}; - - - -/// -/// Concrete instance of lld::SharedLibraryAtom created parsing YAML files. -/// -class YAMLSharedLibraryAtom : public SharedLibraryAtom { -public: - YAMLSharedLibraryAtom( YAMLFile &f - , int32_t - , StringRef name - , StringRef loadName - , bool cbn) - : _file(f) - , _name(name) - , _loadName(loadName) - , _canBeNull(cbn) { - } - - virtual const class File &file() const { - return _file; - } - - virtual StringRef name() const { - return _name; - } - - virtual StringRef loadName() const { - return _loadName; - } - - virtual bool canBeNullAtRuntime() const { - return _canBeNull; - } - -private: - YAMLFile &_file; - StringRef _name; - StringRef _loadName; - bool _canBeNull; -}; - - - -/// -/// Concrete instance of lld::AbsoluteAtom created parsing YAML object files. -/// -class YAMLAbsoluteAtom : public AbsoluteAtom { -public: - YAMLAbsoluteAtom(YAMLFile &f, int32_t, StringRef name, uint64_t v, Atom::Scope scope) - : _file(f) - , _name(name) - , _value(v) - , _scope(scope){ - } - - virtual const class File &file() const { - return _file; - } - - virtual Scope scope() const { - return _scope; - } - - virtual StringRef name() const { - return _name; - } - - virtual uint64_t value() const { - return _value; - } - -private: - YAMLFile &_file; - StringRef _name; - uint64_t _value; - Atom::Scope _scope; -}; - - - - -//===----------------------------------------------------------------------===// -// YAMLFile methods -//===----------------------------------------------------------------------===// - -YAMLFile::~YAMLFile() { - for (char *s : _stringCopies) { - delete [] s; - } -} - - -error_code YAMLFile::bindTargetReferences(llvm::yaml::Stream &stream) { - error_code ec; - for (const DefinedAtom *defAtom : _definedAtoms) { - const YAMLDefinedAtom *atom = - reinterpret_cast<const YAMLDefinedAtom*>(defAtom); - ec = atom->bindTargetReferences(stream); - if ( ec ) - return ec; - } - return ec; -} - -Atom *YAMLFile::findAtom(StringRef name) { - for (auto &ci : _nameToAtomMapping) { - if (ci.name == name) - return ci.atom; - } - return nullptr; -} - -void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) { - _definedAtoms._atoms.push_back(atom); - _nameToAtomMapping.push_back(NameAtomPair(refName, atom)); -} - -void YAMLFile::addUndefinedAtom(UndefinedAtom *atom) { - _undefinedAtoms._atoms.push_back(atom); - _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom)); -} - -void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom *atom) { - _sharedLibraryAtoms._atoms.push_back(atom); - _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom)); -} - -void YAMLFile::addAbsoluteAtom(AbsoluteAtom *atom) { - _absoluteAtoms._atoms.push_back(atom); - _nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom)); -} - -void YAMLFile::setName(StringRef name) { - _path = StringRef(name); -} - - -// Allocate a new copy of this string and keep track of allocations -// in _stringCopies, so they can be freed when YAMLFile is destroyed. -StringRef YAMLFile::copyString(StringRef str) { - char* s = new char[str.size()]; - memcpy(s, str.data(), str.size()); - _stringCopies.push_back(s); - return StringRef(s, str.size()); -} - -const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const { - for (auto &file : _memberFiles) { - for (const DefinedAtom *atom : file->defined() ) { - if (name == atom->name()) - return file.get(); - } - } - return nullptr; -} - - - -/// -/// The state machine that drives the YAMLParser stream and instantiates -/// Files and Atoms. This class also buffers all the attribures for the -/// current atom and current fixup. Once all attributes are accumulated, -/// a new atom or fixup instance is instantiated. -/// -class YAMLState { -public: - YAMLState(const ReaderOptionsYAML &opts, llvm::yaml::Stream *s, YAMLFile *f); - - void parse(llvm::yaml::Node *node, StringRef keyword, - llvm::yaml::Node *keywordNode=nullptr); - error_code error() { return _error; } - -private: - typedef llvm::yaml::Node Node; - typedef llvm::yaml::ScalarNode ScalarNode; - typedef llvm::yaml::SequenceNode SequenceNode; - typedef llvm::yaml::MappingNode MappingNode; - typedef llvm::yaml::Stream Stream; - - void resetState(); - void setAlign2(StringRef n); - - void makeReference(); - void makeAtom(Node *node); - void makeDefinedAtom(Node *node); - void makeUndefinedAtom(Node *node); - void makeSharedLibraryAtom(Node *node); - void makeAbsoluteAtom(Node *node); - - void parseMemberName(ScalarNode *node); - void parseAtomName(ScalarNode *node); - void parseAtomRefName(ScalarNode *node); - void parseAtomType(ScalarNode *node); - void parseAtomScope(ScalarNode *node); - void parseAtomDefinition(ScalarNode *node); - void parseAtomDeadStrip(ScalarNode *node); - void parseAtomSectionChoice(ScalarNode *node); - void parseAtomInterposable(ScalarNode *node); - void parseAtomMerge(ScalarNode *node); - void parseAtomIsThumb(ScalarNode *node); - void parseAtomIsAlias(ScalarNode *node); - void parseAtomSectionName(ScalarNode *node); - void parseAtomSize(ScalarNode *node); - void parseAtomPermissions(ScalarNode *node); - void parseAtomCanBeNull(ScalarNode *node); - void parseFixUpOffset(ScalarNode *node); - void parseFixUpKind(ScalarNode *node); - void parseFixUpTarget(ScalarNode *node); - void parseFixUpAddend(ScalarNode *node); - void parseAtomContentByte(ScalarNode *node); - void parseAtomLoadName(ScalarNode *node); - void parseAtomValue(ScalarNode *node); - - StringRef extractString(ScalarNode *node); - - typedef void (YAMLState:: *ParseScalar)(ScalarNode *node); - typedef void (YAMLState:: *ParseSeq)(SequenceNode *node); - typedef void (YAMLState:: *ParseMap)(MappingNode *node); - - enum State { inError, inTop, inDoc, inArch, inMemb, - inAtoms, inAtom, inFixUps, inFixUp, inBytes }; - struct Transistion { - State state; - const char* keyword; - State newState; - ParseScalar customAction; - }; - - static const char* stateName(State); - - void moveToState(State s); - void returnToState(State s, Node *node); - - static const Transistion _s_transistions[]; - - const ReaderOptionsYAML &_options; - error_code _error; - llvm::yaml::Stream *_stream; - YAMLFile *_file; - YAMLFile *_archiveFile; - State _state; - StringRef _name; - StringRef _refName; - StringRef _sectionName; - StringRef _loadName; - StringRef _memberName; - unsigned long long _size; - uint64_t _value; - uint32_t _ordinal; - std::vector<uint8_t> _content; - DefinedAtom::Alignment _alignment; - Atom::Definition _definition; - DefinedAtom::Scope _scope; - DefinedAtom::ContentType _type; - DefinedAtom::SectionChoice _sectionChoice; - DefinedAtom::Interposable _interpose; - DefinedAtom::Merge _merge; - DefinedAtom::DeadStripKind _deadStrip; - DefinedAtom::ContentPermissions _permissions; - bool _isThumb; - bool _isAlias; - UndefinedAtom::CanBeNull _canBeNull; - YAMLReference _ref; - bool _hasDefinedAtomAttributes; - bool _hasUndefinedAtomAttributes; - bool _hasSharedLibraryAtomAttributes; - bool _hasAbsoluteAtomAttributes; -}; - - -// -// This transition table is the heart of the state machine. -// The table is read left-to-right columns A,B,C,D as: -// If the state is A and key B is seen switch to state C then -// if D is not nullptr call that method with the key's value, -// if D is nullptr, recursively parse in the new state. -// -const YAMLState::Transistion YAMLState::_s_transistions[] = { - { inTop, "<root>", inDoc, nullptr }, - { inDoc, "archive", inArch, nullptr }, - { inArch, "<any-seq-item>", inMemb, nullptr }, - { inMemb, "atoms", inAtoms, nullptr }, - { inMemb, "name", inMemb, &YAMLState::parseMemberName }, - { inDoc, "atoms", inAtoms, nullptr }, - { inAtoms, "<any-seq-item>", inAtom, nullptr }, - { inAtom, "name", inAtom, &YAMLState::parseAtomName }, - { inAtom, "ref-name", inAtom, &YAMLState::parseAtomRefName }, - { inAtom, "type", inAtom, &YAMLState::parseAtomType }, - { inAtom, "scope", inAtom, &YAMLState::parseAtomScope }, - { inAtom, "definition", inAtom, &YAMLState::parseAtomDefinition }, - { inAtom, "dead-strip", inAtom, &YAMLState::parseAtomDeadStrip }, - { inAtom, "section-choice", inAtom, &YAMLState::parseAtomSectionChoice }, - { inAtom, "interposable", inAtom, &YAMLState::parseAtomInterposable }, - { inAtom, "merge", inAtom, &YAMLState::parseAtomMerge }, - { inAtom, "is-thumb", inAtom, &YAMLState::parseAtomIsThumb }, - { inAtom, "is-alias", inAtom, &YAMLState::parseAtomIsAlias }, - { inAtom, "section-name", inAtom, &YAMLState::parseAtomSectionName }, - { inAtom, "size", inAtom, &YAMLState::parseAtomSize }, - { inAtom, "permissions", inAtom, &YAMLState::parseAtomPermissions }, - { inAtom, "can-be-null", inAtom, &YAMLState::parseAtomCanBeNull }, - { inAtom, "content", inBytes, nullptr }, - { inAtom, "fixups", inFixUps,nullptr }, - { inBytes, "<any-seq-item>", inBytes, &YAMLState::parseAtomContentByte }, - { inFixUps,"<any-seq-item>", inFixUp, nullptr }, - { inFixUp, "offset", inFixUp, &YAMLState::parseFixUpOffset }, - { inFixUp, "kind", inFixUp, &YAMLState::parseFixUpKind }, - { inFixUp, "target", inFixUp, &YAMLState::parseFixUpTarget }, - { inFixUp, "addend", inFixUp, &YAMLState::parseFixUpAddend }, - { inAtom, "load-name", inAtom, &YAMLState::parseAtomLoadName }, - { inAtom, "value", inAtom, &YAMLState::parseAtomValue }, - { inError, nullptr, inAtom, nullptr }, -}; - - - -YAMLState::YAMLState(const ReaderOptionsYAML &opts, Stream *stream, - YAMLFile *file) - : _options(opts) - , _error(make_error_code(yaml_reader_error::success)) - , _stream(stream) - , _file(file) - , _archiveFile(nullptr) - , _state(inTop) - , _alignment(0, 0) { - this->resetState(); -} - -void YAMLState::makeAtom(Node *node) { - switch (_definition ) { - case Atom::definitionRegular: - this->makeDefinedAtom(node); - break; - case Atom::definitionUndefined: - this->makeUndefinedAtom(node); - break; - case Atom::definitionSharedLibrary: - this->makeSharedLibraryAtom(node); - break; - case Atom::definitionAbsolute: - this->makeAbsoluteAtom(node); - break; - } - ++_ordinal; - - // reset state for next atom - this->resetState(); -} - -void YAMLState::makeDefinedAtom(Node *node) { - if ( _hasAbsoluteAtomAttributes ) { - _stream->printError(node, "Defined atom '" + _name - + "' has attributes only allowed on absolute atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - if ( _hasSharedLibraryAtomAttributes ) { - _stream->printError(node, "Defined atom '" + _name - + "' has attributes only allowed on shared library atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - - YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, *_file, _scope, _type - , _sectionChoice, _interpose, _merge, _deadStrip - , _permissions, _isThumb, _isAlias, _alignment - , _name, _sectionName, _size, _content); - _file->addDefinedAtom(a, !_refName.empty() ? _refName : _name); -} - -void YAMLState::makeUndefinedAtom(Node *node) { - if ( _hasDefinedAtomAttributes ) { - _stream->printError(node, "Undefined atom '" + _name - + "' has attributes only allowed on defined atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - if ( _hasAbsoluteAtomAttributes ) { - _stream->printError(node, "Defined atom '" + _name - + "' has attributes only allowed on absolute atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - UndefinedAtom *a = new YAMLUndefinedAtom(*_file, _ordinal, _name, _canBeNull); - _file->addUndefinedAtom(a); -} - -void YAMLState::makeSharedLibraryAtom(Node *node) { - if ( _hasDefinedAtomAttributes ) { - _stream->printError(node, "SharedLibrary atom '" + _name - + "' has attributes only allowed on defined atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - if ( _hasAbsoluteAtomAttributes ) { - _stream->printError(node, "Defined atom '" + _name - + "' has attributes only allowed on absolute atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime); - SharedLibraryAtom *a = new YAMLSharedLibraryAtom(*_file, _ordinal, _name, - _loadName, nullable); - _file->addSharedLibraryAtom(a); -} - -void YAMLState::makeAbsoluteAtom(Node *node) { - if ( _hasDefinedAtomAttributes ) { - _stream->printError(node, "Absolute atom '" + _name - + "' has attributes only allowed on defined atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - if ( _hasSharedLibraryAtomAttributes ) { - _stream->printError(node, "Absolute atom '" + _name - + "' has attributes only allowed on shared library atoms"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - AbsoluteAtom *a = new YAMLAbsoluteAtom(*_file, _ordinal, _name, _value, - _scope); - _file->addAbsoluteAtom(a); -} - - - -void YAMLState::resetState() { - _name = StringRef(); - _refName = StringRef(); - _sectionName = StringRef(); - _loadName = StringRef(); - _memberName = StringRef(); - _size = 0; - _value = 0; - _ordinal = 0; - _content.clear(); - _alignment.powerOf2 = 0; - _alignment.modulus = 0; - _definition = KeyValues::definitionDefault; - _scope = KeyValues::scopeDefault; - _type = KeyValues::contentTypeDefault; - _sectionChoice = KeyValues::sectionChoiceDefault; - _interpose = KeyValues::interposableDefault; - _merge = KeyValues::mergeDefault; - _deadStrip = KeyValues::deadStripKindDefault; - _permissions = KeyValues::permissionsDefault; - _isThumb = KeyValues::isThumbDefault; - _isAlias = KeyValues::isAliasDefault; - _canBeNull = KeyValues::canBeNullDefault; - _ref._target = nullptr; - _ref._targetNameNode= nullptr; - _ref._addend = 0; - _ref._offsetInAtom = 0; - _ref._kind = 0; - - _hasDefinedAtomAttributes = false; - _hasUndefinedAtomAttributes = false; - _hasSharedLibraryAtomAttributes = false; - _hasAbsoluteAtomAttributes = false; -} - - -void YAMLState::makeReference() { - _file->_references.push_back(_ref); - // clear for next ref - _ref._target = nullptr; - _ref._targetNameNode= nullptr; - _ref._addend = 0; - _ref._offsetInAtom = 0; - _ref._kind = 0; -} - - - -void YAMLState::setAlign2(StringRef s) { - if (StringRef(s).getAsInteger(10, _alignment.powerOf2)) - _alignment.powerOf2 = 1; -} - - -// For debug logging -const char* YAMLState::stateName(State s) { - switch ( s ) { - case inError: - return "inError"; - case inTop: - return "inTop"; - case inDoc: - return "inDoc"; - case inArch: - return "inArch"; - case inMemb: - return "inMemb"; - case inAtoms: - return "inAtoms"; - case inAtom: - return "inAtom"; - case inFixUps: - return "inFixUps"; - case inFixUp: - return "inFixUp"; - case inBytes: - return "inBytes"; - } - return "unknown case"; -} - -// Called by parse() when recursing and switching to a new state. -void YAMLState::moveToState(State newState) { - if ( newState == _state ) - return; - DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "moveToState(" << stateName(newState) - << "), _state=" << stateName(_state) << "\n"); - - if ( newState == inArch ) { - // Seen "archive:", repurpose existing YAMLFile to be archive file - _file->_kind = File::kindArchiveLibrary; - _archiveFile = _file; - _file = nullptr; - } - - if ( newState == inMemb ) { - assert(_state == inArch); - // Make new YAMLFile for this member - std::unique_ptr<YAMLFile> memberFile(new YAMLFile); - _file = memberFile.get(); - assert(_archiveFile != nullptr); - _archiveFile->_memberFiles.emplace_back(memberFile.release()); - } - - _state = newState; -} - -// Called by parse() when returning from recursion and restoring the old state. -void YAMLState::returnToState(State prevState, Node *node) { - if ( prevState == _state ) - return; - DEBUG_WITH_TYPE("objtxt", llvm::dbgs() - << "returnToState(" << stateName(prevState) - << "), _state=" << stateName(_state) << "\n"); - // If done with an atom, instantiate an object for it. - if ( (_state == inAtom) && (prevState == inAtoms) ) - this->makeAtom(node); - // If done wit a fixup, instantiate an object for it. - if ( (_state == inFixUp) && (prevState == inFixUps) ) - this->makeReference(); - _state = prevState; -} - -// If a string in the yaml document is quoted in a way that there is no -// contiguous range of bytes that a StringRef can point to, then we make -// a copy of the string and have the StringRef point to that. -StringRef YAMLState::extractString(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef str = node->getValue(storage); - //if ( str.data() == storage.begin() ) { - str = _file->copyString(str); - //} - return str; -} - - -void YAMLState::parseMemberName(ScalarNode *node) { - _memberName = extractString(node); -} - -void YAMLState::parseAtomName(ScalarNode *node) { - _name = extractString(node); -} - -void YAMLState::parseAtomRefName(ScalarNode *node) { - _refName = extractString(node); -} - -void YAMLState::parseAtomScope(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::scope(node->getValue(storage), _scope) ) { - _stream->printError(node, "Invalid value for 'scope:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } -} - -void YAMLState::parseAtomDefinition(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::definition(node->getValue(storage), _definition) ) { - _stream->printError(node, "Invalid value for 'definition:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } -} - -void YAMLState::parseAtomType(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::contentType(node->getValue(storage), _type) ) { - _stream->printError(node, "Invalid value for 'type:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomDeadStrip(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::deadStripKind(node->getValue(storage), _deadStrip) ) { - _stream->printError(node, "Invalid value for 'dead-strip:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomSectionChoice(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::sectionChoice(node->getValue(storage), _sectionChoice) ) { - _stream->printError(node, "Invalid value for 'section-choice:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomInterposable(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::interposable(node->getValue(storage), _interpose) ) { - _stream->printError(node, "Invalid value for 'interposable:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomMerge(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::merge(node->getValue(storage), _merge) ) { - _stream->printError(node, "Invalid value for 'merge:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomIsThumb(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::isThumb(node->getValue(storage), _isThumb) ) { - _stream->printError(node, "Invalid value for 'thumb:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomIsAlias(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::isAlias(node->getValue(storage), _isAlias) ) { - _stream->printError(node, "Invalid value for 'is-alias:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomSectionName(ScalarNode *node) { - _sectionName = extractString(node); - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomSize(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef offsetStr = node->getValue(storage); - if ( offsetStr.getAsInteger(0, _size) ) { - _stream->printError(node, "Invalid value for atom 'size:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomPermissions(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::permissions(node->getValue(storage), _permissions) ) { - _stream->printError(node, "Invalid value for 'permissions:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomCanBeNull(ScalarNode *node) { - llvm::SmallString<32> storage; - if ( KeyValues::canBeNull(node->getValue(storage), _canBeNull) ) { - _stream->printError(node, "Invalid value for 'can-be-null:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } -} - -void YAMLState::parseFixUpOffset(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef offsetStr = node->getValue(storage); - if ( offsetStr.getAsInteger(0, _ref._offsetInAtom) ) { - _stream->printError(node, "Invalid value for fixup 'offset:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseFixUpKind(ScalarNode *node) { - llvm::SmallString<32> storage; - _ref._kind = _options.kindFromString(node->getValue(storage)); - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseFixUpTarget(ScalarNode *node) { - _ref._targetNameNode = node; - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseFixUpAddend(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef offsetStr = node->getValue(storage); - if ( offsetStr.getAsInteger(0, _ref._addend) ) { - _stream->printError(node, "Invalid value for fixup 'addend:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomContentByte(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef str = node->getValue(storage); - unsigned int contentByte; - if ( str.getAsInteger(16, contentByte) ) { - _stream->printError(node, "Invalid content hex byte '0x" + str + "'"); - _error = make_error_code(yaml_reader_error::illegal_value); - return; - } - if (contentByte > 0xFF) { - _stream->printError(node, "Content hex byte out of range (0x" - + str + " > 0xFF)"); - _error = make_error_code(yaml_reader_error::illegal_value); - return; - } - _content.push_back(contentByte & 0xFF); - _hasDefinedAtomAttributes = true; -} - -void YAMLState::parseAtomLoadName(ScalarNode *node) { - _loadName = extractString(node); - _hasSharedLibraryAtomAttributes = true; -} - - -void YAMLState::parseAtomValue(ScalarNode *node) { - llvm::SmallString<32> storage; - StringRef offsetStr = node->getValue(storage); - if ( offsetStr.getAsInteger(0, _value) ) { - _stream->printError(node, "Invalid value for fixup 'addend:'"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - _hasAbsoluteAtomAttributes = true; -} - -// -// This is the parsing engine that walks the nodes in the yaml document -// stream. It is table driven. See _s_transistions. -// -void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) { - using namespace llvm::yaml; - DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "parse(" << keyword << "), _state=" - << stateName(_state) << "\n"); - if ( _error ) - return; - State savedState = _state; - for(const Transistion* t=_s_transistions; t->state != inError; ++t) { - if ( t->state != _state ) - continue; - if ( ! keyword.equals(t->keyword) ) - continue; - ParseScalar action = t->customAction; - this->moveToState(t->newState); - if ( ScalarNode *sc = llvm::dyn_cast<ScalarNode>(node) ) { - if ( action ) { - (*this.*action)(sc); - } - else { - _stream->printError(node, "unexpected scalar"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - } - else if ( SequenceNode *seq = llvm::dyn_cast<SequenceNode>(node) ) { - if ( action ) { - _stream->printError(node, "unexpected sequence"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - else { - for (Node &seqEntry : *seq ) { - this->parse(&seqEntry, StringRef("<any-seq-item>")); - if ( _error ) - break; - } - } - } - else if ( MappingNode *map = llvm::dyn_cast<MappingNode>(node) ) { - if ( action ) { - _stream->printError(node, "unexpected map"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - else { - llvm::SmallString<32> storage; - for (auto &keyVal : *map) { - ScalarNode *keyScalar = llvm::dyn_cast<ScalarNode>(keyVal.getKey()); - llvm::StringRef keyStr = keyScalar->getValue(storage); - this->parse(keyVal.getValue(), keyStr, keyScalar); - if ( _error ) - break; - } - } - } - else { - _stream->printError(node, "unexpected node type"); - _error = make_error_code(yaml_reader_error::illegal_value); - } - this->returnToState(savedState, node); - return; - } - switch (_state) { - case inAtom: - _stream->printError(keywordNode, "Unknown atom attribute '" - + keyword + ":'"); - break; - case inFixUp: - _stream->printError(keywordNode, "Unknown fixup attribute '" - + keyword + ":'"); - break; - case inDoc: - _stream->printError(keywordNode, "Unknown file attribute '" - + keyword + ":'"); - break; - default: - _stream->printError(keywordNode, "Unknown keyword '" - + keyword + ":'"); - } - _error = make_error_code(yaml_reader_error::illegal_value); -} - - -/// parseFile - Parse the specified YAML formatted MemoryBuffer -/// into lld::File object(s) and append each to the specified vector<File*>. -static error_code parseFile(std::unique_ptr<MemoryBuffer> &mb, - const ReaderOptionsYAML &options, - std::vector<std::unique_ptr<File>> &result) { - llvm::SourceMgr srcMgr; - llvm::yaml::Stream stream(mb->getBuffer(), srcMgr); - - for (llvm::yaml::Document &d : stream) { - std::unique_ptr<yaml::YAMLFile> curFile(new yaml::YAMLFile); - if (llvm::isa<llvm::yaml::NullNode>(d.getRoot())) - continue; // Empty files are allowed. - yaml::YAMLState yamlState(options, &stream, curFile.get()); - yamlState.parse(d.getRoot(), StringRef("<root>")); - - if ( stream.failed() ) - return make_error_code(yaml_reader_error::illegal_value); - if ( yamlState.error() ) - return yamlState.error(); - - error_code ec = curFile->bindTargetReferences(stream); - if ( ec ) - return ec; - result.emplace_back(curFile.release()); - } - - return make_error_code(yaml_reader_error::success); -} - - - -} // namespace yaml - - - -class ReaderYAML: public Reader { -public: - ReaderYAML(const ReaderOptionsYAML &options) : _options(options) { - } - - error_code parseFile(std::unique_ptr<MemoryBuffer> mb, - std::vector<std::unique_ptr<File>> &result) { - return lld::yaml::parseFile(mb, _options, result); - } - -private: - const ReaderOptionsYAML &_options; -}; - - - -Reader* createReaderYAML(const ReaderOptionsYAML &options) { - return new ReaderYAML(options); -} - -ReaderOptionsYAML::ReaderOptionsYAML() { -} - -ReaderOptionsYAML::~ReaderOptionsYAML() { -} - - - - -} // namespace lld diff --git a/lld/lib/ReaderWriter/YAML/WriterYAML.cpp b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp deleted file mode 100644 index 76773b7e88d..00000000000 --- a/lld/lib/ReaderWriter/YAML/WriterYAML.cpp +++ /dev/null @@ -1,505 +0,0 @@ -//===- lib/ReaderWriter/YAML/WriterYAML.cpp - Writes YAML object files ----===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/ReaderWriter/WriterYAML.h" - -#include "lld/Core/Atom.h" -#include "lld/Core/File.h" -#include "lld/Core/Reference.h" - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" - -#include "YamlKeyValues.h" - -#include <vector> - -namespace lld { -namespace yaml { - -/// -/// In most cases, atoms names are unambiguous, so references can just -/// use the atom name as the target (e.g. target: foo). But in a few -/// cases that does not work, so ref-names are added. These are labels -/// used only in yaml. The labels do not exist in the Atom model. -/// -/// One need for ref-names are when atoms have no user supplied name -/// (e.g. c-string literal). Another case is when two object files with -/// identically named static functions are merged (ld -r) into one object file. -/// In that case referencing the function by name is ambiguous, so a unique -/// ref-name is added. -/// -class RefNameBuilder { -public: - RefNameBuilder(const File& file) - : _collisionCount(0), _unnamedCounter(0) { - // visit all atoms - for( const DefinedAtom *atom : file.defined() ) { - // Build map of atoms names to detect duplicates - if ( ! atom->name().empty() ) - buildDuplicateNameMap(*atom); - - // Find references to unnamed atoms and create ref-names for them. - for (const Reference *ref : *atom) { - // create refname for any unnamed reference target - const Atom *target = ref->target(); - if ( (target != nullptr) && target->name().empty() ) { - std::string Storage; - llvm::raw_string_ostream Buffer(Storage); - Buffer << llvm::format("L%03d", _unnamedCounter++); - _refNames[target] = Buffer.str(); - } - } - } - for( const UndefinedAtom *undefAtom : file.undefined() ) { - buildDuplicateNameMap(*undefAtom); - } - for( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) { - buildDuplicateNameMap(*shlibAtom); - } - for( const AbsoluteAtom *absAtom : file.absolute() ) { - buildDuplicateNameMap(*absAtom); - } - - - } - - void buildDuplicateNameMap(const Atom& atom) { - assert(!atom.name().empty()); - NameToAtom::iterator pos = _nameMap.find(atom.name()); - if ( pos != _nameMap.end() ) { - // Found name collision, give each a unique ref-name. - std::string Storage; - llvm::raw_string_ostream Buffer(Storage); - Buffer << atom.name() << llvm::format(".%03d", ++_collisionCount); - _refNames[&atom] = Buffer.str(); - const Atom* prevAtom = pos->second; - AtomToRefName::iterator pos2 = _refNames.find(prevAtom); - if ( pos2 == _refNames.end() ) { - // only create ref-name for previous if none already created - Buffer << prevAtom->name() << llvm::format(".%03d", ++_collisionCount); - _refNames[prevAtom] = Buffer.str(); - } - } - else { - // First time we've seen this name, just add it to map. - _nameMap[atom.name()] = &atom; - } - } - - bool hasRefName(const Atom* atom) { - return _refNames.count(atom); - } - - StringRef refName(const Atom *atom) { - return _refNames.find(atom)->second; - } - -private: - typedef llvm::StringMap<const Atom*> NameToAtom; - typedef llvm::DenseMap<const Atom*, std::string> AtomToRefName; - - unsigned int _collisionCount; - unsigned int _unnamedCounter; - NameToAtom _nameMap; - AtomToRefName _refNames; -}; - - -/// -/// Helper class for writeObjectText() to write out atoms in yaml format. -/// -class AtomWriter { -public: - AtomWriter(const File& file, const WriterOptionsYAML &options, - RefNameBuilder& rnb) - : _file(file), _options(options), _rnb(rnb), _firstAtom(true) { } - - - void write(raw_ostream &out) { - // write header - out << "---\n"; - - // visit all atoms - for( const DefinedAtom *atom : _file.defined() ) { - writeDefinedAtom(*atom, out); - } - for( const UndefinedAtom *undefAtom : _file.undefined() ) { - writeUndefinedAtom(*undefAtom, out); - } - for( const SharedLibraryAtom *shlibAtom : _file.sharedLibrary() ) { - writeSharedLibraryAtom(*shlibAtom, out); - } - for( const AbsoluteAtom *absAtom : _file.absolute() ) { - writeAbsoluteAtom(*absAtom, out); - } - - out << "...\n"; - } - - - void writeDefinedAtom(const DefinedAtom &atom, raw_ostream &out) { - if ( _firstAtom ) { - out << "atoms:\n"; - _firstAtom = false; - } - else { - // add blank line between atoms for readability - out << "\n"; - } - - bool hasDash = false; - if ( !atom.name().empty() ) { - out << " - " - << "name:" - << spacePadding(strlen("name")) - << atom.name() - << "\n"; - hasDash = true; - } - - if ( _rnb.hasRefName(&atom) ) { - out << (hasDash ? " " : " - ") - << "ref-name:" - << spacePadding(strlen("ref-name")) - << _rnb.refName(&atom) - << "\n"; - hasDash = true; - } - - if ( atom.definition() != KeyValues::definitionDefault ) { - out << (hasDash ? " " : " - ") - << "definition:" - << spacePadding(strlen("definition")) - << KeyValues::definition(atom.definition()) - << "\n"; - hasDash = true; - } - - if ( atom.scope() != KeyValues::scopeDefault ) { - out << (hasDash ? " " : " - ") - << "scope:" - << spacePadding(strlen("scope")) - << KeyValues::scope(atom.scope()) - << "\n"; - } - - if ( atom.interposable() != KeyValues::interposableDefault ) { - out << " " - << "interposable:" - << spacePadding(strlen("interposable")) - << KeyValues::interposable(atom.interposable()) - << "\n"; - } - - if ( atom.merge() != KeyValues::mergeDefault ) { - out << " " - << "merge:" - << spacePadding(strlen("merge")) - << KeyValues::merge(atom.merge()) - << "\n"; - } - - if ( atom.contentType() != KeyValues::contentTypeDefault ) { - out << " " - << "type:" - << spacePadding(strlen("type")) - << KeyValues::contentType(atom.contentType()) - << "\n"; - } - - if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) { - out << " " - << "dead-strip:" - << spacePadding(strlen("dead-strip")) - << KeyValues::deadStripKind(atom.deadStrip()) - << "\n"; - } - - if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) { - out << " " - << "section-choice:" - << spacePadding(strlen("section-choice")) - << KeyValues::sectionChoice(atom.sectionChoice()) - << "\n"; - assert( ! atom.customSectionName().empty() ); - out << " " - << "section-name:" - << spacePadding(strlen("section-name")) - << atom.customSectionName() - << "\n"; - } - - if ( atom.isThumb() != KeyValues::isThumbDefault ) { - out << " " - << "is-thumb:" - << spacePadding(strlen("is-thumb")) - << KeyValues::isThumb(atom.isThumb()) - << "\n"; - } - - if ( atom.isAlias() != KeyValues::isAliasDefault ) { - out << " " - << "is-alias:" - << spacePadding(strlen("is-alias")) - << KeyValues::isAlias(atom.isAlias()) - << "\n"; - } - - if ( (atom.contentType() != DefinedAtom::typeZeroFill) - && (atom.size() != 0) ) { - out << " " - << "content:" - << spacePadding(strlen("content")) - << "[ "; - ArrayRef<uint8_t> arr = atom.rawContent(); - bool needComma = false; - for (unsigned int i=0; i < arr.size(); ++i) { - if ( needComma ) - out << ", "; - if ( ((i % 12) == 0) && (i != 0) ) { - out << "\n "; - } - out << hexdigit(arr[i] >> 4); - out << hexdigit(arr[i] & 0x0F); - needComma = true; - } - out << " ]\n"; - } - - bool wroteFirstFixup = false; - for (const Reference *ref : atom) { - if ( !wroteFirstFixup ) { - out << " fixups:\n"; - wroteFirstFixup = true; - } - out << " - " - << "offset:" - << spacePadding(strlen("offset")) - << ref->offsetInAtom() - << "\n"; - out << " " - << "kind:" - << spacePadding(strlen("kind")) - << _options.kindToString(ref->kind()) - << "\n"; - const Atom* target = ref->target(); - if (target != nullptr) { - StringRef refName = target->name(); - if ( _rnb.hasRefName(target) ) - refName = _rnb.refName(target); - assert(!refName.empty()); - out << " " - << "target:" - << spacePadding(strlen("target")) - << refName - << "\n"; - } - if ( ref->addend() != 0 ) { - out << " " - << "addend:" - << spacePadding(strlen("addend")) - << ref->addend() - << "\n"; - } - } - } - - - void writeUndefinedAtom(const UndefinedAtom &atom, raw_ostream &out) { - if ( _firstAtom ) { - out << "atoms:\n"; - _firstAtom = false; - } - else { - // add blank line between atoms for readability - out << "\n"; - } - - out << " - " - << "name:" - << spacePadding(strlen("name")) - << atom.name() - << "\n"; - - out << " " - << "definition:" - << spacePadding(strlen("definition")) - << KeyValues::definition(atom.definition()) - << "\n"; - - if ( atom.canBeNull() != KeyValues::canBeNullDefault ) { - out << " " - << "can-be-null:" - << spacePadding(strlen("can-be-null")) - << KeyValues::canBeNull(atom.canBeNull()) - << "\n"; - } - } - - void writeSharedLibraryAtom(const SharedLibraryAtom &atom, raw_ostream &out) { - if ( _firstAtom ) { - out << "atoms:\n"; - _firstAtom = false; - } - else { - // add blank line between atoms for readability - out << "\n"; - } - - out << " - " - << "name:" - << spacePadding(strlen("name")) - << atom.name() - << "\n"; - - out << " " - << "definition:" - << spacePadding(strlen("definition")) - << KeyValues::definition(atom.definition()) - << "\n"; - - if ( !atom.loadName().empty() ) { - out << " " - << "load-name:" - << spacePadding(strlen("load-name")) - << atom.loadName() - << "\n"; - } - - if ( atom.canBeNullAtRuntime() ) { - out << " " - << "can-be-null:" - << spacePadding(strlen("can-be-null")) - << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime) - << "\n"; - } - } - - void writeAbsoluteAtom(const AbsoluteAtom &atom, raw_ostream &out) { - if ( _firstAtom ) { - out << "atoms:\n"; - _firstAtom = false; - } - else { - // add blank line between atoms for readability - out << "\n"; - } - - out << " - " - << "name:" - << spacePadding(strlen("name")) - << atom.name() - << "\n"; - - out << " " - << "definition:" - << spacePadding(strlen("definition")) - << KeyValues::definition(atom.definition()) - << "\n"; - - if ( atom.scope() != KeyValues::scopeDefault ) { - out << " " - << "scope:" - << spacePadding(strlen("scope")) - << KeyValues::scope(atom.scope()) - << "\n"; - } - - out << " " - << "value:" - << spacePadding(strlen("value")) - << "0x"; - out.write_hex(atom.value()); - out << "\n"; - } - - -private: - // return a string of the correct number of spaces to align value - const char* spacePadding(size_t keyLen) { - const char* spaces = " "; - assert(strlen(spaces) > keyLen); - return &spaces[keyLen]; - } - - char hexdigit(uint8_t nibble) { - if ( nibble < 0x0A ) - return '0' + nibble; - else - return 'A' + nibble - 0x0A; - } - - const File &_file; - const WriterOptionsYAML &_options; - RefNameBuilder &_rnb; - bool _firstAtom; -}; - - - - -class Writer : public lld::Writer { -public: - Writer(const WriterOptionsYAML &options) : _options(options) { - } - - virtual error_code writeFile(const lld::File &file, StringRef path) { - // Create stream to path. - std::string errorInfo; - llvm::raw_fd_ostream out(path.data(), errorInfo); - if (!errorInfo.empty()) - return llvm::make_error_code(llvm::errc::no_such_file_or_directory); - - // Figure what ref-name labels are needed. - RefNameBuilder rnb(file); - - // Write out all atoms. - AtomWriter writer(file, _options, rnb); - writer.write(out); - return error_code::success(); - } - - virtual StubsPass *stubPass() { - return _options.stubPass(); - } - - virtual GOTPass *gotPass() { - return _options.gotPass(); - } - - -private: - const WriterOptionsYAML &_options; -}; - - -} // namespace yaml - - -Writer* createWriterYAML(const WriterOptionsYAML &options) { - return new lld::yaml::Writer(options); -} - -WriterOptionsYAML::WriterOptionsYAML() { -} - -WriterOptionsYAML::~WriterOptionsYAML() { -} - - -} // namespace lld diff --git a/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp deleted file mode 100644 index d464f9282c2..00000000000 --- a/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp +++ /dev/null @@ -1,431 +0,0 @@ -//===- lib/ReaderWriter/YAML/YamlKeyValues.cpp ----------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "YamlKeyValues.h" - -#include "llvm/Support/ErrorHandling.h" -#include "lld/Core/File.h" - -#include <cstring> - -namespace lld { -namespace yaml { - - -const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular; -const DefinedAtom::Scope KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit; -const DefinedAtom::ContentType KeyValues::contentTypeDefault = DefinedAtom::typeData; -const DefinedAtom::DeadStripKind KeyValues::deadStripKindDefault = DefinedAtom::deadStripNormal; -const DefinedAtom::SectionChoice KeyValues::sectionChoiceDefault = DefinedAtom::sectionBasedOnContent; -const DefinedAtom::Interposable KeyValues::interposableDefault = DefinedAtom::interposeNo; -const DefinedAtom::Merge KeyValues::mergeDefault = DefinedAtom::mergeNo; -const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__; -const bool KeyValues::isThumbDefault = false; -const bool KeyValues::isAliasDefault = false; -const UndefinedAtom::CanBeNull KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever; - - - - -struct DefinitionMapping { - const char* string; - Atom::Definition value; -}; - -static const DefinitionMapping defMappings[] = { - { "regular", Atom::definitionRegular }, - { "absolute", Atom::definitionAbsolute }, - { "undefined", Atom::definitionUndefined }, - { "shared-library", Atom::definitionSharedLibrary }, - { nullptr, Atom::definitionRegular } -}; - -bool KeyValues::definition(StringRef s, Atom::Definition &out) -{ - for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::definition(Atom::Definition s) { - for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) { - if ( p->value == s ) - return p->string; - } - llvm::report_fatal_error("bad definition value"); -} - - - - - -struct ScopeMapping { - const char* string; - DefinedAtom::Scope value; -}; - -static const ScopeMapping scopeMappings[] = { - { "global", Atom::scopeGlobal }, - { "hidden", Atom::scopeLinkageUnit }, - { "static", Atom::scopeTranslationUnit }, - { nullptr, Atom::scopeGlobal } -}; - -bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out) -{ - for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::scope(Atom::Scope s) { - for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) { - if ( p->value == s ) - return p->string; - } - llvm::report_fatal_error("bad scope value"); -} - - - - - - - -struct ContentTypeMapping { - const char* string; - DefinedAtom::ContentType value; -}; - -static const ContentTypeMapping typeMappings[] = { - { "unknown", DefinedAtom::typeUnknown }, - { "code", DefinedAtom::typeCode }, - { "stub", DefinedAtom::typeStub }, - { "stub-helper", DefinedAtom::typeStubHelper }, - { "resolver", DefinedAtom::typeResolver }, - { "constant", DefinedAtom::typeConstant }, - { "c-string", DefinedAtom::typeCString }, - { "utf16-string", DefinedAtom::typeUTF16String }, - { "CFI", DefinedAtom::typeCFI }, - { "LSDA", DefinedAtom::typeLSDA }, - { "literal-4", DefinedAtom::typeLiteral4 }, - { "literal-8", DefinedAtom::typeLiteral8 }, - { "literal-16", DefinedAtom::typeLiteral16 }, - { "data", DefinedAtom::typeData }, - { "zero-fill", DefinedAtom::typeZeroFill }, - { "cf-string", DefinedAtom::typeCFString }, - { "got", DefinedAtom::typeGOT }, - { "lazy-pointer", DefinedAtom::typeLazyPointer }, - { "initializer-ptr",DefinedAtom::typeInitializerPtr }, - { "terminator-ptr", DefinedAtom::typeTerminatorPtr }, - { "c-string-ptr", DefinedAtom::typeCStringPtr }, - { "objc1-class", DefinedAtom::typeObjC1Class }, - { "objc1-class-ptr",DefinedAtom::typeObjCClassPtr }, - { "objc2-cat-ptr", DefinedAtom::typeObjC2CategoryList }, - { "tlv-thunk", DefinedAtom::typeThunkTLV }, - { "tlv-data", DefinedAtom::typeTLVInitialData }, - { "tlv-zero-fill", DefinedAtom::typeTLVInitialZeroFill }, - { "tlv-init-ptr", DefinedAtom::typeTLVInitializerPtr }, - { nullptr, DefinedAtom::typeUnknown } -}; - -bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out) -{ - for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::contentType(DefinedAtom::ContentType s) { - for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) { - if ( p->value == s ) - return p->string; - } - llvm::report_fatal_error("bad content type value"); -} - - - - - - - -struct DeadStripMapping { - const char* string; - DefinedAtom::DeadStripKind value; -}; - -static const DeadStripMapping dsMappings[] = { - { "normal", DefinedAtom::deadStripNormal }, - { "never", DefinedAtom::deadStripNever }, - { "always", DefinedAtom::deadStripAlways }, - { nullptr, DefinedAtom::deadStripNormal } -}; - -bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out) -{ - for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) { - for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) { - if ( p->value == dsk ) - return p->string; - } - llvm::report_fatal_error("bad dead strip value"); -} - - - - - -struct InterposableMapping { - const char* string; - DefinedAtom::Interposable value; -}; - -static const InterposableMapping interMappings[] = { - { "no", DefinedAtom::interposeNo }, - { "yes", DefinedAtom::interposeYes }, - { "yesAndWeak", DefinedAtom::interposeYesAndRuntimeWeak }, - { nullptr, DefinedAtom::interposeNo } -}; - -bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out) -{ - for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){ - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::interposable(DefinedAtom::Interposable in) { - for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){ - if ( p->value == in ) - return p->string; - } - llvm::report_fatal_error("bad interposable value"); -} - - - - - - -struct MergeMapping { - const char* string; - DefinedAtom::Merge value; -}; - -static const MergeMapping mergeMappings[] = { - { "no", DefinedAtom::mergeNo }, - { "asTentative", DefinedAtom::mergeAsTentative }, - { "asWeak", DefinedAtom::mergeAsWeak }, - { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed }, - { nullptr, DefinedAtom::mergeNo } -}; - -bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out) -{ - for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::merge(DefinedAtom::Merge in) { - for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) { - if ( p->value == in ) - return p->string; - } - llvm::report_fatal_error("bad merge value"); -} - - - - - - -struct SectionChoiceMapping { - const char* string; - DefinedAtom::SectionChoice value; -}; - -static const SectionChoiceMapping sectMappings[] = { - { "content", DefinedAtom::sectionBasedOnContent }, - { "custom", DefinedAtom::sectionCustomPreferred }, - { "custom-required", DefinedAtom::sectionCustomRequired }, - { nullptr, DefinedAtom::sectionBasedOnContent } -}; - -bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out) -{ - for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){ - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) { - for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){ - if ( p->value == s ) - return p->string; - } - llvm::report_fatal_error("bad dead strip value"); -} - - - - - - - -struct PermissionsMapping { - const char* string; - DefinedAtom::ContentPermissions value; -}; - -static const PermissionsMapping permMappings[] = { - { "---", DefinedAtom::perm___ }, - { "r--", DefinedAtom::permR__ }, - { "r-x", DefinedAtom::permR_X }, - { "rw-", DefinedAtom::permRW_ }, - { "rw-l", DefinedAtom::permRW_L }, - { nullptr, DefinedAtom::perm___ } -}; - -bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out) -{ - for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) { - for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) { - if ( p->value == s ) - return p->string; - } - llvm::report_fatal_error("bad permissions value"); -} - - -bool KeyValues::isThumb(StringRef s, bool &out) -{ - if ( s.equals("true") ) { - out = true; - return false; - } - - if ( s.equals("false") ) { - out = false; - return false; - } - - return true; -} - -const char* KeyValues::isThumb(bool b) { - return b ? "true" : "false"; -} - - -bool KeyValues::isAlias(StringRef s, bool &out) -{ - if ( s.equals("true") ) { - out = true; - return false; - } - - if ( s.equals("false") ) { - out = false; - return false; - } - - return true; -} - -const char* KeyValues::isAlias(bool b) { - return b ? "true" : "false"; -} - - - - -struct CanBeNullMapping { - const char* string; - UndefinedAtom::CanBeNull value; -}; - -static const CanBeNullMapping cbnMappings[] = { - { "never", UndefinedAtom::canBeNullNever }, - { "at-runtime", UndefinedAtom::canBeNullAtRuntime }, - { "at-buildtime", UndefinedAtom::canBeNullAtBuildtime }, - { nullptr, UndefinedAtom::canBeNullNever } -}; - - -bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out) -{ - for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) { - if (s == p->string) { - out = p->value; - return false; - } - } - return true; -} - -const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) { - for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) { - if ( p->value == c ) - return p->string; - } - llvm::report_fatal_error("bad can-be-null value"); -} - - - - - - - -} // namespace yaml -} // namespace lld diff --git a/lld/lib/ReaderWriter/YAML/YamlKeyValues.h b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h deleted file mode 100644 index 3d099da9ac5..00000000000 --- a/lld/lib/ReaderWriter/YAML/YamlKeyValues.h +++ /dev/null @@ -1,84 +0,0 @@ -//===- lib/ReaderWriter/YAML/YamlKeyValues.h ------------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_YAML_KEY_VALUES_H_ -#define LLD_CORE_YAML_KEY_VALUES_H_ - -#include "lld/Core/Atom.h" -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/UndefinedAtom.h" -#include "lld/Core/File.h" - -namespace lld { -namespace yaml { - -class KeyValues { -public: - - static const char* const definitionKeyword; - static const Atom::Definition definitionDefault; - static bool definition(StringRef, Atom::Definition&); - static const char* definition(Atom::Definition); - - static const char* const scopeKeyword; - static const DefinedAtom::Scope scopeDefault; - static bool scope(StringRef, DefinedAtom::Scope&); - static const char* scope(Atom::Scope); - - static const char* const contentTypeKeyword; - static const DefinedAtom::ContentType contentTypeDefault; - static bool contentType(StringRef, DefinedAtom::ContentType&); - static const char* contentType(DefinedAtom::ContentType); - - static const char* const deadStripKindKeyword; - static const DefinedAtom::DeadStripKind deadStripKindDefault; - static bool deadStripKind(StringRef, DefinedAtom::DeadStripKind&); - static const char* deadStripKind(DefinedAtom::DeadStripKind); - - static const char* const sectionChoiceKeyword; - static const DefinedAtom::SectionChoice sectionChoiceDefault; - static bool sectionChoice(StringRef, DefinedAtom::SectionChoice&); - static const char* sectionChoice(DefinedAtom::SectionChoice); - - static const char* const interposableKeyword; - static const DefinedAtom::Interposable interposableDefault; - static bool interposable(StringRef, DefinedAtom::Interposable&); - static const char* interposable(DefinedAtom::Interposable); - - static const char* const mergeKeyword; - static const DefinedAtom::Merge mergeDefault; - static bool merge(StringRef, DefinedAtom::Merge&); - static const char* merge(DefinedAtom::Merge); - - static const char* const permissionsKeyword; - static const DefinedAtom::ContentPermissions permissionsDefault; - static bool permissions(StringRef, DefinedAtom::ContentPermissions&); - static const char* permissions(DefinedAtom::ContentPermissions); - - static const char* const isThumbKeyword; - static const bool isThumbDefault; - static bool isThumb(StringRef, bool&); - static const char* isThumb(bool); - - static const char* const isAliasKeyword; - static const bool isAliasDefault; - static bool isAlias(StringRef, bool&); - static const char* isAlias(bool); - - static const char* const canBeNullKeyword; - static const UndefinedAtom::CanBeNull canBeNullDefault; - static bool canBeNull(StringRef, UndefinedAtom::CanBeNull&); - static const char* canBeNull(UndefinedAtom::CanBeNull); - -}; - -} // namespace yaml -} // namespace lld - -#endif // LLD_CORE_YAML_KEY_VALUES_H_ diff --git a/lld/test/absolute-basic.objtxt b/lld/test/absolute-basic.objtxt index f5f1eedaf08..19772881340 100644 --- a/lld/test/absolute-basic.objtxt +++ b/lld/test/absolute-basic.objtxt @@ -5,21 +5,19 @@ # --- -atoms: +absolute-atoms: - name: putchar - definition: absolute value: 0xFFFF0040 - name: reset - definition: absolute value: 0xFFFF0080 ... + +# CHECK: absolute-atoms: # CHECK: name: putchar -# CHECK: definition: absolute -# CHECK: value: 0xffff0040 +# CHECK: value: 0x00000000FFFF0040 # CHECK: name: reset -# CHECK: definition: absolute -# CHECK: value: 0xffff0080 +# CHECK: value: 0x00000000FFFF0080 # CHECK: ... diff --git a/lld/test/absolute-local.objtxt b/lld/test/absolute-local.objtxt index 0db54e5df7e..e9324255cec 100644 --- a/lld/test/absolute-local.objtxt +++ b/lld/test/absolute-local.objtxt @@ -4,23 +4,22 @@ # Test that absolute symbols with local scope do not cause name conflict # --- -atoms: +absolute-atoms: - name: putchar - definition: absolute + ref-name: pc1 value: 0xFFFF0040 scope: static - name: putchar - definition: absolute + ref-name: pc2 value: 0xFFFF0040 scope: static ... -# CHECK: --- +# CHECK: --- +# CHECK: absolute-atoms: # CHECK: - name: putchar -# CHECK: definition: absolute -# CHECK: value: 0xffff0040 +# CHECK: value: 0x00000000FFFF0040 # CHECK: - name: putchar -# CHECK: definition: absolute -# CHECK: value: 0xffff0040 -# CHECK: ... +# CHECK: value: 0x00000000FFFF0040 +# CHECK: ... diff --git a/lld/test/archive-basic.objtxt b/lld/test/archive-basic.objtxt index 0e4a754ed45..80d945457f8 100644 --- a/lld/test/archive-basic.objtxt +++ b/lld/test/archive-basic.objtxt @@ -6,37 +6,40 @@ # --- -atoms: +defined-atoms: - name: foo type: code +undefined-atoms: - name: bar - definition: undefined --- -archive: - - name: bar.o - atoms: - - name: bar - scope: global - type: code - - - name: bar2 - type: code - - - name: baz.o - atoms: - - name: baz - scope: global - type: code - - - name: baz2 - type: code +kind: archive +members: + - name: bar.o + content: + defined-atoms: + - name: bar + scope: global + type: code + + - name: bar2 + type: code + + - name: baz.o + content: + defined-atoms: + - name: baz + scope: global + type: code + + - name: baz2 + type: code ... # CHECK: name: foo +# CHECK-NOT: undefined-atoms: # CHECK: name: bar -# CHECK-NOT: definition: undefined # CHECK: name: bar2 # CHECK-NOT: name: baz # CHECK: ... diff --git a/lld/test/archive-chain.objtxt b/lld/test/archive-chain.objtxt index f0d8e6c08ed..286b60da22a 100644 --- a/lld/test/archive-chain.objtxt +++ b/lld/test/archive-chain.objtxt @@ -5,55 +5,61 @@ # --- -atoms: +defined-atoms: - name: foo type: code +undefined-atoms: - name: bar1 - definition: undefined --- -archive: - - name: bar1.o - - atoms: - - name: bar1 - scope: global - type: code +kind: archive +members: + - name: bar1.o + content: + defined-atoms: + - name: bar1 + scope: global + type: code - - name: bar1b - type: code + - name: bar1b + type: code - - name: baz1 - definition: undefined + undefined-atoms: + - name: baz1 - - name: bar2.o - - atoms: - - name: bar2 - scope: global - type: code + - name: bar2.o + content: + defined-atoms: + - name: bar2 + scope: global + type: code - - name: bar2b - type: code + - name: bar2b + type: code --- -archive: - - name: baz1.o - - atoms: - - name: baz1 - scope: global - type: code +kind: archive +members: + - name: baz1.o + content: + defined-atoms: + - name: baz1 + scope: global + type: code + + - name: baz1b + type: code - - name: baz1b - type: code + - name: baz2.o + content: + defined-atoms: + - name: baz2 + scope: global + type: code - - name: baz2.o - - atoms: - - name: baz2 - scope: global - type: code - - - name: baz2b - type: code + - name: baz2b + type: code ... # CHECK: name: foo diff --git a/lld/test/archive-tentdef-search.objtxt b/lld/test/archive-tentdef-search.objtxt index 09cb3673ec5..730bf59e0d4 100644 --- a/lld/test/archive-tentdef-search.objtxt +++ b/lld/test/archive-tentdef-search.objtxt @@ -8,34 +8,36 @@ # --- -atoms: +defined-atoms: - name: foo type: code - name: bar scope: global type: zero-fill - merge: asTentative + merge: as-tentative --- -archive: - - name: bar.o - - atoms: - - name: bar - scope: global - type: data +kind: archive +members: + - name: bar.o + content: + defined-atoms: + - name: bar + scope: global + type: data - - name: bar2 - type: data + - name: bar2 + type: data ... # CHK1: name: foo # CHK1: name: bar -# CHK1: merge: asTentative +# CHK1: merge: as-tentative # CHK1: ... # CHK2: name: foo # CHK2: name: bar -# CHK2-NOT: merge: asTentative +# CHK2-NOT: merge: as-tentative # CHK2: name: bar2 # CHK2: ... diff --git a/lld/test/auto-hide-coalesce.objtxt b/lld/test/auto-hide-coalesce.objtxt index 5471809491b..8d621b75400 100644 --- a/lld/test/auto-hide-coalesce.objtxt +++ b/lld/test/auto-hide-coalesce.objtxt @@ -5,64 +5,56 @@ # --- -atoms: +defined-atoms: - name: _inlineFunc1 scope: global - definition: regular type: code - merge: asWeak + merge: as-weak - name: _inlineFunc2 scope: global - definition: regular type: code - merge: asWeak + merge: as-weak - name: _inlineFunc3 scope: global - definition: regular type: code - merge: asAddressedWeak + merge: as-addressed-weak - name: _inlineFunc4 scope: global - definition: regular type: code - merge: asAddressedWeak + merge: as-addressed-weak --- -atoms: +defined-atoms: - name: _inlineFunc1 scope: global - definition: regular type: code - merge: asWeak + merge: as-weak - name: _inlineFunc2 scope: global - definition: regular type: code - merge: asAddressedWeak + merge: as-addressed-weak - name: _inlineFunc3 scope: global - definition: regular type: code - merge: asWeak + merge: as-weak - name: _inlineFunc4 scope: global - definition: regular type: code - merge: asAddressedWeak + merge: as-addressed-weak ... # CHECK: name: _inlineFunc1 -# CHECK: merge: asWeak +# CHECK: merge: as-weak # CHECK: name: _inlineFunc3 -# CHECK: merge: asAddressedWeak +# CHECK: merge: as-addressed-weak # CHECK: name: _inlineFunc4 -# CHECK: merge: asAddressedWeak +# CHECK: merge: as-addressed-weak # CHECK: name: _inlineFunc2 -# CHECK: merge: asAddressedWeak +# CHECK: merge: as-addressed-weak # CHECK: ... diff --git a/lld/test/cstring-coalesce.objtxt b/lld/test/cstring-coalesce.objtxt index faf35486e6b..5b37acca5c7 100644 --- a/lld/test/cstring-coalesce.objtxt +++ b/lld/test/cstring-coalesce.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - ref-name: L0 scope: hidden type: c-string @@ -16,13 +16,13 @@ atoms: type: c-string content: [ 74, 68, 65, 72, 65, 00 ] --- -atoms: +defined-atoms: - ref-name: L2 scope: hidden type: c-string content: [ 68, 65, 6c, 6c, 6f, 00 ] --- -atoms: +defined-atoms: - ref-name: L2 scope: hidden type: c-string diff --git a/lld/test/custom-section.objtxt b/lld/test/custom-section.objtxt index 99a119fcef1..f92b3fdc91f 100644 --- a/lld/test/custom-section.objtxt +++ b/lld/test/custom-section.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: _foo1 scope: global section-choice: content diff --git a/lld/test/darwin/hello-world.objtxt b/lld/test/darwin/hello-world.objtxt index 49df58b85e3..b2e42d15e96 100644 --- a/lld/test/darwin/hello-world.objtxt +++ b/lld/test/darwin/hello-world.objtxt @@ -5,12 +5,13 @@ # --- -atoms: +defined-atoms: - name: _main type: code scope: global - content: [ 55, 48, 89, E5, 48, 8D, 3D, 00, 00, 00, 00, - E8, 00, 00, 00, 00, 31, C0, 5D, C3 ] + content: [ 55, 48, 89, E5, 48, 8D, 3D, 00, + 00, 00, 00, E8, 00, 00, 00, 00, + 31, C0, 5D, C3 ] fixups: - offset: 7 kind: pcrel32 @@ -24,8 +25,8 @@ atoms: type: c-string content: [ 68, 65, 6C, 6C, 6F, 0A, 00 ] +shared-library-atoms: - name: _printf - definition: shared-library load-name: /usr/lib/libSystem.B.dylib ... diff --git a/lld/test/dead-strip-attributes.objtxt b/lld/test/dead-strip-attributes.objtxt index 47f46c60f48..a5d21b67245 100644 --- a/lld/test/dead-strip-attributes.objtxt +++ b/lld/test/dead-strip-attributes.objtxt @@ -5,15 +5,15 @@ # --- -atoms: +defined-atoms: - name: _foo1 dead-strip: normal --- -atoms: +defined-atoms: - name: _foo2 dead-strip: never --- -atoms: +defined-atoms: - name: _foo3 dead-strip: always ... diff --git a/lld/test/dead-strip-basic.objtxt b/lld/test/dead-strip-basic.objtxt index cd09b34b089..a647d9d6927 100644 --- a/lld/test/dead-strip-basic.objtxt +++ b/lld/test/dead-strip-basic.objtxt @@ -7,7 +7,7 @@ # --- -atoms: +defined-atoms: - name: entry dead-strip: never fixups: @@ -21,13 +21,12 @@ atoms: - name: mydead1 scope: global +undefined-atoms: - name: bar - definition: undefined - name: baz - definition: undefined --- -atoms: +defined-atoms: - name: mydead2 scope: global type: data @@ -36,7 +35,7 @@ atoms: scope: global type: data --- -atoms: +defined-atoms: - name: baz scope: global type: code diff --git a/lld/test/dead-strip-globals.objtxt b/lld/test/dead-strip-globals.objtxt index be0d1f8189e..3c975d69e79 100644 --- a/lld/test/dead-strip-globals.objtxt +++ b/lld/test/dead-strip-globals.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry dead-strip: never fixups: @@ -20,13 +20,11 @@ atoms: - name: myglobal1 scope: global +undefined-atoms: - name: bar - definition: undefined - - name: baz - definition: undefined --- -atoms: +defined-atoms: - name: myglobal2 scope: global type: data @@ -35,7 +33,7 @@ atoms: scope: hidden type: data --- -atoms: +defined-atoms: - name: baz scope: hidden type: code diff --git a/lld/test/elf/abs.objtxt b/lld/test/elf/abs.objtxt index 4ec9fa97c39..1466831d35f 100644 --- a/lld/test/elf/abs.objtxt +++ b/lld/test/elf/abs.objtxt @@ -11,11 +11,9 @@ # RUN: lld-core -reader ELF %p/Inputs/abs-test.i386 | FileCheck -check-prefix=YAML %s +YAML: absolute-atoms: YAML: - name: absLocalSymbol -YAML: definition: absolute -YAML: value: 0xc0000 - +YAML: value: {{0x[0]+C0000}} YAML: - name: absGlobalSymbol -YAML: definition: absolute YAML: scope: global -YAML: value: 0xd0000 +YAML: value: {{0x[0]+D0000}} diff --git a/lld/test/elf/archive-elf-forceload.objtxt b/lld/test/elf/archive-elf-forceload.objtxt index 2e53a2114aa..efcd1fce96f 100644 --- a/lld/test/elf/archive-elf-forceload.objtxt +++ b/lld/test/elf/archive-elf-forceload.objtxt @@ -25,6 +25,7 @@ RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 -force-load | FileCheck -check-prefix FORCELOAD %s +FORCELOAD: defined-atoms: FORCELOAD: - name: fn1 FORCELOAD: scope: global FORCELOAD: type: code @@ -37,12 +38,10 @@ FORCELOAD: type: code FORCELOAD: section-choice: custom-required FORCELOAD: section-name: .text FORCELOAD: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ] +FORCELOAD: absolute-atoms: FORCELOAD: - name: main.c -FORCELOAD: definition: absolute FORCELOAD: value: 0x0 FORCELOAD: - name: fn1.c -FORCELOAD: definition: absolute FORCELOAD: value: 0x0 FORCELOAD: - name: fn.c -FORCELOAD: definition: absolute FORCELOAD: value: 0x0 diff --git a/lld/test/elf/archive-elf.objtxt b/lld/test/elf/archive-elf.objtxt index 0b85e4238f3..34e36d04367 100644 --- a/lld/test/elf/archive-elf.objtxt +++ b/lld/test/elf/archive-elf.objtxt @@ -25,15 +25,12 @@ RUN: lld-core -reader ELF %p/Inputs/mainobj.x86_64 %p/Inputs/libfnarchive.x86_64 | FileCheck -check-prefix NOFORCELOAD %s +NOFORCELOAD: defined-atoms: NOFORCELOAD: - name: fn NOFORCELOAD: scope: global -NOFORCELOAD: type: code -NOFORCELOAD: section-choice: custom-required -NOFORCELOAD: section-name: .text NOFORCELOAD: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, 5D, C3 ] +NOFORCELOAD: absolute-atoms: NOFORCELOAD: - name: main.c -NOFORCELOAD: definition: absolute NOFORCELOAD: value: 0x0 NOFORCELOAD: - name: fn.c -NOFORCELOAD: definition: absolute NOFORCELOAD: value: 0x0 diff --git a/lld/test/elf/branch.objtxt b/lld/test/elf/branch.objtxt index 91c25b6754f..ce3caee2169 100644 --- a/lld/test/elf/branch.objtxt +++ b/lld/test/elf/branch.objtxt @@ -4,24 +4,24 @@ RUN: elf-dump %t1 | FileCheck -check-prefix=hexagon-elfdump %s hexagon-yaml: - name: back hexagon-yaml: scope: global -hexagon-yaml: type: code -hexagon-yaml: section-choice: custom-required -hexagon-yaml: section-name: .text hexagon-yaml: content: [ 00, C0, 00, 7F, 00, C0, 00, 5A, 00, 00, 00, 00, hexagon-yaml: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 ] +hexagon-yaml: section-choice: custom-required +hexagon-yaml: section-name: .text hexagon-yaml: fixups: -hexagon-yaml: - offset: 4 +hexagon-yaml: - kind: +hexagon-yaml: offset: 4 hexagon-yaml: target: target hexagon-yaml: - name: target hexagon-yaml: scope: global -hexagon-yaml: type: code +hexagon-yaml: content: [ 00, C0, 00, 5A ] hexagon-yaml: section-choice: custom-required hexagon-yaml: section-name: .text -hexagon-yaml: content: [ 00, C0, 00, 5A ] hexagon-yaml: fixups: -hexagon-yaml: - offset: 0 +hexagon-yaml: - kind: +hexagon-yaml: offset: 0 hexagon-yaml: target: back diff --git a/lld/test/elf/check.objtxt b/lld/test/elf/check.objtxt index cb0f6bb9288..6ad87fb1253 100644 --- a/lld/test/elf/check.objtxt +++ b/lld/test/elf/check.objtxt @@ -1,144 +1,106 @@ RUN: lld-core -reader ELF %p/Inputs/object-test.elf-i386 | FileCheck %s -check-prefix ELF-i386 RUN: lld-core -arch hexagon -reader ELF %p/Inputs/object-test.elf-hexagon | FileCheck %s -check-prefix ELF-hexagon -ELF-i386:atoms: +ELF-i386:defined-atoms: ELF-i386: - name: global_func ELF-i386: scope: global -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 83, EC, 18, C7, 04, 24, 00, 00, 00, ELF-i386: 00, E8, FC, FF, FF, FF, C9, C3 ] ELF-i386: - name: static_func -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 83, EC, 18, C7, 04, 24, 07, 00, 00, ELF-i386: 00, E8, FC, FF, FF, FF, C9, C3 ] ELF-i386: - name: weak_func ELF-i386: scope: global -ELF-i386: merge: asWeak -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 83, EC, 18, C7, 04, 24, 0E, 00, 00, ELF-i386: 00, E8, FC, FF, FF, FF, C9, C3 ] +ELF-i386: merge: as-weak ELF-i386: - name: hidden_func ELF-i386: scope: hidden -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 83, EC, 18, C7, 04, 24, 13, 00, 00, ELF-i386: 00, E8, FC, FF, FF, FF, C9, C3 ] ELF-i386: - name: no_dead_strip ELF-i386: scope: global -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 5D, C3 ] ELF-i386: - name: no_special_section_func ELF-i386: scope: global -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text ELF-i386: content: [ 55, 89, E5, 5D, C3 ] ELF-i386: - name: special_section_func ELF-i386: scope: global -ELF-i386: type: code +ELF-i386: content: [ 55, 89, E5, 5D, C3 ] ELF-i386: section-choice: custom-required ELF-i386: section-name: special_section -ELF-i386: content: [ 55, 89, E5, 5D, C3 ] ELF-i386: - name: tentative ELF-i386: scope: global -ELF-i386: merge: asTentative ELF-i386: type: zero-fill +ELF-i386: merge: as-tentative ELF-i386: - name: common_symbol ELF-i386: scope: global -ELF-i386: merge: asTentative ELF-i386: type: zero-fill +ELF-i386: merge: as-tentative +ELF-i386:undefined-atoms: ELF-i386: - name: puts -ELF-i386: definition: undefined +ELF-i386:absolute-atoms: ELF-i386: - name: sample.c -ELF-i386: definition: absolute ELF-i386: value: 0x0 ELF-hexagon:atoms: ELF-hexagon: - name: global_func ELF-hexagon: scope: global -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 00, 40, 00, 00, 00, C0, 00, 78, ELF-hexagon: 00, C0, 00, 5A, 1E, C0, 1E, 96 ] ELF-hexagon: - name: static_func -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 00, 40, 00, 00, 00, C0, 00, 78, ELF-hexagon: 00, C0, 00, 5A, 1E, C0, 1E, 96 ] ELF-hexagon: - name: weak_func ELF-hexagon: scope: global -ELF-hexagon: merge: asWeak -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 00, 40, 00, 00, 00, C0, 00, 78, ELF-hexagon: 00, C0, 00, 5A, 1E, C0, 1E, 96 ] +ELF-hexagon: merge: as-weak ELF-hexagon: - name: hidden_func ELF-hexagon: scope: hidden -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 00, 40, 00, 00, 00, C0, 00, 78, ELF-hexagon: 00, C0, 00, 5A, 1E, C0, 1E, 96 ] ELF-hexagon: - name: no_dead_strip ELF-hexagon: scope: global -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 1E, C0, 1E, 96 ] ELF-hexagon: - name: no_special_section_func ELF-hexagon: scope: global -ELF-hexagon: type: code -ELF-hexagon: section-choice: custom-required -ELF-hexagon: section-name: .text ELF-hexagon: content: [ 00, C0, 9D, A0, 1E, C0, 1E, 96 ] ELF-hexagon: - name: special_section_func ELF-hexagon: scope: global -ELF-hexagon: type: code +ELF-hexagon: content: [ 00, C0, 9D, A0, 1E, C0, 1E, 96 ] ELF-hexagon: section-choice: custom-required ELF-hexagon: section-name: special_section -ELF-hexagon: content: [ 00, C0, 9D, A0, 1E, C0, 1E, 96 ] ELF-hexagon: - name: tentative ELF-hexagon: scope: global -ELF-hexagon: merge: asTentative ELF-hexagon: type: zero-fill +ELF-hexagon: merge: as-tentative ELF-hexagon: - name: common_symbol ELF-hexagon: scope: global -ELF-hexagon: merge: asTentative ELF-hexagon: type: zero-fill +ELF-hexagon: merge: as-tentative +ELF-hexagon: undefined-atoms: ELF-hexagon: - name: puts -ELF-hexagon: definition: undefined +ELF-hexagon: absolute-atoms: ELF-hexagon: - name: sample.c -ELF-hexagon: definition: absolute ELF-hexagon: value: 0x0 diff --git a/lld/test/elf/reloc.objtxt b/lld/test/elf/reloc.objtxt index 5c8b5ff85c1..aedb06d85b8 100644 --- a/lld/test/elf/reloc.objtxt +++ b/lld/test/elf/reloc.objtxt @@ -1,9 +1,8 @@ RUN: lld-core -reader ELF %p/Inputs/reloc-test.elf-i386 | FileCheck %s -check-prefix ELF-i386 ELF-i386:--- -ELF-i386:atoms: +ELF-i386:defined-atoms: ELF-i386: - name: .text -ELF-i386: type: code ELF-i386: section-choice: custom-required ELF-i386: section-name: .text @@ -18,61 +17,57 @@ ELF-i386: section-name: .bss ELF-i386: - name: .rodata.str1.1 ELF-i386: type: constant +ELF-i386: content: [ 68, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ] ELF-i386: section-choice: custom-required ELF-i386: section-name: .rodata.str1.1 -ELF-i386: content: [ 68, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ] ELF-i386: - name: .text.startup -ELF-i386: type: code ELF-i386: section-choice: custom-required ELF-i386: section-name: .text.startup ELF-i386: - name: main ELF-i386: scope: global -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .text.startup ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24, ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9, ELF-i386: C3 ] +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .text.startup ELF-i386: fixups: -ELF-i386: - offset: 12 -ELF-i386: kind: ??? +ELF-i386: - kind: ??? +ELF-i386: offset: 12 ELF-i386: target: .rodata.str1.1 -ELF-i386: - offset: 17 -ELF-i386: kind: call32 +ELF-i386: - kind: call32 +ELF-i386: offset: 17 ELF-i386: target: puts ELF-i386: - name: .comment ELF-i386: type: constant -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .comment ELF-i386: content: [ 00, 47, 43, 43, 3A, 20, 28, 47, 4E, 55, 29, 20, ELF-i386: 34, 2E, 37, 2E, 30, 00 ] +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .comment ELF-i386: - name: .note.GNU-stack -ELF-i386: type: code ELF-i386: section-choice: custom-required ELF-i386: section-name: .note.GNU-stack ELF-i386: - name: .eh_frame -ELF-i386: type: code -ELF-i386: section-choice: custom-required -ELF-i386: section-name: .eh_frame ELF-i386: content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, ELF-i386: 01, 7C, 08, 01, 1B, 0C, 04, 04, 88, 01, 00, 00, ELF-i386: 1C, 00, 00, 00, 1C, 00, 00, 00, 00, 00, 00, 00, ELF-i386: 19, 00, 00, 00, 00, 41, 0E, 08, 85, 02, 42, 0D, ELF-i386: 05, 55, C5, 0C, 04, 04, 00, 00 ] +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .eh_frame ELF-i386: fixups: -ELF-i386: - offset: 32 -ELF-i386: kind: call32 +ELF-i386: - kind: call32 +ELF-i386: offset: 32 ELF-i386: target: .text.startup +ELF-i386:undefined-atoms: ELF-i386: - name: puts -ELF-i386: definition: undefined +ELF-i386:absolute-atoms: ELF-i386: - name: test.c -ELF-i386: definition: absolute ELF-i386: value: 0x0 ELF-i386:... diff --git a/lld/test/elf/x86.objtxt b/lld/test/elf/x86.objtxt index bad6c255aec..750a0a77515 100644 --- a/lld/test/elf/x86.objtxt +++ b/lld/test/elf/x86.objtxt @@ -22,21 +22,17 @@ RUN: lld-core -reader ELF -arch=i386 %p/Inputs/reloc-xb.x86 %p/Inputs/reloc-xt.x x86-yaml: - name: back x86-yaml: scope: global -x86-yaml: type: code -x86-yaml: section-name: .text x86-yaml: content: [ E8, FC, FF, FF, FF ] x86-yaml: fixups: -x86-yaml: - offset: 1 -x86-yaml: kind: call32 +x86-yaml: - kind: call32 +x86-yaml: offset: 1 x86-yaml: target: target x86-yaml: - name: target x86-yaml: scope: global -x86-yaml: type: code -x86-yaml: section-name: .text x86-yaml: content: [ E8, FC, FF, FF, FF ] x86-yaml: fixups: -x86-yaml: - offset: 1 -x86-yaml: kind: call32 +x86-yaml: - kind: call32 +x86-yaml: offset: 1 x86-yaml: target: back diff --git a/lld/test/error-atom-attribute.objtxt b/lld/test/error-atom-attribute.objtxt index 5be6287bbbd..9355a18d045 100644 --- a/lld/test/error-atom-attribute.objtxt +++ b/lld/test/error-atom-attribute.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden foobar: true @@ -15,5 +15,5 @@ atoms: ... -# CHECK: error: Unknown atom attribute +# CHECK: error: unknown key 'foobar' # CHECK: foobar diff --git a/lld/test/error-atom-content-byte-value.objtxt b/lld/test/error-atom-content-byte-value.objtxt index 4113cad5e2b..42fe53376b0 100644 --- a/lld/test/error-atom-content-byte-value.objtxt +++ b/lld/test/error-atom-content-byte-value.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden content: [ A5, 00, 4G, 1F ] @@ -14,5 +14,5 @@ atoms: ... -# CHECK: error: Invalid content hex byte +# CHECK: error: invalid two-digit-hex number # CHECK: 4G diff --git a/lld/test/error-atom-content-bytes.objtxt b/lld/test/error-atom-content-bytes.objtxt index 40e9d6e4b6a..f887da56953 100644 --- a/lld/test/error-atom-content-bytes.objtxt +++ b/lld/test/error-atom-content-bytes.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden content: [ A5, 1234, 00, 4F ] @@ -14,6 +14,6 @@ atoms: ... -# CHECK: error: Content hex byte out of range +# CHECK: error: out of range two-digit-hex number # CHECK: 1234 diff --git a/lld/test/error-atom-type.objtxt b/lld/test/error-atom-type.objtxt index 85a568e6503..aae1ffff862 100644 --- a/lld/test/error-atom-type.objtxt +++ b/lld/test/error-atom-type.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden type: superluminal @@ -15,5 +15,5 @@ atoms: ... -# CHECK: error: Invalid value for 'type:' +# CHECK: error: unknown enumerated scalar # CHECK: superluminal diff --git a/lld/test/error-atom-undefined-wrong-attribue.objtxt b/lld/test/error-atom-undefined-wrong-attribue.objtxt index 342adfb3208..b5a117fac7f 100644 --- a/lld/test/error-atom-undefined-wrong-attribue.objtxt +++ b/lld/test/error-atom-undefined-wrong-attribue.objtxt @@ -6,13 +6,12 @@ # --- -atoms: +undefined-atoms: - name: foo type: code - definition: undefined ... -# CHECK: error: Undefined atom 'foo' has attributes only allowed on defined atoms +# CHECK: error: unknown key 'type' diff --git a/lld/test/error-file-attribute.objtxt b/lld/test/error-file-attribute.objtxt index 4806e4c8562..3a3997f0d63 100644 --- a/lld/test/error-file-attribute.objtxt +++ b/lld/test/error-file-attribute.objtxt @@ -7,12 +7,11 @@ --- aardvark: true -atoms: +defined-atoms: - name: entry scope: hidden ... -# CHECK: error: Unknown file attribute -# CHECK: aardvark +# CHECK: error: unknown key 'aardvark' diff --git a/lld/test/error-fixup-attribute.objtxt b/lld/test/error-fixup-attribute.objtxt index 6a2fd2a94e1..1942e086d52 100644 --- a/lld/test/error-fixup-attribute.objtxt +++ b/lld/test/error-fixup-attribute.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden fixups: @@ -18,5 +18,4 @@ atoms: ... -# CHECK: error: Unknown fixup attribute -# CHECK: weasel +# CHECK: error: unknown key 'weasel' diff --git a/lld/test/error-fixup-target.objtxt b/lld/test/error-fixup-target.objtxt index 664d0904692..3d4220c1b5f 100644 --- a/lld/test/error-fixup-target.objtxt +++ b/lld/test/error-fixup-target.objtxt @@ -6,7 +6,7 @@ # --- -atoms: +defined-atoms: - name: entry scope: hidden fixups: @@ -17,11 +17,10 @@ atoms: kind: 3 target: baz +undefined-atoms: - name: bar - definition: undefined ... -# CHECK: error: Fixup has target 'baz' which does not exist -# CHECK: baz +# CHECK: error: no such atom name: baz diff --git a/lld/test/fixups-addend.objtxt b/lld/test/fixups-addend.objtxt index 70bf92fd429..2ccea16633f 100644 --- a/lld/test/fixups-addend.objtxt +++ b/lld/test/fixups-addend.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: foo type: code content: [ 48, 8D, 3D, 00, 00, 00, 00, @@ -34,8 +34,8 @@ atoms: target: bar addend: -50 +undefined-atoms: - name: bar - definition: undefined ... diff --git a/lld/test/fixups-dup-named.objtxt b/lld/test/fixups-dup-named.objtxt index d1b1284e8f3..7e78687d5d5 100644 --- a/lld/test/fixups-dup-named.objtxt +++ b/lld/test/fixups-dup-named.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: foo type: code content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ] diff --git a/lld/test/fixups-named.objtxt b/lld/test/fixups-named.objtxt index 1bf38c06e56..1cb5b31b0b0 100644 --- a/lld/test/fixups-named.objtxt +++ b/lld/test/fixups-named.objtxt @@ -5,10 +5,11 @@ # --- -atoms: +defined-atoms: - name: foo type: code - content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ] + content: [ E8, 00, 00, 00, 00, + E8, 00, 00, 00, 00 ] fixups: - offset: 1 kind: 3 @@ -21,8 +22,8 @@ atoms: scope: static type: code +undefined-atoms: - name: bar - definition: undefined ... diff --git a/lld/test/fixups-unnamed.objtxt b/lld/test/fixups-unnamed.objtxt index 9dbab812445..340e1487847 100644 --- a/lld/test/fixups-unnamed.objtxt +++ b/lld/test/fixups-unnamed.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: foo type: code content: [ 48, 8D, 3D, 00, 00, 00, 00, diff --git a/lld/test/inline-coalesce.objtxt b/lld/test/inline-coalesce.objtxt index edd7f471f42..218967e7d08 100644 --- a/lld/test/inline-coalesce.objtxt +++ b/lld/test/inline-coalesce.objtxt @@ -5,30 +5,27 @@ # --- -atoms: +defined-atoms: - name: _inlineFunc scope: global - definition: regular type: code - merge: asWeak + merge: as-weak --- -atoms: +defined-atoms: - name: _inlineFunc scope: global - definition: regular type: code - merge: asWeak + merge: as-weak --- -atoms: +defined-atoms: - name: _inlineFunc scope: global - definition: regular type: code - merge: asWeak + merge: as-weak ... # CHECK: name: _inlineFunc -# CHECK: merge: asWeak +# CHECK: merge: as-weak # CHECK-NOT: name: _inlineFunc # CHECK: ... diff --git a/lld/test/multiple-def-error.objtxt b/lld/test/multiple-def-error.objtxt index 3017ad64945..62281e889d1 100644 --- a/lld/test/multiple-def-error.objtxt +++ b/lld/test/multiple-def-error.objtxt @@ -7,15 +7,13 @@ # CHECK: duplicate symbol --- -atoms: +defined-atoms: - name: _foo - definition: regular scope: global type: data --- -atoms: +defined-atoms: - name: _foo - definition: regular scope: global type: data ... diff --git a/lld/test/pass-got-basic.objtxt b/lld/test/pass-got-basic.objtxt index bce1d8331d0..d1f04f6dc1c 100644 --- a/lld/test/pass-got-basic.objtxt +++ b/lld/test/pass-got-basic.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: foo type: code content: [ 48, 8B, 0D, 00, 00, 00, 00, @@ -43,32 +43,33 @@ atoms: scope: global interposable: yes +shared-library-atoms: - name: malloc - definition: shared-library load-name: libc.so ... +# CHECK: defined-atoms: # CHECK: name: foo # CHECK: fixups: -# CHECK: offset: 3 -# CHECK: kind: pcrel32 -# CHECK: target: L -# CHECK: offset: 10 -# CHECK: kind: lea32wasGot -# CHECK: target: myPrivate -# CHECK: offset: 17 -# CHECK: kind: pcrel32 -# CHECK: target: L -# CHECK: offset: 24 -# CHECK: kind: pcrel32 -# CHECK: target: L -# CHECK: offset: 32 -# CHECK: kind: pcrel32 -# CHECK: target: L -# CHECK: offset: 40 -# CHECK: kind: pcrel32 -# CHECK: target: L +# CHECK: kind: pcrel32 +# CHECK: offset: 3 +# CHECK: target: L +# CHECK: kind: lea32wasGot +# CHECK: offset: 10 +# CHECK: target: myPrivate +# CHECK: kind: pcrel32 +# CHECK: offset: 17 +# CHECK: target: L +# CHECK: kind: pcrel32 +# CHECK: offset: 24 +# CHECK: target: L +# CHECK: kind: pcrel32 +# CHECK: offset: 32 +# CHECK: target: L +# CHECK: kind: pcrel32 +# CHECK: offset: 40 +# CHECK: target: L # CHECK: name: myPrivate # CHECK: name: myInterposable # CHECK: interposable: yes @@ -76,6 +77,6 @@ atoms: # CHECK: type: got # CHECK: type: got # CHECK: type: got +# CHECK: shared-library-atoms: # CHECK: name: malloc -# CHECK: definition: shared-library # CHECK: ... diff --git a/lld/test/pass-stubs-basic.objtxt b/lld/test/pass-stubs-basic.objtxt index 317372b0400..d05ba139c24 100644 --- a/lld/test/pass-stubs-basic.objtxt +++ b/lld/test/pass-stubs-basic.objtxt @@ -5,7 +5,7 @@ # --- -atoms: +defined-atoms: - name: foo type: code content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, @@ -21,12 +21,11 @@ atoms: kind: gotLoad32 target: malloc +shared-library-atoms: - name: malloc - definition: shared-library load-name: libc.so - name: free - definition: shared-library load-name: libc.so ... @@ -44,7 +43,5 @@ atoms: # CHECK: name: L # CHECK: type: stub # CHECK: name: malloc -# CHECK: definition: shared-library # CHECK: name: free -# CHECK: definition: shared-library # CHECK: ... diff --git a/lld/test/shared-library-basic.objtxt b/lld/test/shared-library-basic.objtxt index 553af50b621..bcdf04d3176 100644 --- a/lld/test/shared-library-basic.objtxt +++ b/lld/test/shared-library-basic.objtxt @@ -5,30 +5,25 @@ # --- -atoms: +shared-library-atoms: - name: malloc - definition: shared-library load-name: libc.so - name: free - definition: shared-library load-name: libc.so - name: fast_malloc - definition: shared-library load-name: libc.so can-be-null: at-runtime ... +# CHECK: shared-library-atoms: # CHECK: name: malloc -# CHECK: definition: shared-library # CHECK: load-name: libc.so # CHECK: name: free -# CHECK: definition: shared-library # CHECK: load-name: libc.so # CHECK: name: fast_malloc -# CHECK: definition: shared-library # CHECK: load-name: libc.so # CHECK: can-be-null: at-runtime # CHECK: ... diff --git a/lld/test/shared-library-coalesce.objtxt b/lld/test/shared-library-coalesce.objtxt index d3c548d9e89..04102487919 100644 --- a/lld/test/shared-library-coalesce.objtxt +++ b/lld/test/shared-library-coalesce.objtxt @@ -5,106 +5,80 @@ # --- -atoms: +shared-library-atoms: - name: foo1 - definition: shared-library load-name: libc.so - name: foo2 - definition: shared-library load-name: libc.so - name: bar1 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: bar2 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: mismatchNull1 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: mismatchNull2 - definition: shared-library load-name: libc.so - name: mismatchload1 - definition: shared-library load-name: liba.so - name: mismatchload2 - definition: shared-library load-name: libb.so --- -atoms: +shared-library-atoms: - name: foo2 - definition: shared-library load-name: libc.so - name: foo3 - definition: shared-library load-name: libc.so - name: bar2 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: bar3 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: mismatchNull1 - definition: shared-library load-name: libc.so - name: mismatchNull2 - definition: shared-library load-name: libc.so can-be-null: at-runtime - name: mismatchload1 - definition: shared-library load-name: libb.so - name: mismatchload2 - definition: shared-library load-name: liba.so ... # CHECK: name: foo1 -# CHECK: definition: shared-library # CHECK: name: foo2 -# CHECK: definition: shared-library # CHECK: name: bar1 -# CHECK: definition: shared-library # CHECK: can-be-null: at-runtime # CHECK: name: bar2 -# CHECK: definition: shared-library # CHECK: can-be-null: at-runtime # CHECK: name: mismatchNull1 -# CHECK: definition: shared-library # CHECK: can-be-null: at-runtime # CHECK: name: mismatchNull2 -# CHECK: definition: shared-library # CHECK-NOT: can-be-null: at-runtime # CHECK: name: mismatchload1 -# CHECK: definition: shared-library # CHECK: load-name: liba.so # CHECK: name: mismatchload2 -# CHECK: definition: shared-library # CHECK: load-name: libb.so # CHECK: name: foo3 -# CHECK: definition: shared-library # CHECK: name: bar3 -# CHECK: definition: shared-library # CHECK: can-be-null: at-runtime # CHECK: ... diff --git a/lld/test/tent-merge.objtxt b/lld/test/tent-merge.objtxt index 4872b163ee6..18d6f56662a 100644 --- a/lld/test/tent-merge.objtxt +++ b/lld/test/tent-merge.objtxt @@ -6,17 +6,15 @@ # --- -atoms: +defined-atoms: - name: _foo - definition: regular - merge: asTentative + merge: as-tentative scope: global type: zero-fill size: 4 --- -atoms: +defined-atoms: - name: _foo - definition: regular scope: global type: data content: [ 00, 00, 00, 00 ] @@ -24,4 +22,4 @@ atoms: # CHECK: name: _foo -# CHECK-NOT: merge: asTentative +# CHECK-NOT: merge: as-tentative diff --git a/lld/test/undef-coalesce-error.objtxt b/lld/test/undef-coalesce-error.objtxt index ab2092fb952..bbf6d1db765 100644 --- a/lld/test/undef-coalesce-error.objtxt +++ b/lld/test/undef-coalesce-error.objtxt @@ -8,44 +8,40 @@ # --- -atoms: +defined-atoms: - name: foo type: code +undefined-atoms: - name: malloc - definition: undefined - - name: free - definition: undefined --- -atoms: +defined-atoms: - name: bar type: code +undefined-atoms: - name: malloc - definition: undefined - - name: myfunc - definition: undefined --- -atoms: +defined-atoms: - name: myfunc scope: global type: code +undefined-atoms: - name: free - definition: undefined ... # CHECKERR: free # CHECKERR: malloc # CHECKERR: symbol(s) not found +# CHECK: defined-atoms: # CHECK: name: foo # CHECK: name: bar # CHECK: name: myfunc +# CHECK: undefined-atoms: # CHECK: name: malloc -# CHECK: definition: undefined # CHECK: name: free -# CHECK: definition: undefined # CHECK: ... diff --git a/lld/test/undef-coalesce.objtxt b/lld/test/undef-coalesce.objtxt index 0ae8f78d18d..08e1cf80a53 100644 --- a/lld/test/undef-coalesce.objtxt +++ b/lld/test/undef-coalesce.objtxt @@ -6,41 +6,37 @@ # --- -atoms: +defined-atoms: - name: foo type: code +undefined-atoms: - name: malloc - definition: undefined - - name: free - definition: undefined --- -atoms: +defined-atoms: - name: bar type: code +undefined-atoms: - name: malloc - definition: undefined - - name: myfunc - definition: undefined --- -atoms: +defined-atoms: - name: myfunc scope: global type: code +undefined-atoms: - name: free - definition: undefined ... +# CHECK: defined-atoms: # CHECK: name: foo # CHECK: name: bar # CHECK: name: myfunc # CHECK: scope: global +# CHECK: undefined-atoms: # CHECK: name: malloc -# CHECK: definition: undefined # CHECK: name: free -# CHECK: definition: undefined # CHECK: ... diff --git a/lld/test/undef-weak-coalesce.objtxt b/lld/test/undef-weak-coalesce.objtxt index f3ba7039b52..7a324e0166d 100644 --- a/lld/test/undef-weak-coalesce.objtxt +++ b/lld/test/undef-weak-coalesce.objtxt @@ -5,101 +5,77 @@ # --- -atoms: +undefined-atoms: - name: regular_func - definition: undefined can-be-null: never - name: weak_import_func - definition: undefined can-be-null: at-runtime - name: weak_func - definition: undefined can-be-null: at-buildtime - name: bar1 - definition: undefined can-be-null: never - name: bar2 - definition: undefined can-be-null: at-runtime - name: bar3 - definition: undefined can-be-null: at-buildtime - name: bar4 - definition: undefined can-be-null: never - name: bar5 - definition: undefined can-be-null: at-runtime - name: bar6 - definition: undefined can-be-null: at-buildtime - name: bar7 - definition: undefined can-be-null: never - name: bar8 - definition: undefined can-be-null: at-runtime - name: bar9 - definition: undefined can-be-null: at-buildtime --- -atoms: +undefined-atoms: - name: bar1 - definition: undefined can-be-null: never - name: bar2 - definition: undefined can-be-null: at-runtime - name: bar3 - definition: undefined can-be-null: at-buildtime - name: bar4 - definition: undefined can-be-null: at-runtime - name: bar5 - definition: undefined can-be-null: at-buildtime - name: bar6 - definition: undefined can-be-null: never - name: bar7 - definition: undefined can-be-null: at-buildtime - name: bar8 - definition: undefined can-be-null: never - name: bar9 - definition: undefined can-be-null: at-runtime ... # CHECK: name: regular_func -# CHECK: definition: undefined # CHECK: name: weak_import_func -# CHECK: definition: undefined # CHECK: can-be-null: at-runtime # CHECK: name: weak_func -# CHECK: definition: undefined # CHECK: can-be-null: at-buildtime # CHECK: name: bar1 # CHECK: name: bar2 diff --git a/lld/test/weak-coalesce.objtxt b/lld/test/weak-coalesce.objtxt index 48f088c2670..fdeae89a386 100644 --- a/lld/test/weak-coalesce.objtxt +++ b/lld/test/weak-coalesce.objtxt @@ -5,29 +5,26 @@ # --- -atoms: +defined-atoms: - name: _foo - definition: regular - merge: asWeak + merge: as-weak scope: global type: data --- -atoms: +defined-atoms: - name: _foo - definition: regular scope: global type: data --- -atoms: +defined-atoms: - name: _foo - definition: regular - merge: asWeak + merge: as-weak scope: global type: data ... # CHECK: name: _foo -# CHECK-NOT: merge: asWeak +# CHECK-NOT: merge: as-weak # CHECK-NOT: name: _foo # CHECK: ... |