diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h index b1753b2ccb85..9362aac71e36 100644 --- a/lld/include/lld/ReaderWriter/ELFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -49,6 +49,10 @@ public: return false; } + virtual StringRef getInterpreter() const { + return "/lib64/ld-linux-x86-64.so.2"; + } + /// \brief Does the output have dynamic sections. bool isDynamic() const { return _options._outputKind == OutputKind::DynamicExecutable || diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h index cda2c6532d54..84bcde9f6319 100644 --- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h @@ -183,7 +183,8 @@ bool ProgramHeader::addSegment(Segment *segment) { for (auto slice : segment->slices()) { // If we have a TLS segment, emit a LOAD first. if (segment->segmentType() == llvm::ELF::PT_TLS || - segment->segmentType() == llvm::ELF::PT_DYNAMIC) { + segment->segmentType() == llvm::ELF::PT_DYNAMIC || + segment->segmentType() == llvm::ELF::PT_INTERP) { auto phdr = allocateProgramHeader(); if (phdr.second) allocatedNew = true; diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index f67e5350a439..c5b80475891a 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -758,6 +758,31 @@ public: private: EntriesT _entries; }; + +template class InterpSection : public Section { +public: + InterpSection(const ELFTargetInfo &ti, StringRef str, int32_t order, + StringRef interp) + : Section(ti, str), + _interp(interp){ + this->setOrder(order); + this->_align2 = 1; + // + 1 for null term. + this->_fsize = interp.size() + 1; + this->_msize = this->_fsize; + this->_type = SHT_PROGBITS; + this->_flags = SHF_ALLOC; + } + + void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) { + uint8_t *chunkBuffer = buffer.getBufferStart(); + uint8_t *dest = chunkBuffer + this->fileOffset(); + std::memcpy(dest, _interp.data(), _interp.size()); + } + +private: + StringRef _interp; +}; } // end namespace elf } // end namespace lld diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp index 411fee31f757..49a876b013d1 100644 --- a/lld/lib/ReaderWriter/ELF/Writer.cpp +++ b/lld/lib/ReaderWriter/ELF/Writer.cpp @@ -69,6 +69,7 @@ private: /// \name Dynamic sections. /// @{ LLD_UNIQUE_BUMP_PTR(DynamicTable) _dynamicTable; + LLD_UNIQUE_BUMP_PTR(InterpSection) _interpSection; /// @} CRuntimeFile _runtimeFile; }; @@ -337,7 +338,11 @@ void ExecutableWriter::createDefaultSections() { if (_targetInfo.isDynamic()) { _dynamicTable.reset(new (_alloc) DynamicTable( _targetInfo, ".dynamic", DefaultLayout::ORDER_DYNAMIC)); + _interpSection.reset(new (_alloc) InterpSection( + _targetInfo, ".interp", DefaultLayout::ORDER_INTERP, + _targetInfo.getInterpreter())); _layout->addSection(_dynamicTable.get()); + _layout->addSection(_interpSection.get()); } // give a chance for the target to add sections diff --git a/lld/test/elf/dynamic-interp.test b/lld/test/elf/dynamic-interp.test new file mode 100644 index 000000000000..d7b631c0f35c --- /dev/null +++ b/lld/test/elf/dynamic-interp.test @@ -0,0 +1,8 @@ +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