Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -88,22 +88,6 @@ bool useShlibUndefines() const { return _useShlibUndefines; } /// @} - /// \brief Does this relocation belong in the dynamic relocation table? - /// - /// This table is evaluated at loadtime by the dynamic loader and is - /// referenced by the DT_RELA{,ENT,SZ} entries in the dynamic table. - /// Relocations that return true will be added to the dynamic relocation - /// table. - virtual bool isDynamicRelocation(const Reference &) const { return false; } - - /// \brief Is this a copy relocation? - /// - /// If this is a copy relocation, its target must be an ObjectAtom. We must - /// include in DT_NEEDED the name of the library where this object came from. - virtual bool isCopyRelocation(const Reference &) const { - return false; - } - bool validateImpl(raw_ostream &diagnostics) override; /// \brief Does the linker allow dynamic libraries to be linked with? @@ -119,15 +103,6 @@ /// \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. - /// It will be evaluated at load time if LD_BIND_NOW is set. It is referenced - /// by the DT_{JMPREL,PLTRELSZ} entries in the dynamic table. - /// Relocations that return true will be added to the dynamic plt relocation - /// table. - virtual bool isPLTRelocation(const Reference &) const { return false; } - /// \brief The path to the dynamic interpreter virtual StringRef getDefaultInterpreter() const { return "/lib64/ld-linux-x86-64.so.2"; Index: lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h +++ lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h @@ -34,60 +34,6 @@ return 0x400000; return _baseAddress; } - - bool isDynamicRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::AArch64); - switch (r.kindValue()) { - case llvm::ELF::R_AARCH64_COPY: - case llvm::ELF::R_AARCH64_GLOB_DAT: - case llvm::ELF::R_AARCH64_RELATIVE: - case llvm::ELF::R_AARCH64_TLS_DTPREL64: - case llvm::ELF::R_AARCH64_TLS_DTPMOD64: - case llvm::ELF::R_AARCH64_TLS_TPREL64: - case llvm::ELF::R_AARCH64_TLSDESC: - case llvm::ELF::R_AARCH64_IRELATIVE: - return true; - default: - return false; - } - } - - bool isCopyRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::AArch64); - if (r.kindValue() == llvm::ELF::R_AARCH64_COPY) - return true; - return false; - } - - bool isPLTRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::AArch64); - switch (r.kindValue()) { - case llvm::ELF::R_AARCH64_JUMP_SLOT: - case llvm::ELF::R_AARCH64_IRELATIVE: - return true; - default: - return false; - } - } - - bool isRelativeReloc(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::AArch64); - switch (r.kindValue()) { - case llvm::ELF::R_AARCH64_IRELATIVE: - case llvm::ELF::R_AARCH64_RELATIVE: - return true; - default: - return false; - } - } }; } // end namespace elf } // end namespace lld Index: lib/ReaderWriter/ELF/Atoms.h =================================================================== --- lib/ReaderWriter/ELF/Atoms.h +++ lib/ReaderWriter/ELF/Atoms.h @@ -23,6 +23,12 @@ template class DynamicFile; template class ELFFile; +// Predicates for ELF references. +bool isDynamicRelocation(const Reference &r); +bool isCopyRelocation(const Reference &r); +bool isPLTRelocation(const Reference &r); +bool isRelativeRelocation(const Reference &r); + /// \brief Relocation References: Defined Atoms may contain references that will /// need to be patched before the executable is written. /// Index: lib/ReaderWriter/ELF/Atoms.cpp =================================================================== --- /dev/null +++ lib/ReaderWriter/ELF/Atoms.cpp @@ -0,0 +1,176 @@ +//===- lib/ReaderWriter/ELF/Atoms.cpp -------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Atoms.h" + +namespace lld { +namespace elf { + +// Returns true if a given relocation belongs in the dynamic relocation table. +// +// The relocation table is evaluated at loadtime by the dynamic loader +// and is referenced by the DT_RELA{,ENT,SZ} entries in the dynamic table. +// Relocations that return true will be added to the dynamic relocation +// table. +bool isDynamicRelocation(const Reference &r) { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + switch (r.kindArch()) { + case Reference::KindArch::AArch64: + switch (r.kindValue()) { + case llvm::ELF::R_AARCH64_COPY: + case llvm::ELF::R_AARCH64_GLOB_DAT: + case llvm::ELF::R_AARCH64_RELATIVE: + case llvm::ELF::R_AARCH64_TLS_DTPREL64: + case llvm::ELF::R_AARCH64_TLS_DTPMOD64: + case llvm::ELF::R_AARCH64_TLS_TPREL64: + case llvm::ELF::R_AARCH64_TLSDESC: + case llvm::ELF::R_AARCH64_IRELATIVE: + return true; + } + return false; + case Reference::KindArch::ARM: + return false; + case Reference::KindArch::Hexagon: + switch (r.kindValue()) { + case llvm::ELF::R_HEX_RELATIVE: + case llvm::ELF::R_HEX_GLOB_DAT: + return true; + } + return false; + case Reference::KindArch::Mips: + switch (r.kindValue()) { + case llvm::ELF::R_MIPS_COPY: + case llvm::ELF::R_MIPS_REL32: + case llvm::ELF::R_MIPS_TLS_DTPMOD32: + case llvm::ELF::R_MIPS_TLS_DTPREL32: + case llvm::ELF::R_MIPS_TLS_TPREL32: + return true; + } + return false; + case Reference::KindArch::x86: + return false; + case Reference::KindArch::x86_64: + switch (r.kindValue()) { + case llvm::ELF::R_X86_64_RELATIVE: + case llvm::ELF::R_X86_64_GLOB_DAT: + case llvm::ELF::R_X86_64_COPY: + case llvm::ELF::R_X86_64_DTPMOD64: + case llvm::ELF::R_X86_64_DTPOFF64: + return true; + } + return false; + case Reference::KindArch::all: + llvm_unreachable("internal error"); + } +} + +// Returns true if a given reference is a copy relocation. +// +// If this is a copy relocation, its target must be an ObjectAtom. +// We must include in DT_NEEDED the name of the library where this +// object came from. +bool isCopyRelocation(const Reference &r) { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + switch (r.kindArch()) { + case Reference::KindArch::AArch64: + return r.kindValue() == llvm::ELF::R_AARCH64_COPY; + case Reference::KindArch::ARM: + case Reference::KindArch::Hexagon: + return false; + case Reference::KindArch::Mips: + return r.kindValue() == llvm::ELF::R_MIPS_COPY; + case Reference::KindArch::x86: + return false; + case Reference::KindArch::x86_64: + return r.kindValue() == llvm::ELF::R_X86_64_COPY; + case Reference::KindArch::all: + llvm_unreachable("internal error"); + } +} + +// Returns true if a given reference belongs in the dynamic plt relocation +// table. +// +// This table holds all of the relocations used for delayed symbol binding. +// It will be evaluated at load time if LD_BIND_NOW is set. It is referenced +// by the DT_{JMPREL,PLTRELSZ} entries in the dynamic table. +// Relocations that return true will be added to the dynamic plt relocation +// table. +bool isPLTRelocation(const Reference &r) { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + switch (r.kindArch()) { + case Reference::KindArch::AArch64: + switch (r.kindValue()) { + case llvm::ELF::R_AARCH64_JUMP_SLOT: + case llvm::ELF::R_AARCH64_IRELATIVE: + return true; + } + return false; + case Reference::KindArch::ARM: + return false; + case Reference::KindArch::Hexagon: + return r.kindValue() == llvm::ELF::R_HEX_JMP_SLOT; + case Reference::KindArch::Mips: + return r.kindValue() == llvm::ELF::R_MIPS_JUMP_SLOT; + case Reference::KindArch::x86: + return false; + case Reference::KindArch::x86_64: + switch (r.kindValue()) { + case llvm::ELF::R_X86_64_JUMP_SLOT: + case llvm::ELF::R_X86_64_IRELATIVE: + return true; + } + return false; + case Reference::KindArch::all: + llvm_unreachable("internal error"); + } +} + +// Returns true if a given reference is is a relative relocation. +bool isRelativeRelocation(const Reference &r) { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + switch (r.kindArch()) { + case Reference::KindArch::AArch64: + switch (r.kindValue()) { + case llvm::ELF::R_AARCH64_IRELATIVE: + case llvm::ELF::R_AARCH64_RELATIVE: + return true; + } + return false; + case Reference::KindArch::ARM: + return false; + case Reference::KindArch::Hexagon: + return r.kindValue() == llvm::ELF::R_HEX_RELATIVE; + case Reference::KindArch::Mips: + return false; + case Reference::KindArch::x86: + switch (r.kindValue()) { + case llvm::ELF::R_386_IRELATIVE: + case llvm::ELF::R_386_RELATIVE: + return true; + } + return false; + case Reference::KindArch::x86_64: + switch (r.kindValue()) { + case llvm::ELF::R_X86_64_IRELATIVE: + case llvm::ELF::R_X86_64_RELATIVE: + return true; + } + return false; + case Reference::KindArch::all: + llvm_unreachable("internal error"); + } +} + +} // end namespace elf +} // end namespace lld Index: lib/ReaderWriter/ELF/CMakeLists.txt =================================================================== --- lib/ReaderWriter/ELF/CMakeLists.txt +++ lib/ReaderWriter/ELF/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(lldELF + Atoms.cpp ELFLinkingContext.cpp Reader.cpp Writer.cpp Index: lib/ReaderWriter/ELF/DefaultLayout.h =================================================================== --- lib/ReaderWriter/ELF/DefaultLayout.h +++ lib/ReaderWriter/ELF/DefaultLayout.h @@ -571,10 +571,10 @@ // Add runtime relocations to the .rela section. for (const auto &reloc : *definedAtom) { bool isLocalReloc = true; - if (_context.isDynamicRelocation(*reloc)) { + if (isDynamicRelocation(*reloc)) { getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc); isLocalReloc = false; - } else if (_context.isPLTRelocation(*reloc)) { + } else if (isPLTRelocation(*reloc)) { getPLTRelocationTable()->addRelocation(*definedAtom, *reloc); isLocalReloc = false; } @@ -586,7 +586,7 @@ if (isa(reloc->target()) && isLocalReloc) continue; - if (_context.isCopyRelocation(*reloc)) { + if (isCopyRelocation(*reloc)) { _copiedDynSymNames.insert(definedAtom->name()); continue; } Index: lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h +++ lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h @@ -25,42 +25,6 @@ HexagonLinkingContext(llvm::Triple triple); void addPasses(PassManager &) override; - - bool isDynamicRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - switch (r.kindValue()) { - case llvm::ELF::R_HEX_RELATIVE: - case llvm::ELF::R_HEX_GLOB_DAT: - return true; - default: - return false; - } - } - - bool isPLTRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - switch (r.kindValue()) { - case llvm::ELF::R_HEX_JMP_SLOT: - return true; - default: - return false; - } - } - - /// \brief Hexagon has only one relative relocation - /// a) for supporting relative relocs - R_HEX_RELATIVE - bool isRelativeReloc(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - switch (r.kindValue()) { - case llvm::ELF::R_HEX_RELATIVE: - return true; - default: - return false; - } - } }; } // elf Index: lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h +++ lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h @@ -50,9 +50,6 @@ StringRef getDefaultInterpreter() const override; void addPasses(PassManager &pm) override; bool isRelaOutputFormat() const override { return false; } - bool isDynamicRelocation(const Reference &r) const override; - bool isCopyRelocation(const Reference &r) const override; - bool isPLTRelocation(const Reference &r) const override; private: MipsELFFlagsMerger _flagsMerger; Index: lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp +++ lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp @@ -73,40 +73,3 @@ ELFLinkingContext::addPasses(pm); pm.add(llvm::make_unique()); } - -bool MipsLinkingContext::isDynamicRelocation(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_COPY: - case llvm::ELF::R_MIPS_REL32: - case llvm::ELF::R_MIPS_TLS_DTPMOD32: - case llvm::ELF::R_MIPS_TLS_DTPREL32: - case llvm::ELF::R_MIPS_TLS_TPREL32: - return true; - default: - return false; - } -} - -bool MipsLinkingContext::isCopyRelocation(const Reference &r) const { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::Mips); - if (r.kindValue() == llvm::ELF::R_MIPS_COPY) - return true; - return false; -} - -bool MipsLinkingContext::isPLTRelocation(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; - } -} Index: lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/SectionChunks.h +++ lib/ReaderWriter/ELF/SectionChunks.h @@ -1043,7 +1043,7 @@ 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)) + if (isRelativeRelocation(ref)) r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend(); DEBUG_WITH_TYPE("ELFRelocationTable", llvm::dbgs() << ref.kindValue() << " relocation at " Index: lib/ReaderWriter/ELF/X86/X86LinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/X86/X86LinkingContext.h +++ lib/ReaderWriter/ELF/X86/X86LinkingContext.h @@ -20,22 +20,6 @@ public: static std::unique_ptr create(llvm::Triple); X86LinkingContext(llvm::Triple); - - /// \brief X86 has only two relative relocation - /// a) for supporting IFUNC relocs - R_386_IRELATIVE - /// b) for supporting relative relocs - R_386_RELATIVE - bool isRelativeReloc(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::x86); - switch (r.kindValue()) { - case llvm::ELF::R_386_IRELATIVE: - case llvm::ELF::R_386_RELATIVE: - return true; - default: - return false; - } - } }; } // end namespace elf } // end namespace lld Index: lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h +++ lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h @@ -36,60 +36,6 @@ return 0x400000; return _baseAddress; } - - bool isDynamicRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::x86_64); - switch (r.kindValue()) { - case llvm::ELF::R_X86_64_RELATIVE: - case llvm::ELF::R_X86_64_GLOB_DAT: - case llvm::ELF::R_X86_64_COPY: - case llvm::ELF::R_X86_64_DTPMOD64: - case llvm::ELF::R_X86_64_DTPOFF64: - return true; - default: - return false; - } - } - - bool isCopyRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::x86_64); - if (r.kindValue() == llvm::ELF::R_X86_64_COPY) - return true; - return false; - } - - virtual bool isPLTRelocation(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::x86_64); - switch (r.kindValue()) { - case llvm::ELF::R_X86_64_JUMP_SLOT: - case llvm::ELF::R_X86_64_IRELATIVE: - return true; - default: - return false; - } - } - - /// \brief X86_64 has two relative relocations - /// a) for supporting IFUNC - R_X86_64_IRELATIVE - /// b) for supporting relative relocs - R_X86_64_RELATIVE - bool isRelativeReloc(const Reference &r) const override { - if (r.kindNamespace() != Reference::KindNamespace::ELF) - return false; - assert(r.kindArch() == Reference::KindArch::x86_64); - switch (r.kindValue()) { - case llvm::ELF::R_X86_64_IRELATIVE: - case llvm::ELF::R_X86_64_RELATIVE: - return true; - default: - return false; - } - } }; } // end namespace elf } // end namespace lld