From 8caf4de31fd15917766af6546dfd4da5b7501fc1 Mon Sep 17 00:00:00 2001 From: Sid Manning Date: Mon, 17 Sep 2012 12:49:38 +0000 Subject: [PATCH] Add ELFReference class - parse relocations needed by that class and update DefinedAtom to use the class. Tweak coding style. Add testcase to check relocations. Change was signed-off-by: Michael Spencer llvm-svn: 164027 --- lld/lib/ReaderWriter/ELF/ReaderELF.cpp | 554 +++++++++++++++++------- lld/test/elf/Inputs/reloc-test.elf-i386 | Bin 0 -> 1076 bytes lld/test/elf/reloc.objtxt | 79 ++++ 3 files changed, 469 insertions(+), 164 deletions(-) create mode 100644 lld/test/elf/Inputs/reloc-test.elf-i386 create mode 100644 lld/test/elf/reloc.objtxt diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp index 9b15b2a5bc57..5aa5e91a78c5 100644 --- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp +++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp @@ -14,8 +14,10 @@ #include "lld/ReaderWriter/ReaderELF.h" #include "lld/Core/File.h" +#include "lld/Core/Reference.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ObjectFile.h" @@ -39,58 +41,133 @@ using namespace lld; namespace { // anonymous -// This atom class corresponds to absolute symbol -class ELFAbsoluteAtom: public AbsoluteAtom { +/// \brief Relocation References: Defined Atoms may contain +/// references that will need to be patched before +/// the executable is written. +template +class ELFReference final : public Reference { + + typedef llvm::object::Elf_Rel_Impl + Elf_Rel; + typedef llvm::object::Elf_Rel_Impl + Elf_Rela; public: - ELFAbsoluteAtom(const File &F, - llvm::StringRef N, - uint64_t V) - : OwningFile(F) - , Name(N) - , Value(V) - {} - virtual const class File &file() const { - return OwningFile; + 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 llvm::StringRef name() const { - return Name; + virtual Kind kind() const { + return _kind; } - virtual uint64_t value() const { - return Value; + virtual void setKind(Kind kind) { + _kind = kind; } + virtual const Atom *target() const { + return _target; + } + +/// \brief targetSymbolIndex: This is 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 File &OwningFile; - llvm::StringRef Name; - uint64_t Value; + const Atom *_target; + uint64_t _targetSymbolIndex; + uint64_t _offsetInAtom; + Addend _addend; + Kind _kind; }; -// This atom corresponds to undefined symbols. +/// \brief ELFAbsoluteAtom: 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 ELFUndefinedAtom: public UndefinedAtom { +class ELFAbsoluteAtom final: public AbsoluteAtom { + +public: + ELFAbsoluteAtom(const File &file, + llvm::StringRef name, + uint64_t value) + : _owningFile(file) + , _name(name) + , _value(value) + {} + + virtual const class File &file() const { + return _owningFile; + } + + virtual llvm::StringRef name() const { + return _name; + } + + virtual uint64_t value() const { + return _value; + } + +private: + const File &_owningFile; + llvm::StringRef _name; + 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 ELFUndefinedAtom final: public UndefinedAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; public: - ELFUndefinedAtom(const File &F, - llvm::StringRef N, - const Elf_Sym *E) - : OwningFile(F) - , Name(N) - , Symbol(E) + 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; + return _owningFile; } virtual llvm::StringRef name() const { - return Name; + return _name; } // FIXME What distinguishes a symbol in ELF that can help @@ -100,49 +177,58 @@ public: // virtual CanBeNull canBeNull() const { - if (Symbol->getBinding() == llvm::ELF::STB_WEAK) + 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; + const File &_owningFile; + llvm::StringRef _name; + const Elf_Sym *_symbol; }; -// This atom corresponds to defined symbols. +/// \brief ELFDefinedAtom: This atom stores defined symbols and will contain +/// either data or code. template -class ELFDefinedAtom: public DefinedAtom { +class ELFDefinedAtom final: public DefinedAtom { typedef llvm::object::Elf_Sym_Impl Elf_Sym; typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; public: - ELFDefinedAtom(const File &F, - llvm::StringRef N, - llvm::StringRef SN, - const Elf_Sym *E, - const Elf_Shdr *S, - llvm::ArrayRef D) - : OwningFile(F) - , SymbolName(N) - , SectionName(SN) - , Symbol(E) - , Section(S) - , ContentData(D) { - static uint64_t ordernumber = 0; - _ordinal = ++ordernumber; + ELFDefinedAtom(const File &file, + llvm::StringRef symbolName, + llvm::StringRef sectionName, + const Elf_Sym *symbol, + const Elf_Shdr *section, + llvm::ArrayRef contentData, + unsigned int referenceStart, + unsigned int referenceEnd, + std::vector *> &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; + return _owningFile; } virtual llvm::StringRef name() const { - return SymbolName; + return _symbolName; } virtual uint64_t ordinal() const { @@ -153,18 +239,18 @@ public: // Common symbols are not allocated in object files so // their size is zero. - if ((Symbol->getType() == llvm::ELF::STT_COMMON) - || Symbol->st_shndx == llvm::ELF::SHN_COMMON) + if ((_symbol->getType() == llvm::ELF::STT_COMMON) + || _symbol->st_shndx == llvm::ELF::SHN_COMMON) return (uint64_t)0; - return ContentData.size(); + return _contentData.size(); } virtual Scope scope() const { - if (Symbol->st_other == llvm::ELF::STV_HIDDEN) + if (_symbol->st_other == llvm::ELF::STV_HIDDEN) return scopeLinkageUnit; - else if (Symbol->getBinding() != llvm::ELF::STB_LOCAL) + else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL) return scopeGlobal; else return scopeTranslationUnit; @@ -180,11 +266,11 @@ public: virtual Merge merge() const { - if (Symbol->getBinding() == llvm::ELF::STB_WEAK) + if (_symbol->getBinding() == llvm::ELF::STB_WEAK) return mergeAsWeak; - if ((Symbol->getType() == llvm::ELF::STT_COMMON) - || Symbol->st_shndx == llvm::ELF::SHN_COMMON) + if ((_symbol->getType() == llvm::ELF::STT_COMMON) + || _symbol->st_shndx == llvm::ELF::SHN_COMMON) return mergeAsTentative; return mergeNo; @@ -192,14 +278,14 @@ public: virtual ContentType contentType() const { - if (Symbol->getType() == llvm::ELF::STT_FUNC) + if (_symbol->getType() == llvm::ELF::STT_FUNC) return typeCode; - if ((Symbol->getType() == llvm::ELF::STT_COMMON) - || Symbol->st_shndx == llvm::ELF::SHN_COMMON) + if ((_symbol->getType() == llvm::ELF::STT_COMMON) + || _symbol->st_shndx == llvm::ELF::SHN_COMMON) return typeZeroFill; - if (Symbol->getType() == llvm::ELF::STT_OBJECT) + if (_symbol->getType() == llvm::ELF::STT_OBJECT) return typeData; return typeUnknown; @@ -209,25 +295,25 @@ public: // 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(Symbol->st_value)); + if ((_symbol->getType() == llvm::ELF::STT_COMMON) + || _symbol->st_shndx == llvm::ELF::SHN_COMMON) { + return (Alignment(_symbol->st_value)); } - return Alignment(llvm::Log2_64(Section->sh_addralign)); + 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) + if (_symbol->st_shndx > llvm::ELF::SHN_LORESERVE) return sectionBasedOnContent; return sectionCustomRequired; } virtual llvm::StringRef customSectionName() const { - return SectionName; + return _sectionName; } // It isn't clear that __attribute__((used)) is transmitted to @@ -238,7 +324,7 @@ public: virtual ContentPermissions permissions() const { - switch (Section->sh_type) { + switch (_section->sh_type) { // permRW_L is for sections modified by the runtime // loader. case llvm::ELF::SHT_REL: @@ -247,7 +333,7 @@ public: case llvm::ELF::SHT_DYNAMIC: case llvm::ELF::SHT_PROGBITS: - switch (Section->sh_flags) { + switch (_section->sh_flags) { case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR): return permR_X; @@ -281,34 +367,49 @@ public: } virtual llvm::ArrayRef rawContent() const { - return ContentData; + return _contentData; } - virtual reference_iterator begin() const { - return reference_iterator(*this, nullptr); + DefinedAtom::reference_iterator begin() const { + uintptr_t index = _referenceStartIndex; + const void *it = reinterpret_cast(index); + return reference_iterator(*this, it); } - virtual reference_iterator end() const { - return reference_iterator(*this, nullptr); + DefinedAtom::reference_iterator end() const { + uintptr_t index = _referenceEndIndex; + const void *it = reinterpret_cast(index); + return reference_iterator(*this, it); + } + + const Reference *derefIterator(const void *It) const { + uintptr_t index = reinterpret_cast(It); + assert(index >= _referenceStartIndex); + assert(index < _referenceEndIndex); + return ((_referenceList)[index]); + } + + void incrementIterator(const void*& It) const { + uintptr_t index = reinterpret_cast(It); + ++index; + It = reinterpret_cast(index); } private: - virtual const Reference *derefIterator(const void *iter) const { - return nullptr; - } - virtual void incrementIterator(const void *&iter) const { - } - const File &OwningFile; - llvm::StringRef SymbolName; - llvm::StringRef SectionName; - const Elf_Sym *Symbol; - const Elf_Shdr *Section; + const File &_owningFile; + llvm::StringRef _symbolName; + llvm::StringRef _sectionName; + const Elf_Sym *_symbol; + const Elf_Shdr *_section; - // ContentData will hold the bits that make up the atom. - llvm::ArrayRef ContentData; + // _contentData will hold the bits that make up the atom. + llvm::ArrayRef _contentData; uint64_t _ordinal; + unsigned int _referenceStartIndex; + unsigned int _referenceEndIndex; + std::vector *> &_referenceList; }; @@ -318,91 +419,152 @@ private: template class FileELF: public File { - typedef llvm::object::Elf_Sym_Impl Elf_Sym; - typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; + typedef llvm::object::Elf_Sym_Impl + Elf_Sym; + typedef llvm::object::Elf_Shdr_Impl + Elf_Shdr; + typedef llvm::object::Elf_Rel_Impl + Elf_Rel; + typedef llvm::object::Elf_Rel_Impl + Elf_Rela; public: FileELF(std::unique_ptr MB, llvm::error_code &EC) : File(MB->getBufferIdentifier()) { - llvm::OwningPtr Bin; - EC = llvm::object::createBinary(MB.release(), Bin); + llvm::OwningPtr binaryFile; + EC = llvm::object::createBinary(MB.release(), binaryFile); if (EC) return; // Point Obj to correct class and bitwidth ELF object - Obj.reset(llvm::dyn_cast >(Bin.get())); + _objFile.reset(llvm::dyn_cast >(binaryFile.get())); - if (!Obj) { + if (!_objFile) { EC = make_error_code(llvm::object::object_error::invalid_file_type); return; } - Bin.take(); + binaryFile.take(); - std::map< const Elf_Shdr *, std::vector> SectionSymbols; + std::map< const Elf_Shdr *, std::vector> sectionSymbols; - llvm::object::symbol_iterator it(Obj->begin_symbols()); - llvm::object::symbol_iterator ie(Obj->end_symbols()); +// Handle: SHT_REL and SHT_RELA sections: +// Increment over the sections, when REL/RELA section types are +// found add the contents to the RelocationReferences map. + + llvm::object::section_iterator sit(_objFile->begin_sections()); + llvm::object::section_iterator sie(_objFile->end_sections()); + for (; sit != sie; sit.increment(EC)) { + if (EC) + return; + + const Elf_Shdr *section = _objFile->getElfSection(sit); + + if (section->sh_type == llvm::ELF::SHT_RELA) { + llvm::StringRef sectionName; + if ((EC = _objFile->getSectionName(section, sectionName))) + return; + // Get rid of the leading .rela so Atoms can use their own section + // name to find the relocs. + sectionName = sectionName.drop_front(5); + + auto rai(_objFile->beginELFRela(section)); + auto rae(_objFile->endELFRela(section)); + + auto &Ref = _relocationAddendRefences[sectionName]; + for (; rai != rae; rai++) { + Ref.push_back(&*rai); + } + } + + if (section->sh_type == llvm::ELF::SHT_REL) { + llvm::StringRef sectionName; + if ((EC = _objFile->getSectionName(section, sectionName))) + return; + // Get rid of the leading .rel so Atoms can use their own section + // name to find the relocs. + sectionName = sectionName.drop_front(4); + + auto ri(_objFile->beginELFRel(section)); + auto re(_objFile->endELFRel(section)); + + auto &Ref = _relocationReferences[sectionName]; + for (; ri != re; ri++) { + Ref.push_back(&*ri); + } + } + } + + +// Increment over all the symbols collecting atoms and symbol +// names for later use. + + llvm::object::symbol_iterator it(_objFile->begin_symbols()); + llvm::object::symbol_iterator ie(_objFile->end_symbols()); for (; it != ie; it.increment(EC)) { if (EC) return; - llvm::object::SectionRef SR; - llvm::object::section_iterator section(SR); - if ((EC = it->getSection(section))) + if ((EC = it->getSection(sit))) return; - const Elf_Shdr *Section = Obj->getElfSection(section); - const Elf_Sym *Symbol = Obj->getElfSymbol(it); + const Elf_Shdr *section = _objFile->getElfSection(sit); + const Elf_Sym *symbol = _objFile->getElfSymbol(it); - llvm::StringRef SymbolName; - if ((EC = Obj->getSymbolName(Section, Symbol, SymbolName))) + llvm::StringRef symbolName; + if ((EC = _objFile->getSymbolName(section, symbol, symbolName))) return; - if (Symbol->st_shndx == llvm::ELF::SHN_ABS) { + if (symbol->st_shndx == llvm::ELF::SHN_ABS) { // Create an absolute atom. - AbsoluteAtoms._atoms.push_back( - new (AtomStorage.Allocate ()) - ELFAbsoluteAtom(*this, SymbolName, - Symbol->st_value)); + auto *newAtom = new (_readerStorage.Allocate + > ()) + ELFAbsoluteAtom + (*this, symbolName, symbol->st_value); - } else if (Symbol->st_shndx == llvm::ELF::SHN_UNDEF) { + _absoluteAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); + + } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) { // Create an undefined atom. - UndefinedAtoms._atoms.push_back( - new (AtomStorage.Allocate>()) - ELFUndefinedAtom ( - *this, SymbolName, Symbol)); + auto *newAtom = new (_readerStorage.Allocate + > ()) + ELFUndefinedAtom + (*this, symbolName, symbol); + + _undefinedAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); + } else { // This is actually a defined symbol. Add it to its section's list of // symbols. - if (Symbol->getType() == llvm::ELF::STT_NOTYPE - || Symbol->getType() == llvm::ELF::STT_OBJECT - || Symbol->getType() == llvm::ELF::STT_FUNC - || Symbol->getType() == llvm::ELF::STT_SECTION - || Symbol->getType() == llvm::ELF::STT_FILE - || Symbol->getType() == llvm::ELF::STT_TLS - || Symbol->getType() == llvm::ELF::STT_COMMON - || Symbol->st_shndx == llvm::ELF::SHN_COMMON) { - SectionSymbols[Section].push_back(Symbol); + if (symbol->getType() == llvm::ELF::STT_NOTYPE + || symbol->getType() == llvm::ELF::STT_OBJECT + || symbol->getType() == llvm::ELF::STT_FUNC + || symbol->getType() == llvm::ELF::STT_SECTION + || symbol->getType() == llvm::ELF::STT_FILE + || symbol->getType() == llvm::ELF::STT_TLS + || symbol->getType() == llvm::ELF::STT_COMMON + || symbol->st_shndx == llvm::ELF::SHN_COMMON) { + sectionSymbols[section].push_back(symbol); } else { - llvm::errs() << "Unable to create atom for: " << SymbolName << "\n"; + llvm::errs() << "Unable to create atom for: " << symbolName << "\n"; EC = llvm::object::object_error::parse_failed; return; } } } - for (auto &i : SectionSymbols) { - auto &Symbs = i.second; - llvm::StringRef SymbolName; - llvm::StringRef SectionName; + for (auto &i : sectionSymbols) { + auto &symbols = i.second; + llvm::StringRef symbolName; + llvm::StringRef sectionName; // Sort symbols by position. - std::stable_sort(Symbs.begin(), Symbs.end(), + std::stable_sort(symbols.begin(), symbols.end(), // From ReaderCOFF.cpp: // For some reason MSVC fails to allow the lambda in this context with // a "illegal use of local type in type instantiation". MSVC is clearly @@ -413,47 +575,93 @@ public: })); // i.first is the section the symbol lives in - for (auto si = Symbs.begin(), se = Symbs.end(); si != se; ++si) { + for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { StringRef symbolContents; - if ((EC = Obj->getSectionContents(i.first, symbolContents))) + if ((EC = _objFile->getSectionContents(i.first, symbolContents))) return; - if ((EC = Obj->getSymbolName(i.first, *si, SymbolName))) + if ((EC = _objFile->getSymbolName(i.first, *si, symbolName))) return; - if ((EC = Obj->getSectionName(i.first, SectionName))) + if ((EC = _objFile->getSectionName(i.first, sectionName))) return; - bool IsCommon = false; + bool isCommon = false; if (((*si)->getType() == llvm::ELF::STT_COMMON) - || (*si)->st_shndx == llvm::ELF::SHN_COMMON) - IsCommon = true; + || (*si)->st_shndx == llvm::ELF::SHN_COMMON) + isCommon = true; // Get the symbol's content: - llvm::ArrayRef SymbolData; + llvm::ArrayRef symbolData; + uint64_t contentSize; if (si + 1 == se) { // if this is the last symbol, take up the remaining data. - SymbolData = llvm::ArrayRef((uint8_t *)symbolContents.data() - + (*si)->st_value, - (IsCommon) ? 0 : - ((i.first)->sh_size - (*si)->st_value)); + contentSize = (isCommon) ? 0 + : ((i.first)->sh_size - (*si)->st_value); } else { - SymbolData = llvm::ArrayRef((uint8_t *)symbolContents.data() - + (*si)->st_value, - (IsCommon) ? 0 : - (*(si + 1))->st_value - (*si)->st_value); + contentSize = (isCommon) ? 0 + : (*(si + 1))->st_value - (*si)->st_value; } - DefinedAtoms._atoms.push_back( - new (AtomStorage.Allocate > ()) - ELFDefinedAtom (*this, - SymbolName, SectionName, - *si, i.first, SymbolData)); + symbolData = llvm::ArrayRef((uint8_t *)symbolContents.data() + + (*si)->st_value, contentSize); + + + unsigned int referenceStart = _references.size(); + + // Only relocations that are inside the domain of the atom are + // added. + + // Add Rela (those with r_addend) references: + for (auto &rai : _relocationAddendRefences[sectionName]) { + if ((rai->r_offset >= (*si)->st_value) && + (rai->r_offset < (*si)->st_value+contentSize)) { + + auto *ERef = new (_readerStorage.Allocate + > ()) + ELFReference ( + rai, rai->r_offset-(*si)->st_value, nullptr); + + _references.push_back(ERef); + } + } + + // Add Rel references: + for (auto &ri : _relocationReferences[sectionName]) { + if (((ri)->r_offset >= (*si)->st_value) && + ((ri)->r_offset < (*si)->st_value+contentSize)) { + + auto *ERef = new (_readerStorage.Allocate + > ()) + ELFReference ( + (ri), (ri)->r_offset-(*si)->st_value, nullptr); + + _references.push_back(ERef); + } + } + + // Create the DefinedAtom and add it to the list of DefinedAtoms. + auto *newAtom = new (_readerStorage.Allocate + > ()) + ELFDefinedAtom + (*this, symbolName, sectionName, + *si, i.first, symbolData, + referenceStart, _references.size(), _references); + + _definedAtoms._atoms.push_back(newAtom); + _symbolToAtomMapping.insert(std::make_pair((*si), newAtom)); + } } + +// All the Atoms and References are created. Now update each Reference's +// target with the Atom pointer it refers to. + for (auto &ri : _references) { + const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex()); + ri->setTarget(findAtom (Symbol)); + } } virtual void addAtom(const Atom&) { @@ -461,30 +669,49 @@ public: } virtual const atom_collection &defined() const { - return DefinedAtoms; + return _definedAtoms; } virtual const atom_collection &undefined() const { - return UndefinedAtoms; + return _undefinedAtoms; } virtual const atom_collection &sharedLibrary() const { - return SharedLibraryAtoms; + return _sharedLibraryAtoms; } virtual const atom_collection &absolute() const { - return AbsoluteAtoms; + return _absoluteAtoms; } + Atom *findAtom(const Elf_Sym *symbol) { + return (_symbolToAtomMapping.lookup(symbol)); + } + + private: std::unique_ptr > - Obj; - atom_collection_vector DefinedAtoms; - atom_collection_vector UndefinedAtoms; - atom_collection_vector SharedLibraryAtoms; - atom_collection_vector AbsoluteAtoms; - llvm::BumpPtrAllocator AtomStorage; + _objFile; + atom_collection_vector _definedAtoms; + atom_collection_vector _undefinedAtoms; + atom_collection_vector _sharedLibraryAtoms; + atom_collection_vector _absoluteAtoms; +/// \brief _relocationAddendRefences and _relocationReferences contain the list +/// of relocations references. In ELF, if a section named, ".text" has +/// relocations will also have a section named ".rel.text" or ".rela.text" +/// which will hold the entries. -- .rel or .rela is prepended to create +/// the SHT_REL(A) section name. +/// + std::map > + _relocationAddendRefences; + std::map > + _relocationReferences; + + std::vector *> _references; + llvm::DenseMap _symbolToAtomMapping; + + llvm::BumpPtrAllocator _readerStorage; }; // ReaderELF is reader object that will instantiate correct FileELF @@ -541,7 +768,6 @@ ReaderOptionsELF::ReaderOptionsELF() { ReaderOptionsELF::~ReaderOptionsELF() { } - Reader *createReaderELF(const ReaderOptionsELF &options) { return new ReaderELF(options); } diff --git a/lld/test/elf/Inputs/reloc-test.elf-i386 b/lld/test/elf/Inputs/reloc-test.elf-i386 new file mode 100644 index 0000000000000000000000000000000000000000..1a5558131fffa9f88521d5a84949238b2b823d0e GIT binary patch literal 1076 zcma)5O-md>5UttSjq4{W9+dU4fj~B3nrsjf^k8&}=AbzQHjq;o*O66cc4Vd{Q3MYn z#Q)(B5kx}%M+6TZ%ssGqZ>F1_O$f<@>Z{EytF3V%(v%<<~sd)_se3cxA+S`QIai-hW(*9>HYRl7} zsLdo16-RW)tgAX)KTzag!;AI7zNl6dhJFW!I+6Aj`g@8{YcHev?T_2B7y9htzfb{- zBYI%i*_?Vu**@_QLY_+p_#5vrVr9s`cyr(|-*X7Td?TrqEsRl?jJEx~f}hS9ni$WN zEJ6<&n`#z~Gsc`H2=BqZHXzK4=S=Yd>!h)%Y~A<9wxK<17)>6r3!z=00|bzlsg*5u ze%o;K{mmi3e%K%PZGRK6?d)L61w_*@uyyk_8G3_5m(Zh-AqeyF{>+`vS4QCX`-1WZ zY#j!Q@}rw4^#5VZZ*QNm+`fv8vzs2=^hNSMC((o3Hz}SUNM}U`-+mJ3c~6V<8_<5D cRZBu|rz86ZIzf=Lb@2F{X<=BTN{tWc7nEXE8UO$Q literal 0 HcmV?d00001 diff --git a/lld/test/elf/reloc.objtxt b/lld/test/elf/reloc.objtxt new file mode 100644 index 000000000000..1fc371343006 --- /dev/null +++ b/lld/test/elf/reloc.objtxt @@ -0,0 +1,79 @@ +RUN: lld-core -reader ELF %p/Inputs/reloc-test.elf-i386 | FileCheck %s -check-prefix ELF-i386 + +ELF-i386:--- +ELF-i386:atoms: +ELF-i386: - name: .text +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .text + +ELF-i386: - name: .data +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .data + +ELF-i386: - name: .bss +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .bss + +ELF-i386: - name: .rodata.str1.1 +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .rodata.str1.1 +ELF-i386: content: [ 68, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ] + +ELF-i386: - name: .text.startup +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .text.startup + +ELF-i386: - name: main +ELF-i386: scope: global +ELF-i386: type: code +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .text.startup +ELF-i386: content: [ 55, 89, E5, 83, E4, F0, 83, EC, 10, C7, 04, 24, +ELF-i386: 00, 00, 00, 00, E8, FC, FF, FF, FF, 31, C0, C9, +ELF-i386: C3 ] +ELF-i386: fixups: +ELF-i386: - offset: 12 +ELF-i386: kind: ??? +ELF-i386: target: .rodata.str1.1 +ELF-i386: - offset: 17 +ELF-i386: kind: call32 +ELF-i386: target: puts + +ELF-i386: - name: .comment +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .comment +ELF-i386: content: [ 00, 47, 43, 43, 3A, 20, 28, 47, 4E, 55, 29, 20, +ELF-i386: 34, 2E, 37, 2E, 30, 00 ] + +ELF-i386: - name: .note.GNU-stack +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .note.GNU-stack + +ELF-i386: - name: .eh_frame +ELF-i386: type: unknown +ELF-i386: section-choice: custom-required +ELF-i386: section-name: .eh_frame +ELF-i386: content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, +ELF-i386: 01, 7C, 08, 01, 1B, 0C, 04, 04, 88, 01, 00, 00, +ELF-i386: 1C, 00, 00, 00, 1C, 00, 00, 00, 00, 00, 00, 00, +ELF-i386: 19, 00, 00, 00, 00, 41, 0E, 08, 85, 02, 42, 0D, +ELF-i386: 05, 55, C5, 0C, 04, 04, 00, 00 ] +ELF-i386: fixups: +ELF-i386: - offset: 32 +ELF-i386: kind: call32 +ELF-i386: target: .text.startup + +ELF-i386: - name: puts +ELF-i386: definition: undefined + +ELF-i386: - name: test.c +ELF-i386: definition: absolute +ELF-i386: value: 0x0 +ELF-i386:...