changes for the ELF Reader : split up into AtomsELF.h/Adding new permissions permRWX
llvm-svn: 171127
diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
index a25180b..6563175 100644
--- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
+++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
@@ -25,6 +25,7 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
@@ -34,6 +35,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include "AtomsELF.h"
#include <map>
#include <vector>
@@ -43,384 +45,6 @@
using llvm::support::endianness;
namespace {
-/// \brief Relocation References: Defined Atoms may contain references that will
-/// need to be patched before the executable is written.
-template <endianness target_endianness, bool is64Bits>
-class ELFReference final : public Reference {
- typedef llvm::object::Elf_Rel_Impl
- <target_endianness, is64Bits, false> Elf_Rel;
- typedef llvm::object::Elf_Rel_Impl
- <target_endianness, is64Bits, true> Elf_Rela;
-public:
-
- ELFReference(const Elf_Rela *rela, uint64_t offset, const Atom *target)
- : _target(target)
- , _targetSymbolIndex(rela->getSymbol())
- , _offsetInAtom(offset)
- , _addend(rela->r_addend)
- , _kind(rela->getType()) {}
-
- ELFReference(const Elf_Rel *rel, uint64_t offset, const Atom *target)
- : _target(target)
- , _targetSymbolIndex(rel->getSymbol())
- , _offsetInAtom(offset)
- , _addend(0)
- , _kind(rel->getType()) {}
-
- virtual uint64_t offsetInAtom() const {
- return _offsetInAtom;
- }
-
- virtual Kind kind() const {
- return _kind;
- }
-
- virtual void setKind(Kind kind) {
- _kind = kind;
- }
-
- virtual const Atom *target() const {
- return _target;
- }
-
- /// \brief The symbol table index that contains the target reference.
- uint64_t targetSymbolIndex() const {
- return _targetSymbolIndex;
- }
-
- virtual Addend addend() const {
- return _addend;
- }
-
- virtual void setAddend(Addend A) {
- _addend = A;
- }
-
- virtual void setTarget(const Atom *newAtom) {
- _target = newAtom;
- }
-private:
- const Atom *_target;
- uint64_t _targetSymbolIndex;
- uint64_t _offsetInAtom;
- Addend _addend;
- Kind _kind;
-};
-
-/// \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<endianness target_endianness, bool is64Bits>
-class ELFAbsoluteAtom final : public AbsoluteAtom {
- typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-
-public:
- ELFAbsoluteAtom(const File &file,
- llvm::StringRef name,
- const Elf_Sym *symbol,
- uint64_t value)
- : _owningFile(file)
- , _name(name)
- , _symbol(symbol)
- , _value(value)
- {}
-
- virtual const class File &file() const {
- return _owningFile;
- }
-
- virtual Scope scope() const {
- if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
- return scopeTranslationUnit;
- else
- return scopeGlobal;
- }
-
- virtual llvm::StringRef name() const {
- return _name;
- }
-
- virtual uint64_t value() const {
- return _value;
- }
-
-private:
- const File &_owningFile;
- llvm::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<endianness target_endianness, bool is64Bits>
-class ELFUndefinedAtom final: public UndefinedAtom {
- typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-
-public:
- ELFUndefinedAtom(const File &file,
- llvm::StringRef name,
- const Elf_Sym *symbol)
- : _owningFile(file)
- , _name(name)
- , _symbol(symbol)
- {}
-
- virtual const class File &file() const {
- return _owningFile;
- }
-
- virtual llvm::StringRef name() const {
- 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.
- virtual CanBeNull canBeNull() const {
- if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
- return CanBeNull::canBeNullAtBuildtime;
- else
- return CanBeNull::canBeNullNever;
- }
-
-private:
- const File &_owningFile;
- llvm::StringRef _name;
- const Elf_Sym *_symbol;
-};
-
-/// \brief This atom stores defined symbols and will contain either data or
-/// code.
-template<endianness target_endianness, bool is64Bits>
-class ELFDefinedAtom final: public DefinedAtom {
- typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
-
-public:
- ELFDefinedAtom(const File &file,
- llvm::StringRef symbolName,
- llvm::StringRef sectionName,
- const Elf_Sym *symbol,
- const Elf_Shdr *section,
- llvm::ArrayRef<uint8_t> contentData,
- unsigned int referenceStart,
- unsigned int referenceEnd,
- std::vector<ELFReference
- <target_endianness, is64Bits> *> &referenceList)
-
- : _owningFile(file)
- , _symbolName(symbolName)
- , _sectionName(sectionName)
- , _symbol(symbol)
- , _section(section)
- , _contentData(contentData)
- , _referenceStartIndex(referenceStart)
- , _referenceEndIndex(referenceEnd)
- , _referenceList(referenceList) {
- static uint64_t orderNumber = 0;
- _ordinal = ++orderNumber;
- }
-
- virtual const class File &file() const {
- return _owningFile;
- }
-
- virtual llvm::StringRef name() const {
- return _symbolName;
- }
-
- virtual uint64_t ordinal() const {
- return _ordinal;
- }
-
- virtual uint64_t size() const {
- // 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();
- }
-
- 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;
- }
-
- // FIXME: Need to revisit this in future.
- virtual Interposable interposable() const {
- return interposeNo;
- }
-
- // FIXME: What ways can we determine this in ELF?
- virtual Merge merge() const {
- 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;
- }
-
- virtual ContentType contentType() const {
- ContentType ret = typeUnknown;
-
- switch (_section->sh_type) {
- case llvm::ELF::SHT_PROGBITS:
- case llvm::ELF::SHT_DYNAMIC:
- switch (_section->sh_flags & ~llvm::ELF::SHF_GROUP) {
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR
- | llvm::ELF::SHF_WRITE):
- ret = typeCode;
- break;
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR):
- ret = typeCode;
- break;
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE):
- ret = typeData;
- break;
- case llvm::ELF::SHF_ALLOC:
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE):
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE |
- llvm::ELF::SHF_STRINGS):
- ret = typeConstant;
- 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;
- }
-
- return ret;
- }
-
- virtual Alignment alignment() const {
- // 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));
- }
-
- // Do we have a choice for ELF? All symbols live in explicit sections.
- virtual SectionChoice sectionChoice() const {
- if (_symbol->st_shndx > llvm::ELF::SHN_LORESERVE)
- return sectionBasedOnContent;
-
- return sectionCustomRequired;
- }
-
- virtual llvm::StringRef customSectionName() const {
- return _sectionName;
- }
-
- // It isn't clear that __attribute__((used)) is transmitted to the ELF object
- // file.
- virtual DeadStripKind deadStrip() const {
- return deadStripNormal;
- }
-
- virtual ContentPermissions permissions() const {
- 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 permRW_L;
-
- case llvm::ELF::SHT_DYNAMIC:
- case llvm::ELF::SHT_PROGBITS:
- switch (_section->sh_flags & ~llvm::ELF::SHF_GROUP) {
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR):
- return permR_X;
-
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE):
- return permRW_;
-
- case llvm::ELF::SHF_ALLOC:
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE):
- case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE
- | llvm::ELF::SHF_STRINGS):
- return permR__;
- }
- default:
- return perm___;
- }
- }
-
- // Many non ARM architectures use ELF file format This not really a place to
- // put a architecture specific method in an atom. A better approach is needed.
- virtual bool isThumb() const {
- return false;
- }
-
- // FIXME: Not Sure if ELF supports alias atoms. Find out more.
- virtual bool isAlias() const {
- return false;
- }
-
- virtual llvm::ArrayRef<uint8_t> rawContent() const {
- return _contentData;
- }
-
- DefinedAtom::reference_iterator begin() const {
- uintptr_t index = _referenceStartIndex;
- const void *it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
- }
-
- DefinedAtom::reference_iterator end() const {
- uintptr_t index = _referenceEndIndex;
- 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 >= _referenceStartIndex);
- assert(index < _referenceEndIndex);
- return ((_referenceList)[index]);
- }
-
- void incrementIterator(const void*& It) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(It);
- ++index;
- It = reinterpret_cast<const void*>(index);
- }
-
-private:
-
- const File &_owningFile;
- llvm::StringRef _symbolName;
- llvm::StringRef _sectionName;
- const Elf_Sym *_symbol;
- const Elf_Shdr *_section;
- /// \brief Holds the bits that make up the atom.
- llvm::ArrayRef<uint8_t> _contentData;
-
- uint64_t _ordinal;
- unsigned int _referenceStartIndex;
- unsigned int _referenceEndIndex;
- std::vector<ELFReference<target_endianness, is64Bits> *> &_referenceList;
-};
-
// \brief Read a binary, find out based on the symbol table contents what kind
// of symbol it is and create corresponding atoms for it
template<endianness target_endianness, bool is64Bits>
@@ -636,7 +260,7 @@
<ELFDefinedAtom<target_endianness, is64Bits> > ())
ELFDefinedAtom<target_endianness, is64Bits>
(*this, symbolName, sectionName,
- *si, i.first, symbolData,
+ *si, i.first, symbolData,
referenceStart, _references.size(), _references);
_definedAtoms._atoms.push_back(newAtom);