From: Michael J. Spencer Date: Thu, 28 Feb 2013 20:04:32 +0000 (+0000) Subject: [ELF][x86-64] Separate static and dynamic GOT/PLT generation. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a26f71c9edd842cba1f162fe071a771756991eb4;p=platform%2Fupstream%2Fllvm.git [ELF][x86-64] Separate static and dynamic GOT/PLT generation. llvm-svn: 176294 --- diff --git a/lld/include/lld/ReaderWriter/Simple.h b/lld/include/lld/ReaderWriter/Simple.h index e149f5e..9d723ef 100644 --- a/lld/include/lld/ReaderWriter/Simple.h +++ b/lld/include/lld/ReaderWriter/Simple.h @@ -164,9 +164,11 @@ public: _references.push_back(SimpleReference(kind, offset, target, addend)); } + void setOrdinal(uint64_t ord) { _ordinal = ord; } + private: const File &_file; - uint32_t _ordinal; + uint64_t _ordinal; std::vector _references; }; diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index 702131a..814337a 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -184,10 +184,7 @@ public: , _referenceStartIndex(referenceStart) , _referenceEndIndex(referenceEnd) , _referenceList(referenceList) - , _targetAtomHandler(nullptr) { - static uint64_t orderNumber = 0; - _ordinal = ++orderNumber; - } + , _targetAtomHandler(nullptr) {} virtual const ELFFile &file() const { return _owningFile; @@ -480,8 +477,9 @@ public: _referenceEndIndex = _referenceList.size(); } -private: + void setOrdinal(uint64_t ord) { _ordinal = ord; } +private: const ELFFile &_owningFile; StringRef _symbolName; StringRef _sectionName; diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp index 720bd3c..2508160 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -98,7 +98,8 @@ ErrorOr X86_64TargetRelocationHandler::applyRelocation( *reinterpret_cast(location) = result; } break; - case R_X86_64_TLSLD: + } + case R_X86_64_TLSLD: { // Rewrite to move %fs:0 into %rax. Technically we should verify that the // next relocation is a PC32 to __tls_get_addr... static uint8_t instr[] = { 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25, @@ -106,9 +107,25 @@ ErrorOr X86_64TargetRelocationHandler::applyRelocation( std::memcpy(location - 3, instr, sizeof(instr)); break; } + case LLD_R_X86_64_GOTRELINDEX: { + const DefinedAtom *target = cast(ref.target()); + for (const Reference *r : *target) { + if (r->kind() == R_X86_64_JUMP_SLOT) { + uint32_t index; + if (!_targetInfo.getTargetHandler().targetLayout() + .getPLTRelocationTable()->getRelocationIndex(*r, index)) + llvm_unreachable("Relocation doesn't exist"); + reloc32(location, 0, index, 0); + break; + } + } + break; + } // Runtime only relocations. Ignore here. case R_X86_64_RELATIVE: case R_X86_64_IRELATIVE: + case R_X86_64_JUMP_SLOT: + case R_X86_64_GLOB_DAT: break; case lld::Reference::kindLayoutAfter: @@ -142,7 +159,7 @@ public: virtual SectionChoice sectionChoice() const { return sectionCustomRequired; } - virtual StringRef customSectionName() const { return ".got"; } + virtual StringRef customSectionName() const { return ".got.plt"; } virtual ContentType contentType() const { return typeGOT; } diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp index cf2aa04..0ef4a78 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringSwitch.h" using namespace lld; +using namespace lld::elf; namespace { using namespace llvm::ELF; @@ -90,8 +91,7 @@ public: } virtual Alignment alignment() const { - // The alignment should be 4 byte aligned - return Alignment(2); + return Alignment(4); // 16 } #ifndef NDEBUG @@ -105,10 +105,31 @@ public: const uint8_t PLTAtom::_defaultContent[16] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *gotatom(%rip) - 0x68, 0x00, 0x00, 0x00, 0x00, // pushq pltentry + 0x68, 0x00, 0x00, 0x00, 0x00, // pushq reloc-index 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[-1] }; +class PLT0Atom : public PLTAtom { + static const uint8_t _plt0Content[16]; + +public: + PLT0Atom(const File &f) : PLTAtom(f, ".plt") { +#ifndef NDEBUG + _name = ".PLT0"; +#endif + } + + virtual ArrayRef rawContent() const { + return ArrayRef(_plt0Content, 16); + } +}; + +const uint8_t PLT0Atom::_plt0Content[16] = { + 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip) + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip) + 0x90, 0x90, 0x90, 0x90 // nopnopnop +}; + class ELFPassFile : public SimpleFile { public: ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {} @@ -121,16 +142,15 @@ public: template class GOTPLTPass : public Pass { /// \brief Handle a specific reference. void handleReference(const DefinedAtom &atom, const Reference &ref) { - const DefinedAtom *da = dyn_cast_or_null(ref.target()); switch (ref.kind()) { case R_X86_64_PLT32: static_cast(this)->handlePLT32(ref); break; case R_X86_64_PC32: - static_cast(this)->handleIFUNC(ref, da); + static_cast(this)->handlePC32(ref); break; case R_X86_64_GOTTPOFF: // GOT Thread Pointer Offset - static_cast(this)->handleGOTTPOFF(ref, da); + static_cast(this)->handleGOTTPOFF(ref); break; case R_X86_64_GOTPCREL: static_cast(this)->handleGOTPCREL(ref); @@ -165,7 +185,8 @@ protected: /// /// This create a PLT and GOT entry for the IFUNC if one does not exist. The /// GOT entry and a IRELATIVE relocation to the original target resolver. - ErrorOr handleIFUNC(const Reference &ref, const DefinedAtom *target) { + ErrorOr handleIFUNC(const Reference &ref) { + auto target = dyn_cast_or_null(ref.target()); if (target && target->contentType() == DefinedAtom::typeResolver) const_cast(ref).setTarget(getIFUNCPLTEntry(target)); return error_code::success(); @@ -189,7 +210,8 @@ protected: /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to /// the GOT. - void handleGOTTPOFF(const Reference &ref, const DefinedAtom *target) { + void handleGOTTPOFF(const Reference &ref) { + auto target = dyn_cast_or_null(ref.target()); const_cast(ref).setTarget(getGOTTPOFF(target)); const_cast(ref).setKind(R_X86_64_PC32); } @@ -197,7 +219,7 @@ protected: /// \brief Create a GOT entry containing 0. const GOTAtom *getNullGOT() { if (!_null) { - _null = new (_file._alloc) GOTAtom(_file, ".got"); + _null = new (_file._alloc) GOTAtom(_file, ".got.plt"); #ifndef NDEBUG _null->_name = "__got_null"; #endif @@ -231,7 +253,9 @@ protected: } public: - GOTPLTPass(const ELFTargetInfo &ti) : _file(ti), _null(nullptr) {} + GOTPLTPass(const ELFTargetInfo &ti) + : _file(ti), _null(nullptr), _PLT0(nullptr), _got0(nullptr), + _got1(nullptr) {} /// \brief Do the pass. /// @@ -248,23 +272,51 @@ public: handleReference(*atom, *ref); // Add all created atoms to the link. - if (_null) + uint64_t ordinal = 0; + if (_PLT0) { + _PLT0->setOrdinal(ordinal++); + mf.addAtom(*_PLT0); + } + for (const auto &plt : _pltMap) { + plt.second->setOrdinal(ordinal++); + mf.addAtom(*plt.second); + } + if (_null) { + _null->setOrdinal(ordinal++); mf.addAtom(*_null); - for (const auto &got : _gotMap) + } + if (_PLT0) { + _got0->setOrdinal(ordinal++); + _got1->setOrdinal(ordinal++); + mf.addAtom(*_got0); + mf.addAtom(*_got1); + } + for (const auto &got : _gotMap) { + got.second->setOrdinal(ordinal++); mf.addAtom(*got.second); - for (const auto &plt : _pltMap) - mf.addAtom(*plt.second); + } } protected: /// \brief Owner of all the Atoms created by this pass. ELFPassFile _file; + /// \brief Map Atoms to their GOT entries. - llvm::DenseMap _gotMap; + llvm::DenseMap _gotMap; + /// \brief Map Atoms to their PLT entries. - llvm::DenseMap _pltMap; + llvm::DenseMap _pltMap; + /// \brief GOT entry that is always 0. Used for undefined weaks. GOTAtom *_null; + + /// \brief The got and plt entries for .PLT0. This is used to call into the + /// dynamic linker for symbol resolution. + /// @{ + PLT0Atom *_PLT0; + GOTAtom *_got0; + GOTAtom *_got1; + /// @} }; /// This implements the static relocation model. Meaning GOT and PLT entries are @@ -288,23 +340,47 @@ public: // Handle IFUNC. if (const DefinedAtom *da = dyn_cast_or_null(ref.target())) if (da->contentType() == DefinedAtom::typeResolver) - return handleIFUNC(ref, da); + return handleIFUNC(ref); return error_code::success(); } + + ErrorOr handlePC32(const Reference &ref) { return handleIFUNC(ref); } }; class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass { public: DynamicGOTPLTPass(const elf::X86_64TargetInfo &ti) : GOTPLTPass(ti) {} + const PLT0Atom *getPLT0() { + if (_PLT0) + return _PLT0; + // Fill in the null entry. + getNullGOT(); + _PLT0 = new (_file._alloc) PLT0Atom(_file); + _got0 = new (_file._alloc) GOTAtom(_file, ".got.plt"); + _got1 = new (_file._alloc) GOTAtom(_file, ".got.plt"); + _PLT0->addReference(R_X86_64_PC32, 2, _got0, -4); + _PLT0->addReference(R_X86_64_PC32, 8, _got1, -4); +#ifndef NDEBUG + _got0->_name = "__got0"; + _got1->_name = "__got1"; +#endif + return _PLT0; + } + const PLTAtom *getPLTEntry(const Atom *a) { auto plt = _pltMap.find(a); if (plt != _pltMap.end()) return plt->second; auto ga = new (_file._alloc) GOTAtom(_file, ".got.plt"); - ga->addReference(R_X86_64_RELATIVE, 0, a, 0); + ga->addReference(R_X86_64_JUMP_SLOT, 0, a, 0); auto pa = new (_file._alloc) PLTAtom(_file, ".plt"); pa->addReference(R_X86_64_PC32, 2, ga, -4); + pa->addReference(LLD_R_X86_64_GOTRELINDEX, 7, ga, 0); + pa->addReference(R_X86_64_PC32, 12, getPLT0(), -4); + // Set the starting address of the got entry to the second instruction in + // the plt entry. + ga->addReference(R_X86_64_64, 0, pa, 6); #ifndef NDEBUG ga->_name = "__got_"; ga->_name += a->name(); @@ -322,10 +398,16 @@ public: // Handle IFUNC. if (const DefinedAtom *da = dyn_cast_or_null(ref.target())) if (da->contentType() == DefinedAtom::typeResolver) - return handleIFUNC(ref, da); + return handleIFUNC(ref); const_cast(ref).setTarget(getPLTEntry(ref.target())); return error_code::success(); } + + ErrorOr handlePC32(const Reference &ref) { + if (ref.target() && isa(ref.target())) + return handlePLT32(ref); + return handleIFUNC(ref); + } }; } // end anon namespace @@ -335,6 +417,7 @@ void elf::X86_64TargetInfo::addPasses(PassManager &pm) const { else if (_options._outputKind == OutputKind::DynamicExecutable || _options._outputKind == OutputKind::Shared) pm.add(std::unique_ptr(new DynamicGOTPLTPass(*this))); + ELFTargetInfo::addPasses(pm); } #define LLD_CASE(name) .Case(#name, llvm::ELF::name) @@ -380,6 +463,7 @@ ErrorOr elf::X86_64TargetInfo::relocKindFromString( LLD_CASE(R_X86_64_TLSDESC_CALL) LLD_CASE(R_X86_64_TLSDESC) LLD_CASE(R_X86_64_IRELATIVE) + .Case("LLD_R_X86_64_GOTRELINDEX", LLD_R_X86_64_GOTRELINDEX) .Default(-1); if (ret == -1) @@ -432,6 +516,8 @@ ErrorOr elf::X86_64TargetInfo::stringFromRelocKind( LLD_CASE(R_X86_64_TLSDESC_CALL) LLD_CASE(R_X86_64_TLSDESC) LLD_CASE(R_X86_64_IRELATIVE) + case LLD_R_X86_64_GOTRELINDEX: + return std::string("LLD_R_X86_64_GOTRELINDEX"); } return make_error_code(yaml_reader_error::illegal_value); diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h index 146bd25..11adab4 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h @@ -20,6 +20,12 @@ namespace lld { namespace elf { +/// \brief x86-64 internal references. +enum { + /// \brief The 32 bit index of the relocation in the got this reference refers + /// to. + LLD_R_X86_64_GOTRELINDEX = 1024, +}; class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo { public: @@ -38,9 +44,26 @@ public: return _options._baseAddress; } - virtual bool isRuntimeRelocation(const DefinedAtom &, + virtual bool isDynamicRelocation(const DefinedAtom &, const Reference &r) const { - return r.kind() == llvm::ELF::R_X86_64_IRELATIVE; + switch (r.kind()){ + case llvm::ELF::R_X86_64_RELATIVE: + case llvm::ELF::R_X86_64_GLOB_DAT: + return true; + default: + return false; + } + } + + virtual bool isPLTRelocation(const DefinedAtom &, + const Reference &r) const { + switch (r.kind()){ + case llvm::ELF::R_X86_64_JUMP_SLOT: + case llvm::ELF::R_X86_64_IRELATIVE: + return true; + default: + return false; + } } virtual ErrorOr relocKindFromString(StringRef str) const; diff --git a/lld/test/elf/dynamic-hash.test b/lld/test/elf/dynamic-hash.test deleted file mode 100644 index 094d0bb..0000000 --- a/lld/test/elf/dynamic-hash.test +++ /dev/null @@ -1,7 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ -RUN: -output-type=dynamic -RUN: llvm-readobj %t | FileCheck %s - -CHECK: Sections: -CHECK: .hash {{[0-9a-f]+}} 8 4 required,rodata diff --git a/lld/test/elf/dynamic-interp.test b/lld/test/elf/dynamic-interp.test deleted file mode 100644 index d7b631c..0000000 --- a/lld/test/elf/dynamic-interp.test +++ /dev/null @@ -1,8 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ -RUN: -output-type=dynamic -RUN: llvm-objdump -p %t | FileCheck %s - -CHECK: INTERP -CHECK: flags r-- -CHECK: off diff --git a/lld/test/elf/dynamic-library.test b/lld/test/elf/dynamic-library.test deleted file mode 100644 index d78354c..0000000 --- a/lld/test/elf/dynamic-library.test +++ /dev/null @@ -1,18 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=- -noinhibit-exec \ -RUN: -output-type=dynamic \ -RUN: | FileCheck %s - -CHECK: name: main -CHECK: kind: R_X86_64_PC32 -CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]] - -CHECK: type: got -CHECK: R_X86_64_RELATIVE - -CHECK: name: [[PLTNAME]] -CHECK: type: stub - -CHECK: shared-library-atoms: -CHECK: name: foo -CHECK: load-name: shared.so-x86-64 diff --git a/lld/test/elf/dynamic-phdr.test b/lld/test/elf/dynamic-phdr.test deleted file mode 100644 index 55b81fcc..0000000 --- a/lld/test/elf/dynamic-phdr.test +++ /dev/null @@ -1,7 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ -RUN: -output-type=dynamic -RUN: llvm-objdump -p %t | FileCheck %s - -CHECK: PHDR off 0x{{0+}}40 -CHECK: flags r-- diff --git a/lld/test/elf/dynamic-symbols.test b/lld/test/elf/dynamic-symbols.test deleted file mode 100644 index 1d446ae..0000000 --- a/lld/test/elf/dynamic-symbols.test +++ /dev/null @@ -1,8 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ -RUN: -output-type=dynamic -RUN: llvm-readobj %t | FileCheck %s - -CHECK: Dynamic Symbols: -CHECK: foo FUNC {{[0-9a-f]+}} 0 {{[0-9a-f]+}} undef,global -CHECK: Total: 1 diff --git a/lld/test/elf/dynamic-table.test b/lld/test/elf/dynamic-table.test deleted file mode 100644 index 14965c9..0000000 --- a/lld/test/elf/dynamic-table.test +++ /dev/null @@ -1,15 +0,0 @@ -RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ -RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ -RUN: -output-type=dynamic -RUN: llvm-readobj %t | FileCheck %s - -CHECK: Dynamic section contains 7 entries -CHECK: Tag Type Name/Value -CHECK: 0x0000000000000004 (HASH) -CHECK: 0x0000000000000005 (STRTAB) -CHECK: 0x0000000000000006 (SYMTAB) -CHECK: 0x000000000000000a (STRSZ) -CHECK: 0x000000000000000b (SYMENT) 24 -CHECK: 0x0000000000000001 (NEEDED) Shared library: [shared.so-x86-64] -CHECK: 0x0000000000000000 (NULL) 0x0 -CHECK: Total: 7 diff --git a/lld/test/elf/dynamic.test b/lld/test/elf/dynamic.test new file mode 100644 index 0000000..548613c --- /dev/null +++ b/lld/test/elf/dynamic.test @@ -0,0 +1,49 @@ +RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ +RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \ +RUN: -output-type=dynamic +RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ +RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=%t2 -noinhibit-exec \ +RUN: -output-type=dynamic +RUN: llvm-objdump -p %t >> %t2 +RUN: llvm-readobj %t >> %t2 +RUN: FileCheck %s < %t2 + +CHECK: type: got +CHECK: R_X86_64_JUMP_SLOT + +CHECK: name: main +CHECK: kind: R_X86_64_PC32 +CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]] + +CHECK: name: [[PLTNAME]] +CHECK: type: stub + +CHECK: shared-library-atoms: +CHECK: name: foo +CHECK: load-name: shared.so-x86-64 + +CHECK: PHDR off 0x{{0+}}40 +CHECK: INTERP +CHECK: flags r-- + +CHECK: Dynamic Symbols: +CHECK: foo FUNC {{[0-9a-f]+}} 0 {{[0-9a-f]+}} undef,global +CHECK: Total: 1 + +CHECK: Sections: +CHECK: .hash {{[0-9a-f]+}} 8 4 required,rodata + +CHECK: Dynamic section contains 11 entries +CHECK: Tag Type Name/Value +CHECK: 0x0000000000000004 (HASH) +CHECK: 0x0000000000000005 (STRTAB) +CHECK: 0x0000000000000006 (SYMTAB) +CHECK: 0x000000000000000a (STRSZ) +CHECK: 0x000000000000000b (SYMENT) 24 +CHECK: 0x0000000000000002 (PLTRELSZ) 24 +CHECK: 0x0000000000000003 (PLTGOT) +CHECK: 0x0000000000000014 (PLTREL) RELA +CHECK: 0x0000000000000017 (JMPREL) +CHECK: 0x0000000000000001 (NEEDED) Shared library: [shared.so-x86-64] +CHECK: 0x0000000000000000 (NULL) 0x0 +CHECK: Total: 11 diff --git a/lld/test/elf/gotpcrel.test b/lld/test/elf/gotpcrel.test index 01a5280..42300ba 100644 --- a/lld/test/elf/gotpcrel.test +++ b/lld/test/elf/gotpcrel.test @@ -2,16 +2,16 @@ RUN: lld -core -target x86_64-linux -output=- -entry=main -output-type=static \ RUN: %p/Inputs/gotpcrel.x86-64 -emit-yaml -noinhibit-exec \ RUN: | FileCheck %s -check-prefix=YAML -YAML: name: main -YAML: kind: R_X86_64_PC32 -YAML: target: [[NULLGOT:[a-zA-Z0-9_]+]] -YAML: kind: R_X86_64_PC32 -YAML: target: [[MAINGOT:[a-zA-Z0-9_]+]] - -YAML: name: [[NULLGOT]] +YAML: name: [[NULLGOT:[a-zA-Z0-9_]+]] YAML: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] YAML-NOT: references: -YAML: name: [[MAINGOT]] +YAML: name: [[MAINGOT:[a-zA-Z0-9_]+]] YAML: kind: R_X86_64_64 YAML: target: main + +YAML: name: main +YAML: kind: R_X86_64_PC32 +YAML: target: [[NULLGOT]] +YAML: kind: R_X86_64_PC32 +YAML: target: [[MAINGOT]] diff --git a/lld/test/elf/ifunc.test b/lld/test/elf/ifunc.test index 25dde578..a1c55f2 100644 --- a/lld/test/elf/ifunc.test +++ b/lld/test/elf/ifunc.test @@ -9,9 +9,10 @@ RUN: lld -core -target x86_64-linux -output=%t %p/Inputs/ifunc.x86-64 \ RUN: -entry=main -output-type=static %p/Inputs/ifunc.cpp.x86-64 \ RUN: && llvm-objdump -d -s %t| FileCheck %s --check-prefix=BIN -CHECK: name: hey -CHECK: scope: global -CHECK: type: resolver +// Make sure there's a got entry with a IRELATIVE relocation. +PLT: type: got +PLT: kind: R_X86_64_IRELATIVE +PLT: target: hey PLT: name: plt PLT: scope: global @@ -24,9 +25,9 @@ PLT: references PLT: kind: R_X86_64_PC32 PLT: target: [[PLTNAME]] -// Make sure there's a got entry with a IRELATIVE relocation. -PLT: type: got -PLT: kind: R_X86_64_IRELATIVE +CHECK: name: hey +CHECK: scope: global +CHECK: type: resolver // Make sure the target of main's relocation is a stub with a PC32 relocation. // This relocation is to the got atom, but you can't really write that check in @@ -36,8 +37,6 @@ PLT: type: stub PLT: references PLT: kind: R_X86_64_PC32 -// This is a horribly brittle test. We need a way to do arithmetic on captured -// variables. -BIN: 4000ec: ff 25 0e 0f 00 00 jmpq *3854(%rip) +BIN: {{[0-9a-f]+}}: ff 25 {{[0-9a-f]+}} {{[0-9a-f]+}} 00 00 jmpq *{{[0-9]+}}(%rip) BIN: .got.plt: -BIN-NEXT: 401000 00000000 00000000 +BIN-NEXT: {{[0-9a-f]+}} 00000000 00000000 diff --git a/lld/test/elf/tls.test b/lld/test/elf/tls.test index 1620883..c3efdca 100644 --- a/lld/test/elf/tls.test +++ b/lld/test/elf/tls.test @@ -8,6 +8,10 @@ RUN: | FileCheck %s // Verify that the TLS accesses have the correct offsets. +YAML: type: got +YAML: kind: R_X86_64_TPOFF64 +YAML: target: tls2 + YAML: name: main YAML: kind: R_X86_64_TPOFF32 YAML: offset: 9 @@ -23,11 +27,6 @@ YAML: name: GOTTPOFF YAML: kind: R_X86_64_PC32 YAML: target: [[GOTNAME:[a-zA-Z0-9_]+]] -YAML: name: [[GOTNAME]] -YAML: type: got -YAML: kind: R_X86_64_TPOFF64 -YAML: target: tls2 - // main CHECK: addl %fs:-4 CHECK: addl %fs:-8 diff --git a/lld/test/elf/x86-64-dynamic.test b/lld/test/elf/x86-64-dynamic.test new file mode 100644 index 0000000..591d69e --- /dev/null +++ b/lld/test/elf/x86-64-dynamic.test @@ -0,0 +1,90 @@ +RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \ +RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=- -noinhibit-exec \ +RUN: -output-type=dynamic | FileCheck %s + +// Don't check the GOT and PLT names as they are only present in assert builds. + + - name: __got_null +CHECK: type: got +CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] +CHECK: alignment: 2^3 +CHECK: section-choice: custom-required +CHECK: section-name: .got.plt +CHECK: permissions: rw- + - name: __got0 +CHECK: type: got +CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] +CHECK: alignment: 2^3 +CHECK: section-choice: custom-required +CHECK: section-name: .got.plt +CHECK: permissions: rw- + - name: __got1 +CHECK: type: got +CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] +CHECK: alignment: 2^3 +CHECK: section-choice: custom-required +CHECK: section-name: .got.plt +CHECK: permissions: rw- + - name: __got_foo +CHECK: type: got +CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] +CHECK: alignment: 2^3 +CHECK: section-choice: custom-required +CHECK: section-name: .got.plt +CHECK: permissions: rw- +CHECK: references: +CHECK: - kind: R_X86_64_JUMP_SLOT +CHECK: offset: 0 +CHECK: target: foo +CHECK: - kind: R_X86_64_64 +CHECK: offset: 0 + target: __plt_foo +CHECK: addend: 6 + +CHECK: - name: main +CHECK: scope: global +CHECK: references: +CHECK: - kind: R_X86_64_PC32 +CHECK: offset: 7 + target: __plt_foo +CHECK: addend: -4 + + - name: .PLT0 +CHECK: type: stub +CHECK: content: [ FF, 35, 00, 00, 00, 00, FF, 25, 00, 00, 00, 00, +CHECK: 90, 90, 90, 90 ] +CHECK: alignment: 2^4 +CHECK: section-choice: custom-required +CHECK: section-name: .plt +CHECK: references: +CHECK: - kind: R_X86_64_PC32 +CHECK: offset: 2 + target: __got0 +CHECK: addend: -4 +CHECK: - kind: R_X86_64_PC32 +CHECK: offset: 8 + target: __got1 +CHECK: addend: -4 + - name: __plt_foo +CHECK: type: stub +CHECK: content: [ FF, 25, 00, 00, 00, 00, 68, 00, 00, 00, 00, E9, +CHECK: 00, 00, 00, 00 ] +CHECK: alignment: 2^4 +CHECK: section-choice: custom-required +CHECK: section-name: .plt +CHECK: references: +CHECK: - kind: R_X86_64_PC32 +CHECK: offset: 2 + target: __got_foo +CHECK: addend: -4 +CHECK: - kind: LLD_R_X86_64_GOTRELINDEX +CHECK: offset: 7 + target: __got_foo +CHECK: - kind: R_X86_64_PC32 +CHECK: offset: 12 + target: .PLT0 +CHECK: addend: -4 + +CHECK:shared-library-atoms: +CHECK: - name: foo +CHECK: load-name: shared.so-x86-64