diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2015-03-24 09:57:05 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2015-03-24 09:57:05 +0000 |
| commit | 623d3b0043d547a510851bfc2363a96527deaee0 (patch) | |
| tree | db34648bebcd83e058a7393974025e14046a92da | |
| parent | 774b441b5e11a92d179f57a90c277b48ec74c802 (diff) | |
| download | bcm5719-llvm-623d3b0043d547a510851bfc2363a96527deaee0.tar.gz bcm5719-llvm-623d3b0043d547a510851bfc2363a96527deaee0.zip | |
[Mips] Support MIPS N64 relocation record format
N64 ABI relocation record r_info field in fact consists of five subfields:
* r_sym - symbol index
* r_ssym - special symbol
* r_type3 - third relocation type
* r_type2 - second relocation type
* r_type - first relocation type
Up to three these relocations applied one by one. The first relocation
uses an addendum from the relocation record. Each subsequent relocation
takes as its addend the result of the previous operation. Only the final
operation actually modifies the location relocated. The first relocation
uses as a reference symbol specified by the `r_sym` field. The third
relocation assumes NULL symbol.
The patch represents these data using LLD model and takes in account
additional relocation types during a relocation calculation.
Additional relocations do not introduce any new relations between two
atoms and just specify operations need to be done during a relocation
calculation. The first relocation type (`r_type`) stored in the
`Reference::_kindValue`. The rest of relocations and `r_ssym` value are
stored in the new `Reference::_tag` field "as-is". I decided to do not
"decode" these data on the core LLD level to prevent pollution of the
core LLD model by very target specific data.
Also I have to override writing of relocation records in the `RelocationTable`
class to convert MIPS N64 ABI relocation information from the `Reference`
class back to the ELF relocation record.
http://reviews.llvm.org/D8533
llvm-svn: 233057
| -rw-r--r-- | lld/include/lld/Core/Reference.h | 3 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultLayout.h | 15 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h | 70 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 22 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h | 31 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h | 8 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/SectionChunks.h | 73 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/Native/NativeFileFormat.h | 1 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/Native/ReaderNative.cpp | 3 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/Native/WriterNative.cpp | 1 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 7 | ||||
| -rw-r--r-- | lld/test/elf/Mips/n64-rel-chain.test | 134 | ||||
| -rw-r--r-- | lld/test/elf/Mips/rel-dynamic-06-64.test | 101 | ||||
| -rw-r--r-- | lld/test/elf/Mips/rel-dynamic-07-64.test | 261 | ||||
| -rw-r--r-- | lld/test/elf/Mips/rel-dynamic-08-64.test | 233 | ||||
| -rw-r--r-- | lld/test/elf/Mips/rel-gprel32-64.test | 70 |
17 files changed, 973 insertions, 62 deletions
diff --git a/lld/include/lld/Core/Reference.h b/lld/include/lld/Core/Reference.h index cfbfabc8b72..7a804c31e18 100644 --- a/lld/include/lld/Core/Reference.h +++ b/lld/include/lld/Core/Reference.h @@ -101,6 +101,9 @@ public: /// During linking, some optimzations may change addend value. virtual void setAddend(Addend) = 0; + /// Returns target specific attributes of the reference. + virtual uint32_t tag() const { return 0; } + protected: /// Reference is an abstract base class. Only subclasses can use constructor. Reference(KindNamespace ns, KindArch a, KindValue value) diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index 98f0af3e54c..9af3b8eb8dc 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -282,8 +282,8 @@ public: /// table are processed at startup. RelocationTable<ELFT> *getDynamicRelocationTable() { if (!_dynamicRelocationTable) { - _dynamicRelocationTable.reset(new (_allocator) RelocationTable<ELFT>( - _context, _context.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn", + _dynamicRelocationTable = std::move(createRelocationTable( + _context.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn", ORDER_DYNAMIC_RELOCS)); addSection(_dynamicRelocationTable.get()); } @@ -293,8 +293,8 @@ public: /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL. RelocationTable<ELFT> *getPLTRelocationTable() { if (!_pltRelocationTable) { - _pltRelocationTable.reset(new (_allocator) RelocationTable<ELFT>( - _context, _context.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt", + _pltRelocationTable = std::move(createRelocationTable( + _context.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt", ORDER_DYNAMIC_PLT_RELOCS)); addSection(_pltRelocationTable.get()); } @@ -331,6 +331,13 @@ protected: DefinedAtom::ContentPermissions contentPermissions, SectionOrder sectionOrder); + /// \brief Create a new relocation table. + virtual unique_bump_ptr<RelocationTable<ELFT>> + createRelocationTable(StringRef name, int32_t order) { + return unique_bump_ptr<RelocationTable<ELFT>>( + new (_allocator) RelocationTable<ELFT>(_context, name, order)); + } + private: /// Helper function that returns the priority value from an input section. uint32_t getPriorityFromSectionName(StringRef sectionName) const; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h index 04b3853c5f5..e2e6fdbf5f0 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h @@ -89,6 +89,33 @@ public: } }; +template <class ELFT> class MipsELFReference : public ELFReference<ELFT> { + typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; + typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela; + + static const bool _isMips64EL = + ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; + +public: + MipsELFReference(uint64_t symValue, const Elf_Rela &rel) + : ELFReference<ELFT>( + &rel, rel.r_offset - symValue, Reference::KindArch::Mips, + rel.getType(_isMips64EL) & 0xff, rel.getSymbol(_isMips64EL)), + _tag(rel.getType(_isMips64EL) >> 8) {} + + MipsELFReference(uint64_t symValue, const Elf_Rel &rel) + : ELFReference<ELFT>(rel.r_offset - symValue, Reference::KindArch::Mips, + rel.getType(_isMips64EL) & 0xff, + rel.getSymbol(_isMips64EL)), + _tag(rel.getType(_isMips64EL) >> 8) {} + + uint32_t tag() const override { return _tag; } + void setTag(uint32_t tag) { _tag = tag; } + +private: + uint32_t _tag; +}; + template <class ELFT> class MipsELFFile : public ELFFile<ELFT> { public: MipsELFFile(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx) @@ -125,9 +152,13 @@ private: typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr; typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter Elf_Rela_Iter; enum { TP_OFFSET = 0x7000, DTP_OFFSET = 0x8000 }; + static const bool _isMips64EL = + ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; + llvm::Optional<int64_t> _gp0; llvm::Optional<uint64_t> _tpOff; llvm::Optional<uint64_t> _dtpOff; @@ -200,19 +231,30 @@ private: } void createRelocationReferences(const Elf_Sym *symbol, + ArrayRef<uint8_t> content, + range<Elf_Rela_Iter> rels) override { + const auto value = this->getSymbolValue(symbol); + for (const auto &rel : rels) { + if (rel.r_offset < value || value + content.size() <= rel.r_offset) + continue; + auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, rel); + this->addReferenceToSymbol(r, symbol); + this->_references.push_back(r); + } + } + + void createRelocationReferences(const Elf_Sym *symbol, ArrayRef<uint8_t> symContent, ArrayRef<uint8_t> secContent, range<Elf_Rel_Iter> rels) override { + const auto value = this->getSymbolValue(symbol); for (Elf_Rel_Iter rit = rels.begin(), eit = rels.end(); rit != eit; ++rit) { - if (rit->r_offset < symbol->st_value || - symbol->st_value + symContent.size() <= rit->r_offset) + if (rit->r_offset < value || value + symContent.size() <= rit->r_offset) continue; - auto elfReference = new (this->_readerStorage) ELFReference<ELFT>( - rit->r_offset - symbol->st_value, this->kindArch(), - rit->getType(isMips64EL()), rit->getSymbol(isMips64EL())); - ELFFile<ELFT>::addReferenceToSymbol(elfReference, symbol); - this->_references.push_back(elfReference); + auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit); + this->addReferenceToSymbol(r, symbol); + this->_references.push_back(r); auto addend = readAddend(*rit, secContent); auto pairRelType = getPairRelocation(*rit); @@ -234,11 +276,11 @@ private: const auto &rh = this->_ctx.template getTargetHandler<ELFT>().getRelocationHandler(); return static_cast<const MipsRelocationHandler &>(rh) - .readAddend(ri.getType(isMips64EL()), content.data() + ri.r_offset); + .readAddend(getPrimaryType(ri), content.data() + ri.r_offset); } uint32_t getPairRelocation(const Elf_Rel &rel) const { - switch (rel.getType(isMips64EL())) { + switch (getPrimaryType(rel)) { case llvm::ELF::R_MIPS_HI16: return llvm::ELF::R_MIPS_LO16; case llvm::ELF::R_MIPS_PCHI16: @@ -263,14 +305,16 @@ private: Elf_Rel_Iter findMatchingRelocation(uint32_t pairRelType, Elf_Rel_Iter rit, Elf_Rel_Iter eit) const { return std::find_if(rit, eit, [&](const Elf_Rel &rel) { - return rel.getType(isMips64EL()) == pairRelType && - rel.getSymbol(isMips64EL()) == rit->getSymbol(isMips64EL()); + return getPrimaryType(rel) == pairRelType && + rel.getSymbol(_isMips64EL) == rit->getSymbol(_isMips64EL); }); } - bool isMips64EL() const { return this->_objFile->isMips64EL(); } + static uint8_t getPrimaryType(const Elf_Rel &rel) { + return rel.getType(_isMips64EL) & 0xff; + } bool isLocalBinding(const Elf_Rel &rel) const { - return this->_objFile->getSymbol(rel.getSymbol(isMips64EL())) + return this->_objFile->getSymbol(rel.getSymbol(_isMips64EL)) ->getBinding() == llvm::ELF::STB_LOCAL; } }; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index 6664fd8fd92..173ce0e6b1a 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -230,18 +230,16 @@ static uint32_t relocGOTOfst(uint64_t S, int64_t A) { /// \brief R_MIPS_GPREL16 /// local: sign-extend(A) + S + GP0 - GP /// external: sign-extend(A) + S - GP -static uint32_t relocGPRel16(uint64_t S, int64_t A, uint64_t GP) { +static uint64_t relocGPRel16(uint64_t S, int64_t A, uint64_t GP) { // We added GP0 to addendum for a local symbol during a Relocation pass. - int32_t result = llvm::SignExtend32<16>(A) + S - GP; - return result; + return llvm::SignExtend32<16>(A) + S - GP; } /// \brief R_MIPS_GPREL32 /// local: rel32 A + S + GP0 - GP (truncate) -static uint32_t relocGPRel32(uint64_t S, int64_t A, uint64_t GP) { +static uint64_t relocGPRel32(uint64_t S, int64_t A, uint64_t GP) { // We added GP0 to addendum for a local symbol during a Relocation pass. - int32_t result = A + S - GP; - return result; + return A + S - GP; } /// \brief R_MIPS_PC18_S3 @@ -556,7 +554,17 @@ std::error_code RelocationHandler<ELFT>::applyRelocation( if (auto ec = res.getError()) return ec; - auto params = getRelocationParams(ref.kindValue()); + Reference::KindValue op = ref.kindValue(); + + // FIXME (simon): Handle r_ssym value. + for (auto tag = (ref.tag() & 0xffff); tag & 0xff; tag >>= 8) { + op = tag & 0xff; + res = calculateRelocation(op, *res, 0, relAddr, gpAddr, isGpDisp, jumpMode); + if (auto ec = res.getError()) + return ec; + } + + auto params = getRelocationParams(op); uint64_t ins = relocRead<ELFT>(params, location); if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode)) diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index bf69b14f0ab..a1b3530dfcd 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -435,6 +435,8 @@ void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) { if (!isDynamic(ref->target()) || hasPLTEntry(ref->target())) continue; ref->setKindValue(R_MIPS_REL32); + if (ELFT::Is64Bits) + static_cast<MipsELFReference<ELFT> *>(ref)->setTag(R_MIPS_64); if (!isLocalCall(ref->target())) getGlobalGOTEntry(ref->target()); } diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h index c9abf1b7bde..8246468f7aa 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h @@ -131,6 +131,37 @@ private: std::unordered_map<const Atom *, const AtomLayout *> _pltLayoutMap; }; +template <class ELFT> class MipsRelocationTable : public RelocationTable<ELFT> { + typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; + typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela; + + static const bool _isMips64EL = + ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; + +public: + using RelocationTable<ELFT>::RelocationTable; + +protected: + void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, + const Reference &ref) override { + uint32_t rType = ref.kindValue() | (ref.tag() << 8); + r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL); + r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); + // The addend is used only by relative relocations + if (this->_context.isRelativeReloc(ref)) + r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend(); + else + r.r_addend = 0; + } + + void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, + const Reference &ref) override { + uint32_t rType = ref.kindValue() | (ref.tag() << 8); + r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL); + r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); + } +}; + } // elf } // lld diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h index 22f2955a7af..79509addf40 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h @@ -74,6 +74,14 @@ public: contentPermissions); } +protected: + unique_bump_ptr<RelocationTable<ELFT>> + createRelocationTable(StringRef name, int32_t order) override { + return unique_bump_ptr<RelocationTable<ELFT>>( + new (this->_allocator) + MipsRelocationTable<ELFT>(this->_context, name, order)); + } + private: MipsGOTSection<ELFT> *_gotSection; MipsPLTSection<ELFT> *_pltSection; diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index 721e14b131e..03bdb59e656 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -1019,54 +1019,55 @@ public: uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); for (const auto &rel : _relocs) { - if (this->_context.isRelaOutputFormat()) - writeRela(writer, *reinterpret_cast<Elf_Rela *>(dest), *rel.first, - *rel.second); - else - writeRel(writer, *reinterpret_cast<Elf_Rel *>(dest), *rel.first, - *rel.second); + if (this->_context.isRelaOutputFormat()) { + auto &r = *reinterpret_cast<Elf_Rela *>(dest); + writeRela(writer, r, *rel.first, *rel.second); + DEBUG_WITH_TYPE("ELFRelocationTable", + llvm::dbgs() + << rel.second->kindValue() << " relocation at " + << rel.first->name() << "@" << r.r_offset << " to " + << rel.second->target()->name() << "@" << r.r_addend + << "\n";); + } else { + auto &r = *reinterpret_cast<Elf_Rel *>(dest); + writeRel(writer, r, *rel.first, *rel.second); + DEBUG_WITH_TYPE("ELFRelocationTable", + llvm::dbgs() << rel.second->kindValue() + << " relocation at " << rel.first->name() + << "@" << r.r_offset << " to " + << rel.second->target()->name() << "\n";); + } dest += this->_entSize; } } -private: - std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs; +protected: const DynamicSymbolTable<ELFT> *_symbolTable; - bool isMips64ELOutput() const { - return this->_context.getTriple().getArch() == llvm::Triple::mips64el; - } - - void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, - const Reference &ref) { - uint32_t index = - _symbolTable ? _symbolTable->getSymbolTableIndex(ref.target()) - : (uint32_t)STN_UNDEF; - r.setSymbolAndType(index, ref.kindValue(), isMips64ELOutput()); + virtual void writeRela(ELFWriter *writer, Elf_Rela &r, + const DefinedAtom &atom, const Reference &ref) { + r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false); r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); - r.r_addend = 0; // The addend is used only by relative relocations if (this->_context.isRelativeReloc(ref)) r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend(); - DEBUG_WITH_TYPE("ELFRelocationTable", - llvm::dbgs() << ref.kindValue() << " relocation at " - << atom.name() << "@" << r.r_offset << " to " - << ref.target()->name() << "@" << r.r_addend - << "\n";); - } - - void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, - const Reference &ref) { - uint32_t index = - _symbolTable ? _symbolTable->getSymbolTableIndex(ref.target()) - : (uint32_t)STN_UNDEF; - r.setSymbolAndType(index, ref.kindValue(), isMips64ELOutput()); + else + r.r_addend = 0; + } + + virtual void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, + const Reference &ref) { + r.setSymbolAndType(getSymbolIndex(ref.target()), ref.kindValue(), false); r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); - DEBUG_WITH_TYPE("ELFRelocationTable", - llvm::dbgs() << ref.kindValue() << " relocation at " - << atom.name() << "@" << r.r_offset << " to " - << ref.target()->name() << "\n";); } + + uint32_t getSymbolIndex(const Atom *a) { + return _symbolTable ? _symbolTable->getSymbolTableIndex(a) + : (uint32_t)STN_UNDEF; + } + +private: + std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs; }; template <class ELFT> class HashSection; diff --git a/lld/lib/ReaderWriter/Native/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h index d31cc784031..535072fe231 100644 --- a/lld/lib/ReaderWriter/Native/NativeFileFormat.h +++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h @@ -225,6 +225,7 @@ struct NativeReferenceIvarsV2 { uint8_t kindNamespace; uint8_t kindArch; uint32_t targetIndex; + uint32_t tag; }; diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp index 7cf66cea17c..84cdb4b997e 100644 --- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp +++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp @@ -241,6 +241,7 @@ public: Addend addend() const override; void setTarget(const Atom* newAtom) override; void setAddend(Addend a) override; + uint32_t tag() const override; private: const File *_file; @@ -978,6 +979,8 @@ inline void NativeReferenceV2::setAddend(Addend a) { llvm_unreachable("setAddend() not supported"); } +uint32_t NativeReferenceV2::tag() const { return _ivarData->tag; } + } // end namespace native namespace { diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp index 8f499a421f7..5e01a6ce1c7 100644 --- a/lld/lib/ReaderWriter/Native/WriterNative.cpp +++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp @@ -448,6 +448,7 @@ private: nref.kindValue = ref->kindValue(); nref.targetIndex = this->getTargetIndex(ref->target()); nref.addend = ref->addend(); + nref.tag = ref->tag(); _referencesV2.push_back(nref); } refsCount = _referencesV2.size() - startRefSize; diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index e936a89332c..868b9497c4c 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -729,13 +729,14 @@ template <> struct MappingTraits<const lld::Reference *> { NormalizedReference(IO &io) : lld::Reference(lld::Reference::KindNamespace::all, lld::Reference::KindArch::all, 0), - _target(nullptr), _targetName(), _offset(0), _addend(0) {} + _target(nullptr), _targetName(), _offset(0), _addend(0), _tag(0) {} NormalizedReference(IO &io, const lld::Reference *ref) : lld::Reference(ref->kindNamespace(), ref->kindArch(), ref->kindValue()), _target(nullptr), _targetName(targetName(io, ref)), - _offset(ref->offsetInAtom()), _addend(ref->addend()) { + _offset(ref->offsetInAtom()), _addend(ref->addend()), + _tag(ref->tag()) { _mappedKind.ns = ref->kindNamespace(); _mappedKind.arch = ref->kindArch(); _mappedKind.value = ref->kindValue(); @@ -772,6 +773,7 @@ template <> struct MappingTraits<const lld::Reference *> { uint32_t _offset; Addend _addend; RefKind _mappedKind; + uint32_t _tag; }; static void mapping(IO &io, const lld::Reference *&ref) { @@ -782,6 +784,7 @@ template <> struct MappingTraits<const lld::Reference *> { io.mapOptional("offset", keys->_offset); io.mapOptional("target", keys->_targetName); io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0); + io.mapOptional("tag", keys->_tag, 0u); } }; diff --git a/lld/test/elf/Mips/n64-rel-chain.test b/lld/test/elf/Mips/n64-rel-chain.test new file mode 100644 index 00000000000..0ae7af73ae8 --- /dev/null +++ b/lld/test/elf/Mips/n64-rel-chain.test @@ -0,0 +1,134 @@ +# Check handling MIPS N64 ABI relocation "chains". + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o +# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t-so.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o +# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so +# RUN: llvm-objdump -s %t.exe | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK-NEXT: 1200001d0 01000000 00000000 208e0000 00000000 ........ ....... +# CHECK-NEXT: 1200001e0 20800000 f8010000 28800000 00000000 .......(....... +# CHECK: Contents of section .pdr: +# CHECK-NEXT: 0000 d0010020 e0010020 ... ... + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 8 + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + + Global: + - Name: T1 + Type: STT_FUNC + Section: .text + Value: 0 + Size: 8 + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 32 + + - Name: .rela.text + Type: SHT_RELA + Link: .symtab + AddressAlign: 8 + Info: .text + Relocations: + - Offset: 0x00 + Symbol: LT1 + Type: R_MIPS_GPREL16 + Type2: R_MIPS_SUB + Type3: R_MIPS_HI16 + - Offset: 0x08 + Symbol: LT1 + Type: R_MIPS_GPREL16 + Type2: R_MIPS_SUB + Type3: R_MIPS_LO16 + - Offset: 0x10 + Symbol: .rodata + Type: R_MIPS_GOT_PAGE + Addend: 8 + - Offset: 0x14 + Symbol: .rodata + Type: R_MIPS_GOT_OFST + Addend: 8 + - Offset: 0x18 + Symbol: T1 + Type: R_MIPS_CALL16 + + - Name: .pdr + Type: SHT_PROGBITS + AddressAlign: 4 + Size: 8 + + - Name: .rela.pdr + Type: SHT_RELA + Link: .symtab + AddressAlign: 8 + Info: .pdr + Relocations: + - Offset: 0x00 + Symbol: LT1 + Type: R_MIPS_32 + - Offset: 0x04 + Symbol: T0 + Type: R_MIPS_32 + + - Name: .rodata + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 16 + Size: 16 + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .rodata + Type: STT_SECTION + Section: .rodata + - Name: .pdr + Type: STT_SECTION + Section: .pdr + + Global: + - Name: LT1 + Type: STT_FUNC + Section: .text + Value: 0x00 + Size: 0x10 + - Name: T0 + Type: STT_FUNC + Section: .text + Value: 0x10 + Size: 0x10 + - Name: T1 +... diff --git a/lld/test/elf/Mips/rel-dynamic-06-64.test b/lld/test/elf/Mips/rel-dynamic-06-64.test new file mode 100644 index 00000000000..c153eb22af4 --- /dev/null +++ b/lld/test/elf/Mips/rel-dynamic-06-64.test @@ -0,0 +1,101 @@ +# Conditions: +# a) Linking a shared library. +# b) The first relocation modifies a regular .text section. +# c) The second relocation modifies a .pdr section without SHF_ALLOC flag. +# Check: +# a) There should be no PLT entries. +# b) Linker creates a single R_MIPS_REL32 relocation. +# +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.o +# RUN: llvm-readobj -dt -r -s %t.so | FileCheck -check-prefix=CHECK %s + +# CHECK: Sections [ +# CHECK: Section { +# CHECK-NOT: Name: .plt ({{[0-9]+}}) + +# CHECK: Relocations [ +# CHECK-NEXT: Section (4) .rel.dyn { +# CHECK-NEXT: 0x170 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T0 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T1@ (4) +# CHECK-NEXT: Value: 0x174 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text (0x5) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T0@ (1) +# CHECK-NEXT: Value: 0x170 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text (0x5) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Size: 8 + AddressAlign: 16 + Flags: [SHF_EXECINSTR, SHF_ALLOC] + +- Name: .rel.text + Type: SHT_RELA + Info: .text + AddressAlign: 4 + Relocations: + - Offset: 0 + Symbol: T0 + Type: R_MIPS_64 + +- Name: .pdr + Type: SHT_PROGBITS + Size: 8 + AddressAlign: 16 + +- Name: .rel.pdr + Type: SHT_RELA + Info: .pdr + AddressAlign: 4 + Relocations: + - Offset: 0 + Symbol: T1 + Type: R_MIPS_64 + +Symbols: + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0x0 + Size: 4 + - Name: T1 + Section: .text + Type: STT_FUNC + Value: 4 + Size: 4 diff --git a/lld/test/elf/Mips/rel-dynamic-07-64.test b/lld/test/elf/Mips/rel-dynamic-07-64.test new file mode 100644 index 00000000000..f7a1c442582 --- /dev/null +++ b/lld/test/elf/Mips/rel-dynamic-07-64.test @@ -0,0 +1,261 @@ +# Conditions: +# a) Linking a shared library. +# b) There ars multiple R_MIPS_64 relocations with various targets. +# Check: +# a) Emitting of R_MIPS_REL32 relocations. +# +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o +# RUN: lld -flavor gnu -target mips64el -shared -o %t1.so %t-so.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o +# RUN: lld -flavor gnu -target mips64el -shared --noinhibit-exec \ +# RUN: -o %t2.so %t-o.o %t1.so +# RUN: llvm-readobj -dt -r -sections %t2.so | FileCheck %s + +# CHECK: Sections [ +# CHECK: Section { +# CHECK-NOT: Name: .plt ({{[0-9]+}}) + +# CHECK: Relocations [ +# CHECK-NEXT: Section (4) .rel.dyn { +# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T0 0x0 +# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T4 0x0 +# CHECK-NEXT: 0x2000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D2 0x0 +# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T1 0x0 +# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T2 0x0 +# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D0 0x0 +# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D1 0x0 +# CHECK-NEXT: 0x2004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D4 0x0 +# CHECK-NEXT: 0x2008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE U1 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T0@ (1) +# CHECK-NEXT: Value: 0x324 +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text (0x5) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T4@ (7) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D2@ (25) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T1@ (16) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T2@ (19) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D0@ (4) +# CHECK-NEXT: Value: 0x2004 +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .data (0x8) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D1@ (22) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D4@ (10) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: U1@ (13) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# so.o +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_EXECINSTR, SHF_ALLOC] + +- Name: .data + Type: SHT_PROGBITS + Size: 0x08 + AddressAlign: 16 + Flags: [SHF_WRITE, SHF_ALLOC] + +Symbols: + Global: + - Name: T1 + Section: .text + Type: STT_FUNC + Value: 0x0 + Size: 4 + - Name: T2 + Section: .text + Type: STT_FUNC + Value: 0x4 + Size: 4 + - Name: D1 + Section: .data + Type: STT_OBJECT + Value: 0x0 + Size: 4 + - Name: D2 + Section: .data + Type: STT_OBJECT + Value: 0x4 + Size: 4 + +# o.o +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_EXECINSTR, SHF_ALLOC] + +- Name: .data + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_WRITE, SHF_ALLOC] + +- Name: .rel.data + Type: SHT_RELA + Info: .data + AddressAlign: 4 + Relocations: + - Offset: 0x00 # T0 is a defined function + Symbol: T0 + Type: R_MIPS_64 + - Offset: 0x04 # T1 is a function from shared lib + Symbol: T1 + Type: R_MIPS_64 + - Offset: 0x08 # T2 has unknown type and defined in shared lib + Symbol: T2 + Type: R_MIPS_64 + - Offset: 0x00 # T4 is an undefined function + Symbol: T4 + Type: R_MIPS_64 + - Offset: 0x04 # D0 is a defined data object + Symbol: D0 + Type: R_MIPS_64 + - Offset: 0x08 # D1 is a data object from shared lib + Symbol: D1 + Type: R_MIPS_64 + - Offset: 0x00 # D2 has unknown type and defined in shared lib + Symbol: D2 + Type: R_MIPS_64 + - Offset: 0x04 # D4 is an undefined data object + Symbol: D4 + Type: R_MIPS_64 + - Offset: 0x08 # U1 is undefined and has unknown type + Symbol: U1 + Type: R_MIPS_64 + +Symbols: + Local: + - Name: LT0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 + - Name: LD0 + Section: .data + Type: STT_OBJECT + Value: 0 + Size: 4 + + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0x4 + Size: 8 + - Name: T1 + Type: STT_FUNC + - Name: T2 + - Name: T4 + Type: STT_FUNC + + - Name: D0 + Section: .data + Type: STT_OBJECT + Value: 0x4 + Size: 8 + - Name: D1 + Type: STT_OBJECT + - Name: D2 + - Name: D4 + Type: STT_OBJECT + - Name: U1 +... diff --git a/lld/test/elf/Mips/rel-dynamic-08-64.test b/lld/test/elf/Mips/rel-dynamic-08-64.test new file mode 100644 index 00000000000..d845d7407c1 --- /dev/null +++ b/lld/test/elf/Mips/rel-dynamic-08-64.test @@ -0,0 +1,233 @@ +# Conditions: +# a) Linking a non-shared executable file. +# b) There ars multiple R_MIPS_64/R_MIPS_HI16/R_MIPS_LO16 relocations +# with various targets. +# Check: +# a) Emitting of R_MIPS_REL32 relocations. +# +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o +# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t-so.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o +# RUN: lld -flavor gnu -target mips64el -e T0 --noinhibit-exec \ +# RUN: -o %t.exe %t-o.o %t.so +# RUN: llvm-readobj -dt -r -sections %t.exe | FileCheck %s + +# CHECK: Sections [ +# CHECK: Section { +# CHECK-NOT: Name: .plt ({{[0-9]+}}) + +# CHECK: Relocations [ +# CHECK-NEXT: Section (5) .rel.dyn { +# CHECK-NEXT: 0x120002000 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D2 0x0 +# CHECK-NEXT: 0x120002004 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T1 0x0 +# CHECK-NEXT: 0x120002008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T2 0x0 +# CHECK-NEXT: 0x120002008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE D1 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D2@ (10) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T1@ (1) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: T2@ (4) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Function (0x2) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: D1@ (7) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: Object (0x1) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +# so.o +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_EXECINSTR, SHF_ALLOC] + +- Name: .data + Type: SHT_PROGBITS + Size: 0x08 + AddressAlign: 16 + Flags: [SHF_WRITE, SHF_ALLOC] + +Symbols: + Global: + - Name: T1 + Section: .text + Type: STT_FUNC + Value: 0x0 + Size: 4 + - Name: T2 + Section: .text + Type: STT_FUNC + Value: 0x4 + Size: 4 + - Name: D1 + Section: .data + Type: STT_OBJECT + Value: 0x0 + Size: 4 + - Name: D2 + Section: .data + Type: STT_OBJECT + Value: 0x4 + Size: 4 + +# o.o +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_EXECINSTR, SHF_ALLOC] + +- Name: .data + Type: SHT_PROGBITS + Size: 0x0C + AddressAlign: 16 + Flags: [SHF_WRITE, SHF_ALLOC] + +- Name: .rel.text + Type: SHT_RELA + Info: .text + AddressAlign: 4 + Relocations: + - Offset: 0x00 + Symbol: _gp_disp + Type: R_MIPS_HI16 + - Offset: 0x00 + Symbol: _gp_disp + Type: R_MIPS_LO16 + +- Name: .rel.data + Type: SHT_RELA + Info: .data + AddressAlign: 4 + Relocations: + - Offset: 0x00 # LT0 is a locally defined function + Symbol: LT0 + Type: R_MIPS_64 + - Offset: 0x00 # LD0 is a locally defined data object + Symbol: LD0 + Type: R_MIPS_64 + - Offset: 0x00 # T0 is a defined function + Symbol: T0 + Type: R_MIPS_64 + - Offset: 0x04 # T1 is a function from shared lib + Symbol: T1 + Type: R_MIPS_64 + - Offset: 0x08 # T2 has unknown type and defined in shared lib + Symbol: T2 + Type: R_MIPS_64 + - Offset: 0x00 # T4 is an undefined function + Symbol: T4 + Type: R_MIPS_64 + - Offset: 0x04 # D0 is a defined data object + Symbol: D0 + Type: R_MIPS_64 + - Offset: 0x08 # D1 is a data object from shared lib + Symbol: D1 + Type: R_MIPS_64 + - Offset: 0x00 # D2 has unknown type and defined in shared lib + Symbol: D2 + Type: R_MIPS_64 + - Offset: 0x04 # D4 is an undefined data object + Symbol: D4 + Type: R_MIPS_64 + - Offset: 0x08 # U1 is undefined and has unknown type + Symbol: U1 + Type: R_MIPS_64 + +Symbols: + Local: + - Name: LT0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 + - Name: LD0 + Section: .data + Type: STT_OBJECT + Value: 0 + Size: 4 + + Global: + - Name: _gp_disp + Type: STT_OBJECT + + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0x4 + Size: 8 + - Name: T1 + Type: STT_FUNC + - Name: T2 + - Name: T4 + Type: STT_FUNC + + - Name: D0 + Section: .data + Type: STT_OBJECT + Value: 0x4 + Size: 8 + - Name: D1 + Type: STT_OBJECT + - Name: D2 + - Name: D4 + Type: STT_OBJECT + - Name: U1 +... diff --git a/lld/test/elf/Mips/rel-gprel32-64.test b/lld/test/elf/Mips/rel-gprel32-64.test new file mode 100644 index 00000000000..723c8e1ee73 --- /dev/null +++ b/lld/test/elf/Mips/rel-gprel32-64.test @@ -0,0 +1,70 @@ +# Check R_MIPS_GPREL32/R_MIPS_64 relocations handling. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t.o +# RUN: llvm-objdump -s %t.exe | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK-NEXT: 1200001a0 c871ffff ffffffff c871ffff c871ffff .q.......q...q.. +# CHECK-NEXT: 1200001b0 c871ffff ffffffff 00000000 00000000 .q.............. + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 32 + + - Name: .rela.text + Type: SHT_RELA + Link: .symtab + AddressAlign: 8 + Info: .text + Relocations: + - Offset: 0x00 + Symbol: LT1 + Type: R_MIPS_GPREL16 + Type2: R_MIPS_64 + Type3: R_MIPS_NONE + - Offset: 0x08 + Symbol: LT1 + Type: R_MIPS_GPREL16 + Type2: R_MIPS_64 + Type3: R_MIPS_NONE + - Offset: 0x0C + Symbol: LT1 + Type: R_MIPS_GPREL32 + Type2: R_MIPS_64 + Type3: R_MIPS_NONE + - Offset: 0x10 + Symbol: LT1 + Type: R_MIPS_GPREL32 + Type2: R_MIPS_64 + Type3: R_MIPS_NONE + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + + Global: + - Name: LT1 + Type: STT_FUNC + Section: .text + Value: 0x18 + Size: 0x8 + - Name: T0 + Type: STT_FUNC + Section: .text + Value: 0x0 + Size: 0x18 +... |

