diff options
| -rw-r--r-- | lld/include/lld/ReaderWriter/ELFLinkingContext.h | 3 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultLayout.h | 6 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ExecutableWriter.h | 14 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h | 1 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/SectionChunks.h | 85 | ||||
| -rw-r--r-- | lld/test/elf/Mips/exe-dynamic.test | 48 | ||||
| -rw-r--r-- | lld/test/elf/Mips/exe-fileheader.test | 2 | ||||
| -rw-r--r-- | lld/test/elf/Mips/r26.test | 28 |
8 files changed, 138 insertions, 49 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index 302854fe269..3921bfe6d58 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -93,6 +93,9 @@ public: static std::unique_ptr<ELFLinkingContext> create(llvm::Triple); + /// \brief Use Elf_Rela format to output relocation tables. + virtual bool isRelaOutputFormat() const { return true; } + /// \brief Does this relocation belong in the dynamic plt relocation table? /// /// This table holds all of the relocations used for delayed symbol binding. diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index 4bcd5760e80..fef915d7650 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -270,7 +270,8 @@ public: RelocationTable<ELFT> *getDynamicRelocationTable() { if (!_dynamicRelocationTable) { _dynamicRelocationTable.reset(new (_allocator) RelocationTable<ELFT>( - _context, ".rela.dyn", ORDER_DYNAMIC_RELOCS)); + _context, _context.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn", + ORDER_DYNAMIC_RELOCS)); addSection(_dynamicRelocationTable.get()); } return _dynamicRelocationTable.get(); @@ -280,7 +281,8 @@ public: RelocationTable<ELFT> *getPLTRelocationTable() { if (!_pltRelocationTable) { _pltRelocationTable.reset(new (_allocator) RelocationTable<ELFT>( - _context, ".rela.plt", ORDER_DYNAMIC_PLT_RELOCS)); + _context, _context.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt", + ORDER_DYNAMIC_PLT_RELOCS)); addSection(_pltRelocationTable.get()); } return _pltRelocationTable.get(); diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h index 380e47c726a..e4f84c8271a 100644 --- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h +++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h @@ -55,8 +55,13 @@ void ExecutableWriter<ELFT>::addDefaultAtoms() { _runtimeFile->addAbsoluteAtom("__preinit_array_end"); _runtimeFile->addAbsoluteAtom("__init_array_start"); _runtimeFile->addAbsoluteAtom("__init_array_end"); - _runtimeFile->addAbsoluteAtom("__rela_iplt_start"); - _runtimeFile->addAbsoluteAtom("__rela_iplt_end"); + if (this->_context.isRelaOutputFormat()) { + _runtimeFile->addAbsoluteAtom("__rela_iplt_start"); + _runtimeFile->addAbsoluteAtom("__rela_iplt_end"); + } else { + _runtimeFile->addAbsoluteAtom("__rel_iplt_start"); + _runtimeFile->addAbsoluteAtom("__rel_iplt_end"); + } _runtimeFile->addAbsoluteAtom("__fini_array_start"); _runtimeFile->addAbsoluteAtom("__fini_array_end"); } @@ -111,7 +116,10 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() { startEnd("preinit_array", ".preinit_array"); startEnd("init_array", ".init_array"); - startEnd("rela_iplt", ".rela.plt"); + if (this->_context.isRelaOutputFormat()) + startEnd("rela_iplt", ".rela.plt"); + else + startEnd("rel_iplt", ".rel.plt"); startEnd("fini_array", ".fini_array"); assert(!(bssStartAtomIter == this->_layout->absoluteAtoms().end() || diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h index 797964dd372..ed46c6c20c5 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h @@ -45,6 +45,7 @@ public: virtual StringRef entrySymbolName() const; virtual StringRef getDefaultInterpreter() const; virtual void addPasses(PassManager &pm); + virtual bool isRelaOutputFormat() const { return false; } virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const; }; diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index bcdcd909dd1..dc3e4bb6275 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -900,22 +900,29 @@ private: template <class ELFT> class RelocationTable : public Section<ELFT> { public: + typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel; typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela; RelocationTable(const ELFLinkingContext &context, StringRef str, int32_t order) : Section<ELFT>(context, str), _symbolTable(nullptr) { this->setOrder(order); - this->_entSize = sizeof(Elf_Rela); - this->_align2 = llvm::alignOf<Elf_Rela>(); - this->_type = SHT_RELA; this->_flags = SHF_ALLOC; + if (context.isRelaOutputFormat()) { + this->_entSize = sizeof(Elf_Rela); + this->_align2 = llvm::alignOf<Elf_Rela>(); + this->_type = SHT_RELA; + } else { + this->_entSize = sizeof(Elf_Rel); + this->_align2 = llvm::alignOf<Elf_Rel>(); + this->_type = SHT_REL; + } } /// \returns the index of the relocation added. uint32_t addRelocation(const DefinedAtom &da, const Reference &r) { _relocs.emplace_back(&da, &r); - this->_fsize = _relocs.size() * sizeof(Elf_Rela); + this->_fsize = _relocs.size() * this->_entSize; this->_msize = this->_fsize; return _relocs.size() - 1; } @@ -945,34 +952,52 @@ public: } virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { - uint8_t *chunkBuffer = buffer.getBufferStart(); - uint8_t *dest = chunkBuffer + this->fileOffset(); + uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); for (const auto &rel : _relocs) { - Elf_Rela *r = reinterpret_cast<Elf_Rela *>(dest); - uint32_t index = - _symbolTable ? _symbolTable->getSymbolTableIndex(rel.second->target()) - : (uint32_t) STN_UNDEF; - r->setSymbolAndType(index, rel.second->kindValue()); - r->r_offset = - writer->addressOfAtom(rel.first) + rel.second->offsetInAtom(); - r->r_addend = 0; - // The addend is used only by relative relocations - if (this->_context.isRelativeReloc(*rel.second)) - r->r_addend = - writer->addressOfAtom(rel.second->target()) + rel.second->addend(); - dest += sizeof(Elf_Rela); - 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";); + 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); + dest += this->_entSize; } } private: std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs; const DynamicSymbolTable<ELFT> *_symbolTable; + + 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()); + 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()); + 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";); + } }; template <class ELFT> class HashSection; @@ -1017,6 +1042,8 @@ public: } virtual void createDefaultEntries() { + bool isRela = this->_context.isRelaOutputFormat(); + Elf_Dyn dyn; dyn.d_un.d_val = 0; @@ -1035,11 +1062,11 @@ public: dyn.d_tag = DT_FINI_ARRAYSZ; _dt_fini_arraysz = addEntry(dyn); if (_layout->hasDynamicRelocationTable()) { - dyn.d_tag = DT_RELA; + dyn.d_tag = isRela ? DT_RELA : DT_REL; _dt_rela = addEntry(dyn); - dyn.d_tag = DT_RELASZ; + dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ; _dt_relasz = addEntry(dyn); - dyn.d_tag = DT_RELAENT; + dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT; _dt_relaent = addEntry(dyn); } if (_layout->hasPLTRelocationTable()) { @@ -1048,7 +1075,7 @@ public: dyn.d_tag = DT_PLTGOT; _dt_pltgot = addEntry(dyn); dyn.d_tag = DT_PLTREL; - dyn.d_un.d_val = DT_RELA; + dyn.d_un.d_val = isRela ? DT_RELA : DT_REL; _dt_pltrel = addEntry(dyn); dyn.d_un.d_val = 0; dyn.d_tag = DT_JMPREL; diff --git a/lld/test/elf/Mips/exe-dynamic.test b/lld/test/elf/Mips/exe-dynamic.test new file mode 100644 index 00000000000..822f443a716 --- /dev/null +++ b/lld/test/elf/Mips/exe-dynamic.test @@ -0,0 +1,48 @@ +# Check MIPS specific tags in the dynamic table in case executable linking. + +# Build shared library +# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \ +# RUN: -o=%t-obj %p/Inputs/ext.s +# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj + +# Build executable +# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s +# RUN: lld -flavor gnu -target mipsel -e glob -o %t-exe %t-obj %t-so +# RUN: llvm-readobj -dynamic-table %t-exe | FileCheck %s + +# CHECK: Format: ELF32-mips +# CHECK: Arch: mipsel +# CHECK: AddressSize: 32bit +# CHECK: LoadName: +# CHECK: DynamicSection [ (20 entries) +# CHECK: Tag Type Name/Value +# CHECK: 0x00000004 HASH 0x400110 +# CHECK: 0x00000005 STRTAB 0x400144 +# CHECK: 0x00000006 SYMTAB 0x400124 +# CHECK: 0x0000000A STRSZ 30 (bytes) +# CHECK: 0x0000000B SYMENT 16 (bytes) +# CHECK: 0x0000001A FINI_ARRAY 0x0 +# CHECK: 0x0000001C FINI_ARRAYSZ 0 (bytes) +# CHECK: 0x00000002 PLTRELSZ 8 (bytes) +# CHECK: 0x00000003 PLTGOT 0x402000 +# CHECK: 0x00000014 PLTREL REL +# CHECK: 0x00000017 JMPREL 0x400162 +# CHECK: 0x70000001 MIPS_RLD_VERSION 1 +# CHECK: 0x70000005 MIPS_FLAGS 0x2 +# CHECK: 0x70000006 MIPS_BASE_ADDRESS 0x400000 +# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 2 +# CHECK: 0x70000011 MIPS_SYMTABNO 2 +# CHECK: 0x70000013 MIPS_GOTSYM 0x2 +# CHECK: 0x00000001 NEEDED SharedLibrary (exe-dynamic.test.{{.*}}) +# CHECK: 0x00000000 NULL 0x0 +# CHECK: ] + + .abicalls + .global glob + .ent glob +loc: + jal ext1 +glob: + jal loc + jal glob + .end glob diff --git a/lld/test/elf/Mips/exe-fileheader.test b/lld/test/elf/Mips/exe-fileheader.test index f0919bbbbb2..9b8cc5b0f95 100644 --- a/lld/test/elf/Mips/exe-fileheader.test +++ b/lld/test/elf/Mips/exe-fileheader.test @@ -27,7 +27,7 @@ # CHECK: Type: Executable (0x2) # CHECK: Machine: EM_MIPS (0x8) # CHECK: Version: 1 -# CHECK: Entry: 0x4001B0 +# CHECK: Entry: 0x4001A0 # CHECK: ProgramHeaderOffset: 0x34 # CHECK: SectionHeaderOffset: 0x2268 # CHECK: Flags [ (0x70001005) diff --git a/lld/test/elf/Mips/r26.test b/lld/test/elf/Mips/r26.test index 2e221ce1644..c54129ae070 100644 --- a/lld/test/elf/Mips/r26.test +++ b/lld/test/elf/Mips/r26.test @@ -24,7 +24,7 @@ # Executable file has the only relocation for external symbol # EXE-REL: Relocations [ -# EXE-REL: Section (5) .rela.plt { +# EXE-REL: Section (5) .rel.plt { # EXE-REL: 0x402008 R_MIPS_JUMP_SLOT ext1 0x0 # EXE-REL: } # EXE-REL: ] @@ -32,32 +32,32 @@ # EXE: Disassembly of section .plt: # EXE: .plt: # PLTA entry. Points to the .got.plt[1] -# EXE: 400190: 40 00 0f 3c lui $15, 64 -# EXE: 400194: 08 20 f9 8d lw $25, 8200($15) -# EXE: 400198: 08 00 20 03 jr $25 -# EXE: 40019c: 08 20 f8 25 addiu $24, $15, 8200 +# EXE: 400180: 40 00 0f 3c lui $15, 64 +# EXE: 400184: 08 20 f9 8d lw $25, 8200($15) +# EXE: 400188: 08 00 20 03 jr $25 +# EXE: 40018c: 08 20 f8 25 addiu $24, $15, 8200 # EXE: Disassembly of section .text: # EXE: glob: -# EXE: 4001a0: 09 f8 20 03 jalr $25 -# EXE: 4001a4: 00 00 00 00 nop +# EXE: 400190: 09 f8 20 03 jalr $25 +# EXE: 400194: 00 00 00 00 nop # # Jump to 'loc' label address -# EXE: 4001a8: 6c 00 10 0c jal 4194736 -# EXE: 4001ac: 00 00 00 00 nop +# EXE: 400198: 6c 00 10 0c jal 4194736 +# EXE: 40019c: 00 00 00 00 nop # # EXE: loc: # Jump to 'glob' label address -# EXE: 4001b0: 68 00 10 0c jal 4194720 -# EXE: 4001b4: 00 00 00 00 nop +# EXE: 4001a0: 64 00 10 0c jal 4194704 +# EXE: 4001a4: 00 00 00 00 nop # # Jump to the first PLT entry (.plt + 32) for ext1 entry -# EXE: 4001b8: 64 00 10 0c jal 4194704 -# EXE: 4001bc: 00 00 00 00 nop +# EXE: 4001a8: 60 00 10 0c jal 4194688 +# EXE: 4001ac: 00 00 00 00 nop # EXE: Sections: # EXE: Idx Name Size Address Type -# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA +# EXE: 6 .plt 00000030 0000000000400160 TEXT DATA # EXE: 10 .got.plt 0000000c 0000000000402000 DATA .abicalls |

