summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/ReaderWriter/ELFTargetInfo.h4
-rw-r--r--lld/lib/ReaderWriter/ELF/HeaderChunks.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h25
-rw-r--r--lld/lib/ReaderWriter/ELF/Writer.cpp5
-rw-r--r--lld/test/elf/dynamic-interp.test8
5 files changed, 44 insertions, 1 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h
index b1753b2ccb8..9362aac71e3 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 cda2c6532d5..84bcde9f631 100644
--- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -183,7 +183,8 @@ bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *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 f67e5350a43..c5b80475891 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 ELFT> class InterpSection : public Section<ELFT> {
+public:
+ InterpSection(const ELFTargetInfo &ti, StringRef str, int32_t order,
+ StringRef interp)
+ : Section<ELFT>(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 411fee31f75..49a876b013d 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<ELFT>) _dynamicTable;
+ LLD_UNIQUE_BUMP_PTR(InterpSection<ELFT>) _interpSection;
/// @}
CRuntimeFile<ELFT> _runtimeFile;
};
@@ -337,7 +338,11 @@ void ExecutableWriter<ELFT>::createDefaultSections() {
if (_targetInfo.isDynamic()) {
_dynamicTable.reset(new (_alloc) DynamicTable<ELFT>(
_targetInfo, ".dynamic", DefaultLayout<ELFT>::ORDER_DYNAMIC));
+ _interpSection.reset(new (_alloc) InterpSection<ELFT>(
+ _targetInfo, ".interp", DefaultLayout<ELFT>::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 00000000000..d7b631c0f35
--- /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
OpenPOWER on IntegriCloud