Index: lib/ReaderWriter/ELF/SectionChunks.h =================================================================== --- lib/ReaderWriter/ELF/SectionChunks.h +++ lib/ReaderWriter/ELF/SectionChunks.h @@ -911,7 +911,8 @@ RelocationTable(const ELFLinkingContext &context, StringRef str, int32_t order) - : Section(context, str), _symbolTable(nullptr) { + : Section(context, str), _symbolTable(nullptr), + _canModifyReadonlySection(false) { this->setOrder(order); this->_flags = SHF_ALLOC; // Set the alignment properly depending on the target architecture @@ -933,6 +934,8 @@ _relocs.emplace_back(&da, &r); this->_fsize = _relocs.size() * this->_entSize; this->_msize = this->_fsize; + if ((da.permissions() & DefinedAtom::permRW_) != DefinedAtom::permRW_) + _canModifyReadonlySection = true; return _relocs.size() - 1; } @@ -954,6 +957,10 @@ _symbolTable = symbolTable; } + /// \brief There is at least one relocation which can modify + /// a read-only section. + bool canModifyReadonlySection() const { return _canModifyReadonlySection; } + virtual void finalize() { this->_link = _symbolTable ? _symbolTable->ordinal() : 0; if (this->_parent) @@ -978,6 +985,7 @@ private: std::vector > _relocs; const DynamicSymbolTable *_symbolTable; + bool _canModifyReadonlySection; void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, const Reference &ref) { @@ -1080,6 +1088,11 @@ _dt_relasz = addEntry(dyn); dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT; _dt_relaent = addEntry(dyn); + + if (_layout.getDynamicRelocationTable()->canModifyReadonlySection()) { + dyn.d_tag = DT_TEXTREL; + _dt_textrel = addEntry(dyn); + } } if (_layout.hasPLTRelocationTable()) { dyn.d_tag = DT_PLTRELSZ; @@ -1165,6 +1178,7 @@ std::size_t _dt_jmprel; std::size_t _dt_fini_array; std::size_t _dt_fini_arraysz; + std::size_t _dt_textrel; TargetLayout &_layout; DynamicSymbolTable *_dynamicSymbolTable; HashSection *_hashTable; Index: test/elf/Mips/dt-textrel.test =================================================================== --- /dev/null +++ test/elf/Mips/dt-textrel.test @@ -0,0 +1,47 @@ +# Check that if a dynamic relocation modify a read-only section, +# .dynamic section contains the DT_TEXTREL tag. + +# RUN: yaml2obj -format=elf %S/Inputs/pic-obj.yaml > %t-so-obj +# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-so-obj +# RUN: yaml2obj -format=elf %s > %t-obj +# RUN: lld -flavor gnu -target mipsel -e T0 -o %t-exe %t-obj %t-so +# RUN: llvm-readobj -dynamic-table %t-exe | FileCheck %s + +# CHECK: 0x{{[0-9A-F]+}} TEXTREL + +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, + EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x04 + Content: '00000000' + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + Info: .text + AddressAlign: 0x04 + Relocations: + - Offset: 0 + Symbol: T1 + Type: R_MIPS_32 + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + + Global: + - Name: T0 + Type: STT_FUNC + Section: .text + Size: 0x04 + - Name: T1