Index: include/lld/Core/Reference.h =================================================================== --- include/lld/Core/Reference.h +++ include/lld/Core/Reference.h @@ -101,6 +101,9 @@ /// 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) Index: lib/ReaderWriter/ELF/DefaultLayout.h =================================================================== --- lib/ReaderWriter/ELF/DefaultLayout.h +++ lib/ReaderWriter/ELF/DefaultLayout.h @@ -282,8 +282,8 @@ /// table are processed at startup. RelocationTable *getDynamicRelocationTable() { if (!_dynamicRelocationTable) { - _dynamicRelocationTable.reset(new (_allocator) RelocationTable( - _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 @@ /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL. RelocationTable *getPLTRelocationTable() { if (!_pltRelocationTable) { - _pltRelocationTable.reset(new (_allocator) RelocationTable( - _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 @@ DefinedAtom::ContentPermissions contentPermissions, SectionOrder sectionOrder); + /// \brief Create a new relocation table. + virtual unique_bump_ptr> + createRelocationTable(StringRef name, int32_t order) { + return unique_bump_ptr>( + new (_allocator) RelocationTable(_context, name, order)); + } + private: /// Helper function that returns the priority value from an input section. uint32_t getPriorityFromSectionName(StringRef sectionName) const; Index: lib/ReaderWriter/ELF/Mips/MipsELFFile.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsELFFile.h +++ lib/ReaderWriter/ELF/Mips/MipsELFFile.h @@ -89,6 +89,33 @@ } }; +template class MipsELFReference : public ELFReference { + typedef llvm::object::Elf_Rel_Impl Elf_Rel; + typedef llvm::object::Elf_Rel_Impl Elf_Rela; + + static const bool _isMips64EL = + ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; + +public: + MipsELFReference(uint64_t symValue, const Elf_Rela &rel) + : ELFReference( + &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(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 MipsELFFile : public ELFFile { public: MipsELFFile(std::unique_ptr mb, MipsLinkingContext &ctx) @@ -125,9 +152,13 @@ typedef llvm::object::Elf_Shdr_Impl Elf_Shdr; typedef llvm::object::Elf_Rel_Impl Elf_Rel; typedef typename llvm::object::ELFFile::Elf_Rel_Iter Elf_Rel_Iter; + typedef typename llvm::object::ELFFile::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 _gp0; llvm::Optional _tpOff; llvm::Optional _dtpOff; @@ -200,19 +231,30 @@ } void createRelocationReferences(const Elf_Sym *symbol, + ArrayRef content, + range 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(value, rel); + this->addReferenceToSymbol(r, symbol); + this->_references.push_back(r); + } + } + + void createRelocationReferences(const Elf_Sym *symbol, ArrayRef symContent, ArrayRef secContent, range 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( - rit->r_offset - symbol->st_value, this->kindArch(), - rit->getType(isMips64EL()), rit->getSymbol(isMips64EL())); - ELFFile::addReferenceToSymbol(elfReference, symbol); - this->_references.push_back(elfReference); + auto r = new (this->_readerStorage) MipsELFReference(value, *rit); + this->addReferenceToSymbol(r, symbol); + this->_references.push_back(r); auto addend = readAddend(*rit, secContent); auto pairRelType = getPairRelocation(*rit); @@ -234,11 +276,11 @@ const auto &rh = this->_ctx.template getTargetHandler().getRelocationHandler(); return static_cast(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 @@ 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; } }; Index: lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -230,18 +230,16 @@ /// \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 @@ 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(params, location); if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode)) Index: lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -435,6 +435,8 @@ if (!isDynamic(ref->target()) || hasPLTEntry(ref->target())) continue; ref->setKindValue(R_MIPS_REL32); + if (ELFT::Is64Bits) + static_cast *>(ref)->setTag(R_MIPS_64); if (!isLocalCall(ref->target())) getGlobalGOTEntry(ref->target()); } Index: lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h +++ lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h @@ -131,6 +131,37 @@ std::unordered_map _pltLayoutMap; }; +template class MipsRelocationTable : public RelocationTable { + typedef llvm::object::Elf_Rel_Impl Elf_Rel; + typedef llvm::object::Elf_Rel_Impl Elf_Rela; + + static const bool _isMips64EL = + ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; + +public: + using RelocationTable::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 Index: lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h +++ lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h @@ -74,6 +74,14 @@ contentPermissions); } +protected: + unique_bump_ptr> + createRelocationTable(StringRef name, int32_t order) override { + return unique_bump_ptr>( + new (this->_allocator) + MipsRelocationTable(this->_context, name, order)); + } + private: MipsGOTSection *_gotSection; MipsPLTSection *_pltSection; Index: lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/SectionChunks.h +++ lib/ReaderWriter/ELF/SectionChunks.h @@ -1019,54 +1019,55 @@ uint8_t *chunkBuffer = buffer.getBufferStart(); uint8_t *dest = chunkBuffer + this->fileOffset(); for (const auto &rel : _relocs) { - if (this->_context.isRelaOutputFormat()) - writeRela(writer, *reinterpret_cast(dest), *rel.first, - *rel.second); - else - writeRel(writer, *reinterpret_cast(dest), *rel.first, - *rel.second); + if (this->_context.isRelaOutputFormat()) { + auto &r = *reinterpret_cast(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(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 > _relocs; +protected: const DynamicSymbolTable *_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 > _relocs; }; template class HashSection; Index: lib/ReaderWriter/Native/NativeFileFormat.h =================================================================== --- lib/ReaderWriter/Native/NativeFileFormat.h +++ lib/ReaderWriter/Native/NativeFileFormat.h @@ -225,6 +225,7 @@ uint8_t kindNamespace; uint8_t kindArch; uint32_t targetIndex; + uint32_t tag; }; Index: lib/ReaderWriter/Native/ReaderNative.cpp =================================================================== --- lib/ReaderWriter/Native/ReaderNative.cpp +++ lib/ReaderWriter/Native/ReaderNative.cpp @@ -241,6 +241,7 @@ 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 @@ llvm_unreachable("setAddend() not supported"); } +uint32_t NativeReferenceV2::tag() const { return _ivarData->tag; } + } // end namespace native namespace { Index: lib/ReaderWriter/Native/WriterNative.cpp =================================================================== --- lib/ReaderWriter/Native/WriterNative.cpp +++ lib/ReaderWriter/Native/WriterNative.cpp @@ -448,6 +448,7 @@ 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; Index: lib/ReaderWriter/YAML/ReaderWriterYAML.cpp =================================================================== --- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -729,13 +729,14 @@ 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 @@ uint32_t _offset; Addend _addend; RefKind _mappedKind; + uint32_t _tag; }; static void mapping(IO &io, const lld::Reference *&ref) { @@ -782,6 +784,7 @@ 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); } }; Index: test/elf/Mips/n64-rel-chain.test =================================================================== --- /dev/null +++ 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 +... Index: test/elf/Mips/rel-dynamic-06-64.test =================================================================== --- /dev/null +++ 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 Index: test/elf/Mips/rel-dynamic-07-64.test =================================================================== --- /dev/null +++ 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 +... Index: test/elf/Mips/rel-dynamic-08-64.test =================================================================== --- /dev/null +++ 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 +... Index: test/elf/Mips/rel-gprel32-64.test =================================================================== --- /dev/null +++ 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 +...