summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-02-28 00:10:58 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-02-28 00:10:58 +0000
commit3a4d0a7c17d90d78d299122b44576576da7d9311 (patch)
treeb86319c5dc6c1b39e9a6530121a446be615af0ad /lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
parent985ff20a9caff5091ade54ddc2e21dd8ef016194 (diff)
downloadbcm5719-llvm-3a4d0a7c17d90d78d299122b44576576da7d9311.tar.gz
bcm5719-llvm-3a4d0a7c17d90d78d299122b44576576da7d9311.zip
Remove the old ELF linker.
I think it is clear by now that the new linker is viable. llvm-svn: 262158
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp')
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp1415
1 files changed, 0 insertions, 1415 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
deleted file mode 100644
index 45f6467c95c..00000000000
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
+++ /dev/null
@@ -1,1415 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsELFFile.h"
-#include "MipsLinkingContext.h"
-#include "MipsRelocationPass.h"
-#include "MipsTargetHandler.h"
-#include "llvm/ADT/DenseSet.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-// Lazy resolver
-static const uint8_t mipsGot0AtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-// Module pointer
-static const uint8_t mipsGotModulePointerAtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80
-};
-
-// TLS GD Entry
-static const uint8_t mipsGotTlsGdAtomContent[] = {
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-// Regular big-endian PLT0 entry
-static const uint8_t mipsBePlt0AtomContent[] = {
- 0x3c, 0x1c, 0x00, 0x00, // lui $28, %hi(&GOTPLT[0])
- 0x8f, 0x99, 0x00, 0x00, // lw $25, %lo(&GOTPLT[0])($28)
- 0x27, 0x9c, 0x00, 0x00, // addiu $28, $28, %lo(&GOTPLT[0])
- 0x03, 0x1c, 0xc0, 0x23, // subu $24, $24, $28
- 0x03, 0xe0, 0x78, 0x25, // move $15, $31
- 0x00, 0x18, 0xc0, 0x82, // srl $24, $24, 2
- 0x03, 0x20, 0xf8, 0x09, // jalr $25
- 0x27, 0x18, 0xff, 0xfe // subu $24, $24, 2
-};
-
-// Regular little-endian PLT0 entry
-static const uint8_t mipsLePlt0AtomContent[] = {
- 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
- 0x25, 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
-};
-
-// N32 big-endian PLT0 entry
-static const uint8_t mipsN32BePlt0AtomContent[] = {
- 0x3c, 0x0e, 0x00, 0x00, // lui $14, %hi(&GOTPLT[0])
- 0x8d, 0xd9, 0x00, 0x00, // lw $25, %lo(&GOTPLT[0])($14)
- 0x25, 0xce, 0x00, 0x00, // addiu $14, $14, %lo(&GOTPLT[0])
- 0x03, 0x0e, 0xc0, 0x23, // subu $24, $24, $14
- 0x03, 0xe0, 0x78, 0x25, // move $15, $31
- 0x00, 0x18, 0xc0, 0x82, // srl $24, $24, 2
- 0x03, 0x20, 0xf8, 0x09, // jalr $25
- 0x27, 0x18, 0xff, 0xfe // subu $24, $24, 2
-};
-
-// N32 little-endian PLT0 entry
-static const uint8_t mipsN32LePlt0AtomContent[] = {
- 0x00, 0x00, 0x0e, 0x3c, // lui $14, %hi(&GOTPLT[0])
- 0x00, 0x00, 0xd9, 0x8d, // lw $25, %lo(&GOTPLT[0])($14)
- 0x00, 0x00, 0xce, 0x25, // addiu $14, $14, %lo(&GOTPLT[0])
- 0x23, 0xc0, 0x0e, 0x03, // subu $24, $24, $14
- 0x25, 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
-};
-
-// microMIPS big-endian PLT0 entry
-static const uint8_t microMipsBePlt0AtomContent[] = {
- 0x79, 0x80, 0x00, 0x00, // addiupc $3, (&GOTPLT[0]) - .
- 0xff, 0x23, 0x00, 0x00, // lw $25, 0($3)
- 0x05, 0x35, // subu $2, $2, $3
- 0x25, 0x25, // srl $2, $2, 2
- 0x33, 0x02, 0xff, 0xfe, // subu $24, $2, 2
- 0x0d, 0xff, // move $15, $31
- 0x45, 0xf9, // jalrs $25
- 0x0f, 0x83, // move $28, $3
- 0x0c, 0x00 // nop
-};
-
-// microMIPS little-endian PLT0 entry
-static const uint8_t microMipsLePlt0AtomContent[] = {
- 0x80, 0x79, 0x00, 0x00, // addiupc $3, (&GOTPLT[0]) - .
- 0x23, 0xff, 0x00, 0x00, // lw $25, 0($3)
- 0x35, 0x05, // subu $2, $2, $3
- 0x25, 0x25, // srl $2, $2, 2
- 0x02, 0x33, 0xfe, 0xff, // subu $24, $2, 2
- 0xff, 0x0d, // move $15, $31
- 0xf9, 0x45, // jalrs $25
- 0x83, 0x0f, // move $28, $3
- 0x00, 0x0c // nop
-};
-
-// Regular big-endian PLT entry
-static const uint8_t mipsBePltAAtomContent[] = {
- 0x3c, 0x0f, 0x00, 0x00, // lui $15, %hi(.got.plt entry)
- 0x8d, 0xf9, 0x00, 0x00, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x03, 0x20, 0x00, 0x08, // jr $25
- 0x25, 0xf8, 0x00, 0x00 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// Regular little-endian PLT entry
-static const uint8_t mipsLePltAAtomContent[] = {
- 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)
-};
-
-// microMIPS big-endian PLT entry
-static const uint8_t microMipsBePltAAtomContent[] = {
- 0x79, 0x00, 0x00, 0x00, // addiupc $2, (.got.plt entry) - .
- 0xff, 0x22, 0x00, 0x00, // lw $25, 0($2)
- 0x45, 0x99, // jr $25
- 0x0f, 0x02 // move $24, $2
-};
-
-// microMIPS little-endian PLT entry
-static const uint8_t microMipsLePltAAtomContent[] = {
- 0x00, 0x79, 0x00, 0x00, // addiupc $2, (.got.plt entry) - .
- 0x22, 0xff, 0x00, 0x00, // lw $25, 0($2)
- 0x99, 0x45, // jr $25
- 0x02, 0x0f // move $24, $2
-};
-
-// R6 big-endian PLT entry
-static const uint8_t mipsR6BePltAAtomContent[] = {
- 0x3c, 0x0f, 0x00, 0x00, // lui $15, %hi(.got.plt entry)
- 0x8d, 0xf9, 0x00, 0x00, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x03, 0x20, 0x00, 0x09, // jr $25
- 0x25, 0xf8, 0x00, 0x00 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// R6 little-endian PLT entry
-static const uint8_t mipsR6LePltAAtomContent[] = {
- 0x00, 0x00, 0x0f, 0x3c, // lui $15, %hi(.got.plt entry)
- 0x00, 0x00, 0xf9, 0x8d, // l[wd] $25, %lo(.got.plt entry)($15)
- 0x09, 0x00, 0x20, 0x03, // jr $25
- 0x00, 0x00, 0xf8, 0x25 // addiu $24, $15, %lo(.got.plt entry)
-};
-
-// LA25 big-endian stub entry
-static const uint8_t mipsBeLA25AtomContent[] = {
- 0x3c, 0x19, 0x00, 0x00, // lui $25, %hi(func)
- 0x08, 0x00, 0x00, 0x00, // j func
- 0x27, 0x39, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// LA25 little-endian stub entry
-static const uint8_t mipsLeLA25AtomContent[] = {
- 0x00, 0x00, 0x19, 0x3c, // lui $25, %hi(func)
- 0x00, 0x00, 0x00, 0x08, // j func
- 0x00, 0x00, 0x39, 0x27, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// microMIPS LA25 big-endian stub entry
-static const uint8_t microMipsBeLA25AtomContent[] = {
- 0x41, 0xbe, 0x00, 0x00, // lui $25, %hi(func)
- 0xd4, 0x00, 0x00, 0x00, // j func
- 0x33, 0x39, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-// microMIPS LA25 little-endian stub entry
-static const uint8_t microMipsLeLA25AtomContent[] = {
- 0xb9, 0x41, 0x00, 0x00, // lui $25, %hi(func)
- 0x00, 0xd4, 0x00, 0x00, // j func
- 0x39, 0x33, 0x00, 0x00, // addiu $25, $25, %lo(func)
- 0x00, 0x00, 0x00, 0x00 // nop
-};
-
-namespace {
-
-/// \brief Abstract base class represent MIPS GOT entries.
-class MipsGOTAtom : public GOTAtom {
-public:
- MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
- Alignment alignment() const override { return 4; }
-};
-
-/// \brief MIPS GOT entry initialized by zero.
-template <typename ELFT> class GOT0Atom : public MipsGOTAtom {
-public:
- GOT0Atom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <> ArrayRef<uint8_t> GOT0Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent);
-}
-template <> ArrayRef<uint8_t> GOT0Atom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGot0AtomContent);
-}
-
-/// \brief MIPS GOT entry initialized by zero.
-template <typename ELFT> class GOTModulePointerAtom : public MipsGOTAtom {
-public:
- GOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent).slice(4);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent).slice(4);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
-}
-template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
-}
-
-/// \brief MIPS GOT TLS GD entry.
-template <typename ELFT> class GOTTLSGdAtom : public MipsGOTAtom {
-public:
- GOTTLSGdAtom(const File &f) : MipsGOTAtom(f) {}
-
- ArrayRef<uint8_t> rawContent() const override;
-};
-
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF64BE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent);
-}
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF64LE>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent);
-}
-
-class GOTPLTAtom : public GOTAtom {
-public:
- GOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {}
- GOTPLTAtom(const Atom *a, const File &f) : GOTAtom(f, ".got.plt") {
- // Create dynamic relocation to adjust the .got.plt entry at runtime.
- addReferenceELF_Mips(R_MIPS_JUMP_SLOT, 0, a, 0);
- }
-
- /// Setup reference to assign initial value to the .got.plt entry.
- void setPLT0(const PLTAtom *plt0) {
- addReferenceELF_Mips(R_MIPS_32, 0, plt0, 0);
- }
-
- Alignment alignment() const override { return 4; }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
- }
-};
-
-template <class ELFT> class PLT0Atom : public PLTAtom {
-public:
- PLT0Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLePlt0AtomContent);
-}
-
-template <class ELFT> class PLT0N32Atom : public PLTAtom {
-public:
- PLT0N32Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsN32BePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsN32LePlt0AtomContent);
-}
-
-template <class ELFT> class PLT0MicroAtom : public PLTAtom {
-public:
- PLT0MicroAtom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT0 entry.
- addReferenceELF_Mips(R_MICROMIPS_PC23_S2, 0, got, 0);
- }
-
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT0 is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLT0MicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBePlt0AtomContent);
-}
-template <> ArrayRef<uint8_t> PLT0MicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLePlt0AtomContent);
-}
-
-class PLTAAtom : public PLTAtom {
-public:
- PLTAAtom(const GOTPLTAtom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the PLT entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 12, got, 0);
- }
-};
-
-template <class ELFT> class PLTARegAtom : public PLTAAtom {
-public:
- PLTARegAtom(const GOTPLTAtom *got, const File &f) : PLTAAtom(got, f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTARegAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTARegAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLePltAAtomContent);
-}
-
-template <class ELFT> class PLTR6Atom : public PLTAAtom {
-public:
- PLTR6Atom(const GOTPLTAtom *got, const File &f) : PLTAAtom(got, f) {}
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTR6Atom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsR6BePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTR6Atom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsR6LePltAAtomContent);
-}
-
-template <class ELFT> class PLTMicroAtom : public PLTAtom {
-public:
- PLTMicroAtom(const GOTPLTAtom *got, const File &f) : PLTAtom(f, ".plt") {
- // Setup reference to fixup the microMIPS PLT entry.
- addReferenceELF_Mips(R_MICROMIPS_PC23_S2, 0, got, 0);
- }
-
- Alignment alignment() const override { return 2; }
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("PLT is not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> PLTMicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBePltAAtomContent);
-}
-template <> ArrayRef<uint8_t> PLTMicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLePltAAtomContent);
-}
-
-class LA25Atom : public PLTAtom {
-public:
- LA25Atom(const File &f) : PLTAtom(f, ".text") {}
-};
-
-template <typename ELFT> class LA25RegAtom : public LA25Atom {
-public:
- LA25RegAtom(const Atom *a, const File &f) : LA25Atom(f) {
- // Setup reference to fixup the LA25 stub entry.
- addReferenceELF_Mips(R_MIPS_HI16, 0, a, 0);
- addReferenceELF_Mips(R_MIPS_26, 4, a, 0);
- addReferenceELF_Mips(R_MIPS_LO16, 8, a, 0);
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("LA25 stubs are not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> LA25RegAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(mipsBeLA25AtomContent);
-}
-template <> ArrayRef<uint8_t> LA25RegAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(mipsLeLA25AtomContent);
-}
-
-template <typename ELFT> class LA25MicroAtom : public LA25Atom {
-public:
- LA25MicroAtom(const Atom *a, const File &f) : LA25Atom(f) {
- // Setup reference to fixup the microMIPS LA25 stub entry.
- addReferenceELF_Mips(R_MICROMIPS_HI16, 0, a, 0);
- addReferenceELF_Mips(R_MICROMIPS_26_S1, 4, a, 0);
- addReferenceELF_Mips(R_MICROMIPS_LO16, 8, a, 0);
- }
-
- CodeModel codeModel() const override { return codeMipsMicro; }
-
- ArrayRef<uint8_t> rawContent() const override {
- llvm_unreachable("LA25 stubs are not applicable for this target");
- }
-};
-
-template <> ArrayRef<uint8_t> LA25MicroAtom<ELF32BE>::rawContent() const {
- return llvm::makeArrayRef(microMipsBeLA25AtomContent);
-}
-template <> ArrayRef<uint8_t> LA25MicroAtom<ELF32LE>::rawContent() const {
- return llvm::makeArrayRef(microMipsLeLA25AtomContent);
-}
-
-class MipsGlobalOffsetTableAtom : public GlobalOffsetTableAtom {
-public:
- MipsGlobalOffsetTableAtom(const File &f) : GlobalOffsetTableAtom(f) {}
-
- StringRef customSectionName() const override { return ".got"; }
-};
-
-template <typename ELFT> class MipsRldAtom : public SimpleELFDefinedAtom {
-public:
- MipsRldAtom(const File &f) : SimpleELFDefinedAtom(f) {}
-
- Scope scope() const override { return scopeGlobal; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".rld_map"; }
- ContentType contentType() const override { return typeData; }
- uint64_t size() const override { return rawContent().size(); }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return rawContent().size(); }
- StringRef name() const override { return "__RLD_MAP"; }
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(mipsGot0AtomContent)
- .slice(ELFT::Is64Bits ? 0 : 4);
- }
-};
-
-class RelocationPassFile : public SimpleFile {
-public:
- RelocationPassFile(const ELFLinkingContext &ctx)
- : SimpleFile("RelocationPassFile", kindELFObject) {
- setOrdinal(ctx.getNextOrdinalAndIncrement());
- }
-
- llvm::BumpPtrAllocator _alloc;
-};
-
-template <typename ELFT> class RelocationPass : public Pass {
-public:
- RelocationPass(MipsLinkingContext &ctx);
-
- std::error_code perform(SimpleFile &mf) override;
-
-private:
- /// \brief Reference to the linking context.
- const MipsLinkingContext &_ctx;
-
- /// \brief Owner of all the Atoms created by this pass.
- RelocationPassFile _file;
-
- /// \brief Map Atoms and addend to local GOT entries.
- typedef std::pair<const Atom *, int64_t> LocalGotMapKeyT;
- llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalMap;
- llvm::DenseMap<LocalGotMapKeyT, GOTAtom *> _gotLocalPageMap;
-
- /// \brief Map Atoms to global GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotGlobalMap;
-
- /// \brief Map Atoms to TLS GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSMap;
-
- /// \brief Map Atoms to TLS GD GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSGdMap;
-
- /// \brief GOT entry for the R_xxxMIPS_TLS_LDM relocations.
- GOTTLSGdAtom<ELFT> *_gotLDMEntry = nullptr;
-
- /// \brief the list of local GOT atoms.
- std::vector<GOTAtom *> _localGotVector;
-
- /// \brief the list of global GOT atoms.
- std::vector<GOTAtom *> _globalGotVector;
-
- /// \brief the list of TLS GOT atoms.
- std::vector<GOTAtom *> _tlsGotVector;
-
- /// \brief Map Atoms to their GOTPLT entries.
- llvm::DenseMap<const Atom *, GOTPLTAtom *> _gotpltMap;
-
- /// \brief Map Atoms to their PLT entries.
- llvm::DenseMap<const Atom *, PLTAAtom *> _pltRegMap;
- llvm::DenseMap<const Atom *, PLTMicroAtom<ELFT> *> _pltMicroMap;
-
- /// \brief Map Atoms to their Object entries.
- llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
-
- /// \brief Map Atoms to their LA25 entries.
- llvm::DenseMap<const Atom *, LA25Atom *> _la25RegMap;
- llvm::DenseMap<const Atom *, LA25Atom *> _la25MicroMap;
-
- /// \brief Atoms referenced by static relocations.
- llvm::DenseSet<const Atom *> _hasStaticRelocations;
-
- /// \brief Atoms require pointers equality.
- llvm::DenseSet<const Atom *> _requiresPtrEquality;
-
- /// \brief References which are candidates for converting
- /// to the R_MIPS_REL32 relocation.
- std::vector<Reference *> _rel32Candidates;
-
- /// \brief the list of PLT atoms.
- std::vector<PLTAtom *> _pltRegVector;
- std::vector<PLTAtom *> _pltMicroVector;
-
- /// \brief the list of GOTPLT atoms.
- std::vector<GOTPLTAtom *> _gotpltVector;
-
- /// \brief the list of Object entries.
- std::vector<ObjectAtom *> _objectVector;
-
- /// \brief the list of LA25 entries.
- std::vector<LA25Atom *> _la25Vector;
-
- /// \brief Handle a specific reference.
- void handleReference(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
-
- /// \brief Collect information about the reference to use it
- /// later in the handleReference() routine.
- std::error_code collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref);
-
- /// \brief Check that the relocation is valid for the current linking mode.
- std::error_code validateRelocation(const DefinedAtom &atom,
- const Reference &ref) const;
-
- void handlePlain(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
- void handleBranch(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
- void handleGOT(Reference &ref);
-
- const GOTAtom *getLocalGOTEntry(const Reference &ref);
- const GOTAtom *getLocalGOTPageEntry(const Reference &ref);
- const GOTAtom *getGlobalGOTEntry(const Atom *a);
- const GOTAtom *getTLSGOTEntry(const Atom *a, Reference::Addend addend);
- const GOTAtom *getTLSGdGOTEntry(const Atom *a, Reference::Addend addend);
- const GOTAtom *getTLSLdmGOTEntry(const Atom *a);
- const GOTPLTAtom *getGOTPLTEntry(const Atom *a);
- const PLTAtom *getPLTEntry(const Atom *a);
- const PLTAtom *getPLTRegEntry(const Atom *a);
- const PLTAtom *getPLTMicroEntry(const Atom *a);
- const LA25Atom *getLA25RegEntry(const Atom *a);
- const LA25Atom *getLA25MicroEntry(const Atom *a);
- const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a);
-
- PLTAtom *createPLTHeader(bool isMicroMips);
-
- bool isLocal(const Atom *a) const;
- bool isLocalCall(const Atom *a) const;
- bool isDynamic(const Atom *atom) const;
- bool requireLA25Stub(const MipsELFDefinedAtom<ELFT> &atom,
- const Reference &ref) const;
- bool requirePLTEntry(const Atom *a) const;
- bool requireCopy(const Atom *a) const;
- bool mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) const;
- bool hasPLTEntry(const Atom *atom) const;
-
- /// \brief Linked files contain microMIPS code.
- bool isMicroMips();
- /// \brief Linked files contain MIPS R6 code.
- bool isMipsR6();
-};
-
-template <typename ELFT>
-RelocationPass<ELFT>::RelocationPass(MipsLinkingContext &ctx)
- : _ctx(ctx), _file(ctx) {
- _localGotVector.push_back(new (_file._alloc) GOT0Atom<ELFT>(_file));
- _localGotVector.push_back(new (_file._alloc)
- GOTModulePointerAtom<ELFT>(_file));
-}
-
-template <typename ELFT>
-std::error_code RelocationPass<ELFT>::perform(SimpleFile &mf) {
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom) {
- const auto &da = *cast<MipsELFDefinedAtom<ELFT>>(atom);
- if (auto ec = collectReferenceInfo(da, const_cast<Reference &>(*ref)))
- return ec;
- }
-
- // Process all references.
- for (const auto &atom : mf.defined())
- for (const auto &ref : *atom)
- handleReference(*cast<MipsELFDefinedAtom<ELFT>>(atom),
- const_cast<Reference &>(*ref));
-
- // Create R_MIPS_REL32 relocations.
- for (auto *ref : _rel32Candidates) {
- bool forceRel = isLocal(ref->target()) && _ctx.getOutputELFType() == ET_DYN;
- if (!forceRel && (!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());
- }
-
- uint64_t ordinal = 0;
-
- if (_ctx.isDynamic() && _ctx.getOutputELFType() == ET_EXEC) {
- auto rlda = new (_file._alloc) MipsRldAtom<ELFT>(_file);
- rlda->setOrdinal(ordinal++);
- mf.addAtom(*rlda);
- }
-
- if (!_localGotVector.empty() || !_globalGotVector.empty() ||
- !_tlsGotVector.empty()) {
- SimpleDefinedAtom *ga = new (_file._alloc) MipsGlobalOffsetTableAtom(_file);
- ga->setOrdinal(ordinal++);
- mf.addAtom(*ga);
- }
-
- for (auto &got : _localGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- for (auto &got : _globalGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- for (auto &got : _tlsGotVector) {
- got->setOrdinal(ordinal++);
- mf.addAtom(*got);
- }
-
- // Create and emit PLT0 entry.
- PLTAtom *plt0Atom = nullptr;
- if (!_pltRegVector.empty())
- plt0Atom = createPLTHeader(false);
- else if (!_pltMicroVector.empty())
- plt0Atom = createPLTHeader(true);
-
- if (plt0Atom) {
- plt0Atom->setOrdinal(ordinal++);
- mf.addAtom(*plt0Atom);
- }
-
- // Emit regular PLT entries firts.
- for (auto &plt : _pltRegVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
-
- // microMIPS PLT entries come after regular ones.
- for (auto &plt : _pltMicroVector) {
- plt->setOrdinal(ordinal++);
- mf.addAtom(*plt);
- }
-
- // Assign PLT0 to GOTPLT entries.
- assert(_gotpltMap.empty() || plt0Atom);
- for (auto &a: _gotpltMap)
- a.second->setPLT0(plt0Atom);
-
- for (auto &gotplt : _gotpltVector) {
- gotplt->setOrdinal(ordinal++);
- mf.addAtom(*gotplt);
- }
-
- for (auto obj : _objectVector) {
- obj->setOrdinal(ordinal++);
- mf.addAtom(*obj);
- }
-
- for (auto la25 : _la25Vector) {
- la25->setOrdinal(ordinal++);
- mf.addAtom(*la25);
- }
-
- return std::error_code();
-}
-
-static bool isMicroMipsReloc(Reference::KindValue kind) {
- return R_MICROMIPS_26_S1 <= kind && kind <= R_MICROMIPS_PC19_S2;
-}
-
-static bool isHiLo16Reloc(Reference::KindValue kind) {
- return kind == R_MIPS_HI16 || kind == R_MIPS_LO16 || kind == R_MIPS_PCHI16 ||
- kind == R_MIPS_PCLO16 || kind == R_MICROMIPS_HI16 ||
- kind == R_MICROMIPS_LO16 || kind == R_MICROMIPS_HI0_LO16;
-}
-
-static bool isBranchReloc(Reference::KindValue kind) {
- return kind == R_MIPS_26 || kind == R_MICROMIPS_26_S1 ||
- kind == R_MIPS_PC16 || kind == R_MIPS_PC21_S2 ||
- kind == R_MIPS_PC26_S2 || kind == R_MICROMIPS_PC7_S1 ||
- kind == R_MICROMIPS_PC10_S1 || kind == R_MICROMIPS_PC16_S1 ||
- kind == R_MICROMIPS_PC23_S2;
-}
-
-static bool isGotReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT16 || kind == R_MICROMIPS_GOT16;
-}
-
-static bool isAllGotReloc(Reference::KindValue kind) {
- return isGotReloc(kind) || kind == R_MIPS_GOT_HI16 ||
- kind == R_MIPS_GOT_LO16 || kind == R_MICROMIPS_GOT_HI16 ||
- kind == R_MICROMIPS_GOT_LO16;
-}
-
-static bool isCallReloc(Reference::KindValue kind) {
- return kind == R_MIPS_CALL16 || kind == R_MICROMIPS_CALL16;
-}
-
-static bool isAllCallReloc(Reference::KindValue kind) {
- return isCallReloc(kind) || kind == R_MIPS_CALL_HI16 ||
- kind == R_MIPS_CALL_LO16 || kind == R_MICROMIPS_CALL_HI16 ||
- kind == R_MICROMIPS_CALL_LO16;
-}
-
-static bool isGotDispReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT_DISP || kind == R_MICROMIPS_GOT_DISP;
-}
-
-static bool isGotPageReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GOT_PAGE || kind == R_MICROMIPS_GOT_PAGE;
-}
-
-static bool isTlsDtpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_DTPREL_HI16 || kind == R_MIPS_TLS_DTPREL_LO16 ||
- kind == R_MICROMIPS_TLS_DTPREL_HI16 ||
- kind == R_MICROMIPS_TLS_DTPREL_LO16;
-}
-
-static bool isTlsTpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_TPREL_HI16 || kind == R_MIPS_TLS_TPREL_LO16 ||
- kind == R_MICROMIPS_TLS_TPREL_HI16 ||
- kind == R_MICROMIPS_TLS_TPREL_LO16;
-}
-
-static bool isTlsGdReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_GD || kind == R_MICROMIPS_TLS_GD;
-}
-
-static bool isTlsLdmReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_LDM || kind == R_MICROMIPS_TLS_LDM;
-}
-
-static bool isTlsGotTpReloc(Reference::KindValue kind) {
- return kind == R_MIPS_TLS_GOTTPREL || kind == R_MICROMIPS_TLS_GOTTPREL;
-}
-
-static bool isGpRelReloc(Reference::KindValue kind) {
- return kind == R_MIPS_GPREL32 || kind == R_MIPS_GPREL16 ||
- kind == R_MICROMIPS_GPREL16 || kind == R_MICROMIPS_GPREL7_S2 ||
- kind == R_MIPS_LITERAL || kind == R_MICROMIPS_LITERAL;
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!ref.target())
- return;
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return;
-
- assert(ref.kindArch() == Reference::KindArch::Mips);
- Reference::KindValue kind = ref.kindValue();
- if (isHiLo16Reloc(kind) || kind == R_MIPS_32 || kind == R_MIPS_PC32)
- handlePlain(atom, ref);
- else if (isBranchReloc(kind))
- handleBranch(atom, ref);
- else if (isAllGotReloc(kind) || isAllCallReloc(kind) ||
- isGotDispReloc(kind) || isGotPageReloc(kind) || kind == R_MIPS_EH)
- handleGOT(ref);
- else if (isTlsDtpReloc(kind))
- ref.setAddend(ref.addend() - atom.file().getDTPOffset());
- else if (isTlsTpReloc(kind))
- ref.setAddend(ref.addend() - atom.file().getTPOffset());
- else if (isTlsGdReloc(kind))
- ref.setTarget(getTLSGdGOTEntry(ref.target(), ref.addend()));
- else if (isTlsLdmReloc(kind))
- ref.setTarget(getTLSLdmGOTEntry(ref.target()));
- else if (isTlsGotTpReloc(kind))
- ref.setTarget(getTLSGOTEntry(ref.target(), ref.addend()));
- else if (kind == R_MIPS_GPREL32 || (isLocal(ref.target()) && isGpRelReloc(kind)))
- ref.setAddend(ref.addend() + atom.file().getGP0());
- else if (kind == R_MIPS_JALR) {
- if (_ctx.getOutputELFType() != ET_EXEC || !isLocalCall(ref.target()))
- ref.setKindValue(R_MIPS_NONE);
- }
-}
-
-template <typename ELFT>
-static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) {
- if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
- return false;
- switch (refKind) {
- case R_MIPS_NONE:
- case R_MIPS_JALR:
- case R_MICROMIPS_JALR:
- case R_MIPS_GPREL16:
- case R_MIPS_GPREL32:
- case R_MICROMIPS_GPREL16:
- case R_MICROMIPS_GPREL7_S2:
- case R_MIPS_LITERAL:
- case R_MICROMIPS_LITERAL:
- return false;
- default:
- return true;
- }
-}
-
-template <typename ELFT>
-std::error_code
-RelocationPass<ELFT>::collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!ref.target())
- return std::error_code();
- if (ref.kindNamespace() != Reference::KindNamespace::ELF)
- return std::error_code();
-
- auto refKind = ref.kindValue();
- if (refKind == R_MIPS_EH && this->_ctx.mipsPcRelEhRel())
- ref.setKindValue(R_MIPS_PC32);
-
- if (auto ec = validateRelocation(atom, ref))
- return ec;
-
- if (!isConstrainSym(atom, refKind))
- return std::error_code();
-
- if (!mightBeDynamic(atom, refKind))
- _hasStaticRelocations.insert(ref.target());
- else if (refKind == R_MIPS_32 || refKind == R_MIPS_64)
- _rel32Candidates.push_back(&ref);
-
- if (!isBranchReloc(refKind) && !isAllCallReloc(refKind) &&
- refKind != R_MIPS_EH)
- _requiresPtrEquality.insert(ref.target());
-
- return std::error_code();
-}
-
-static std::error_code
-make_reject_for_shared_lib_reloc_error(const ELFLinkingContext &ctx,
- const DefinedAtom &atom,
- const Reference &ref) {
- StringRef kindValStr = "unknown";
- ctx.registry().referenceKindToString(ref.kindNamespace(), ref.kindArch(),
- ref.kindValue(), kindValStr);
-
- return make_dynamic_error_code(Twine(kindValStr) + " (" +
- Twine(ref.kindValue()) +
- ") relocation cannot be used "
- "when making a shared object, recompile " +
- atom.file().path() + " with -fPIC");
-}
-
-static std::error_code
-make_local_call16_reloc_error(const ELFLinkingContext &ctx,
- const DefinedAtom &atom, const Reference &ref) {
- return make_dynamic_error_code("R_MIPS_CALL16 (11) relocation cannot be used "
- "against local symbol " +
- ref.target()->name() + " in file " +
- atom.file().path());
-}
-
-template <typename ELFT>
-std::error_code
-RelocationPass<ELFT>::validateRelocation(const DefinedAtom &atom,
- const Reference &ref) const {
- if (!ref.target())
- return std::error_code();
-
- if (isCallReloc(ref.kindValue()) && isLocal(ref.target()))
- return make_local_call16_reloc_error(this->_ctx, atom, ref);
-
- if (this->_ctx.getOutputELFType() != ET_DYN)
- return std::error_code();
-
- switch (ref.kindValue()) {
- case R_MIPS16_HI16:
- case R_MIPS_HI16:
- case R_MIPS_HIGHER:
- case R_MIPS_HIGHEST:
- case R_MICROMIPS_HI16:
- case R_MICROMIPS_HIGHER:
- case R_MICROMIPS_HIGHEST:
- // For shared object we accepts "high" relocations
- // against the "_gp_disp" symbol only.
- if (ref.target()->name() != "_gp_disp")
- return make_reject_for_shared_lib_reloc_error(this->_ctx, atom, ref);
- break;
- case R_MIPS16_26:
- case R_MIPS_26:
- case R_MICROMIPS_26_S1:
- // These relocations are position dependent
- // and not acceptable in a shared object.
- return make_reject_for_shared_lib_reloc_error(this->_ctx, atom, ref);
- default:
- break;
- }
- return std::error_code();
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isLocal(const Atom *a) const {
- if (auto *da = dyn_cast<DefinedAtom>(a))
- return da->scope() == Atom::scopeTranslationUnit;
- return false;
-}
-
-template <typename ELFT>
-static bool isMipsReadonly(const MipsELFDefinedAtom<ELFT> &atom) {
- auto secFlags = atom.section()->sh_flags;
- auto secType = atom.section()->sh_type;
-
- if ((secFlags & SHF_ALLOC) == 0)
- return false;
- if (secType == SHT_NOBITS)
- return false;
- if ((secFlags & SHF_WRITE) != 0)
- return false;
- return true;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
- Reference::KindValue refKind) const {
- if (isAllGotReloc(refKind) || isAllCallReloc(refKind))
- return true;
-
- if (refKind != R_MIPS_32 && refKind != R_MIPS_64)
- return false;
- if ((atom.section()->sh_flags & SHF_ALLOC) == 0)
- return false;
-
- if (_ctx.getOutputELFType() == ET_DYN)
- return true;
- if (!isMipsReadonly(atom))
- return true;
- if (atom.isPIC())
- return true;
-
- return false;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::hasPLTEntry(const Atom *atom) const {
- return _pltRegMap.count(atom) || _pltMicroMap.count(atom);
-}
-
-template <typename ELFT> bool RelocationPass<ELFT>::isMicroMips() {
- TargetHandler &handler = this->_ctx.getTargetHandler();
- return static_cast<MipsTargetHandler<ELFT> &>(handler)
- .getAbiInfoHandler()
- .isMicroMips();
-}
-
-template <typename ELFT> bool RelocationPass<ELFT>::isMipsR6() {
- TargetHandler &handler = this->_ctx.getTargetHandler();
- return static_cast<MipsTargetHandler<ELFT> &>(handler)
- .getAbiInfoHandler()
- .isMipsR6();
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requirePLTEntry(const Atom *a) const {
- if (!_hasStaticRelocations.count(a))
- return false;
- const auto *sa = dyn_cast<ELFDynamicAtom<ELFT>>(a);
- if (sa && sa->type() != SharedLibraryAtom::Type::Code)
- return false;
- const auto *da = dyn_cast<ELFDefinedAtom<ELFT>>(a);
- if (da && da->contentType() != DefinedAtom::typeCode)
- return false;
- if (isLocalCall(a))
- return false;
- return true;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requireCopy(const Atom *a) const {
- if (!_hasStaticRelocations.count(a))
- return false;
- const auto *sa = dyn_cast<ELFDynamicAtom<ELFT>>(a);
- return sa && sa->type() == SharedLibraryAtom::Type::Data;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isDynamic(const Atom *atom) const {
- const auto *da = dyn_cast<const DefinedAtom>(atom);
- if (da && da->dynamicExport() == DefinedAtom::dynamicExportAlways)
- return true;
- if (isa<SharedLibraryAtom>(atom))
- return true;
- if (_ctx.getOutputELFType() != ET_DYN)
- return false;
- if (da && da->scope() != DefinedAtom::scopeTranslationUnit)
- return true;
- return isa<UndefinedAtom>(atom);
-}
-
-template <typename ELFT>
-static bool isMicroMips(const MipsELFDefinedAtom<ELFT> &atom) {
- return atom.codeModel() == DefinedAtom::codeMipsMicro ||
- atom.codeModel() == DefinedAtom::codeMipsMicroPIC;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTEntry(const Atom *a) {
- // If file contains microMIPS code try to reuse compressed PLT entry...
- if (isMicroMips()) {
- auto microPLT = _pltMicroMap.find(a);
- if (microPLT != _pltMicroMap.end())
- return microPLT->second;
- }
-
- // ... then try to reuse a regular PLT entry ...
- auto regPLT = _pltRegMap.find(a);
- if (regPLT != _pltRegMap.end())
- return regPLT->second;
-
- // ... and finally prefer to create new compressed PLT entry.
- return isMicroMips() ? getPLTMicroEntry(a) : getPLTRegEntry(a);
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handlePlain(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- if (!isDynamic(ref.target()))
- return;
-
- if (requirePLTEntry(ref.target()))
- ref.setTarget(getPLTEntry(ref.target()));
- else if (requireCopy(ref.target()))
- ref.setTarget(getObjectEntry(cast<SharedLibraryAtom>(ref.target())));
-}
-
-template <typename ELFT>
-void RelocationPass<ELFT>::handleBranch(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- bool isMicro = isMicroMipsReloc(ref.kindValue());
- if (const auto *sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Code)
- ref.setTarget(isMicro ? getPLTMicroEntry(sla) : getPLTRegEntry(sla));
- } else if (requireLA25Stub(atom, ref)) {
- if (isMicro)
- ref.setTarget(getLA25MicroEntry(ref.target()));
- else
- ref.setTarget(getLA25RegEntry(ref.target()));
- }
-
- if (!isLocal(ref.target())) {
- if (ref.kindValue() == R_MICROMIPS_26_S1)
- ref.setKindValue(LLD_R_MICROMIPS_GLOBAL_26_S1);
- else if (ref.kindValue() == R_MIPS_26)
- ref.setKindValue(LLD_R_MIPS_GLOBAL_26);
- }
-}
-
-template <typename ELFT> void RelocationPass<ELFT>::handleGOT(Reference &ref) {
- if (!isLocalCall(ref.target()))
- ref.setTarget(getGlobalGOTEntry(ref.target()));
- else if (isGotPageReloc(ref.kindValue()))
- ref.setTarget(getLocalGOTPageEntry(ref));
- else if (isLocal(ref.target()) &&
- (isCallReloc(ref.kindValue()) || isGotReloc(ref.kindValue())))
- ref.setTarget(getLocalGOTPageEntry(ref));
- else
- ref.setTarget(getLocalGOTEntry(ref));
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
- Atom::Scope scope;
- if (auto *da = dyn_cast<DefinedAtom>(a))
- scope = da->scope();
- else if (auto *aa = dyn_cast<AbsoluteAtom>(a))
- scope = aa->scope();
- else
- return false;
-
- // Local and hidden symbols must be local.
- if (scope == Atom::scopeTranslationUnit || scope == Atom::scopeLinkageUnit)
- return true;
-
- // Calls to external symbols defined in an executable file resolved locally.
- if (_ctx.getOutputELFType() == ET_EXEC)
- return true;
-
- return false;
-}
-
-template <typename ELFT>
-bool RelocationPass<ELFT>::requireLA25Stub(const MipsELFDefinedAtom<ELFT> &atom,
- const Reference &ref) const {
- if (atom.file().isPIC())
- return false;
- if (auto *da = dyn_cast<DefinedAtom>(ref.target()))
- return static_cast<const MipsELFDefinedAtom<ELFT> *>(da)->isPIC();
- return false;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getLocalGOTEntry(const Reference &ref) {
- const Atom *a = ref.target();
- LocalGotMapKeyT key(a, ref.addend());
-
- auto got = _gotLocalMap.find(key);
- if (got != _gotLocalMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotLocalMap[key] = ga;
-
- _localGotVector.push_back(ga);
-
- Reference::KindValue relKind = ELFT::Is64Bits ? R_MIPS_64 : R_MIPS_32;
- ga->addReferenceELF_Mips(relKind, 0, a, 0);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *
-RelocationPass<ELFT>::getLocalGOTPageEntry(const Reference &ref) {
- const Atom *a = ref.target();
- LocalGotMapKeyT key(a, ref.addend());
-
- auto got = _gotLocalPageMap.find(key);
- if (got != _gotLocalPageMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotLocalPageMap[key] = ga;
-
- _localGotVector.push_back(ga);
-
- Reference::KindValue relKind =
- ELFT::Is64Bits ? LLD_R_MIPS_64_HI16 : LLD_R_MIPS_32_HI16;
- ga->addReferenceELF_Mips(relKind, 0, a, ref.addend());
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getGlobalGOTEntry(const Atom *a) {
- auto got = _gotGlobalMap.find(a);
- if (got != _gotGlobalMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotGlobalMap[a] = ga;
-
- _globalGotVector.push_back(ga);
- ga->addReferenceELF_Mips(LLD_R_MIPS_GLOBAL_GOT, 0, a, 0);
-
- if (const DefinedAtom *da = dyn_cast<DefinedAtom>(a))
- ga->addReferenceELF_Mips(R_MIPS_32, 0, da, 0);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSGOTEntry(const Atom *a,
- Reference::Addend addend) {
- auto got = _gotTLSMap.find(a);
- if (got != _gotTLSMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOT0Atom<ELFT>(_file);
- _gotTLSMap[a] = ga;
-
- _tlsGotVector.push_back(ga);
- Reference::KindValue relKind =
- ELFT::Is64Bits ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32;
- ga->addReferenceELF_Mips(relKind, 0, a, addend);
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *
-RelocationPass<ELFT>::getTLSGdGOTEntry(const Atom *a,
- Reference::Addend addend) {
- auto got = _gotTLSGdMap.find(a);
- if (got != _gotTLSGdMap.end())
- return got->second;
-
- auto ga = new (_file._alloc) GOTTLSGdAtom<ELFT>(_file);
- _gotTLSGdMap[a] = ga;
-
- _tlsGotVector.push_back(ga);
- if (ELFT::Is64Bits) {
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD64, 0, a, addend);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL64, 8, a, addend);
- } else {
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD32, 0, a, addend);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL32, 4, a, addend);
- }
-
- return ga;
-}
-
-template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSLdmGOTEntry(const Atom *a) {
- if (_gotLDMEntry)
- return _gotLDMEntry;
-
- _gotLDMEntry = new (_file._alloc) GOTTLSGdAtom<ELFT>(_file);
- _tlsGotVector.push_back(_gotLDMEntry);
- if (ELFT::Is64Bits)
- _gotLDMEntry->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD64, 0, _gotLDMEntry, 0);
- else
- _gotLDMEntry->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD32, 0, _gotLDMEntry, 0);
-
- return _gotLDMEntry;
-}
-
-template <typename ELFT>
-PLTAtom *RelocationPass<ELFT>::createPLTHeader(bool isMicroMips) {
- auto ga1 = new (_file._alloc) GOTPLTAtom(_file);
- _gotpltVector.insert(_gotpltVector.begin(), ga1);
- auto ga0 = new (_file._alloc) GOTPLTAtom(_file);
- _gotpltVector.insert(_gotpltVector.begin(), ga0);
-
- if (isMicroMips)
- return new (_file._alloc) PLT0MicroAtom<ELFT>(ga0, _file);
- if (_ctx.getAbi() == MipsAbi::N32)
- return new (_file._alloc) PLT0N32Atom<ELFT>(ga0, _file);
- return new (_file._alloc) PLT0Atom<ELFT>(ga0, _file);
-}
-
-template <typename ELFT>
-const GOTPLTAtom *RelocationPass<ELFT>::getGOTPLTEntry(const Atom *a) {
- auto it = _gotpltMap.find(a);
- if (it != _gotpltMap.end())
- return it->second;
-
- auto ga = new (_file._alloc) GOTPLTAtom(a, _file);
- _gotpltMap[a] = ga;
- _gotpltVector.push_back(ga);
- return ga;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTRegEntry(const Atom *a) {
- auto plt = _pltRegMap.find(a);
- if (plt != _pltRegMap.end())
- return plt->second;
-
- PLTAAtom *pa = nullptr;
- if (isMipsR6())
- pa = new (_file._alloc) PLTR6Atom<ELFT>(getGOTPLTEntry(a), _file);
- else
- pa = new (_file._alloc) PLTARegAtom<ELFT>(getGOTPLTEntry(a), _file);
- _pltRegMap[a] = pa;
- _pltRegVector.push_back(pa);
-
- // Check that 'a' dynamic symbol table record should point to the PLT.
- if (_hasStaticRelocations.count(a) && _requiresPtrEquality.count(a))
- pa->addReferenceELF_Mips(LLD_R_MIPS_STO_PLT, 0, a, 0);
-
- return pa;
-}
-
-template <typename ELFT>
-const PLTAtom *RelocationPass<ELFT>::getPLTMicroEntry(const Atom *a) {
- auto plt = _pltMicroMap.find(a);
- if (plt != _pltMicroMap.end())
- return plt->second;
-
- auto pa = new (_file._alloc) PLTMicroAtom<ELFT>(getGOTPLTEntry(a), _file);
- _pltMicroMap[a] = pa;
- _pltMicroVector.push_back(pa);
-
- // Check that 'a' dynamic symbol table record should point to the PLT.
- if (_hasStaticRelocations.count(a) && _requiresPtrEquality.count(a))
- pa->addReferenceELF_Mips(LLD_R_MIPS_STO_PLT, 0, a, 0);
-
- return pa;
-}
-
-template <typename ELFT>
-const LA25Atom *RelocationPass<ELFT>::getLA25RegEntry(const Atom *a) {
- auto la25 = _la25RegMap.find(a);
- if (la25 != _la25RegMap.end())
- return la25->second;
-
- auto sa = new (_file._alloc) LA25RegAtom<ELFT>(a, _file);
- _la25RegMap[a] = sa;
- _la25Vector.push_back(sa);
-
- return sa;
-}
-
-template <typename ELFT>
-const LA25Atom *RelocationPass<ELFT>::getLA25MicroEntry(const Atom *a) {
- auto la25 = _la25MicroMap.find(a);
- if (la25 != _la25MicroMap.end())
- return la25->second;
-
- auto sa = new (_file._alloc) LA25MicroAtom<ELFT>(a, _file);
- _la25MicroMap[a] = sa;
- _la25Vector.push_back(sa);
-
- return sa;
-}
-
-template <typename ELFT>
-const ObjectAtom *
-RelocationPass<ELFT>::getObjectEntry(const SharedLibraryAtom *a) {
- auto obj = _objectMap.find(a);
- if (obj != _objectMap.end())
- return obj->second;
-
- auto oa = new (_file._alloc) ObjectAtom(_file);
- oa->addReferenceELF_Mips(R_MIPS_COPY, 0, oa, 0);
- oa->_name = a->name();
- oa->_size = a->size();
-
- _objectMap[a] = oa;
- _objectVector.push_back(oa);
-
- return oa;
-}
-
-} // end anon namespace
-
-static std::unique_ptr<Pass> createPass(MipsLinkingContext &ctx) {
- switch (ctx.getTriple().getArch()) {
- case llvm::Triple::mips:
- return llvm::make_unique<RelocationPass<ELF32BE>>(ctx);
- case llvm::Triple::mipsel:
- return llvm::make_unique<RelocationPass<ELF32LE>>(ctx);
- case llvm::Triple::mips64:
- return llvm::make_unique<RelocationPass<ELF64BE>>(ctx);
- case llvm::Triple::mips64el:
- return llvm::make_unique<RelocationPass<ELF64LE>>(ctx);
- default:
- llvm_unreachable("Unhandled arch");
- }
-}
-
-std::unique_ptr<Pass>
-lld::elf::createMipsRelocationPass(MipsLinkingContext &ctx) {
- switch (ctx.getOutputELFType()) {
- case ET_EXEC:
- case ET_DYN:
- return createPass(ctx);
- case ET_REL:
- return nullptr;
- default:
- llvm_unreachable("Unhandled output file type");
- }
-}
OpenPOWER on IntegriCloud