Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -64,6 +64,7 @@ bool ZNodelete = false; bool ZNow = false; bool ZOrigin = false; + bool ZRelro = false; ELFKind EKind = ELFNoneKind; uint16_t EMachine = llvm::ELF::EM_NONE; uint64_t EntryAddr = -1; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -186,6 +186,10 @@ Config->ZNow = true; else if (S == "origin") Config->ZOrigin = true; + else if (S == "relro") + Config->ZRelro = true; + else if (S == "norelro") + Config->ZRelro = false; } for (auto *Arg : Args) { Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -376,6 +376,11 @@ if (AIsNoBits != BIsNoBits) return BIsNoBits; + bool AIsData = A->getName() == ".data"; + bool BIsData = B->getName() == ".data"; + if (AIsData != BIsData) + return BIsData; + // Some architectures have additional ordering restrictions for sections // within the same PT_LOAD. if (Config->EMachine == EM_PPC64) @@ -702,6 +707,7 @@ Elf_Phdr TlsPhdr{}; uintX_t ThreadBSSOffset = 0; + Elf_Phdr GnuRelroPhdr = {}; // Create phdrs as we assign VAs and file offsets to all output sections. for (OutputSectionBase *Sec : OutputSections) { if (needsPhdr(Sec)) { @@ -730,6 +736,20 @@ } TlsPhdr.p_align = std::max(TlsPhdr.p_align, Sec->getAlign()); } else { + if (Config->ZRelro && !GnuRelroPhdr.p_filesz) { + // If section is .data or .bss, we should calculate the current + // gnu relro size and set the header`s properties. + // If not -z now then it is a partial relro and non-PLT GOT is + // read-only but .got.plt will be writeable. + bool CloseGnuRo = (Sec == Out::GotPlt && !Config->ZNow) || + (Sec == Out::Bss) || + (Sec->getName() == ".data"); + if (CloseGnuRo) { + Elf_Phdr *Cur = &Phdrs[PhdrIdx]; + setPhdr(&GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, + Cur->p_vaddr, VA - Cur->p_vaddr, 1); + } + } VA = RoundUpToAlignment(VA, Sec->getAlign()); Sec->setVA(VA); VA += Sec->getSize(); @@ -768,6 +788,11 @@ copyPhdr(Interp, Out::Interp); } + if (GnuRelroPhdr.p_filesz) { + Elf_Phdr *PH = &Phdrs[++PhdrIdx]; + *PH = GnuRelroPhdr; + } + // Add space for section headers. SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4); FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr); @@ -799,6 +824,8 @@ } if (Tls) ++I; + if (Config->ZRelro) + ++I; return I; } Index: test/elf2/mips-got-relocs.s =================================================================== --- test/elf2/mips-got-relocs.s +++ test/elf2/mips-got-relocs.s @@ -45,21 +45,21 @@ .word 0 # EXE_SYM: Sections: -# EXE_SYM: .got 0000000c 0000000000030004 DATA +# EXE_SYM: .got 0000000c 0000000000030000 DATA # EXE_SYM: SYMBOL TABLE: -# EXE_SYM: 00037ff4 *ABS* 00000000 _gp +# EXE_SYM: 00037ff0 *ABS* 00000000 _gp # ^-- .got + GP offset (0x7ff0) -# EXE_SYM: 00030000 g .data 00000004 v1 +# EXE_SYM: 00030010 g .data 00000004 v1 # EXE_GOT_BE: Contents of section .got: -# EXE_GOT_BE: 30004 00000000 80000000 00030000 -# ^ ^ ^-- v1 (0x30000) +# EXE_GOT_BE: 30000 00000000 80000000 00030010 +# ^ ^ ^-- v1 (0x30010) # | +-- Module pointer (0x80000000) # +-- Lazy resolver (0x0) # EXE_GOT_EL: Contents of section .got: -# EXE_GOT_EL: 30004 00000000 00000080 00000300 -# ^ ^ ^-- v1 (0x30000) +# EXE_GOT_EL: 30000 00000000 00000080 10000300 +# ^ ^ ^-- v1 (0x30010) # | +-- Module pointer (0x80000000) # +-- Lazy resolver (0x0) @@ -68,21 +68,21 @@ # EXE_DIS_EL: 20000: 18 80 02 3c lui $2, 32792 # DSO_SYM: Sections: -# DSO_SYM: .got 0000000c 0000000000020034 DATA +# DSO_SYM: .got 0000000c 0000000000020030 DATA # DSO_SYM: SYMBOL TABLE: -# DSO_SYM: 00028024 *ABS* 00000000 _gp +# DSO_SYM: 00028020 *ABS* 00000000 _gp # ^-- .got + GP offset (0x7ff0) -# DSO_SYM: 00020000 g .data 00000004 v1 +# DSO_SYM: 00020040 g .data 00000004 v1 # DSO_GOT_BE: Contents of section .got: -# DSO_GOT_BE: 20034 00000000 80000000 00020000 -# ^ ^ ^-- v1 (0x20000) +# DSO_GOT_BE: 20030 00000000 80000000 00020040 +# ^ ^ ^-- v1 (0x20040) # | +-- Module pointer (0x80000000) # +-- Lazy resolver (0x0) # DSO_GOT_EL: Contents of section .got: -# DSO_GOT_EL: 20034 00000000 00000080 00000200 -# ^ ^ ^-- v1 (0x20000) +# DSO_GOT_EL: 20030 00000000 00000080 40000200 +# ^ ^ ^-- v1 (0x20040) # | +-- Module pointer (0x80000000) # +-- Lazy resolver (0x0) Index: test/elf2/relro.s =================================================================== --- test/elf2/relro.s +++ test/elf2/relro.s @@ -0,0 +1,224 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +// RUN: ld.lld2 -shared %t2.o -o %t2.so +// RUN: ld.lld2 %t.o %t2.so -z now -z relro -o %t +// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=FULLRELRO %s +// RUN: ld.lld2 %t.o %t2.so -z relro -o %t +// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=PARTRELRO %s +// RUN: ld.lld2 %t.o %t2.so -z norelro -o %t +// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=NORELRO %s +// RUN: ld.lld2 %t.o %t2.so -o %t +// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=NORELRO %s +// REQUIRES: x86 + +// FULLRELRO: Section { +// FULLRELRO: Index: 9 +// FULLRELRO-NEXT: Name: .got +// FULLRELRO-NEXT: Type: SHT_PROGBITS +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: SHF_ALLOC +// FULLRELRO-NEXT: SHF_WRITE +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Address: 0x12100 +// FULLRELRO-NEXT: Offset: 0x2100 +// FULLRELRO-NEXT: Size: 8 +// FULLRELRO-NEXT: Link: 0 +// FULLRELRO-NEXT: Info: 0 +// FULLRELRO-NEXT: AddressAlignment: 8 +// FULLRELRO-NEXT: EntrySize: 0 +// FULLRELRO-NEXT: SectionData ( +// FULLRELRO-NEXT: 0000: 00000000 00000000 +// FULLRELRO-NEXT: ) +// FULLRELRO-NEXT: } +// FULLRELRO-NEXT: Section { +// FULLRELRO-NEXT: Index: 10 +// FULLRELRO-NEXT: Name: .got.plt +// FULLRELRO-NEXT: Type: SHT_PROGBITS +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: SHF_ALLOC +// FULLRELRO-NEXT: SHF_WRITE +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Address: 0x12108 +// FULLRELRO-NEXT: Offset: 0x2108 +// FULLRELRO-NEXT: Size: 32 +// FULLRELRO-NEXT: Link: 0 +// FULLRELRO-NEXT: Info: 0 +// FULLRELRO-NEXT: AddressAlignment: 8 +// FULLRELRO-NEXT: EntrySize: 0 +// FULLRELRO-NEXT: SectionData ( +// FULLRELRO-NEXT: 0000: +// FULLRELRO-NEXT: 0010: +// FULLRELRO-NEXT: ) +// FULLRELRO-NEXT: } +// FULLRELRO-NEXT: Section { +// FULLRELRO-NEXT: Index: 11 +// FULLRELRO-NEXT: Name: .data +// FULLRELRO-NEXT: Type: SHT_PROGBITS +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: SHF_ALLOC +// FULLRELRO-NEXT: SHF_WRITE +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Address: 0x12128 +// FULLRELRO-NEXT: Offset: 0x2128 +// FULLRELRO-NEXT: Size: 12 +// FULLRELRO-NEXT: Link: 0 +// FULLRELRO-NEXT: Info: 0 +// FULLRELRO-NEXT: AddressAlignment: +// FULLRELRO-NEXT: EntrySize: 0 +// FULLRELRO-NEXT: SectionData ( +// FULLRELRO-NEXT: 0000: +// FULLRELRO-NEXT: ) +// FULLRELRO-NEXT: } +// FULLRELRO-NEXT: Section { +// FULLRELRO-NEXT: Index: 12 +// FULLRELRO-NEXT: Name: .bss +// FULLRELRO-NEXT: Type: SHT_NOBITS +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: SHF_ALLOC +// FULLRELRO-NEXT: SHF_WRITE +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Address: 0x12134 +// FULLRELRO-NEXT: Offset: 0x2134 +// FULLRELRO-NEXT: Size: 0 +// FULLRELRO-NEXT: Link: 0 +// FULLRELRO-NEXT: Info: 0 +// FULLRELRO-NEXT: AddressAlignment: +// FULLRELRO-NEXT: EntrySize: 0 +// FULLRELRO-NEXT: } +// 308 - sizeof(.data)(12) = 296 +// FULLRELRO: ProgramHeaders [ +// FULLRELRO: Type: PT_LOAD +// FULLRELRO: Offset: 0x2000 +// FULLRELRO-NEXT: VirtualAddress: [[RWADDR:.*]] +// FULLRELRO-NEXT: PhysicalAddress: +// FULLRELRO-NEXT: FileSize: 308 +// FULLRELRO-NEXT: MemSize: 308 +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: PF_R +// FULLRELRO-NEXT: PF_W +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Alignment: 4096 +// FULLRELRO-NEXT:} +// FULLRELRO: Type: PT_GNU_RELRO +// FULLRELRO-NEXT: Offset: 0x2000 +// FULLRELRO-NEXT: VirtualAddress: [[RWADDR]] +// FULLRELRO-NEXT: PhysicalAddress: +// FULLRELRO-NEXT: FileSize: 296 +// FULLRELRO-NEXT: MemSize: 296 +// FULLRELRO-NEXT: Flags [ +// FULLRELRO-NEXT: PF_R +// FULLRELRO-NEXT: ] +// FULLRELRO-NEXT: Alignment: 1 +// FULLRELRO-NEXT:} + +// PARTRELRO: Section { +// PARTRELRO: Index: 9 +// PARTRELRO-NEXT: Name: .got +// PARTRELRO-NEXT: Type: SHT_PROGBITS +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: SHF_ALLOC +// PARTRELRO-NEXT: SHF_WRITE +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Address: 0x120E0 +// PARTRELRO-NEXT: Offset: 0x20E0 +// PARTRELRO-NEXT: Size: 8 +// PARTRELRO-NEXT: Link: 0 +// PARTRELRO-NEXT: Info: 0 +// PARTRELRO-NEXT: AddressAlignment: 8 +// PARTRELRO-NEXT: EntrySize: 0 +// PARTRELRO-NEXT: SectionData ( +// PARTRELRO-NEXT: 0000: +// PARTRELRO-NEXT: ) +// PARTRELRO-NEXT: } +// PARTRELRO-NEXT: Section { +// PARTRELRO-NEXT: Index: 10 +// PARTRELRO-NEXT: Name: .got.plt +// PARTRELRO-NEXT: Type: SHT_PROGBITS +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: SHF_ALLOC +// PARTRELRO-NEXT: SHF_WRITE +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Address: 0x120E8 +// PARTRELRO-NEXT: Offset: 0x20E8 +// PARTRELRO-NEXT: Size: 32 +// PARTRELRO-NEXT: Link: 0 +// PARTRELRO-NEXT: Info: 0 +// PARTRELRO-NEXT: AddressAlignment: 8 +// PARTRELRO-NEXT: EntrySize: 0 +// PARTRELRO-NEXT: SectionData ( +// PARTRELRO-NEXT: 0000: +// PARTRELRO-NEXT: 0010: +// PARTRELRO-NEXT: ) +// PARTRELRO-NEXT: } +// PARTRELRO-NEXT: Section { +// PARTRELRO-NEXT: Index: 11 +// PARTRELRO-NEXT: Name: .data +// PARTRELRO-NEXT: Type: SHT_PROGBITS +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: SHF_ALLOC +// PARTRELRO-NEXT: SHF_WRITE +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Address: 0x12108 +// PARTRELRO-NEXT: Offset: 0x2108 +// PARTRELRO-NEXT: Size: 12 +// PARTRELRO-NEXT: Link: 0 +// PARTRELRO-NEXT: Info: 0 +// PARTRELRO-NEXT: AddressAlignment: 1 +// PARTRELRO-NEXT: EntrySize: 0 +// PARTRELRO-NEXT: SectionData ( +// PARTRELRO-NEXT: 0000: +// PARTRELRO-NEXT: ) +// PARTRELRO-NEXT: } +// PARTRELRO-NEXT: Section { +// PARTRELRO-NEXT: Index: 12 +// PARTRELRO-NEXT: Name: .bss +// PARTRELRO-NEXT: Type: SHT_NOBITS +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: SHF_ALLOC +// PARTRELRO-NEXT: SHF_WRITE +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Address: 0x12114 +// PARTRELRO-NEXT: Offset: 0x2114 +// PARTRELRO-NEXT: Size: 0 +// PARTRELRO-NEXT: Link: 0 +// PARTRELRO-NEXT: Info: 0 +// PARTRELRO-NEXT: AddressAlignment: 1 +// PARTRELRO-NEXT: EntrySize: 0 +// PARTRELRO-NEXT: } +// 232 + sizeof(.got.plt)(32) + sizeof(.data)(12) = 276 +// PARTRELRO: ProgramHeader { +// PARTRELRO: Type: PT_LOAD +// PARTRELRO: Offset: 0x2000 +// PARTRELRO-NEXT: VirtualAddress: [[RWADDR:.*]] +// PARTRELRO-NEXT: PhysicalAddress: +// PARTRELRO-NEXT: FileSize: 276 +// PARTRELRO-NEXT: MemSize: 276 +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: PF_R (0x4) +// PARTRELRO-NEXT: PF_W (0x2) +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Alignment: 4096 +// PARTRELRO: Type: PT_GNU_RELRO +// PARTRELRO-NEXT: Offset: 0x2000 +// PARTRELRO-NEXT: VirtualAddress: [[RWADDR]] +// PARTRELRO-NEXT: PhysicalAddress: +// PARTRELRO-NEXT: FileSize: 232 +// PARTRELRO-NEXT: MemSize: 232 +// PARTRELRO-NEXT: Flags [ +// PARTRELRO-NEXT: PF_R +// PARTRELRO-NEXT: ] +// PARTRELRO-NEXT: Alignment: 1 + +// NORELRO: ProgramHeaders [ +// NORELRO-NOT: PT_GNU_RELRO + +.global _start +_start: + .long bar + jmp *bar@GOTPCREL(%rip) + +.section .data,"aw" +.quad 0 + +.zero 4 +.bss Index: test/elf2/section-name.s =================================================================== --- test/elf2/section-name.s +++ test/elf2/section-name.s @@ -22,9 +22,9 @@ // CHECK: Name: .rodata // CHECK-NOT: Name: .text.a // CHECK: Name: .text -// CHECK-NOT: Name: .data.a -// CHECK: Name: .data // CHECK: Name: .foo.a // CHECK: Name: .foo +// CHECK-NOT: Name: .data.a +// CHECK: Name: .data // CHECK-NOT: Name: .bss.a // CHECK: Name: .bss