summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/Core/InputFiles.cpp2
-rw-r--r--lld/lib/Core/YamlKeyValues.cpp199
-rw-r--r--lld/lib/Core/YamlKeyValues.h41
-rw-r--r--lld/lib/Core/YamlReader.cpp1086
-rw-r--r--lld/lib/Core/YamlWriter.cpp141
-rw-r--r--lld/test/archive-tentdef-search.objtxt2
-rw-r--r--lld/test/error-atom-attribute.objtxt19
-rw-r--r--lld/test/error-atom-content-byte-value.objtxt18
-rw-r--r--lld/test/error-atom-content-bytes.objtxt19
-rw-r--r--lld/test/error-atom-type.objtxt19
-rw-r--r--lld/test/error-atom-undefined-wrong-attribue.objtxt18
-rw-r--r--lld/test/error-file-attribute.objtxt18
-rw-r--r--lld/test/error-fixup-attribute.objtxt22
-rw-r--r--lld/test/error-fixup-target.objtxt27
14 files changed, 1015 insertions, 616 deletions
diff --git a/lld/lib/Core/InputFiles.cpp b/lld/lib/Core/InputFiles.cpp
index 5840151a894..e9a423d9a30 100644
--- a/lld/lib/Core/InputFiles.cpp
+++ b/lld/lib/Core/InputFiles.cpp
@@ -1,4 +1,4 @@
-//===- Core/InputFiles.cpp - Manages list of Files -----------------------===//
+//===- Core/InputFiles.cpp - Manages list of Files ------------------------===//
//
// The LLVM Linker
//
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp
index e21860ee199..3eab4e6d9c5 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/Core/YamlKeyValues.cpp
@@ -18,35 +18,6 @@ namespace lld {
namespace yaml {
-const char* const KeyValues::nameKeyword = "name";
-const char* const KeyValues::refNameKeyword = "ref-name";
-const char* const KeyValues::definitionKeyword = "definition";
-const char* const KeyValues::scopeKeyword = "scope";
-const char* const KeyValues::contentTypeKeyword = "type";
-const char* const KeyValues::deadStripKindKeyword = "dead-strip";
-const char* const KeyValues::sectionChoiceKeyword = "section-choice";
-const char* const KeyValues::interposableKeyword = "interposable";
-const char* const KeyValues::mergeKeyword = "merge";
-const char* const KeyValues::isThumbKeyword = "is-thumb";
-const char* const KeyValues::isAliasKeyword = "is-alias";
-const char* const KeyValues::sectionNameKeyword = "section-name";
-const char* const KeyValues::contentKeyword = "content";
-const char* const KeyValues::loadNameKeyword = "load-name";
-const char* const KeyValues::sizeKeyword = "size";
-const char* const KeyValues::valueKeyword = "value";
-const char* const KeyValues::fixupsKeyword = "fixups";
-const char* const KeyValues::permissionsKeyword = "permissions";
-const char* const KeyValues::canBeNullKeyword = "can-be-null";
-const char* const KeyValues::fixupsKindKeyword = "kind";
-const char* const KeyValues::fixupsOffsetKeyword = "offset";
-const char* const KeyValues::fixupsTargetKeyword = "target";
-const char* const KeyValues::fixupsAddendKeyword = "addend";
-const char* const KeyValues::fileAtomsKeyword = "atoms";
-const char* const KeyValues::fileKindKeyword = "kind";
-const char* const KeyValues::fileMembersKeyword = "members";
-
-
-
const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular;
const DefinedAtom::Scope KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
const DefinedAtom::ContentType KeyValues::contentTypeDefault = DefinedAtom::typeData;
@@ -58,36 +29,8 @@ const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAto
const bool KeyValues::isThumbDefault = false;
const bool KeyValues::isAliasDefault = false;
const UndefinedAtom::CanBeNull KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
-const File::Kind KeyValues::fileKindDefault = File::kindObject;
-struct FileKindMapping {
- const char* string;
- File::Kind value;
-};
-
-static const FileKindMapping fileKindMappings[] = {
- { "object", File::kindObject },
- { "archive", File::kindArchiveLibrary },
- { "shared-library", File::kindSharedLibrary },
- { nullptr, File::kindObject }
-};
-
- File::Kind KeyValues::fileKind(StringRef str) {
- for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
- if (str == p->string)
- return p->value;
- }
- llvm::report_fatal_error("bad file kind value");
-}
-
-const char* KeyValues::fileKind(File::Kind k) {
- for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
- if ( p->value == k )
- return p->string;
- }
- llvm::report_fatal_error("bad file kind value");
-}
struct DefinitionMapping {
@@ -103,13 +46,15 @@ static const DefinitionMapping defMappings[] = {
{ nullptr, Atom::definitionRegular }
};
-Atom::Definition KeyValues::definition(StringRef s)
+bool KeyValues::definition(StringRef s, Atom::Definition &out)
{
for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad definition value");
+ return true;
}
const char* KeyValues::definition(Atom::Definition s) {
@@ -136,13 +81,15 @@ static const ScopeMapping scopeMappings[] = {
{ nullptr, DefinedAtom::scopeGlobal }
};
-DefinedAtom::Scope KeyValues::scope(StringRef s)
+bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
{
for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad scope value");
+ return true;
}
const char* KeyValues::scope(DefinedAtom::Scope s) {
@@ -197,13 +144,15 @@ static const ContentTypeMapping typeMappings[] = {
{ nullptr, DefinedAtom::typeUnknown }
};
-DefinedAtom::ContentType KeyValues::contentType(StringRef s)
+bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out)
{
for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad content type value");
+ return true;
}
const char* KeyValues::contentType(DefinedAtom::ContentType s) {
@@ -225,26 +174,26 @@ struct DeadStripMapping {
DefinedAtom::DeadStripKind value;
};
-static const DeadStripMapping deadStripMappings[] = {
+static const DeadStripMapping dsMappings[] = {
{ "normal", DefinedAtom::deadStripNormal },
{ "never", DefinedAtom::deadStripNever },
{ "always", DefinedAtom::deadStripAlways },
{ nullptr, DefinedAtom::deadStripNormal }
};
-DefinedAtom::DeadStripKind KeyValues::deadStripKind(StringRef s)
+bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out)
{
- for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
- {
- if (s == p->string)
- return p->value;
+ for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad dead strip value");
+ return true;
}
const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
- for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
- {
+ for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
if ( p->value == dsk )
return p->string;
}
@@ -267,13 +216,15 @@ static const InterposableMapping interMappings[] = {
{ nullptr, DefinedAtom::interposeNo }
};
-DefinedAtom::Interposable KeyValues::interposable(StringRef s)
+bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out)
{
for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad interposable value");
+ return true;
}
const char* KeyValues::interposable(DefinedAtom::Interposable in) {
@@ -302,13 +253,15 @@ static const MergeMapping mergeMappings[] = {
{ nullptr, DefinedAtom::mergeNo }
};
-DefinedAtom::Merge KeyValues::merge(StringRef s)
+bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out)
{
for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad merge value");
+ return true;
}
const char* KeyValues::merge(DefinedAtom::Merge in) {
@@ -336,13 +289,15 @@ static const SectionChoiceMapping sectMappings[] = {
{ nullptr, DefinedAtom::sectionBasedOnContent }
};
-DefinedAtom::SectionChoice KeyValues::sectionChoice(StringRef s)
+bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out)
{
for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad dead strip value");
+ return true;
}
const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
@@ -365,21 +320,23 @@ struct PermissionsMapping {
};
static const PermissionsMapping permMappings[] = {
- { "content", DefinedAtom::perm___ },
- { "custom", DefinedAtom::permR__ },
- { "custom-required", DefinedAtom::permR_X },
- { "custom-required", DefinedAtom::permRW_ },
- { "custom-required", DefinedAtom::permRW_L },
- { nullptr, DefinedAtom::perm___ }
+ { "---", DefinedAtom::perm___ },
+ { "r--", DefinedAtom::permR__ },
+ { "r-x", DefinedAtom::permR_X },
+ { "rw-", DefinedAtom::permRW_ },
+ { "rw-l", DefinedAtom::permRW_L },
+ { nullptr, DefinedAtom::perm___ }
};
-DefinedAtom::ContentPermissions KeyValues::permissions(StringRef s)
+bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out)
{
for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad permissions value");
+ return true;
}
const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
@@ -390,10 +347,42 @@ const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
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";
}
@@ -414,13 +403,15 @@ static const CanBeNullMapping cbnMappings[] = {
};
-UndefinedAtom::CanBeNull KeyValues::canBeNull(StringRef s)
+bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out)
{
for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
- if (s == p->string)
- return p->value;
+ if (s == p->string) {
+ out = p->value;
+ return false;
+ }
}
- llvm::report_fatal_error("bad can-be-null value");
+ return true;
}
const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {
diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h
index 18c8e469b5a..ecb3d2e239a 100644
--- a/lld/lib/Core/YamlKeyValues.h
+++ b/lld/lib/Core/YamlKeyValues.h
@@ -20,81 +20,62 @@ namespace yaml {
class KeyValues {
public:
- static const char* const nameKeyword;
- static const char* const refNameKeyword;
- static const char* const sectionNameKeyword;
- static const char* const contentKeyword;
- static const char* const sizeKeyword;
- static const char* const loadNameKeyword;
- static const char* const valueKeyword;
- static const char* const fixupsKeyword;
- static const char* const fileAtomsKeyword;
- static const char* const fileMembersKeyword;
-
- static const char* const fileKindKeyword;
- static const File::Kind fileKindDefault;
- static File::Kind fileKind(StringRef);
- static const char* fileKind(File::Kind);
static const char* const definitionKeyword;
static const Atom::Definition definitionDefault;
- static Atom::Definition definition(StringRef);
+ static bool definition(StringRef, Atom::Definition&);
static const char* definition(Atom::Definition);
static const char* const scopeKeyword;
static const DefinedAtom::Scope scopeDefault;
- static DefinedAtom::Scope scope(StringRef);
+ static bool scope(StringRef, DefinedAtom::Scope&);
static const char* scope(DefinedAtom::Scope);
static const char* const contentTypeKeyword;
static const DefinedAtom::ContentType contentTypeDefault;
- static DefinedAtom::ContentType contentType(StringRef);
+ static bool contentType(StringRef, DefinedAtom::ContentType&);
static const char* contentType(DefinedAtom::ContentType);
static const char* const deadStripKindKeyword;
static const DefinedAtom::DeadStripKind deadStripKindDefault;
- static DefinedAtom::DeadStripKind deadStripKind(StringRef);
+ static bool deadStripKind(StringRef, DefinedAtom::DeadStripKind&);
static const char* deadStripKind(DefinedAtom::DeadStripKind);
static const char* const sectionChoiceKeyword;
static const DefinedAtom::SectionChoice sectionChoiceDefault;
- static DefinedAtom::SectionChoice sectionChoice(StringRef);
+ static bool sectionChoice(StringRef, DefinedAtom::SectionChoice&);
static const char* sectionChoice(DefinedAtom::SectionChoice);
static const char* const interposableKeyword;
static const DefinedAtom::Interposable interposableDefault;
- static DefinedAtom::Interposable interposable(StringRef);
+ static bool interposable(StringRef, DefinedAtom::Interposable&);
static const char* interposable(DefinedAtom::Interposable);
static const char* const mergeKeyword;
static const DefinedAtom::Merge mergeDefault;
- static DefinedAtom::Merge merge(StringRef);
+ static bool merge(StringRef, DefinedAtom::Merge&);
static const char* merge(DefinedAtom::Merge);
static const char* const permissionsKeyword;
static const DefinedAtom::ContentPermissions permissionsDefault;
- static DefinedAtom::ContentPermissions permissions(StringRef);
+ 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 UndefinedAtom::CanBeNull canBeNull(StringRef);
+ static bool canBeNull(StringRef, UndefinedAtom::CanBeNull&);
static const char* canBeNull(UndefinedAtom::CanBeNull);
-
- static const char* const fixupsKindKeyword;
- static const char* const fixupsOffsetKeyword;
- static const char* const fixupsTargetKeyword;
- static const char* const fixupsAddendKeyword;
-
};
} // namespace yaml
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index 6641f2f6b20..87f1e142355 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlReader.cpp - Reads YAML -----------------------------------===//
+//===- Core/YamlReader.cpp - Reads YAML encode object files ---------------===//
//
// The LLVM Linker
//
@@ -31,43 +31,25 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
#include <cstring>
-#include <set>
-#include <type_traits>
#include <vector>
-using namespace lld;
-
-static bool getAs(const llvm::yaml::ScalarNode *SN, bool &Result) {
- SmallString<4> Storage;
- StringRef Value = SN->getValue(Storage);
- if (Value == "true")
- Result = true;
- else if (Value == "false")
- Result = false;
- else
- return false;
- return true;
-}
-
-template<class T>
-typename std::enable_if<std::numeric_limits<T>::is_integer, bool>::type
-getAs(const llvm::yaml::ScalarNode *SN, T &Result) {
- SmallString<4> Storage;
- StringRef Value = SN->getValue(Storage);
- if (Value.getAsInteger(0, Result))
- return false;
- return true;
-}
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)
@@ -101,24 +83,31 @@ public:
_target = newAtom;
}
+ typedef llvm::yaml::ScalarNode ScalarNode;
+
const Atom *_target;
- StringRef _targetName;
+ ScalarNode * _targetNameNode;
uint64_t _offsetInAtom;
Addend _addend;
Kind _kind;
};
-class YAMLDefinedAtom;
+///
+/// Concrete instance of lld::File created parsing YAML object files.
+///
class YAMLFile : public ArchiveLibraryFile {
public:
YAMLFile()
: ArchiveLibraryFile("<anonymous>")
, _lastRefIndex(0)
- , _kind(File::kindObject)
- , _inArchive(false) {
+ , _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;
}
@@ -140,10 +129,12 @@ public:
assert(0 && "cannot add atoms to YAML files");
}
+ // Standard way that archives are searched.
virtual const File *find(StringRef name, bool dataSymbolOnly) const;
- void bindTargetReferences();
- void addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName);
+ 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);
@@ -151,6 +142,8 @@ public:
void addMember(StringRef);
void setName(StringRef);
+ StringRef copyString(StringRef);
+
struct NameAtomPair {
NameAtomPair(StringRef n, Atom *a) : name(n), atom(a) {}
StringRef name;
@@ -163,13 +156,17 @@ public:
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
std::vector<YAMLReference> _references;
std::vector<NameAtomPair> _nameToAtomMapping;
- std::vector<StringRef> _memberNames;
std::vector<std::unique_ptr<YAMLFile>> _memberFiles;
+ std::vector<char*> _stringCopies;
unsigned int _lastRefIndex;
File::Kind _kind;
- bool _inArchive;
};
+
+
+///
+/// Concrete instance of lld::DefinedAtom created parsing YAML object files.
+///
class YAMLDefinedAtom : public DefinedAtom {
public:
YAMLDefinedAtom( uint32_t ord
@@ -187,13 +184,13 @@ public:
, StringRef name
, StringRef sectionName
, uint64_t size
- , std::vector<uint8_t> content)
+ , std::vector<uint8_t>& content)
: _file(file)
, _name(name)
, _sectionName(sectionName)
, _size(size)
, _ord(ord)
- , _content(std::move(content))
+ , _content(content)
, _alignment(alignment)
, _scope(scope)
, _type(type)
@@ -299,12 +296,23 @@ public:
it = reinterpret_cast<const void*>(index);
}
- void bindTargetReferences() const {
+ // 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) {
- StringRef targetName = _file._references[i]._targetName;
- Atom *targetAtom = _file.findAtom(targetName);
- _file._references[i]._target = targetAtom;
+ 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:
@@ -328,6 +336,11 @@ private:
unsigned int _refEndIndex;
};
+
+
+///
+/// Concrete instance of lld::UndefinedAtom created parsing YAML object files.
+///
class YAMLUndefinedAtom : public UndefinedAtom {
public:
YAMLUndefinedAtom( YAMLFile &f
@@ -359,6 +372,11 @@ private:
UndefinedAtom::CanBeNull _canBeNull;
};
+
+
+///
+/// Concrete instance of lld::SharedLibraryAtom created parsing YAML files.
+///
class YAMLSharedLibraryAtom : public SharedLibraryAtom {
public:
YAMLSharedLibraryAtom( YAMLFile &f
@@ -397,6 +415,11 @@ private:
bool _canBeNull;
};
+
+
+///
+/// Concrete instance of lld::AbsoluteAtom created parsing YAML object files.
+///
class YAMLAbsoluteAtom : public AbsoluteAtom {
public:
YAMLAbsoluteAtom(YAMLFile &f, int32_t ord, StringRef name, uint64_t v)
@@ -425,12 +448,30 @@ private:
uint64_t _value;
};
-void YAMLFile::bindTargetReferences() {
+
+
+
+//===----------------------------------------------------------------------===//
+// 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);
- atom->bindTargetReferences();
+ ec = atom->bindTargetReferences(stream);
+ if ( ec )
+ return ec;
}
+ return ec;
}
Atom *YAMLFile::findAtom(StringRef name) {
@@ -438,7 +479,7 @@ Atom *YAMLFile::findAtom(StringRef name) {
if (ci.name == name)
return ci.atom;
}
- llvm::report_fatal_error("reference to atom that does not exist");
+ return nullptr;
}
void YAMLFile::addDefinedAtom(YAMLDefinedAtom *atom, StringRef refName) {
@@ -461,14 +502,20 @@ void YAMLFile::addAbsoluteAtom(AbsoluteAtom *atom) {
_nameToAtomMapping.push_back(NameAtomPair(atom->name(), atom));
}
-void YAMLFile::addMember(StringRef name) {
- _memberNames.push_back(name);
-}
-
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() ) {
@@ -479,25 +526,96 @@ const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
return nullptr;
}
-class YAMLAtomState {
+
+
+///
+/// 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:
- YAMLAtomState(Platform &platform);
+ YAMLState(Platform &platform, llvm::yaml::Stream *s, YAMLFile *f);
- void setName(StringRef n);
- void setRefName(StringRef n);
+ 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 setFixupKind(StringRef n);
- void setFixupTarget(StringRef n);
- void addFixup(YAMLFile *f);
+ 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 makeAtom(YAMLFile&);
+ void moveToState(State s);
+ void returnToState(State s, Node *node);
+
+ static const Transistion _s_transistions[];
Platform &_platform;
+ 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;
@@ -515,71 +633,164 @@ public:
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 },
};
-YAMLAtomState::YAMLAtomState(Platform &platform)
+
+YAMLState::YAMLState(Platform &platform, Stream *stream, YAMLFile *file)
: _platform(platform)
- , _size(0)
- , _value(0)
- , _ordinal(0)
- , _alignment(0, 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) {
-}
-
-void YAMLAtomState::makeAtom(YAMLFile &f) {
- if (_definition == Atom::definitionRegular) {
- YAMLDefinedAtom *a =
- new YAMLDefinedAtom( _ordinal
- , f
- , _scope
- , _type
- , _sectionChoice
- , _interpose
- , _merge
- , _deadStrip
- , _permissions
- , _isThumb
- , _isAlias
- , _alignment
- , _name
- , _sectionName
- , _size
- , _content
- );
- f.addDefinedAtom(a, !_refName.empty() ? _refName : _name);
- ++_ordinal;
- } else if (_definition == Atom::definitionUndefined) {
- UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull);
- f.addUndefinedAtom(a);
- ++_ordinal;
- } else if (_definition == Atom::definitionSharedLibrary) {
- bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime);
- SharedLibraryAtom *a = new YAMLSharedLibraryAtom(f, _ordinal, _name,
- _loadName, nullable);
- f.addSharedLibraryAtom(a);
- ++_ordinal;
- } else if (_definition == Atom::definitionAbsolute) {
- AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value);
- f.addAbsoluteAtom(a);
- ++_ordinal;
- }
+ , _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);
+ _file->addAbsoluteAtom(a);
+}
+
+
+
+void YAMLState::resetState() {
_name = StringRef();
_refName = StringRef();
_sectionName = StringRef();
_loadName = StringRef();
+ _memberName = StringRef();
_size = 0;
_value = 0;
_ordinal = 0;
@@ -598,346 +809,429 @@ void YAMLAtomState::makeAtom(YAMLFile &f) {
_isAlias = KeyValues::isAliasDefault;
_canBeNull = KeyValues::canBeNullDefault;
_ref._target = nullptr;
- _ref._targetName = StringRef();
+ _ref._targetNameNode= nullptr;
_ref._addend = 0;
_ref._offsetInAtom = 0;
_ref._kind = 0;
+
+ _hasDefinedAtomAttributes = false;
+ _hasUndefinedAtomAttributes = false;
+ _hasSharedLibraryAtomAttributes = false;
+ _hasAbsoluteAtomAttributes = false;
}
-void YAMLAtomState::setName(StringRef n) {
- _name = n;
-}
-void YAMLAtomState::setRefName(StringRef n) {
- _refName = n;
+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 YAMLAtomState::setAlign2(StringRef s) {
+
+
+void YAMLState::setAlign2(StringRef s) {
if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
_alignment.powerOf2 = 1;
}
-void YAMLAtomState::setFixupKind(StringRef s) {
- _ref._kind = _platform.kindFromString(StringRef(s));
+
+// 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";
}
-void YAMLAtomState::setFixupTarget(StringRef s) {
- _ref._targetName = s;
+// Called by parse() when recursing and switching to a new state.
+void YAMLState::moveToState(State newState) {
+ if ( newState == _state )
+ return;
+ DEBUG(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;
}
-void YAMLAtomState::addFixup(YAMLFile *f) {
- f->_references.push_back(_ref);
- // clear for next ref
- _ref._target = nullptr;
- _ref._targetName = StringRef();
- _ref._addend = 0;
- _ref._offsetInAtom = 0;
- _ref._kind = 0;
-}
-
-llvm::error_code parseFixup( llvm::yaml::MappingNode *mn
- , llvm::yaml::Stream &s
- , Platform &p
- , YAMLFile &f
- , YAMLAtomState &yas) {
- using namespace llvm::yaml;
+// Called by parse() when returning from recursion and restoring the old state.
+void YAMLState::returnToState(State prevState, Node *node) {
+ if ( prevState == _state )
+ return;
+ DEBUG(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;
+}
- for (auto &keyval : *mn) {
- ScalarNode *key = llvm::dyn_cast<ScalarNode>(keyval.getKey());
- if (!key) {
- s.printError(key, "Expected a scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- ScalarNode *value = llvm::dyn_cast<ScalarNode>(keyval.getValue());
- if (!value) {
- s.printError(value, "Expected a scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- llvm::StringRef keyValue = key->getValue(storage);
- if (keyValue == KeyValues::fixupsOffsetKeyword) {
- if (!getAs(value, yas._ref._offsetInAtom)) {
- s.printError(value, "Invalid value for offset");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (keyValue == KeyValues::fixupsKindKeyword) {
- yas._ref._kind = p.kindFromString(value->getValue(storage));
- } else if (keyValue == KeyValues::fixupsTargetKeyword) {
- // FIXME: string lifetime.
- yas._ref._targetName = value->getValue(storage);
- } else if (keyValue == KeyValues::fixupsAddendKeyword) {
- if (!getAs(value, yas._ref._addend)) {
- s.printError(value, "Invalid value for addend");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else {
- s.printError(key, "Unrecognized key");
- return make_error_code(yaml_reader_error::unknown_keyword);
- }
+
+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);
}
- yas.addFixup(&f);
- return make_error_code(yaml_reader_error::success);
+ _hasDefinedAtomAttributes = true;
}
-llvm::error_code parseAtom( llvm::yaml::MappingNode *mn
- , llvm::yaml::Stream &s
- , Platform &p
- , YAMLFile &f) {
- using namespace llvm::yaml;
- YAMLAtomState yas(p);
+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);
+ }
+}
- for (MappingNode::iterator i = mn->begin(), e = mn->end(); i != e; ++i) {
- ScalarNode *Key = llvm::dyn_cast<ScalarNode>(i->getKey());
- if (!Key)
- return make_error_code(yaml_reader_error::illegal_value);
- llvm::StringRef KeyValue = Key->getValue(storage);
- if (KeyValue == KeyValues::contentKeyword) {
- ScalarNode *scalarValue = llvm::dyn_cast<ScalarNode>(i->getValue());
- if (scalarValue) {
- yas._type = KeyValues::contentType(scalarValue->getValue(storage));
- } else {
- SequenceNode *Value = llvm::dyn_cast<SequenceNode>(i->getValue());
- if (!Value) {
- s.printError(i->getValue(), "Expected a sequence");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- for (SequenceNode::iterator ci = Value->begin(), ce = Value->end();
- ci != ce; ++ci) {
- ScalarNode *Entry = llvm::dyn_cast<ScalarNode>(&*ci);
- if (!Entry) {
- s.printError(i->getValue(), "Expected a scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- unsigned int ContentByte;
- if (Entry->getValue(storage).getAsInteger(16, ContentByte)) {
- s.printError(i->getValue(), "Invalid content byte");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (ContentByte > 0xFF) {
- s.printError(i->getValue(), "Byte out of range (> 0xFF)");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- yas._content.push_back(ContentByte & 0xFF);
- }
- }
- } else if (KeyValue == KeyValues::fixupsKeyword) {
- SequenceNode *Value = llvm::dyn_cast<SequenceNode>(i->getValue());
- if (!Value) {
- s.printError(i->getValue(), "Expected a sequence");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- for (auto &i : *Value) {
- MappingNode *Fixup = llvm::dyn_cast<MappingNode>(&i);
- if (!Fixup) {
- s.printError(&i, "Expected a map");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (error_code ec = parseFixup(Fixup, s, p, f, yas))
- return ec;
- }
- } else {
- // The rest of theses all require value to be a scalar.
- ScalarNode *Value = llvm::dyn_cast<ScalarNode>(i->getValue());
- if (!Value) {
- s.printError(i->getValue(), "Expected a scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (KeyValue == KeyValues::nameKeyword) {
- // FIXME: String lifetime.
- yas.setName(Value->getValue(storage));
- } else if (KeyValue == KeyValues::refNameKeyword) {
- // FIXME: String lifetime.
- yas.setRefName(Value->getValue(storage));
- } else if (KeyValue == KeyValues::valueKeyword) {
- if (!getAs(Value, yas._value)) {
- s.printError(Value, "Invalid value for value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (KeyValue == KeyValues::loadNameKeyword)
- // FIXME: String lifetime.
- yas._loadName = Value->getValue(storage);
- else if (KeyValue == KeyValues::definitionKeyword)
- yas._definition = KeyValues::definition(Value->getValue(storage));
- else if (KeyValue == KeyValues::scopeKeyword)
- yas._scope = KeyValues::scope(Value->getValue(storage));
- else if (KeyValue == KeyValues::contentTypeKeyword)
- yas._type = KeyValues::contentType(Value->getValue(storage));
- else if (KeyValue == KeyValues::deadStripKindKeyword)
- yas._deadStrip = KeyValues::deadStripKind(Value->getValue(storage));
- else if (KeyValue == KeyValues::sectionChoiceKeyword)
- yas._sectionChoice = KeyValues::sectionChoice(Value->getValue(storage));
- else if (KeyValue == KeyValues::mergeKeyword)
- yas._merge = KeyValues::merge(Value->getValue(storage));
- else if (KeyValue == KeyValues::interposableKeyword)
- yas._interpose = KeyValues::interposable(Value->getValue(storage));
- else if (KeyValue == KeyValues::isThumbKeyword) {
- if (!getAs(Value, yas._isThumb)) {
- s.printError(Value, "Invalid value for isThumb");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (KeyValue == KeyValues::isAliasKeyword) {
- if (!getAs(Value, yas._isAlias)) {
- s.printError(Value, "Invalid value for isAlias");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (KeyValue == KeyValues::canBeNullKeyword) {
- yas._canBeNull = KeyValues::canBeNull(Value->getValue(storage));
- if (yas._definition == Atom::definitionSharedLibrary
- && yas._canBeNull == UndefinedAtom::canBeNullAtBuildtime) {
- s.printError(Value, "Invalid value for can be null");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (KeyValue == KeyValues::sectionNameKeyword)
- // FIXME: String lifetime.
- yas._sectionName = Value->getValue(storage);
- else if (KeyValue == KeyValues::sizeKeyword) {
- if (!getAs(Value, yas._size)) {
- s.printError(Value, "Invalid value for size");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- } else if (KeyValue == "align2")
- yas.setAlign2(Value->getValue(storage));
- else {
- s.printError(Key, "Unrecognized key");
- return make_error_code(yaml_reader_error::unknown_keyword);
- }
- }
+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);
}
- yas.makeAtom(f);
- return make_error_code(yaml_reader_error::success);
+ _hasDefinedAtomAttributes = true;
}
-llvm::error_code parseAtoms( llvm::yaml::SequenceNode *atoms
- , llvm::yaml::Stream &s
- , Platform &p
- , YAMLFile &f) {
- using namespace llvm::yaml;
+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;
+}
- for (auto &atom : *atoms) {
- if (MappingNode *a = llvm::dyn_cast<MappingNode>(&atom)) {
- if (llvm::error_code ec = parseAtom(a, s, p, f))
- return ec;
- } else {
- s.printError(&atom, "Expected map");
- return make_error_code(yaml_reader_error::illegal_value);
- }
+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);
}
- return make_error_code(yaml_reader_error::success);
+ _hasDefinedAtomAttributes = true;
}
-llvm::error_code parseArchive( llvm::yaml::SequenceNode *archive
- , llvm::yaml::Stream &s
- , Platform &p
- , YAMLFile &f) {
- using namespace llvm::yaml;
+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;
+}
- for (auto &member : *archive) {
- std::unique_ptr<YAMLFile> mf(new YAMLFile);
- MappingNode *mem = llvm::dyn_cast<MappingNode>(&member);
- if (!mem) {
- s.printError(&member, "Expected map");
- return make_error_code(yaml_reader_error::illegal_value);
+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 = _platform.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(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);
+ }
}
- for (auto &keyVal : *mem) {
- ScalarNode *key = llvm::dyn_cast<ScalarNode>(keyVal.getKey());
- if (!key) {
- s.printError(keyVal.getKey(), "Expected scalar value");
- return 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);
}
- if (key->getValue(storage) == "name") {
- ScalarNode *value = llvm::dyn_cast<ScalarNode>(keyVal.getValue());
- if (!value) {
- s.printError(keyVal.getValue(), "Expected scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
+ else {
+ for (Node &seqEntry : *seq ) {
+ this->parse(&seqEntry, StringRef("<any-seq-item>"));
+ if ( _error )
+ break;
}
- // FIXME: String lifetime.
- mf->setName(value->getValue(storage));
- } else if (key->getValue(storage) == "atoms") {
- SequenceNode *atoms = llvm::dyn_cast<SequenceNode>(keyVal.getValue());
- if (!atoms) {
- s.printError(keyVal.getValue(), "Expected sequence");
- return make_error_code(yaml_reader_error::illegal_value);
+ }
+ }
+ 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;
}
- if (error_code ec = parseAtoms(atoms, s, p, *mf))
- return ec;
- } else {
- s.printError(key, "Unrecognized key");
- return make_error_code(yaml_reader_error::unknown_keyword);
}
}
- f._memberFiles.push_back(std::move(mf));
+ else {
+ _stream->printError(node, "unexpected node type");
+ _error = make_error_code(yaml_reader_error::illegal_value);
+ }
+ this->returnToState(savedState, node);
+ return;
}
- return make_error_code(yaml_reader_error::success);
+ 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);
}
+
/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
/// into lld::File object(s) and append each to the specified vector<File*>.
error_code parseObjectText( llvm::MemoryBuffer *mb
- , Platform& platform
- , std::vector<std::unique_ptr<const File>> &result) {
- using namespace llvm::yaml;
- llvm::SourceMgr sm;
- Stream stream(mb->getBuffer(), sm);
-
- llvm::SmallString<32> storage;
- for (Document &d : stream) {
- std::unique_ptr<YAMLFile> CurFile(new YAMLFile);
- if (llvm::isa<NullNode>(d.getRoot()))
+ , Platform& platform
+ , std::vector<std::unique_ptr<const File>> &result) {
+ llvm::SourceMgr srcMgr;
+ llvm::yaml::Stream stream(mb->getBuffer(), srcMgr);
+
+ for (llvm::yaml::Document &d : stream) {
+ std::unique_ptr<YAMLFile> curFile(new YAMLFile);
+ if (llvm::isa<llvm::yaml::NullNode>(d.getRoot()))
continue; // Empty files are allowed.
- MappingNode *n = llvm::dyn_cast<MappingNode>(d.getRoot());
- if (!n) {
- stream.printError(d.getRoot(), "Expected map");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- for (MappingNode::iterator mi = n->begin(), me = n->end(); mi != me; ++mi) {
- ScalarNode *key = llvm::dyn_cast<ScalarNode>(mi->getKey());
- if (!key) {
- stream.printError(mi->getValue(), "Expected scalar value");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (key->getValue(storage) == "atoms") {
- SequenceNode *Atoms = llvm::dyn_cast<SequenceNode>(mi->getValue());
- if (!Atoms) {
- stream.printError(mi->getValue(), "Expected sequence");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (error_code ec = parseAtoms(Atoms, stream, platform, *CurFile))
- return ec;
- } else if (key->getValue(storage) == "archive") {
- CurFile->_kind = YAMLFile::kindArchiveLibrary;
- SequenceNode *members = llvm::dyn_cast<SequenceNode>(mi->getValue());
- if (!members) {
- stream.printError(mi->getValue(), "Expected sequence");
- return make_error_code(yaml_reader_error::illegal_value);
- }
- if (error_code ec = parseArchive( members
- , stream
- , platform
- , *CurFile))
- return ec;
- } else {
- stream.printError(key, "Unrecognized key");
- return make_error_code(yaml_reader_error::unknown_keyword);
- }
- }
- if (stream.failed())
+ YAMLState yamlState(platform, &stream, curFile.get());
+ yamlState.parse(d.getRoot(), StringRef("<root>"));
+
+ if ( stream.failed() )
return make_error_code(yaml_reader_error::illegal_value);
- CurFile->bindTargetReferences();
- result.emplace_back(CurFile.release());
+ 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);
}
+
+
//
// Fill in vector<File*> from path to input text file.
//
-error_code parseObjectTextFileOrSTDIN( StringRef path
- , Platform& platform
- , std::vector<
- std::unique_ptr<const File>>& result) {
+error_code
+parseObjectTextFileOrSTDIN( StringRef path
+ , Platform& platform
+ , std::vector<std::unique_ptr<const File>>& result) {
OwningPtr<llvm::MemoryBuffer> mb;
if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
return ec;
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp
index e056eb898c9..03539c99914 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/Core/YamlWriter.cpp
@@ -164,9 +164,8 @@ public:
bool hasDash = false;
if ( !atom.name().empty() ) {
out << " - "
- << KeyValues::nameKeyword
- << ":"
- << spacePadding(KeyValues::nameKeyword)
+ << "name:"
+ << spacePadding(strlen("name"))
<< atom.name()
<< "\n";
hasDash = true;
@@ -174,9 +173,8 @@ public:
if ( _rnb.hasRefName(&atom) ) {
out << (hasDash ? " " : " - ")
- << KeyValues::refNameKeyword
- << ":"
- << spacePadding(KeyValues::refNameKeyword)
+ << "ref-name:"
+ << spacePadding(strlen("ref-name"))
<< _rnb.refName(&atom)
<< "\n";
hasDash = true;
@@ -184,9 +182,8 @@ public:
if ( atom.definition() != KeyValues::definitionDefault ) {
out << (hasDash ? " " : " - ")
- << KeyValues::definitionKeyword
- << ":"
- << spacePadding(KeyValues::definitionKeyword)
+ << "definition:"
+ << spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
hasDash = true;
@@ -194,9 +191,8 @@ public:
if ( atom.scope() != KeyValues::scopeDefault ) {
out << (hasDash ? " " : " - ")
- << KeyValues::scopeKeyword
- << ":"
- << spacePadding(KeyValues::scopeKeyword)
+ << "scope:"
+ << spacePadding(strlen("scope"))
<< KeyValues::scope(atom.scope())
<< "\n";
hasDash = true;
@@ -204,70 +200,62 @@ public:
if ( atom.interposable() != KeyValues::interposableDefault ) {
out << " "
- << KeyValues::interposableKeyword
- << ":"
- << spacePadding(KeyValues::interposableKeyword)
+ << "interposable:"
+ << spacePadding(strlen("interposable"))
<< KeyValues::interposable(atom.interposable())
<< "\n";
}
if ( atom.merge() != KeyValues::mergeDefault ) {
out << " "
- << KeyValues::mergeKeyword
- << ":"
- << spacePadding(KeyValues::mergeKeyword)
+ << "merge:"
+ << spacePadding(strlen("merge"))
<< KeyValues::merge(atom.merge())
<< "\n";
}
if ( atom.contentType() != KeyValues::contentTypeDefault ) {
out << " "
- << KeyValues::contentTypeKeyword
- << ":"
- << spacePadding(KeyValues::contentTypeKeyword)
+ << "type:"
+ << spacePadding(strlen("type"))
<< KeyValues::contentType(atom.contentType())
<< "\n";
}
if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
out << " "
- << KeyValues::deadStripKindKeyword
- << ":"
- << spacePadding(KeyValues::deadStripKindKeyword)
+ << "dead-strip:"
+ << spacePadding(strlen("dead-strip"))
<< KeyValues::deadStripKind(atom.deadStrip())
<< "\n";
}
if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
out << " "
- << KeyValues::sectionChoiceKeyword
- << ":"
- << spacePadding(KeyValues::sectionChoiceKeyword)
+ << "section-choice:"
+ << spacePadding(strlen("section-choice"))
<< KeyValues::sectionChoice(atom.sectionChoice())
<< "\n";
assert( ! atom.customSectionName().empty() );
out << " "
- << KeyValues::sectionNameKeyword
- << ":"
- << spacePadding(KeyValues::sectionNameKeyword)
+ << "section-name:"
+ << spacePadding(strlen("section-name"))
<< atom.customSectionName()
<< "\n";
}
if ( atom.isThumb() != KeyValues::isThumbDefault ) {
out << " "
- << KeyValues::isThumbKeyword
- << ":"
- << spacePadding(KeyValues::isThumbKeyword)
+ << "is-thumb:"
+ << spacePadding(strlen("is-thumb"))
<< KeyValues::isThumb(atom.isThumb())
<< "\n";
}
if ( atom.isAlias() != KeyValues::isAliasDefault ) {
out << " "
- << KeyValues::isAliasKeyword
- << ":"
- << spacePadding(KeyValues::isAliasKeyword)
+ << "is-alias:"
+ << spacePadding(strlen("is-alias"))
<< KeyValues::isAlias(atom.isAlias())
<< "\n";
}
@@ -275,9 +263,8 @@ public:
if ( (atom.contentType() != DefinedAtom::typeZeroFill)
&& (atom.size() != 0) ) {
out << " "
- << KeyValues::contentKeyword
- << ":"
- << spacePadding(KeyValues::contentKeyword)
+ << "content:"
+ << spacePadding(strlen("content"))
<< "[ ";
ArrayRef<uint8_t> arr = atom.rawContent();
bool needComma = false;
@@ -301,15 +288,13 @@ public:
wroteFirstFixup = true;
}
out << " - "
- << KeyValues::fixupsOffsetKeyword
- << ":"
- << spacePadding(KeyValues::fixupsOffsetKeyword)
+ << "offset:"
+ << spacePadding(strlen("offset"))
<< ref->offsetInAtom()
<< "\n";
out << " "
- << KeyValues::fixupsKindKeyword
- << ":"
- << spacePadding(KeyValues::fixupsKindKeyword)
+ << "kind:"
+ << spacePadding(strlen("kind"))
<< _platform.kindToString(ref->kind())
<< "\n";
const Atom* target = ref->target();
@@ -319,17 +304,15 @@ public:
refName = _rnb.refName(target);
assert(!refName.empty());
out << " "
- << KeyValues::fixupsTargetKeyword
- << ":"
- << spacePadding(KeyValues::fixupsTargetKeyword)
+ << "target:"
+ << spacePadding(strlen("target"))
<< refName
<< "\n";
}
if ( ref->addend() != 0 ) {
out << " "
- << KeyValues::fixupsAddendKeyword
- << ":"
- << spacePadding(KeyValues::fixupsAddendKeyword)
+ << "addend:"
+ << spacePadding(strlen("addend"))
<< ref->addend()
<< "\n";
}
@@ -348,24 +331,21 @@ public:
}
out << " - "
- << KeyValues::nameKeyword
- << ":"
- << spacePadding(KeyValues::nameKeyword)
+ << "name:"
+ << spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
- << KeyValues::definitionKeyword
- << ":"
- << spacePadding(KeyValues::definitionKeyword)
+ << "definition:"
+ << spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
out << " "
- << KeyValues::canBeNullKeyword
- << ":"
- << spacePadding(KeyValues::canBeNullKeyword)
+ << "can-be-null:"
+ << spacePadding(strlen("can-be-null"))
<< KeyValues::canBeNull(atom.canBeNull())
<< "\n";
}
@@ -382,33 +362,29 @@ public:
}
out << " - "
- << KeyValues::nameKeyword
- << ":"
- << spacePadding(KeyValues::nameKeyword)
+ << "name:"
+ << spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
- << KeyValues::definitionKeyword
- << ":"
- << spacePadding(KeyValues::definitionKeyword)
+ << "definition:"
+ << spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
if ( !atom.loadName().empty() ) {
out << " "
- << KeyValues::loadNameKeyword
- << ":"
- << spacePadding(KeyValues::loadNameKeyword)
+ << "load-name:"
+ << spacePadding(strlen("load-name"))
<< atom.loadName()
<< "\n";
}
if ( atom.canBeNullAtRuntime() ) {
out << " "
- << KeyValues::canBeNullKeyword
- << ":"
- << spacePadding(KeyValues::canBeNullKeyword)
+ << "can-be-null:"
+ << spacePadding(strlen("can-be-null"))
<< KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
<< "\n";
}
@@ -425,23 +401,20 @@ public:
}
out << " - "
- << KeyValues::nameKeyword
- << ":"
- << spacePadding(KeyValues::nameKeyword)
+ << "name:"
+ << spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
- << KeyValues::definitionKeyword
- << ":"
- << spacePadding(KeyValues::definitionKeyword)
+ << "definition:"
+ << spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
out << " "
- << KeyValues::valueKeyword
- << ":"
- << spacePadding(KeyValues::valueKeyword)
+ << "value:"
+ << spacePadding(strlen("value"))
<< "0x";
out.write_hex(atom.value());
out << "\n";
@@ -450,10 +423,10 @@ public:
private:
// return a string of the correct number of spaces to align value
- const char* spacePadding(const char* key) {
+ const char* spacePadding(int keyLen) {
const char* spaces = " ";
- assert(strlen(spaces) > strlen(key));
- return &spaces[strlen(key)];
+ assert(strlen(spaces) > keyLen);
+ return &spaces[keyLen];
}
char hexdigit(uint8_t nibble) {
diff --git a/lld/test/archive-tentdef-search.objtxt b/lld/test/archive-tentdef-search.objtxt
index 48859088895..09cb3673ec5 100644
--- a/lld/test/archive-tentdef-search.objtxt
+++ b/lld/test/archive-tentdef-search.objtxt
@@ -14,7 +14,7 @@ atoms:
- name: bar
scope: global
- content: zero-fill
+ type: zero-fill
merge: asTentative
---
diff --git a/lld/test/error-atom-attribute.objtxt b/lld/test/error-atom-attribute.objtxt
new file mode 100644
index 00000000000..5be6287bbbd
--- /dev/null
+++ b/lld/test/error-atom-attribute.objtxt
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that unknown atom attribute produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ foobar: true
+ dead-strip: never
+
+...
+
+
+# CHECK: error: Unknown atom attribute
+# CHECK: foobar
diff --git a/lld/test/error-atom-content-byte-value.objtxt b/lld/test/error-atom-content-byte-value.objtxt
new file mode 100644
index 00000000000..4113cad5e2b
--- /dev/null
+++ b/lld/test/error-atom-content-byte-value.objtxt
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that an invalid hex byte produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ content: [ A5, 00, 4G, 1F ]
+
+...
+
+
+# CHECK: error: Invalid content hex byte
+# CHECK: 4G
diff --git a/lld/test/error-atom-content-bytes.objtxt b/lld/test/error-atom-content-bytes.objtxt
new file mode 100644
index 00000000000..40e9d6e4b6a
--- /dev/null
+++ b/lld/test/error-atom-content-bytes.objtxt
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that an out of range byte value produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ content: [ A5, 1234, 00, 4F ]
+
+...
+
+
+# CHECK: error: Content hex byte out of range
+# CHECK: 1234
+
diff --git a/lld/test/error-atom-type.objtxt b/lld/test/error-atom-type.objtxt
new file mode 100644
index 00000000000..85a568e6503
--- /dev/null
+++ b/lld/test/error-atom-type.objtxt
@@ -0,0 +1,19 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that an unknown content type produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ type: superluminal
+ dead-strip: never
+
+...
+
+
+# CHECK: error: Invalid value for 'type:'
+# CHECK: superluminal
diff --git a/lld/test/error-atom-undefined-wrong-attribue.objtxt b/lld/test/error-atom-undefined-wrong-attribue.objtxt
new file mode 100644
index 00000000000..342adfb3208
--- /dev/null
+++ b/lld/test/error-atom-undefined-wrong-attribue.objtxt
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that a defined attribute on an undefined atom produces a readable error.
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ definition: undefined
+
+...
+
+
+# CHECK: error: Undefined atom 'foo' has attributes only allowed on defined atoms
+
diff --git a/lld/test/error-file-attribute.objtxt b/lld/test/error-file-attribute.objtxt
new file mode 100644
index 00000000000..4806e4c8562
--- /dev/null
+++ b/lld/test/error-file-attribute.objtxt
@@ -0,0 +1,18 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that unknown file attribute produces a readable error.
+#
+
+---
+aardvark: true
+atoms:
+ - name: entry
+ scope: hidden
+
+...
+
+
+# CHECK: error: Unknown file attribute
+# CHECK: aardvark
diff --git a/lld/test/error-fixup-attribute.objtxt b/lld/test/error-fixup-attribute.objtxt
new file mode 100644
index 00000000000..6a2fd2a94e1
--- /dev/null
+++ b/lld/test/error-fixup-attribute.objtxt
@@ -0,0 +1,22 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that unknown fixup attribute produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ fixups:
+ - offset: 3
+ kind: 3
+ weasel: bar
+ addend: 100
+
+...
+
+
+# CHECK: error: Unknown fixup attribute
+# CHECK: weasel
diff --git a/lld/test/error-fixup-target.objtxt b/lld/test/error-fixup-target.objtxt
new file mode 100644
index 00000000000..664d0904692
--- /dev/null
+++ b/lld/test/error-fixup-target.objtxt
@@ -0,0 +1,27 @@
+# RUN: not lld-core %s 2> %t.err
+# RUN: FileCheck < %t.err %s
+
+#
+# Test that unbindable target name produces a readable error.
+#
+
+---
+atoms:
+ - name: entry
+ scope: hidden
+ fixups:
+ - offset: 3
+ kind: 3
+ target: bar
+ - offset: 5
+ kind: 3
+ target: baz
+
+ - name: bar
+ definition: undefined
+
+...
+
+
+# CHECK: error: Fixup has target 'baz' which does not exist
+# CHECK: baz
OpenPOWER on IntegriCloud