From 289dcedea5403f8faa670a3c149f991a9e8f9f50 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Tue, 29 Jan 2013 16:38:03 +0000 Subject: [PATCH] [ELF] Add support for IFUNC. This sadly doesn't have a test for the final output because llvm-objdump can't dump relocations that don't belong to a section :( llvm-svn: 173808 --- lld/include/lld/ReaderWriter/ELFTargetInfo.h | 7 ++ lld/include/lld/ReaderWriter/Simple.h | 5 +- lld/lib/ReaderWriter/ELF/DefaultELFLayout.h | 26 ++++- lld/lib/ReaderWriter/ELF/ELFSectionChunks.h | 62 +++++++++++ lld/lib/ReaderWriter/ELF/FileELF.h | 3 + lld/lib/ReaderWriter/ELF/WriterELF.cpp | 78 ++++++++------ .../ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h | 7 ++ .../ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp | 119 +++++++++++++++++++++ lld/lib/ReaderWriter/ELF/X86_64Reference.cpp | 2 + lld/test/elf/Inputs/ifunc.cpp | 3 + lld/test/elf/Inputs/ifunc.cpp.x86-64 | Bin 0 -> 1224 bytes lld/test/elf/ifunc.test | 21 ++++ 12 files changed, 296 insertions(+), 37 deletions(-) create mode 100644 lld/test/elf/Inputs/ifunc.cpp create mode 100644 lld/test/elf/Inputs/ifunc.cpp.x86-64 diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h index 7914083..ee1631b 100644 --- a/lld/include/lld/ReaderWriter/ELFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -18,6 +18,8 @@ #include namespace lld { +class DefinedAtom; +class Reference; namespace elf { template class ELFTargetHandler; } @@ -37,6 +39,11 @@ public: virtual StringRef getEntry() const; virtual uint64_t getBaseAddress() const { return _options._baseAddress; } + virtual bool isRuntimeRelocation(const DefinedAtom &, + const Reference &) const { + return false; + } + static std::unique_ptr create(const LinkerOptions &lo); template diff --git a/lld/include/lld/ReaderWriter/Simple.h b/lld/include/lld/ReaderWriter/Simple.h index be611d6..e149f5e 100644 --- a/lld/include/lld/ReaderWriter/Simple.h +++ b/lld/include/lld/ReaderWriter/Simple.h @@ -23,7 +23,10 @@ namespace lld { class SimpleFile : public MutableFile { public: - SimpleFile(const TargetInfo &ti, StringRef path) : MutableFile(ti, path) {} + SimpleFile(const TargetInfo &ti, StringRef path) : MutableFile(ti, path) { + static uint32_t lastOrdinal = 0; + _ordinal = lastOrdinal++; + } virtual void addAtom(const Atom &atom) { if (const DefinedAtom *defAtom = dyn_cast(&atom)) { diff --git a/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h b/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h index 1a73aaa..eb0418c 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h @@ -61,6 +61,7 @@ public: ORDER_TEXT = 70, ORDER_PLT = 80, ORDER_FINI = 90, + ORDER_REL = 95, ORDER_RODATA = 100, ORDER_EH_FRAME = 110, ORDER_EH_FRAMEHDR = 120, @@ -251,6 +252,16 @@ public: return _programHeader; } + ELFRelocationTable *getRelocationTable() { + // Only create the relocation table if it is needed. + if (!_relocationTable) { + _relocationTable = new (_allocator) + ELFRelocationTable(_targetInfo, ".rela.plt", ORDER_REL); + addSection(_relocationTable); + } + return _relocationTable; + } + private: SectionMapT _sectionMap; MergedSectionMapT _mergedSectionMap; @@ -260,6 +271,7 @@ private: std::vector *> _mergedSections; ELFHeader *_elfHeader; ELFProgramHeader *_programHeader; + ELFRelocationTable *_relocationTable; std::vector _absoluteAtoms; llvm::BumpPtrAllocator _allocator; const ELFTargetInfo &_targetInfo; @@ -272,6 +284,7 @@ DefaultELFLayout::getSectionOrder(const StringRef name, int32_t contentPermissions) { switch (contentType) { + case DefinedAtom::typeResolver: case DefinedAtom::typeCode: return llvm::StringSwitch(name) .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR) @@ -291,6 +304,11 @@ DefaultELFLayout::getSectionOrder(const StringRef name, case DefinedAtom::typeZeroFill: return ORDER_BSS; + + case DefinedAtom::typeGOT: + return ORDER_GOT; + case DefinedAtom::typeStub: + return ORDER_PLT; default: // If we get passed in a section push it to OTHER @@ -327,6 +345,7 @@ DefaultELFLayout::getSegmentType(Section *section) const { case ORDER_HASH: case ORDER_DYNAMIC_SYMBOLS: case ORDER_DYNAMIC_STRINGS: + case ORDER_REL: case ORDER_INIT: case ORDER_PLT: case ORDER_FINI: @@ -343,9 +362,9 @@ DefaultELFLayout::getSegmentType(Section *section) const { case ORDER_CTORS: case ORDER_DTORS: - case ORDER_GOT: return llvm::ELF::PT_GNU_RELRO; + case ORDER_GOT: case ORDER_GOT_PLT: case ORDER_DATA: case ORDER_BSS: @@ -366,6 +385,7 @@ DefaultELFLayout::hasOutputSegment(Section *section) { case ORDER_HASH: case ORDER_DYNAMIC_SYMBOLS: case ORDER_DYNAMIC_STRINGS: + case ORDER_REL: case ORDER_INIT: case ORDER_PLT: case ORDER_TEXT: @@ -415,6 +435,10 @@ DefaultELFLayout::addAtom(const Atom *atom) { section = _sectionMap[sectionKey]; } section->appendAtom(atom); + // Add runtime relocations to the .rela section. + for (const auto &reloc : *definedAtom) + if (_targetInfo.isRuntimeRelocation(*definedAtom, *reloc)) + getRelocationTable()->addRelocation(*definedAtom, *reloc); } else if (const AbsoluteAtom *absoluteAtom = dyn_cast(atom)) { // Absolute atoms are not part of any section, they are global for the whole // link diff --git a/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h b/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h index 2dea2c6..9253938 100644 --- a/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h @@ -227,9 +227,16 @@ Section::appendAtom(const Atom *atom) { case DefinedAtom::typeCode: case DefinedAtom::typeData: case DefinedAtom::typeConstant: + case DefinedAtom::typeGOT: + case DefinedAtom::typeStub: + case DefinedAtom::typeResolver: _atoms.push_back(AtomLayout(atom, fOffset, 0)); this->_fsize = fOffset + definedAtom->size(); this->_msize = mOffset + definedAtom->size(); + DEBUG_WITH_TYPE("Section", + llvm::dbgs() << "[" << this->name() << " " << this << "] " + << "Adding atom: " << atom->name() << "@" + << fOffset << "\n"); break; case DefinedAtom::typeZeroFill: _atoms.push_back(AtomLayout(atom, mOffset, 0)); @@ -286,10 +293,16 @@ Section::flags() { template int Section::type() { + if (_sectionKind == K_SymbolTable) + return llvm::ELF::SHT_SYMTAB; + switch (_contentType) { case DefinedAtom::typeCode: case DefinedAtom::typeData: case DefinedAtom::typeConstant: + case DefinedAtom::typeGOT: + case DefinedAtom::typeStub: + case DefinedAtom::typeResolver: return llvm::ELF::SHT_PROGBITS; case DefinedAtom::typeZeroFill: @@ -332,6 +345,9 @@ template void Section::write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { uint8_t *chunkBuffer = buffer.getBufferStart(); for (auto &ai : _atoms) { + DEBUG_WITH_TYPE("Section", + llvm::dbgs() << "Writing atom: " << ai._atom->name() + << " | " << ai._fileOffset << "\n"); const DefinedAtom *definedAtom = cast(ai._atom); if (definedAtom->contentType() == DefinedAtom::typeZeroFill) continue; @@ -603,11 +619,17 @@ ELFSymbolTable::addSymbol(const Atom *atom, lld::DefinedAtom::ContentType ct; switch (ct = da->contentType()){ case DefinedAtom::typeCode: + case DefinedAtom::typeStub: symbol->st_value = addr; type = llvm::ELF::STT_FUNC; break; + case DefinedAtom::typeResolver: + symbol->st_value = addr; + type = llvm::ELF::STT_GNU_IFUNC; + break; case DefinedAtom::typeData: case DefinedAtom::typeConstant: + case DefinedAtom::typeGOT: symbol->st_value = addr; type = llvm::ELF::STT_OBJECT; break; @@ -678,6 +700,46 @@ void ELFSymbolTable::write(ELFWriter *writer, } } +template class ELFRelocationTable : public Section { +public: + typedef llvm::object::Elf_Rel_Impl Elf_Rela; + + ELFRelocationTable(const ELFTargetInfo &ti, StringRef str, int32_t order) + : Section(ti, str, llvm::ELF::SHT_RELA, DefinedAtom::permR__, order, + Section::K_Default) { + this->setOrder(order); + this->_entSize = sizeof(Elf_Rela); + this->_align2 = llvm::alignOf(); + } + + void addRelocation(const DefinedAtom &da, const Reference &r) { + _relocs.emplace_back(da, r); + this->_fsize = _relocs.size() * sizeof(Elf_Rela); + this->_msize = this->_fsize; + } + + void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *dest = chunkBuffer + this->fileOffset(); + for (const auto &rel : _relocs) { + Elf_Rela *r = reinterpret_cast(dest); + r->setSymbolAndType(0, rel.second.kind()); + r->r_offset = + writer->addressOfAtom(&rel.first) + rel.second.offsetInAtom(); + r->r_addend = + writer->addressOfAtom(rel.second.target()) + rel.second.addend(); + dest += sizeof(Elf_Rela); + DEBUG_WITH_TYPE("ELFRelocationTable", llvm::dbgs() + << "IRELATIVE relocation at " << rel.first.name() << "@" + << r->r_offset << " to " << rel.second.target()->name() + << "@" << r->r_addend << "\n"); + } + } + +private: + std::vector> _relocs; +}; + } // elf } // lld diff --git a/lld/lib/ReaderWriter/ELF/FileELF.h b/lld/lib/ReaderWriter/ELF/FileELF.h index 0b81684..9eecb70 100644 --- a/lld/lib/ReaderWriter/ELF/FileELF.h +++ b/lld/lib/ReaderWriter/ELF/FileELF.h @@ -52,6 +52,9 @@ public: FileELF(const ELFTargetInfo &ti, std::unique_ptr MB, llvm::error_code &EC) : File(MB->getBufferIdentifier()), _elfTargetInfo(ti) { + static uint32_t lastOrdinal = 0; + _ordinal = lastOrdinal++; + llvm::OwningPtr binaryFile; EC = createBinary(MB.release(), binaryFile); if (EC) diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index d43ebfb..fa744ca 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -156,6 +156,8 @@ void ELFExecutableWriter::addDefaultAtoms() { _runtimeFile.addAbsoluteAtom("end"); _runtimeFile.addAbsoluteAtom("__init_array_start"); _runtimeFile.addAbsoluteAtom("__init_array_end"); + _runtimeFile.addAbsoluteAtom("__rela_iplt_start"); + _runtimeFile.addAbsoluteAtom("__rela_iplt_end"); } /// \brief Hook in lld to add CRuntime file @@ -169,41 +171,47 @@ void ELFExecutableWriter::addFiles(InputFiles &inputFiles) { /// created template void ELFExecutableWriter::finalizeDefaultAtomValues() { - auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start"); - auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end"); - auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end"); - auto endAtomIter = _layout->findAbsoluteAtom("end"); - auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start"); - auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end"); - - auto section = _layout->findOutputSection(".init_array"); - if (section) { - initArrayStartIter->setValue(section->virtualAddr()); - initArrayEndIter->setValue(section->virtualAddr() + - section->memSize()); - } else { - initArrayStartIter->setValue(0); - initArrayEndIter->setValue(0); - } - - assert(!(bssStartAtomIter == _layout->absoluteAtoms().end() || - bssEndAtomIter == _layout->absoluteAtoms().end() || - underScoreEndAtomIter == _layout->absoluteAtoms().end() || - endAtomIter == _layout->absoluteAtoms().end()) && - "Unable to find the absolute atoms that have been added by lld"); - - auto phe = _programHeader->findProgramHeader( - llvm::ELF::PT_LOAD, - llvm::ELF::PF_W, - llvm::ELF::PF_X); - - assert(!(phe == _programHeader->end()) && - "Can't find a data segment in the program header!"); - - bssStartAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_filesz); - bssEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz); - underScoreEndAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz); - endAtomIter->setValue((*phe)->p_vaddr+(*phe)->p_memsz); + auto bssStartAtomIter = _layout->findAbsoluteAtom("__bss_start"); + auto bssEndAtomIter = _layout->findAbsoluteAtom("__bss_end"); + auto underScoreEndAtomIter = _layout->findAbsoluteAtom("_end"); + auto endAtomIter = _layout->findAbsoluteAtom("end"); + auto initArrayStartIter = _layout->findAbsoluteAtom("__init_array_start"); + auto initArrayEndIter = _layout->findAbsoluteAtom("__init_array_end"); + auto realIpltStartIter = _layout->findAbsoluteAtom("__rela_iplt_start"); + auto realIpltEndIter = _layout->findAbsoluteAtom("__rela_iplt_end"); + + auto startEnd = [&](typename DefaultELFLayout::AbsoluteAtomIterT start, + typename DefaultELFLayout::AbsoluteAtomIterT end, + StringRef sec) -> void { + auto section = _layout->findOutputSection(sec); + if (section) { + start->setValue(section->virtualAddr()); + end->setValue(section->virtualAddr() + section->memSize()); + } else { + start->setValue(0); + end->setValue(0); + } + }; + + startEnd(initArrayStartIter, initArrayEndIter, ".init_array"); + startEnd(realIpltStartIter, realIpltEndIter, ".rela.plt"); + + assert(!(bssStartAtomIter == _layout->absoluteAtoms().end() || + bssEndAtomIter == _layout->absoluteAtoms().end() || + underScoreEndAtomIter == _layout->absoluteAtoms().end() || + endAtomIter == _layout->absoluteAtoms().end()) && + "Unable to find the absolute atoms that have been added by lld"); + + auto phe = _programHeader->findProgramHeader( + llvm::ELF::PT_LOAD, llvm::ELF::PF_W, llvm::ELF::PF_X); + + assert(!(phe == _programHeader->end()) && + "Can't find a data segment in the program header!"); + + bssStartAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_filesz); + bssEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); + underScoreEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); + endAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz); } template diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h index 7d6d97b..a7380e8 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h @@ -30,12 +30,19 @@ public: virtual uint64_t getPageSize() const { return 0x1000; } + virtual void addPasses(PassManager &) const; + virtual uint64_t getBaseAddress() const { if (_options._baseAddress == 0) return 0x400000; return _options._baseAddress; } + virtual bool isRuntimeRelocation(const DefinedAtom &, + const Reference &r) const { + return r.kind() == llvm::ELF::R_X86_64_IRELATIVE; + } + virtual ErrorOr relocKindFromString(StringRef str) const; virtual ErrorOr stringFromRelocKind(int32_t kind) const; diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp index 0841e33..c3d5856 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp @@ -9,10 +9,129 @@ #include "X86_64ELFTargetInfo.h" +#include "lld/Core/File.h" +#include "lld/Core/Pass.h" +#include "lld/Core/PassManager.h" +#include "lld/ReaderWriter/Simple.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringSwitch.h" using namespace lld; +namespace { +class GOTAtom : public SimpleDefinedAtom { + static const uint8_t _defaultContent[8]; + +public: + GOTAtom(const File &f, const DefinedAtom *target) : SimpleDefinedAtom(f) { + if (target->contentType() == typeResolver) { + DEBUG_WITH_TYPE("GOTAtom", llvm::dbgs() << "IRELATIVE relocation to " + << target->name()); + addReference(llvm::ELF::R_X86_64_IRELATIVE, 0, target, 0); + } + } + + virtual StringRef name() const { return "ELF-GOTAtom"; } + + virtual SectionChoice sectionChoice() const { return sectionCustomRequired; } + + virtual StringRef customSectionName() const { return ".got.plt"; } + + virtual ContentType contentType() const { return typeGOT; } + + virtual uint64_t size() const { return rawContent().size(); } + + virtual ContentPermissions permissions() const { return permRW_; } + + virtual ArrayRef rawContent() const { + return ArrayRef(_defaultContent, 8); + } +}; + +const uint8_t GOTAtom::_defaultContent[8] = { 0 }; + +class PLTAtom : public SimpleDefinedAtom { + static const uint8_t _defaultContent[16]; + +public: + PLTAtom(const File &f, GOTAtom *ga) : SimpleDefinedAtom(f) { + addReference(llvm::ELF::R_X86_64_PC32, 2, ga, -4); + } + + virtual StringRef name() const { return "ELF-PLTAtom"; } + + virtual SectionChoice sectionChoice() const { return sectionCustomRequired; } + + virtual StringRef customSectionName() const { return ".plt"; } + + virtual ContentType contentType() const { return typeStub; } + + virtual uint64_t size() const { return rawContent().size(); } + + virtual ContentPermissions permissions() const { return permR_X; } + + virtual ArrayRef rawContent() const { + return ArrayRef(_defaultContent, 16); + } +}; + +const uint8_t PLTAtom::_defaultContent[16] = { + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *gotatom(%rip) + 0x68, 0x00, 0x00, 0x00, 0x00, // pushq pltentry + 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[-1] +}; + +class ELFPassFile : public SimpleFile { +public: + ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {} + + llvm::BumpPtrAllocator _alloc; +}; + +class PLTPass : public Pass { +public: + PLTPass(const ELFTargetInfo &ti) : _file(ti) {} + + virtual void perform(MutableFile &mf) { + for (const auto &atom : mf.defined()) + for (const auto &ref : *atom) { + if (ref->kind() != llvm::ELF::R_X86_64_PC32) + continue; + if (const DefinedAtom *da = + dyn_cast(ref->target())) { + if (da->contentType() != DefinedAtom::typeResolver) + continue; + // We have a PC32 call to a IFUNC. Create a plt and got entry. + // Look it up first. + const PLTAtom *pa; + auto plt = _pltMap.find(da); + if (plt == _pltMap.end()) { + // Add an entry. + auto ga = new (_file._alloc) GOTAtom(_file, da); + mf.addAtom(*ga); + pa = new (_file._alloc) PLTAtom(_file, ga); + mf.addAtom(*pa); + _pltMap[da] = pa; + } else + pa = plt->second; + // This is dirty. + const_cast(ref)->setTarget(pa); + } + } + } + +private: + llvm::DenseMap _pltMap; + ELFPassFile _file; +}; +} // end anon namespace + +void elf::X86_64ELFTargetInfo::addPasses(PassManager &pm) const { + pm.add(std::unique_ptr(new PLTPass(*this))); +} + #define LLD_CASE(name) .Case(#name, llvm::ELF::name) ErrorOr elf::X86_64ELFTargetInfo::relocKindFromString(StringRef str) const { diff --git a/lld/lib/ReaderWriter/ELF/X86_64Reference.cpp b/lld/lib/ReaderWriter/ELF/X86_64Reference.cpp index fde00bd..c60cc5f 100644 --- a/lld/lib/ReaderWriter/ELF/X86_64Reference.cpp +++ b/lld/lib/ReaderWriter/ELF/X86_64Reference.cpp @@ -112,6 +112,8 @@ bool X86_64KindHandler::isLazyTarget(Kind kind) { void X86_64KindHandler::applyFixup(int32_t reloc, uint64_t addend, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress) { + if (reloc == llvm::ELF::R_X86_64_IRELATIVE) + return; if (_fixupHandler[reloc]) _fixupHandler[reloc](location, fixupAddress, targetAddress, addend); else { diff --git a/lld/test/elf/Inputs/ifunc.cpp b/lld/test/elf/Inputs/ifunc.cpp new file mode 100644 index 0000000..2e52027 --- /dev/null +++ b/lld/test/elf/Inputs/ifunc.cpp @@ -0,0 +1,3 @@ +extern "C" int hey(); + +int main() { return hey(); } diff --git a/lld/test/elf/Inputs/ifunc.cpp.x86-64 b/lld/test/elf/Inputs/ifunc.cpp.x86-64 new file mode 100644 index 0000000000000000000000000000000000000000..20c812cabd2c74a8cc016d855494df2c1ef8579f GIT binary patch literal 1224 zcmbtUy-EW?5T4CN6E(^y7NQo~*m+org+wJ9L_~yiieBP{1WgQgD0#x#)N&B*cu-uoy76I z3)hieQ-V_r0&wb=(sOq93(J9YOXqC&Dko*%t$E-Cl|cH^EuyBeRa5&jSGr-&f2`CO z&86QT=gKmwGq6rzM|4stHfeCQ?JzmRwh=_~P4iy!yUh15itR^?CYZG{=s-FD8b67# z)R!rP>YKhx7)V^gNN~#gRfE^(*YqMP=9$R$6f-}%BOR~jw}PB`c8c%Nf^rZ-e>MBx zM2p!wIX`mJH;x=dOyOtNUqddg{w?>f-wCIQowc?_k@`%+S1-zG-5QX^itU8@i<>a< zLptRTw0^w?z<&b3RHUwc7xW&?H=&YM%UAW1Q))Dz=2q)a@mh-3zBF^1Ww#f~g0hBp H5xtLZO~ypM literal 0 HcmV?d00001 diff --git a/lld/test/elf/ifunc.test b/lld/test/elf/ifunc.test index 0e636a4..43bdc9a 100644 --- a/lld/test/elf/ifunc.test +++ b/lld/test/elf/ifunc.test @@ -1,6 +1,27 @@ RUN: lld -core -target x86_64-linux -emit-yaml -output=- %p/Inputs/ifunc.x86-64 \ RUN: | FileCheck %s +RUN: lld -core -target x86_64-linux -emit-yaml -output=- %p/Inputs/ifunc.x86-64 \ +RUN: %p/Inputs/ifunc.cpp.x86-64 | FileCheck %s --check-prefix=PLT CHECK: name: hey CHECK: scope: global CHECK: type: resolver + +// Get the target that main references. +PLT: name: main +PLT: scope: global +PLT: references +PLT: kind: R_X86_64_PC32 +PLT: target: [[PLTNAME:[a-zA-Z0-9-]+]] + +// Make sure there's a got entry with a IRELATIVE relocation. +PLT: type: got +PLT: kind: R_X86_64_IRELATIVE + +// 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 +// FileCheck. +PLT: name: [[PLTNAME]] +PLT: type: stub +PLT: references +PLT: kind: R_X86_64_PC32 -- 2.7.4