llvm-project/lld/lib/ReaderWriter/ELF/Atoms.h

903 lines
27 KiB
C
Raw Normal View History

//===- lib/ReaderWriter/ELF/Atoms.h ---------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_ATOMS_H
#define LLD_READER_WRITER_ELF_ATOMS_H
#include "TargetHandler.h"
2013-01-25 15:39:18 +08:00
#include "lld/Core/LLVM.h"
#include "lld/Core/Simple.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSwitch.h"
#include <memory>
#include <vector>
namespace lld {
namespace elf {
template <class ELFT> class DynamicFile;
template <typename ELFT> class ELFFile;
2013-01-25 15:39:18 +08:00
/// \brief Relocation References: Defined Atoms may contain references that will
/// need to be patched before the executable is written.
///
/// Construction of ELFReferences is two pass process. ELFReferences are
/// instantiated while we are iterating over symbol tables to atomize
/// symbols. At that time we only know the index of relocation target symbol
/// (not target atom) about a relocation, so we store the index to
/// ELFREference. In the second pass, ELFReferences are revisited to update
/// target atoms by target symbol indexes.
template <class ELFT> class ELFReference : public Reference {
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
public:
ELFReference(const Elf_Rela *rela, uint64_t off, Reference::KindArch arch,
uint16_t relocType, uint32_t idx)
: Reference(Reference::KindNamespace::ELF, arch, relocType),
_target(nullptr), _targetSymbolIndex(idx), _offsetInAtom(off),
_addend(rela->r_addend) {}
ELFReference(const Elf_Rel *rel, uint64_t off, Reference::KindArch arch,
uint16_t relocType, uint32_t idx)
: Reference(Reference::KindNamespace::ELF, arch, relocType),
_target(nullptr), _targetSymbolIndex(idx), _offsetInAtom(off),
_addend(0) {}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
ELFReference(uint32_t edgeKind)
: Reference(Reference::KindNamespace::all, Reference::KindArch::all,
edgeKind),
_target(nullptr), _targetSymbolIndex(0), _offsetInAtom(0), _addend(0) {}
uint64_t offsetInAtom() const override { return _offsetInAtom; }
const Atom *target() const override { return _target; }
/// \brief The symbol table index that contains the target reference.
uint64_t targetSymbolIndex() const {
return _targetSymbolIndex;
}
Addend addend() const override { return _addend; }
virtual void setOffset(uint64_t off) { _offsetInAtom = off; }
void setAddend(Addend A) override { _addend = A; }
void setTarget(const Atom *newAtom) override { _target = newAtom; }
private:
const Atom *_target;
uint64_t _targetSymbolIndex;
uint64_t _offsetInAtom;
Addend _addend;
};
/// \brief These atoms store symbols that are fixed to a particular address.
/// This atom has no content its address will be used by the writer to fixup
/// references that point to it.
template <class ELFT> class ELFAbsoluteAtom : public AbsoluteAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
ELFAbsoluteAtom(const ELFFile<ELFT> &file, StringRef name,
2013-01-25 15:39:18 +08:00
const Elf_Sym *symbol, uint64_t value)
: _owningFile(file), _name(name), _symbol(symbol), _value(value) {
}
const ELFFile<ELFT> &file() const override { return _owningFile; }
2013-05-25 12:59:32 +08:00
Scope scope() const override {
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
return scopeLinkageUnit;
if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
return scopeTranslationUnit;
else
return scopeGlobal;
}
StringRef name() const override { return _name; }
uint64_t value() const override { return _value; }
private:
const ELFFile<ELFT> &_owningFile;
StringRef _name;
const Elf_Sym *_symbol;
uint64_t _value;
};
/// \brief ELFUndefinedAtom: These atoms store undefined symbols and are place
/// holders that will be replaced by defined atoms later in the linking process.
template <class ELFT> class ELFUndefinedAtom : public lld::UndefinedAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
ELFUndefinedAtom(const File &file, StringRef name, const Elf_Sym *symbol)
2013-01-25 15:39:18 +08:00
: _owningFile(file), _name(name), _symbol(symbol) {}
const File &file() const override { return _owningFile; }
StringRef name() const override { return _name; }
// FIXME: What distinguishes a symbol in ELF that can help decide if the
// symbol is undefined only during build and not runtime? This will make us
// choose canBeNullAtBuildtime and canBeNullAtRuntime.
CanBeNull canBeNull() const override {
if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
return CanBeNull::canBeNullAtBuildtime;
else
return CanBeNull::canBeNullNever;
}
private:
const File &_owningFile;
StringRef _name;
const Elf_Sym *_symbol;
};
/// \brief This atom stores defined symbols and will contain either data or
/// code.
template <class ELFT> class ELFDefinedAtom : public DefinedAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
public:
ELFDefinedAtom(const ELFFile<ELFT> &file, StringRef symbolName,
StringRef sectionName, const Elf_Sym *symbol,
const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
unsigned int referenceStart, unsigned int referenceEnd,
std::vector<ELFReference<ELFT> *> &referenceList)
: _owningFile(file), _symbolName(symbolName), _sectionName(sectionName),
_symbol(symbol), _section(section), _contentData(contentData),
_referenceStartIndex(referenceStart), _referenceEndIndex(referenceEnd),
_referenceList(referenceList), _contentType(typeUnknown),
_permissions(permUnknown) {}
~ELFDefinedAtom() {}
const ELFFile<ELFT> &file() const override { return _owningFile; }
StringRef name() const override { return _symbolName; }
uint64_t ordinal() const override { return _ordinal; }
const Elf_Sym *symbol() const { return _symbol; }
const Elf_Shdr *section() const { return _section; }
uint64_t size() const override {
// Common symbols are not allocated in object files,
// so use st_size to tell how many bytes are required.
if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||
_symbol->st_shndx == llvm::ELF::SHN_COMMON)
return (uint64_t) _symbol->st_size;
return _contentData.size();
}
Scope scope() const override {
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
return scopeLinkageUnit;
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
return scopeGlobal;
else
return scopeTranslationUnit;
}
// FIXME: Need to revisit this in future.
Interposable interposable() const override { return interposeNo; }
// FIXME: What ways can we determine this in ELF?
Merge merge() const override {
if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
return mergeAsWeak;
if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||
_symbol->st_shndx == llvm::ELF::SHN_COMMON)
return mergeAsTentative;
return mergeNo;
}
ContentType contentType() const override {
if (_contentType != typeUnknown)
return _contentType;
ContentType ret = typeUnknown;
uint64_t flags = _section->sh_flags;
if (!(flags & llvm::ELF::SHF_ALLOC))
return _contentType = typeNoAlloc;
if (_section->sh_flags ==
(llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS)) {
return _contentType = _section->sh_type == llvm::ELF::SHT_NOBITS ? typeThreadZeroFill
: typeThreadData;
}
if ((_section->sh_flags == llvm::ELF::SHF_ALLOC) &&
(_section->sh_type == llvm::ELF::SHT_PROGBITS))
return _contentType = typeConstant;
if (_symbol->getType() == llvm::ELF::STT_GNU_IFUNC)
return _contentType = typeResolver;
if (_symbol->st_shndx == llvm::ELF::SHN_COMMON)
return _contentType = typeZeroFill;
switch (_section->sh_type) {
case llvm::ELF::SHT_PROGBITS:
flags &= ~llvm::ELF::SHF_ALLOC;
flags &= ~llvm::ELF::SHF_GROUP;
switch (flags) {
case llvm::ELF::SHF_EXECINSTR:
case (llvm::ELF::SHF_WRITE|llvm::ELF::SHF_EXECINSTR):
ret = typeCode;
break;
case llvm::ELF::SHF_WRITE:
ret = typeData;
break;
case (llvm::ELF::SHF_MERGE|llvm::ELF::SHF_STRINGS):
case llvm::ELF::SHF_STRINGS:
case llvm::ELF::SHF_MERGE:
ret = typeConstant;
break;
default:
ret = typeCode;
break;
}
break;
case llvm::ELF::SHT_NOTE:
flags &= ~llvm::ELF::SHF_ALLOC;
switch (flags) {
case llvm::ELF::SHF_WRITE:
ret = typeRWNote;
break;
default:
ret = typeRONote;
break;
}
break;
case llvm::ELF::SHT_NOBITS:
ret = typeZeroFill;
break;
case llvm::ELF::SHT_NULL:
if ((_symbol->getType() == llvm::ELF::STT_COMMON)
|| _symbol->st_shndx == llvm::ELF::SHN_COMMON)
ret = typeZeroFill;
break;
case llvm::ELF::SHT_INIT_ARRAY:
case llvm::ELF::SHT_FINI_ARRAY:
ret = typeData;
break;
}
return _contentType = ret;
}
Alignment alignment() const override {
// Unallocated common symbols specify their alignment constraints in
// st_value.
if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||
_symbol->st_shndx == llvm::ELF::SHN_COMMON) {
return Alignment(llvm::Log2_64(_symbol->st_value));
}
return Alignment(llvm::Log2_64(_section->sh_addralign),
_symbol->st_value % _section->sh_addralign);
}
// Do we have a choice for ELF? All symbols live in explicit sections.
SectionChoice sectionChoice() const override {
switch (contentType()) {
case typeCode:
case typeData:
case typeZeroFill:
case typeThreadZeroFill:
case typeThreadData:
case typeConstant:
if ((_sectionName == ".text") || (_sectionName == ".data") ||
(_sectionName == ".bss") || (_sectionName == ".rodata") ||
(_sectionName == ".tdata") || (_sectionName == ".tbss"))
return sectionBasedOnContent;
default:
break;
}
return sectionCustomRequired;
}
StringRef customSectionName() const override {
if ((contentType() == typeZeroFill) ||
(_symbol->st_shndx == llvm::ELF::SHN_COMMON))
return ".bss";
return _sectionName;
}
SectionPosition sectionPosition() const override {
return sectionPositionAny;
}
// It isn't clear that __attribute__((used)) is transmitted to the ELF object
// file.
DeadStripKind deadStrip() const override { return deadStripNormal; }
ContentPermissions permissions() const override {
if (_permissions != permUnknown)
return _permissions;
uint64_t flags = _section->sh_flags;
if (!(flags & llvm::ELF::SHF_ALLOC))
return _permissions = perm___;
switch (_section->sh_type) {
// permRW_L is for sections modified by the runtime
// loader.
case llvm::ELF::SHT_REL:
case llvm::ELF::SHT_RELA:
return _permissions = permRW_L;
case llvm::ELF::SHT_DYNAMIC:
case llvm::ELF::SHT_PROGBITS:
case llvm::ELF::SHT_NOTE:
flags &= ~llvm::ELF::SHF_ALLOC;
flags &= ~llvm::ELF::SHF_GROUP;
switch (flags) {
// Code
case llvm::ELF::SHF_EXECINSTR:
return _permissions = permR_X;
case (llvm::ELF::SHF_WRITE|llvm::ELF::SHF_EXECINSTR):
return _permissions = permRWX;
// Data
case llvm::ELF::SHF_WRITE:
return _permissions = permRW_;
// Strings
case llvm::ELF::SHF_MERGE:
case llvm::ELF::SHF_STRINGS:
return _permissions = permR__;
default:
if (flags & llvm::ELF::SHF_WRITE)
return _permissions = permRW_;
return _permissions = permR__;
}
case llvm::ELF::SHT_NOBITS:
return _permissions = permRW_;
case llvm::ELF::SHT_INIT_ARRAY:
case llvm::ELF::SHT_FINI_ARRAY:
return _permissions = permRW_;
default:
return _permissions = perm___;
}
}
ArrayRef<uint8_t> rawContent() const override { return _contentData; }
DefinedAtom::reference_iterator begin() const override {
uintptr_t index = _referenceStartIndex;
const void *it = reinterpret_cast<const void*>(index);
return reference_iterator(*this, it);
}
DefinedAtom::reference_iterator end() const override {
uintptr_t index = _referenceEndIndex;
const void *it = reinterpret_cast<const void*>(index);
return reference_iterator(*this, it);
}
const Reference *derefIterator(const void *It) const override {
uintptr_t index = reinterpret_cast<uintptr_t>(It);
assert(index >= _referenceStartIndex);
assert(index < _referenceEndIndex);
return ((_referenceList)[index]);
}
void incrementIterator(const void *&It) const override {
uintptr_t index = reinterpret_cast<uintptr_t>(It);
++index;
It = reinterpret_cast<const void *>(index);
}
void addReference(ELFReference<ELFT> *reference) {
_referenceList.push_back(reference);
_referenceEndIndex = _referenceList.size();
}
virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
protected:
const ELFFile<ELFT> &_owningFile;
StringRef _symbolName;
StringRef _sectionName;
const Elf_Sym *_symbol;
const Elf_Shdr *_section;
/// \brief Holds the bits that make up the atom.
ArrayRef<uint8_t> _contentData;
uint64_t _ordinal;
unsigned int _referenceStartIndex;
unsigned int _referenceEndIndex;
std::vector<ELFReference<ELFT> *> &_referenceList;
mutable ContentType _contentType;
mutable ContentPermissions _permissions;
};
/// \brief This atom stores mergeable Strings
template <class ELFT> class ELFMergeAtom : public DefinedAtom {
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
public:
ELFMergeAtom(const ELFFile<ELFT> &file, StringRef sectionName,
const Elf_Shdr *section, ArrayRef<uint8_t> contentData,
uint64_t offset)
: _owningFile(file), _sectionName(sectionName), _section(section),
_contentData(contentData), _offset(offset) {
}
const ELFFile<ELFT> &file() const override { return _owningFile; }
2013-05-25 12:59:32 +08:00
StringRef name() const override { return ""; }
virtual uint64_t section() const { return _section->sh_name; }
virtual uint64_t offset() const { return _offset; }
virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
uint64_t ordinal() const override { return _ordinal; }
uint64_t size() const override { return _contentData.size(); }
Scope scope() const override { return scopeTranslationUnit; }
Interposable interposable() const override { return interposeNo; }
Merge merge() const override { return mergeByContent; }
ContentType contentType() const override { return typeConstant; }
Alignment alignment() const override {
return Alignment(llvm::Log2_64(_section->sh_addralign));
}
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return _sectionName; }
SectionPosition sectionPosition() const override {
return sectionPositionAny;
}
DeadStripKind deadStrip() const override { return deadStripNormal; }
ContentPermissions permissions() const override { return permR__; }
virtual bool isThumb() const { return false; }
ArrayRef<uint8_t> rawContent() const override { return _contentData; }
DefinedAtom::reference_iterator begin() const override {
uintptr_t index = 0;
const void *it = reinterpret_cast<const void *>(index);
return reference_iterator(*this, it);
}
DefinedAtom::reference_iterator end() const override {
uintptr_t index = 0;
const void *it = reinterpret_cast<const void *>(index);
return reference_iterator(*this, it);
}
const Reference *derefIterator(const void *It) const override {
return nullptr;
}
void incrementIterator(const void *&It) const override {}
private:
const ELFFile<ELFT> &_owningFile;
StringRef _sectionName;
const Elf_Shdr *_section;
/// \brief Holds the bits that make up the atom.
ArrayRef<uint8_t> _contentData;
uint64_t _ordinal;
uint64_t _offset;
};
template <class ELFT> class ELFCommonAtom : public DefinedAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
ELFCommonAtom(const ELFFile<ELFT> &file,
StringRef symbolName,
const Elf_Sym *symbol)
: _owningFile(file),
_symbolName(symbolName),
_symbol(symbol) {}
const ELFFile<ELFT> &file() const override { return _owningFile; }
StringRef name() const override { return _symbolName; }
uint64_t ordinal() const override { return _ordinal; }
virtual void setOrdinal(uint64_t ord) { _ordinal = ord; }
uint64_t size() const override { return _symbol->st_size; }
Scope scope() const override {
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
return scopeLinkageUnit;
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
return scopeGlobal;
else
return scopeTranslationUnit;
}
Interposable interposable() const override { return interposeNo; }
Merge merge() const override { return mergeAsTentative; }
ContentType contentType() const override { return typeZeroFill; }
Alignment alignment() const override {
return Alignment(llvm::Log2_64(_symbol->st_value));
}
SectionChoice sectionChoice() const override { return sectionBasedOnContent; }
StringRef customSectionName() const override { return ".bss"; }
SectionPosition sectionPosition() const override {
return sectionPositionAny;
}
DeadStripKind deadStrip() const override { return deadStripNormal; }
ContentPermissions permissions() const override { return permRW_; }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
DefinedAtom::reference_iterator begin() const override {
uintptr_t index = 0;
const void *it = reinterpret_cast<const void *>(index);
return reference_iterator(*this, it);
}
DefinedAtom::reference_iterator end() const override {
uintptr_t index = 0;
const void *it = reinterpret_cast<const void *>(index);
return reference_iterator(*this, it);
}
protected:
virtual ~ELFCommonAtom() {}
const Reference *derefIterator(const void *iter) const override {
return nullptr;
}
void incrementIterator(const void *&iter) const override {}
const ELFFile<ELFT> &_owningFile;
StringRef _symbolName;
const Elf_Sym *_symbol;
uint64_t _ordinal;
};
/// \brief An atom from a shared library.
template <class ELFT> class ELFDynamicAtom : public SharedLibraryAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
ELFDynamicAtom(const DynamicFile<ELFT> &file, StringRef symbolName,
StringRef loadName, const Elf_Sym *symbol)
: _owningFile(file), _symbolName(symbolName), _loadName(loadName),
_symbol(symbol) {
}
const DynamicFile<ELFT> &file() const override { return _owningFile; }
StringRef name() const override { return _symbolName; }
virtual Scope scope() const {
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
return scopeLinkageUnit;
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
return scopeGlobal;
else
return scopeTranslationUnit;
}
StringRef loadName() const override { return _loadName; }
bool canBeNullAtRuntime() const override {
return _symbol->getBinding() == llvm::ELF::STB_WEAK;
}
Type type() const override {
switch (_symbol->getType()) {
case llvm::ELF::STT_FUNC:
case llvm::ELF::STT_GNU_IFUNC:
return Type::Code;
case llvm::ELF::STT_OBJECT:
return Type::Data;
default:
return Type::Unknown;
}
}
uint64_t size() const override {
return _symbol->st_size;
}
private:
const DynamicFile<ELFT> &_owningFile;
StringRef _symbolName;
StringRef _loadName;
const Elf_Sym *_symbol;
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class SimpleELFDefinedAtom : public SimpleDefinedAtom {
public:
SimpleELFDefinedAtom(const File &f) : SimpleDefinedAtom(f) {}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
void addReferenceELF(Reference::KindArch arch, uint16_t kindValue,
uint64_t off, const Atom *target,
Reference::Addend addend) {
this->addReference(Reference::KindNamespace::ELF, arch, kindValue, off,
target, addend);
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
void addReferenceELF_Hexagon(uint16_t relocType, uint64_t off, const Atom *t,
Reference::Addend a) {
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
this->addReferenceELF(Reference::KindArch::Hexagon, relocType, off, t, a);
}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
void addReferenceELF_x86_64(uint16_t relocType, uint64_t off, const Atom *t,
Reference::Addend a) {
this->addReferenceELF(Reference::KindArch::x86_64, relocType, off, t, a);
}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
void addReferenceELF_PowerPC(uint16_t relocType, uint64_t off, const Atom *t,
Reference::Addend a) {
this->addReferenceELF(Reference::KindArch::PowerPC, relocType, off, t, a);
}
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
void addReferenceELF_Mips(uint16_t relocType, uint64_t off, const Atom *t,
Reference::Addend a) {
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
this->addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
}
};
/// \brief Atom which represents an object for which a COPY relocation will be
/// generated.
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class ObjectAtom : public SimpleELFDefinedAtom {
public:
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
ObjectAtom(const File &f) : SimpleELFDefinedAtom(f) {}
Scope scope() const override { return scopeGlobal; }
SectionChoice sectionChoice() const override { return sectionBasedOnContent; }
ContentType contentType() const override { return typeZeroFill; }
uint64_t size() const override { return _size; }
DynamicExport dynamicExport() const override { return dynamicExportAlways; }
ContentPermissions permissions() const override { return permRW_; }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
Alignment alignment() const override {
// The alignment should be 8 byte aligned
return Alignment(3);
}
StringRef name() const override { return _name; }
std::string _name;
uint64_t _size;
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class GOTAtom : public SimpleELFDefinedAtom {
StringRef _section;
public:
GOTAtom(const File &f, StringRef secName)
: SimpleELFDefinedAtom(f), _section(secName) {}
Scope scope() const override { return scopeTranslationUnit; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return _section; }
ContentType contentType() const override { return typeGOT; }
uint64_t size() const override { return rawContent().size(); }
ContentPermissions permissions() const override { return permRW_; }
virtual ArrayRef<uint8_t> rawContent() const = 0;
Alignment alignment() const override {
// The alignment should be 8 byte aligned
return Alignment(3);
}
#ifndef NDEBUG
StringRef name() const override { return _name; }
std::string _name;
#else
StringRef name() const override { return ""; }
#endif
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class PLTAtom : public SimpleELFDefinedAtom {
StringRef _section;
public:
PLTAtom(const File &f, StringRef secName)
: SimpleELFDefinedAtom(f), _section(secName) {}
Scope scope() const override { return scopeTranslationUnit; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return _section; }
ContentType contentType() const override { return typeStub; }
uint64_t size() const override { return rawContent().size(); }
ContentPermissions permissions() const override { return permR_X; }
virtual ArrayRef<uint8_t> rawContent() const = 0;
Alignment alignment() const override {
return Alignment(4); // 16
}
#ifndef NDEBUG
StringRef name() const override { return _name; }
std::string _name;
#else
StringRef name() const override { return ""; }
#endif
};
class PLT0Atom : public PLTAtom {
public:
PLT0Atom(const File &f) : PLTAtom(f, ".plt") {
#ifndef NDEBUG
_name = ".PLT0";
#endif
}
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class GLOBAL_OFFSET_TABLEAtom : public SimpleELFDefinedAtom {
public:
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
GLOBAL_OFFSET_TABLEAtom(const File &f) : SimpleELFDefinedAtom(f) {}
StringRef name() const override { return "_GLOBAL_OFFSET_TABLE_"; }
Scope scope() const override { return scopeGlobal; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return ".got.plt"; }
ContentType contentType() const override { return typeGOT; }
uint64_t size() const override { return 0; }
ContentPermissions permissions() const override { return permRW_; }
Alignment alignment() const override {
// Needs 8 byte alignment
return Alignment(3);
}
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class TLSGETADDRAtom : public SimpleELFDefinedAtom {
public:
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
TLSGETADDRAtom(const File &f) : SimpleELFDefinedAtom(f) {}
StringRef name() const override { return "__tls_get_addr"; }
Scope scope() const override { return scopeGlobal; }
Merge merge() const override { return mergeAsWeak; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return ".text"; }
ContentType contentType() const override { return typeCode; }
uint64_t size() const override { return 0; }
ContentPermissions permissions() const override { return permR_X; }
Alignment alignment() const override { return Alignment(0); }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class DYNAMICAtom : public SimpleELFDefinedAtom {
public:
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
DYNAMICAtom(const File &f) : SimpleELFDefinedAtom(f) {}
StringRef name() const override { return "_DYNAMIC"; }
Scope scope() const override { return scopeLinkageUnit; }
Merge merge() const override { return mergeNo; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return ".dynamic"; }
ContentType contentType() const override { return typeData; }
uint64_t size() const override { return 0; }
ContentPermissions permissions() const override { return permRW_; }
Alignment alignment() const override { return Alignment(0); }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
};
[lld] Introduce registry and Reference kind tuple The main changes are in: include/lld/Core/Reference.h include/lld/ReaderWriter/Reader.h Everything else is details to support the main change. 1) Registration based Readers Previously, lld had a tangled interdependency with all the Readers. It would have been impossible to make a streamlined linker (say for a JIT) which just supported one file format and one architecture (no yaml, no archives, etc). The old model also required a LinkingContext to read an object file, which would have made .o inspection tools awkward. The new model is that there is a global Registry object. You programmatically register the Readers you want with the registry object. Whenever you need to read/parse a file, you ask the registry to do it, and the registry tries each registered reader. For ease of use with the existing lld code base, there is one Registry object inside the LinkingContext object. 2) Changing kind value to be a tuple Beside Readers, the registry also keeps track of the mapping for Reference Kind values to and from strings. Along with that, this patch also fixes an ambiguity with the previous Reference::Kind values. The problem was that we wanted to reuse existing relocation type values as Reference::Kind values. But then how can the YAML write know how to convert a value to a string? The fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace (e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and a 16-bit value. This tuple system allows conversion to and from strings with no ambiguities. llvm-svn: 197727
2013-12-20 05:58:00 +08:00
class InitFiniAtom : public SimpleELFDefinedAtom {
StringRef _section;
public:
InitFiniAtom(const File &f, StringRef secName)
: SimpleELFDefinedAtom(f), _section(secName) {}
Scope scope() const override { return scopeGlobal; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return _section; }
ContentType contentType() const override { return typeData; }
uint64_t size() const override { return rawContent().size(); }
ContentPermissions permissions() const override { return permRW_; }
virtual ArrayRef<uint8_t> rawContent() const = 0;
Alignment alignment() const override { return size(); }
#ifndef NDEBUG
StringRef name() const override { return _name; }
std::string _name;
#else
StringRef name() const override { return ""; }
#endif
};
} // end namespace elf
} // end namespace lld
#endif