Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -273,6 +273,7 @@ bool isRela() const { return IsRela; } bool Static = false; + bool TextRel = false; private: std::vector> Relocs; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -235,6 +235,15 @@ if (!Reloc.UseSymVA && Sym) Sym->MustBeInDynSym = true; Relocs.push_back(Reloc); + + if (this->TextRel) + return; + + // If dynamic relocation targeted somewhere inside readonly section + // then we have to create DF_TEXTREL flag in .dynamic section. + if (Reloc.OKind == DynamicReloc::Off_Sec) + if (!(Reloc.OffsetSec->OutSec->getFlags() & SHF_WRITE)) + this->TextRel = true; } template @@ -603,6 +612,16 @@ DtFlags1 |= DF_1_ORIGIN; } + // This member's absence signifies that no relocation entry should cause a + // modification to a non-writable segment, as specified by the segment + // permissions in the program header table. If this member is present, one or + // more relocation entries might request modifications to a non-writable + // segment, and the dynamic linker can prepare accordingly. + if (Out::RelaDyn->TextRel) { + Add({DT_TEXTREL, (uint64_t)0}); + DtFlags |= DF_TEXTREL; + } + if (DtFlags) Add({DT_FLAGS, DtFlags}); if (DtFlags1) Index: test/ELF/textrel.s =================================================================== --- test/ELF/textrel.s +++ test/ELF/textrel.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld -shared %t.o -o %t.so +# RUN: llvm-readobj -r -dynamic-table %t.so | FileCheck %s + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.dyn { +# CHECK-NEXT: 0x1000 R_X86_64_RELATIVE - 0x1000 +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK: DynamicSection [ +# CHECK: Tag Type Name/Value +# CHECK: 0x0000000000000016 TEXTREL 0x0 +# CHECK-NEXT: 0x000000000000001E FLAGS TEXTREL + +foo: +.quad foo Index: test/ELF/tls-opt-iele-i686-nopic.s =================================================================== --- test/ELF/tls-opt-iele-i686-nopic.s +++ test/ELF/tls-opt-iele-i686-nopic.s @@ -62,8 +62,8 @@ // GOTRELSHARED-NEXT: SHF_ALLOC // GOTRELSHARED-NEXT: SHF_WRITE // GOTRELSHARED-NEXT: ] -// GOTRELSHARED-NEXT: Address: 0x2050 -// GOTRELSHARED-NEXT: Offset: 0x2050 +// GOTRELSHARED-NEXT: Address: 0x2060 +// GOTRELSHARED-NEXT: Offset: 0x2060 // GOTRELSHARED-NEXT: Size: 16 // GOTRELSHARED-NEXT: Link: 0 // GOTRELSHARED-NEXT: Info: 0 @@ -73,41 +73,41 @@ // GOTRELSHARED: Relocations [ // GOTRELSHARED-NEXT: Section ({{.*}}) .rel.dyn { // GOTRELSHARED-NEXT: 0x1002 R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x2050 R_386_TLS_TPOFF tlslocal0 0x0 +// GOTRELSHARED-NEXT: 0x2060 R_386_TLS_TPOFF tlslocal0 0x0 // GOTRELSHARED-NEXT: 0x100A R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x1013 R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x101C R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x2054 R_386_TLS_TPOFF tlslocal1 0x0 +// GOTRELSHARED-NEXT: 0x2064 R_386_TLS_TPOFF tlslocal1 0x0 // GOTRELSHARED-NEXT: 0x1024 R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x102D R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x1036 R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x2058 R_386_TLS_TPOFF tlsshared0 0x0 +// GOTRELSHARED-NEXT: 0x2068 R_386_TLS_TPOFF tlsshared0 0x0 // GOTRELSHARED-NEXT: 0x103F R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x205C R_386_TLS_TPOFF tlsshared1 0x0 +// GOTRELSHARED-NEXT: 0x206C R_386_TLS_TPOFF tlsshared1 0x0 // GOTRELSHARED-NEXT: } // GOTRELSHARED-NEXT: ] // DISASMSHARED: Disassembly of section .text: // DISASMSHARED-NEXT: _start: -// (.got)[0] = 0x2050 = 8272 -// (.got)[1] = 0x2054 = 8276 -// (.got)[2] = 0x2058 = 8280 -// (.got)[3] = 0x205C = 8284 -// DISASMSHARED-NEXT: 1000: 8b 0d 50 20 00 00 movl 8272, %ecx +// (.got)[0] = 0x2060 = 8288 +// (.got)[1] = 0x2064 = 8292 +// (.got)[2] = 0x2068 = 8296 +// (.got)[3] = 0x206C = 8300 +// DISASMSHARED-NEXT: 1000: 8b 0d 60 20 00 00 movl 8288, %ecx // DISASMSHARED-NEXT: 1006: 65 8b 01 movl %gs:(%ecx), %eax -// DISASMSHARED-NEXT: 1009: a1 50 20 00 00 movl 8272, %eax +// DISASMSHARED-NEXT: 1009: a1 60 20 00 00 movl 8288, %eax // DISASMSHARED-NEXT: 100e: 65 8b 00 movl %gs:(%eax), %eax -// DISASMSHARED-NEXT: 1011: 03 0d 50 20 00 00 addl 8272, %ecx +// DISASMSHARED-NEXT: 1011: 03 0d 60 20 00 00 addl 8288, %ecx // DISASMSHARED-NEXT: 1017: 65 8b 01 movl %gs:(%ecx), %eax -// DISASMSHARED-NEXT: 101a: 8b 0d 54 20 00 00 movl 8276, %ecx +// DISASMSHARED-NEXT: 101a: 8b 0d 64 20 00 00 movl 8292, %ecx // DISASMSHARED-NEXT: 1020: 65 8b 01 movl %gs:(%ecx), %eax -// DISASMSHARED-NEXT: 1023: a1 54 20 00 00 movl 8276, %eax +// DISASMSHARED-NEXT: 1023: a1 64 20 00 00 movl 8292, %eax // DISASMSHARED-NEXT: 1028: 65 8b 00 movl %gs:(%eax), %eax -// DISASMSHARED-NEXT: 102b: 03 0d 54 20 00 00 addl 8276, %ecx +// DISASMSHARED-NEXT: 102b: 03 0d 64 20 00 00 addl 8292, %ecx // DISASMSHARED-NEXT: 1031: 65 8b 01 movl %gs:(%ecx), %eax -// DISASMSHARED-NEXT: 1034: 8b 0d 58 20 00 00 movl 8280, %ecx +// DISASMSHARED-NEXT: 1034: 8b 0d 68 20 00 00 movl 8296, %ecx // DISASMSHARED-NEXT: 103a: 65 8b 01 movl %gs:(%ecx), %eax -// DISASMSHARED-NEXT: 103d: 03 0d 5c 20 00 00 addl 8284, %ecx +// DISASMSHARED-NEXT: 103d: 03 0d 6c 20 00 00 addl 8300, %ecx // DISASMSHARED-NEXT: 1043: 65 8b 01 movl %gs:(%ecx), %eax .type tlslocal0,@object