diff options
author | Simon Atanasyan <simon@atanasyan.com> | 2014-01-17 21:18:37 +0000 |
---|---|---|
committer | Simon Atanasyan <simon@atanasyan.com> | 2014-01-17 21:18:37 +0000 |
commit | 362bdc125e94b32b852b134dba9d67ad3075c6fd (patch) | |
tree | 91c3ac42f475b6f9877dd140ad24e7c604d33422 | |
parent | 66338224be6072b9af6f87aee0e3078076bfb4e3 (diff) | |
download | bcm5719-llvm-362bdc125e94b32b852b134dba9d67ad3075c6fd.tar.gz bcm5719-llvm-362bdc125e94b32b852b134dba9d67ad3075c6fd.zip |
[Mips] Implement .plt and .got.plt section creation.
llvm-svn: 199516
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp | 13 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h | 7 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 21 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 139 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp | 3 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h | 2 | ||||
-rw-r--r-- | lld/test/elf/Mips/plt-header.test | 40 | ||||
-rw-r--r-- | lld/test/elf/Mips/r26.test | 53 |
8 files changed, 261 insertions, 17 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp index c83b891b58c..280943720f8 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp @@ -56,3 +56,16 @@ void MipsLinkingContext::addPasses(PassManager &pm) { pm.add(std::move(pass)); ELFLinkingContext::addPasses(pm); } + +bool MipsLinkingContext::isPLTRelocation(const DefinedAtom &, + const Reference &r) const { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + assert(r.kindArch() == Reference::KindArch::Mips); + switch (r.kindValue()) { + case llvm::ELF::R_MIPS_JUMP_SLOT: + return true; + default: + return false; + } +} diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h index 25c8fd99795..797964dd372 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h @@ -21,7 +21,11 @@ enum { /// \brief The same as R_MIPS_GOT16 but for global symbols. LLD_R_MIPS_GLOBAL_GOT16 = 1025, /// \brief The same as R_MIPS_26 but for global symbols. - LLD_R_MIPS_GLOBAL_26 = 1026 + LLD_R_MIPS_GLOBAL_26 = 1026, + /// \brief Setup hi 16 bits using the symbol this reference refers to. + LLD_R_MIPS_HI16 = 1027, + /// \brief Setup low 16 bits using the symbol this reference refers to. + LLD_R_MIPS_LO16 = 1028 }; typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType; @@ -41,6 +45,7 @@ public: virtual StringRef entrySymbolName() const; virtual StringRef getDefaultInterpreter() const; virtual void addPasses(PassManager &pm); + virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const; }; } // elf diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index 6e14bf3196e..e51ab60bc24 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -105,6 +105,18 @@ void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A, applyReloc(location, result); } +/// \brief LLD_R_MIPS_HI16 +void relocLldHi16(uint8_t *location, uint64_t S) { + int32_t result = lld::scatterBits<uint32_t>((S + 0x8000) >> 16, 0xffff); + applyReloc(location, result); +} + +/// \brief LLD_R_MIPS_LO16 +void relocLldLo16(uint8_t *location, uint64_t S) { + int32_t result = lld::scatterBits<uint32_t>(S, 0xffff); + applyReloc(location, result); +} + } // end anon namespace MipsTargetRelocationHandler::MipsTargetRelocationHandler( @@ -200,6 +212,9 @@ error_code MipsTargetRelocationHandler::applyRelocation( case R_MIPS_JALR: // We do not do JALR optimization now. break; + case R_MIPS_JUMP_SLOT: + // Ignore runtime relocations. + break; case LLD_R_MIPS_GLOBAL_GOT: // Do nothing. break; @@ -210,6 +225,12 @@ error_code MipsTargetRelocationHandler::applyRelocation( case LLD_R_MIPS_GLOBAL_26: reloc26(location, relocVAddress, targetVAddress, false); break; + case LLD_R_MIPS_HI16: + relocLldHi16(location, targetVAddress); + break; + case LLD_R_MIPS_LO16: + relocLldLo16(location, targetVAddress); + break; default: { std::string str; llvm::raw_string_ostream s(str); diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index 09d1d9d008e..7adef094184 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -24,6 +24,26 @@ const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 }; // Module pointer const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 }; +// PLT0 entry +const uint8_t mipsPlt0AtomContent[] = { + 0x00, 0x00, 0x1c, 0x3c, // lui $28, %hi(&GOTPLT[0]) + 0x00, 0x00, 0x99, 0x8f, // lw $25, %lo(&GOTPLT[0])($28) + 0x00, 0x00, 0x9c, 0x27, // addiu $28, $28, %lo(&GOTPLT[0]) + 0x23, 0xc0, 0x1c, 0x03, // subu $24, $24, $28 + 0x21, 0x78, 0xe0, 0x03, // move $15, $31 + 0x82, 0xc0, 0x18, 0x00, // srl $24, $24, 2 + 0x09, 0xf8, 0x20, 0x03, // jalr $25 + 0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2 +}; + +// Regular PLT entry +const uint8_t mipsPltAAtomContent[] = { + 0x00, 0x00, 0x0f, 0x3c, // lui $15, %hi(.got.plt entry) + 0x00, 0x00, 0xf9, 0x8d, // l[wd] $25, %lo(.got.plt entry)($15) + 0x08, 0x00, 0x20, 0x03, // jr $25 + 0x00, 0x00, 0xf8, 0x25 // addiu $24, $15, %lo(.got.plt entry) +}; + /// \brief Abstract base class represent MIPS GOT entries. class MipsGOTAtom : public GOTAtom { public: @@ -52,6 +72,36 @@ public: } }; +class PLT0Atom : public PLTAtom { +public: + PLT0Atom(const File &f) : PLTAtom(f, ".plt") {} + + virtual ArrayRef<uint8_t> rawContent() const { + return llvm::makeArrayRef(mipsPlt0AtomContent); + } +}; + +class PLTAAtom : public PLTAtom { +public: + PLTAAtom(const File &f) : PLTAtom(f, ".plt") {} + + virtual ArrayRef<uint8_t> rawContent() const { + return llvm::makeArrayRef(mipsPltAAtomContent); + } +}; + +/// \brief MIPS GOT PLT entry +class GOTPLTAtom : public GOTAtom { +public: + GOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {} + + virtual Alignment alignment() const { return Alignment(2); } + + virtual ArrayRef<uint8_t> rawContent() const { + return llvm::makeArrayRef(mipsGot0AtomContent); + } +}; + class RelocationPassFile : public SimpleFile { public: RelocationPassFile(const ELFLinkingContext &ctx) @@ -90,6 +140,20 @@ public: got->setOrdinal(ordinal++); mf->addAtom(*got); } + + for (auto &plt : _pltVector) { + DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ PLT ] Adding " + << plt->name() << "\n"); + plt->setOrdinal(ordinal++); + mf->addAtom(*plt); + } + + for (auto &gotplt : _gotpltVector) { + DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOTPLT ] Adding " + << gotplt->name() << "\n"); + gotplt->setOrdinal(ordinal++); + mf->addAtom(*gotplt); + } } private: @@ -105,6 +169,15 @@ private: /// \brief the list of global GOT atoms. std::vector<GOTAtom *> _globalGotVector; + /// \brief Map Atoms to their PLT entries. + llvm::DenseMap<const Atom *, PLTAtom *> _pltMap; + + /// \brief the list of PLT atoms. + std::vector<PLTAtom *> _pltVector; + + /// \brief the list of GOTPLT atoms. + std::vector<GOTAtom *> _gotpltVector; + /// \brief Handle a specific reference. void handleReference(const DefinedAtom &atom, const Reference &ref) { if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF) @@ -131,7 +204,8 @@ private: if (ref.kindValue() == R_MIPS_26 && !isLocal(ref.target())) const_cast<Reference &>(ref).setKindValue(LLD_R_MIPS_GLOBAL_26); - // FIXME (simon): Create PLT entry. + if (isa<SharedLibraryAtom>(ref.target())) + const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target())); } void handleGOT(const Reference &ref) { @@ -187,6 +261,69 @@ private: return ga; } + + void createPLTHeader() { + assert(_pltVector.empty() && _gotpltVector.empty()); + + auto pa = new (_file._alloc) PLT0Atom(_file); + _pltVector.push_back(pa); + + auto ga0 = new (_file._alloc) GOTPLTAtom(_file); + _gotpltVector.push_back(ga0); + auto ga1 = new (_file._alloc) GOTPLTAtom(_file); + _gotpltVector.push_back(ga1); + + // Setup reference to fixup the PLT0 entry. + pa->addReferenceELF_Mips(LLD_R_MIPS_HI16, 0, ga0, 0); + pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, ga0, 0); + pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 8, ga0, 0); + + DEBUG_WITH_TYPE("MipsGOT", { + pa->_name = "__plt0"; + llvm::dbgs() << "[ PLT ] Create PLT0\n"; + ga0->_name = "__gotplt0"; + llvm::dbgs() << "[ GOTPLT ] Create GOTPLT0\n"; + ga1->_name = "__gotplt1"; + llvm::dbgs() << "[ GOTPLT ] Create GOTPLT1\n"; + }); + } + + const PLTAtom *getPLTEntry(const Atom *a) { + auto plt = _pltMap.find(a); + if (plt != _pltMap.end()) + return plt->second; + + if (_pltVector.empty()) + createPLTHeader(); + + auto pa = new (_file._alloc) PLTAAtom(_file); + _pltMap[a] = pa; + _pltVector.push_back(pa); + + auto ga = new (_file._alloc) GOTPLTAtom(_file); + _gotpltVector.push_back(ga); + + // Setup reference to fixup the PLT entry. + pa->addReferenceELF_Mips(LLD_R_MIPS_HI16, 0, ga, 0); + pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, ga, 0); + pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 12, ga, 0); + + // Setup reference to assign initial value to the .got.plt entry. + ga->addReferenceELF_Mips(R_MIPS_32, 0, _pltVector.front(), 0); + // Create dynamic relocation to adjust the .got.plt entry at runtime. + ga->addReferenceELF_Mips(R_MIPS_JUMP_SLOT, 0, a, 0); + + DEBUG_WITH_TYPE("MipsGOT", { + pa->_name = "__plt_"; + pa->_name += a->name(); + llvm::dbgs() << "[ PLT ] Create " << a->name() << "\n"; + ga->_name = "__got_plt_"; + ga->_name += a->name(); + llvm::dbgs() << "[ GOTPLT ] Create " << a->name() << "\n"; + }); + + return pa; + } }; } // end anon namespace diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp index 704e994a15a..5b3ea762b7f 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp @@ -201,8 +201,11 @@ const Registry::KindStrings MipsTargetHandler::kindStrings[] = { LLD_KIND_STRING_ENTRY(R_MIPS_GOT16), LLD_KIND_STRING_ENTRY(R_MIPS_CALL16), LLD_KIND_STRING_ENTRY(R_MIPS_JALR), + LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT), LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT), LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT16), LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_26), + LLD_KIND_STRING_ENTRY(LLD_R_MIPS_HI16), + LLD_KIND_STRING_ENTRY(LLD_R_MIPS_LO16), LLD_KIND_STRING_END }; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h index f826d702c12..d6e83372254 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h @@ -35,7 +35,7 @@ public: createSection(StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions, Layout::SectionOrder order) { - if (type == DefinedAtom::typeGOT) + if (type == DefinedAtom::typeGOT && name == ".got") return _gotSection; return DefaultLayout<ELFType>::createSection(name, type, permissions, order); diff --git a/lld/test/elf/Mips/plt-header.test b/lld/test/elf/Mips/plt-header.test new file mode 100644 index 00000000000..b00d0acf88b --- /dev/null +++ b/lld/test/elf/Mips/plt-header.test @@ -0,0 +1,40 @@ +# Check initialization of .plt header entries. + +# Build shared library +# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \ +# RUN: -o=%t1 %p/Inputs/ext.s +# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t1 + +# Build executable +# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t3 %s +# RUN: lld -flavor gnu -target mipsel -e glob -o %t4 %t3 %t2 +# RUN: llvm-objdump -section-headers -disassemble %t4 | \ +# RUN: FileCheck -check-prefix=EXE %s + +# EXE: Disassembly of section .plt: +# EXE: .plt: +# PLT0 entry. Points to the .got.plt[0] +# EXE: 400170: 40 00 1c 3c lui $gp, 64 +# EXE: 400174: 00 20 99 8f lw $25, 8192($gp) +# EXE: 400178: 00 20 9c 27 addiu $gp, $gp, 8192 +# EXE: 40017c: 23 c0 1c 03 subu $24, $24, $gp +# EXE: 400180: 21 78 e0 03 move $15, $ra +# EXE: 400184: 82 c0 18 00 srl $24, $24, 2 +# EXE: 400188: 09 f8 20 03 jalr $25 +# EXE: 40018c: fe ff 18 27 addiu $24, $24, -2 + +# EXE: Sections: +# EXE: Idx Name Size Address Type +# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA +# EXE: 10 .got.plt 0000000c 0000000000402000 DATA + + .abicalls + .global glob + .ent glob +glob: + jal $t9 + jal loc +loc: + jal glob + jal ext1 + .end glob diff --git a/lld/test/elf/Mips/r26.test b/lld/test/elf/Mips/r26.test index 820a24ddeec..2e221ce1644 100644 --- a/lld/test/elf/Mips/r26.test +++ b/lld/test/elf/Mips/r26.test @@ -7,33 +7,58 @@ # Build executable # RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t3 %s -# RUN: llvm-objdump -r %t3 | FileCheck -check-prefix=REL %s +# RUN: llvm-readobj -relocations %t3 | FileCheck -check-prefix=OBJ-REL %s # RUN: lld -flavor gnu -target mipsel -e glob -o %t4 %t3 %t2 -# RUN: llvm-objdump -disassemble %t4 | FileCheck -check-prefix=EXE %s +# RUN: llvm-objdump -section-headers -disassemble %t4 | \ +# RUN: FileCheck -check-prefix=EXE %s +# RUN: llvm-readobj -relocations %t4 | FileCheck -check-prefix=EXE-REL %s # Object file has three R_MIPS_26 relocations -# REL: RELOCATION RECORDS FOR [.rel.text]: -# REL: 8 R_MIPS_26 Unknown -# REL: 16 R_MIPS_26 Unknown -# REL: 24 R_MIPS_26 Unknown +# OBJ-REL: Relocations [ +# OBJ-REL: Section (2) .rel.text { +# OBJ-REL: 0x8 R_MIPS_26 .text 0x0 +# OBJ-REL: 0x10 R_MIPS_26 glob 0x0 +# OBJ-REL: 0x18 R_MIPS_26 ext1 0x0 +# OBJ-REL: } +# OBJ-REL: ] + +# Executable file has the only relocation for external symbol +# EXE-REL: Relocations [ +# EXE-REL: Section (5) .rela.plt { +# EXE-REL: 0x402008 R_MIPS_JUMP_SLOT ext1 0x0 +# EXE-REL: } +# EXE-REL: ] + +# 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: Disassembly of section .text: # EXE: glob: -# EXE: 40014c: 09 f8 20 03 jalr $25 -# EXE: 400150: 00 00 00 00 nop +# EXE: 4001a0: 09 f8 20 03 jalr $25 +# EXE: 4001a4: 00 00 00 00 nop # # Jump to 'loc' label address -# EXE: 400154: 57 00 10 0c jal 4194652 -# EXE: 400158: 00 00 00 00 nop +# EXE: 4001a8: 6c 00 10 0c jal 4194736 +# EXE: 4001ac: 00 00 00 00 nop # # EXE: loc: # Jump to 'glob' label address -# EXE: 40015c: 53 00 10 0c jal 4194636 -# EXE: 400160: 00 00 00 00 nop +# EXE: 4001b0: 68 00 10 0c jal 4194720 +# EXE: 4001b4: 00 00 00 00 nop # # Jump to the first PLT entry (.plt + 32) for ext1 entry -# EXE: 400164: 00 00 00 0c jal 0 -# EXE: 400168: 00 00 00 00 nop +# EXE: 4001b8: 64 00 10 0c jal 4194704 +# EXE: 4001bc: 00 00 00 00 nop + +# EXE: Sections: +# EXE: Idx Name Size Address Type +# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA +# EXE: 10 .got.plt 0000000c 0000000000402000 DATA .abicalls .global glob |