blob: 6af7111b20ddbf276581479e2de775c1d199d6af [file] [log] [blame]
//===- Core/YamlReader.cpp - Reads YAML -----------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/Core/YamlReader.h"
#include "YamlKeyValues.h"
#include "lld/Core/Atom.h"
#include "lld/Core/AbsoluteAtom.h"
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Platform.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/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/system_error.h"
#include <cstring>
#include <vector>
namespace lld {
namespace yaml {
namespace {
class YAML {
public:
struct Entry {
Entry(const char *k, const char *v, std::vector<uint8_t>* vs,
int d, bool bd, bool bs)
: key(strdup(k))
, value(v ? strdup(v) : nullptr)
, valueSequenceBytes(vs)
, depth(d)
, beginSequence(bs)
, beginDocument(bd) {}
const char * key;
const char * value;
std::vector<uint8_t>* valueSequenceBytes;
int depth;
bool beginSequence;
bool beginDocument;
};
static void parse(llvm::MemoryBuffer *mb, std::vector<const Entry *>&);
private:
enum State {
start,
inHeaderComment,
inTripleDash,
inTriplePeriod,
inDocument,
inKey,
inSpaceBeforeValue,
inValue,
inValueSequence,
inValueSequenceEnd
};
};
void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) {
State state = start;
char key[64];
char value[64];
char *p = nullptr;
unsigned int lineNumber = 1;
int depth = 0;
bool nextKeyIsStartOfDocument = false;
bool nextKeyIsStartOfSequence = false;
std::vector<uint8_t>* sequenceBytes = nullptr;
unsigned contentByte = 0;
for (const char *s = mb->getBufferStart(); s < mb->getBufferEnd(); ++s) {
char c = *s;
if (c == '\n')
++lineNumber;
switch (state) {
case start:
if (c == '#')
state = inHeaderComment;
else if (c == '-') {
p = &key[0];
*p++ = c;
state = inTripleDash;
}
break;
case inHeaderComment:
if (c == '\n') {
state = start;
}
break;
case inTripleDash:
if (c == '-') {
*p++ = c;
} else if (c == '\n') {
*p = '\0';
if (strcmp(key, "---") != 0)
return;
depth = 0;
state = inDocument;
nextKeyIsStartOfDocument = true;
} else {
return;
}
break;
case inTriplePeriod:
if (c == '.') {
*p++ = c;
} else if (c == '\n') {
*p = '\0';
if (strcmp(key, "...") != 0)
return;
depth = 0;
state = inHeaderComment;
} else {
return;
}
break;
case inDocument:
if (isalnum(c)) {
state = inKey;
p = &key[0];
*p++ = c;
} else if (c == '-') {
if (depth == 0) {
p = &key[0];
*p++ = c;
state = inTripleDash;
} else {
nextKeyIsStartOfSequence = true;
++depth;
}
} else if (c == ' ') {
++depth;
} else if (c == '.') {
p = &key[0];
*p++ = c;
state = inTriplePeriod;
} else if (c == '\n') {
// ignore empty lines
depth = 0;
} else if (c == '\t') {
llvm::report_fatal_error("TAB character found in yaml file");
} else {
return;
}
break;
case inKey:
if (isalnum(c) || (c == '-')) {
*p++ = c;
} else if (c == ':') {
*p = '\0';
state = inSpaceBeforeValue;
} else if (c == '\n') {
*p = '\0';
if (strcmp(key, "---") == 0)
state = inDocument;
else
return;
} else {
return;
}
break;
case inSpaceBeforeValue:
if (isalnum(c) || (c == '-') || (c == '_') || (c == '/')) {
p = &value[0];
*p++ = c;
state = inValue;
} else if (c == '\n') {
entries.push_back(new Entry(key, "", nullptr, depth,
nextKeyIsStartOfDocument,
nextKeyIsStartOfSequence));
nextKeyIsStartOfSequence = false;
nextKeyIsStartOfDocument = false;
state = inDocument;
depth = 0;
} else if (c == '[') {
contentByte = 0;
sequenceBytes = new std::vector<uint8_t>();
state = inValueSequence;
} else if (c == ' ') {
// eat space
} else if (c == '\t') {
llvm::report_fatal_error("TAB character found in yaml file");
} else {
return;
}
break;
case inValue:
if (c == '\n') {
*p = '\0';
entries.push_back(new Entry(key, value, nullptr, depth,
nextKeyIsStartOfDocument,
nextKeyIsStartOfSequence));
nextKeyIsStartOfSequence = false;
nextKeyIsStartOfDocument = false;
state = inDocument;
depth = 0;
}
else {
*p++ = c;
}
break;
case inValueSequence:
if (c == ']') {
sequenceBytes->push_back(contentByte);
state = inValueSequenceEnd;
}
else if ( (c == ' ') || (c == '\n') ) {
// eat white space
}
else if (c == ',') {
sequenceBytes->push_back(contentByte);
}
else if ( isdigit(c) ) {
contentByte = (contentByte << 4) | (c-'0');
}
else if ( ('a' <= tolower(c)) && (tolower(c) <= 'f') ) {
contentByte = (contentByte << 4) | (tolower(c)-'a'+10);
}
else {
llvm::report_fatal_error("non-hex digit found in content [ ]");
}
break;
case inValueSequenceEnd:
if (c == '\n') {
entries.push_back(new Entry(key, nullptr, sequenceBytes, depth,
nextKeyIsStartOfDocument,
nextKeyIsStartOfSequence));
nextKeyIsStartOfSequence = false;
nextKeyIsStartOfDocument = false;
state = inDocument;
depth = 0;
}
break;
}
}
}
class YAMLReference : public Reference {
public:
YAMLReference() : _target(nullptr), _targetName(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;
}
const Atom* _target;
const char* _targetName;
uint64_t _offsetInAtom;
Addend _addend;
Kind _kind;
};
class YAMLDefinedAtom;
class YAMLFile : public File {
public:
YAMLFile()
: File("path")
, _lastRefIndex(0) {}
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");
}
void bindTargetReferences();
void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
void addUndefinedAtom(UndefinedAtom* atom);
void addSharedLibraryAtom(SharedLibraryAtom* atom);
void addAbsoluteAtom(AbsoluteAtom* atom);
Atom* findAtom(const char* name);
struct NameAtomPair {
NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
const char* 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;
unsigned int _lastRefIndex;
};
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
, const char* name
, const char* 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 {
if (_name == nullptr)
return StringRef();
else
return _name;
}
virtual uint64_t size() const {
return (_content ? _content->size() : _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 {
if (_content != nullptr)
return ArrayRef<uint8_t>(*_content);
else
return ArrayRef<uint8_t>();
}
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);
}
void bindTargetReferences() const {
for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
const char* targetName = _file._references[i]._targetName;
Atom* targetAtom = _file.findAtom(targetName);
_file._references[i]._target = targetAtom;
}
}
private:
YAMLFile& _file;
const char * _name;
const char * _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;
};
class YAMLUndefinedAtom : public UndefinedAtom {
public:
YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm,
UndefinedAtom::CanBeNull cbn)
: _file(f), _name(nm), _ordinal(ord), _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;
const char * _name;
uint32_t _ordinal;
UndefinedAtom::CanBeNull _canBeNull;
};
class YAMLSharedLibraryAtom : public SharedLibraryAtom {
public:
YAMLSharedLibraryAtom(YAMLFile& f, int32_t ord, const char* nm,
const char* ldnm, bool cbn)
: _file(f), _name(nm), _ordinal(ord),
_loadName(ldnm), _canBeNull(cbn) { }
virtual const class File& file() const {
return _file;
}
virtual StringRef name() const {
return _name;
}
virtual StringRef loadName() const {
if ( _loadName == nullptr )
return StringRef();
else
return StringRef(_loadName);
}
virtual bool canBeNullAtRuntime() const {
return _canBeNull;
}
private:
YAMLFile& _file;
const char * _name;
uint32_t _ordinal;
const char * _loadName;
bool _canBeNull;
};
class YAMLAbsoluteAtom : public AbsoluteAtom {
public:
YAMLAbsoluteAtom(YAMLFile& f, int32_t ord, const char* nm, uint64_t v)
: _file(f), _name(nm), _ordinal(ord), _value(v) { }
virtual const class File& file() const {
return _file;
}
virtual StringRef name() const {
return _name;
}
virtual uint64_t value() const {
return _value;
}
private:
YAMLFile& _file;
const char * _name;
uint32_t _ordinal;
uint64_t _value;
};
void YAMLFile::bindTargetReferences() {
for (const DefinedAtom *defAtom : _definedAtoms) {
const YAMLDefinedAtom* atom =
reinterpret_cast<const YAMLDefinedAtom*>(defAtom);
atom->bindTargetReferences();
}
}
Atom* YAMLFile::findAtom(const char* name) {
for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();
it != _nameToAtomMapping.end(); ++it) {
if ( strcmp(name, it->name) == 0 )
return it->atom;
}
llvm::report_fatal_error("reference to atom that does not exist");
}
void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
_definedAtoms._atoms.push_back(atom);
assert(refName != nullptr);
_nameToAtomMapping.push_back(NameAtomPair(refName, atom));
}
void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
_undefinedAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
_sharedLibraryAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
_absoluteAtoms._atoms.push_back(atom);
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
}
class YAMLAtomState {
public:
YAMLAtomState(Platform& platform);
void setName(const char *n);
void setRefName(const char *n);
void setAlign2(const char *n);
void setFixupKind(const char *n);
void setFixupTarget(const char *n);
void addFixup(YAMLFile *f);
void makeAtom(YAMLFile&);
Platform& _platform;
const char * _name;
const char * _refName;
const char * _sectionName;
const char* _loadName;
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;
};
YAMLAtomState::YAMLAtomState(Platform& platform)
: _platform(platform)
, _name(nullptr)
, _refName(nullptr)
, _sectionName(nullptr)
, _loadName(nullptr)
, _size(0)
, _value(0)
, _ordinal(0)
, _content(nullptr)
, _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 ? _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;
}
// reset state for next atom
_name = nullptr;
_refName = nullptr;
_sectionName = nullptr;
_loadName = nullptr;
_size = 0;
_value = 0;
_ordinal = 0;
_content = nullptr;
_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._targetName = nullptr;
_ref._addend = 0;
_ref._offsetInAtom = 0;
_ref._kind = 0;
}
void YAMLAtomState::setName(const char *n) {
_name = n;
}
void YAMLAtomState::setRefName(const char *n) {
_refName = n;
}
void YAMLAtomState::setAlign2(const char *s) {
if (StringRef(s).getAsInteger(10, _alignment.powerOf2))
_alignment.powerOf2 = 1;
}
void YAMLAtomState::setFixupKind(const char *s) {
_ref._kind = _platform.kindFromString(StringRef(s));
}
void YAMLAtomState::setFixupTarget(const char *s) {
_ref._targetName = s;
}
void YAMLAtomState::addFixup(YAMLFile *f) {
f->_references.push_back(_ref);
// clear for next ref
_ref._target = nullptr;
_ref._targetName = nullptr;
_ref._addend = 0;
_ref._offsetInAtom = 0;
_ref._kind = 0;
}
} // anonymous namespace
/// 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<const File *> &result) {
std::vector<const YAML::Entry *> entries;
YAML::parse(mb, entries);
YAMLFile *file = nullptr;
YAMLAtomState atomState(platform);
bool inAtoms = false;
bool inFixups = false;
int depthForAtoms = -1;
int depthForFixups = -1;
int lastDepth = -1;
bool haveAtom = false;
bool haveFixup = false;
for (std::vector<const YAML::Entry *>::iterator it = entries.begin();
it != entries.end(); ++it) {
const YAML::Entry *entry = *it;
if (entry->beginDocument) {
if (file != nullptr) {
if (haveAtom) {
atomState.makeAtom(*file);
haveAtom = false;
}
file->bindTargetReferences();
result.push_back(file);
}
file = new YAMLFile();
inAtoms = false;
depthForAtoms = -1;
}
if (lastDepth > entry->depth) {
// end of fixup sequence
if (haveFixup) {
atomState.addFixup(file);
haveFixup = false;
}
}
if (inAtoms && (depthForAtoms == -1)) {
depthForAtoms = entry->depth;
}
if (inFixups && (depthForFixups == -1)) {
depthForFixups = entry->depth;
}
if (strcmp(entry->key, "atoms") == 0) {
inAtoms = true;
}
if (inAtoms) {
if (depthForAtoms == entry->depth) {
if (entry->beginSequence) {
if (haveAtom) {
atomState.makeAtom(*file);
haveAtom = false;
}
}
if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
atomState.setName(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {
atomState.setRefName(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
atomState._definition = KeyValues::definition(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::scopeKeyword) == 0) {
atomState._scope = KeyValues::scope(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::contentTypeKeyword) == 0) {
atomState._type = KeyValues::contentType(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::deadStripKindKeyword) == 0) {
atomState._deadStrip = KeyValues::deadStripKind(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::sectionChoiceKeyword) == 0) {
atomState._sectionChoice = KeyValues::sectionChoice(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::mergeKeyword) == 0) {
atomState._merge = KeyValues::merge(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::interposableKeyword) == 0) {
atomState._interpose = KeyValues::interposable(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) {
atomState._isThumb = KeyValues::isThumb(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) {
atomState._isAlias = KeyValues::isAlias(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::canBeNullKeyword) == 0) {
atomState._canBeNull = KeyValues::canBeNull(entry->value);
if ( atomState._definition == Atom::definitionSharedLibrary ) {
if ( atomState._canBeNull == UndefinedAtom::canBeNullAtBuildtime )
return make_error_code(yaml_reader_error::illegal_value);
}
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
atomState._sectionName = entry->value;
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::sizeKeyword) == 0) {
StringRef val = entry->value;
if (val.getAsInteger(0, atomState._size))
return make_error_code(yaml_reader_error::illegal_value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::contentKeyword) == 0) {
atomState._content = entry->valueSequenceBytes;
haveAtom = true;
}
else if (strcmp(entry->key, "align2") == 0) {
atomState.setAlign2(entry->value);
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
inFixups = true;
}
else if (strcmp(entry->key, KeyValues::loadNameKeyword) == 0) {
atomState._loadName = entry->value;
haveAtom = true;
}
else if (strcmp(entry->key, KeyValues::valueKeyword) == 0) {
llvm::APInt Val;
StringRef(entry->value).getAsInteger(0, Val);
atomState._value = Val.getZExtValue();
haveAtom = true;
}
else {
return make_error_code(yaml_reader_error::unknown_keyword);
}
}
else if (depthForFixups == entry->depth) {
if (entry->beginSequence) {
if (haveFixup) {
atomState.addFixup(file);
haveFixup = false;
}
}
if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {
atomState.setFixupKind(entry->value);
haveFixup = true;
}
else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
if (StringRef(entry->value).getAsInteger(0,
atomState._ref._offsetInAtom))
return make_error_code(yaml_reader_error::illegal_value);
haveFixup = true;
}
else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
atomState.setFixupTarget(entry->value);
haveFixup = true;
}
else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
StringRef Addend(entry->value);
if (Addend.getAsInteger(0, atomState._ref._addend))
return make_error_code(yaml_reader_error::illegal_value);
haveFixup = true;
}
}
}
lastDepth = entry->depth;
}
if (haveAtom) {
atomState.makeAtom(*file);
}
if (file != nullptr) {
file->bindTargetReferences();
result.push_back(file);
}
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<const File*>& result) {
OwningPtr<llvm::MemoryBuffer> mb;
if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
return ec;
return parseObjectText(mb.get(), platform, result);
}
} // namespace yaml
} // namespace lld