diff options
author | Michael J. Spencer <bigcheesegs@gmail.com> | 2013-01-29 16:38:03 +0000 |
---|---|---|
committer | Michael J. Spencer <bigcheesegs@gmail.com> | 2013-01-29 16:38:03 +0000 |
commit | 289dcedea5403f8faa670a3c149f991a9e8f9f50 (patch) | |
tree | 64584ebc5841006d6331b61150bb2891fc9ca8cd /lld | |
parent | 978b5a0e02d9f3519e0f7467ea3e2e52f10a0f99 (diff) | |
download | bcm5719-llvm-289dcedea5403f8faa670a3c149f991a9e8f9f50.tar.gz bcm5719-llvm-289dcedea5403f8faa670a3c149f991a9e8f9f50.zip |
[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
Diffstat (limited to 'lld')
-rw-r--r-- | lld/include/lld/ReaderWriter/ELFTargetInfo.h | 7 | ||||
-rw-r--r-- | lld/include/lld/ReaderWriter/Simple.h | 5 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultELFLayout.h | 26 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/ELFSectionChunks.h | 62 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/FileELF.h | 3 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/WriterELF.cpp | 78 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h | 7 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp | 119 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/X86_64Reference.cpp | 2 | ||||
-rw-r--r-- | lld/test/elf/Inputs/ifunc.cpp | 3 | ||||
-rw-r--r-- | lld/test/elf/Inputs/ifunc.cpp.x86-64 | bin | 0 -> 1224 bytes | |||
-rw-r--r-- | lld/test/elf/ifunc.test | 21 |
12 files changed, 296 insertions, 37 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h index 7914083f83c..ee1631be3ac 100644 --- a/lld/include/lld/ReaderWriter/ELFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -18,6 +18,8 @@ #include <memory> namespace lld { +class DefinedAtom; +class Reference; namespace elf { template <typename ELFT> 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<ELFTargetInfo> create(const LinkerOptions &lo); template <typename ELFT> diff --git a/lld/include/lld/ReaderWriter/Simple.h b/lld/include/lld/ReaderWriter/Simple.h index be611d63221..e149f5ea0cb 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<DefinedAtom>(&atom)) { diff --git a/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h b/lld/lib/ReaderWriter/ELF/DefaultELFLayout.h index 1a73aaa0515..eb0418c92a6 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<ELFT> *getRelocationTable() { + // Only create the relocation table if it is needed. + if (!_relocationTable) { + _relocationTable = new (_allocator) + ELFRelocationTable<ELFT>(_targetInfo, ".rela.plt", ORDER_REL); + addSection(_relocationTable); + } + return _relocationTable; + } + private: SectionMapT _sectionMap; MergedSectionMapT _mergedSectionMap; @@ -260,6 +271,7 @@ private: std::vector<MergedSections<ELFT> *> _mergedSections; ELFHeader<ELFT> *_elfHeader; ELFProgramHeader<ELFT> *_programHeader; + ELFRelocationTable<ELFT> *_relocationTable; std::vector<AbsoluteAtomPair> _absoluteAtoms; llvm::BumpPtrAllocator _allocator; const ELFTargetInfo &_targetInfo; @@ -272,6 +284,7 @@ DefaultELFLayout<ELFT>::getSectionOrder(const StringRef name, int32_t contentPermissions) { switch (contentType) { + case DefinedAtom::typeResolver: case DefinedAtom::typeCode: return llvm::StringSwitch<Reference::Kind>(name) .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR) @@ -291,6 +304,11 @@ DefaultELFLayout<ELFT>::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<ELFT>::getSegmentType(Section<ELFT> *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<ELFT>::getSegmentType(Section<ELFT> *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<ELFT>::hasOutputSegment(Section<ELFT> *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<ELFT>::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<AbsoluteAtom>(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 2dea2c6850c..92539381b63 100644 --- a/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/ELFSectionChunks.h @@ -227,9 +227,16 @@ Section<ELFT>::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<ELFT>::flags() { template<class ELFT> int Section<ELFT>::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 <class ELFT> void Section<ELFT>::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<DefinedAtom>(ai._atom); if (definedAtom->contentType() == DefinedAtom::typeZeroFill) continue; @@ -603,11 +619,17 @@ ELFSymbolTable<ELFT>::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<ELFT>::write(ELFWriter *writer, } } +template <class ELFT> class ELFRelocationTable : public Section<ELFT> { +public: + typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela; + + ELFRelocationTable(const ELFTargetInfo &ti, StringRef str, int32_t order) + : Section<ELFT>(ti, str, llvm::ELF::SHT_RELA, DefinedAtom::permR__, order, + Section<ELFT>::K_Default) { + this->setOrder(order); + this->_entSize = sizeof(Elf_Rela); + this->_align2 = llvm::alignOf<Elf_Rela>(); + } + + 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<Elf_Rela *>(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<std::pair<const DefinedAtom &, const Reference &>> _relocs; +}; + } // elf } // lld diff --git a/lld/lib/ReaderWriter/ELF/FileELF.h b/lld/lib/ReaderWriter/ELF/FileELF.h index 0b8168487e1..9eecb703cbd 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<llvm::MemoryBuffer> MB, llvm::error_code &EC) : File(MB->getBufferIdentifier()), _elfTargetInfo(ti) { + static uint32_t lastOrdinal = 0; + _ordinal = lastOrdinal++; + llvm::OwningPtr<llvm::object::Binary> 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 d43ebfba7ea..fa744caf15d 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -156,6 +156,8 @@ void ELFExecutableWriter<ELFT>::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<ELFT>::addFiles(InputFiles &inputFiles) { /// created template<class ELFT> void ELFExecutableWriter<ELFT>::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<ELFT>::AbsoluteAtomIterT start, + typename DefaultELFLayout<ELFT>::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<class ELFT> diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ELFTargetInfo.h index 7d6d97bf199..a7380e80b62 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<int32_t> relocKindFromString(StringRef str) const; virtual ErrorOr<std::string> 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 0841e334ed2..c3d585632e6 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<uint8_t> rawContent() const { + return ArrayRef<uint8_t>(_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<uint8_t> rawContent() const { + return ArrayRef<uint8_t>(_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<const DefinedAtom>(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<Reference *>(ref)->setTarget(pa); + } + } + } + +private: + llvm::DenseMap<const DefinedAtom *, const PLTAtom *> _pltMap; + ELFPassFile _file; +}; +} // end anon namespace + +void elf::X86_64ELFTargetInfo::addPasses(PassManager &pm) const { + pm.add(std::unique_ptr<Pass>(new PLTPass(*this))); +} + #define LLD_CASE(name) .Case(#name, llvm::ELF::name) ErrorOr<int32_t> 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 fde00bd9e5d..c60cc5f2344 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 00000000000..2e520277d36 --- /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 Binary files differnew file mode 100644 index 00000000000..20c812cabd2 --- /dev/null +++ b/lld/test/elf/Inputs/ifunc.cpp.x86-64 diff --git a/lld/test/elf/ifunc.test b/lld/test/elf/ifunc.test index 0e636a49617..43bdc9a12ed 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 |