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
@@ -45,6 +45,8 @@
   void scanRelocs(const InputSection<ELFT> &C,
                   iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
   void scanRelocs(const InputSection<ELFT> &C);
+  void updateRelRo(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
+                   OutputSectionBase<ELFT> *Sec, uintX_t VA);
   void assignAddresses();
   void openFile(StringRef OutputPath);
   void writeHeader();
@@ -319,6 +321,12 @@
            .Default(1);
 }
 
+template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
+  if (Sec == Out<ELFT>::GotPlt)
+    return Config->ZNow;
+  return (Sec->getName() != ".data" && Sec->getType() != SHT_NOBITS);
+}
+
 // Output section ordering is determined by this function.
 template <class ELFT>
 static bool compareOutputSections(OutputSectionBase<ELFT> *A,
@@ -375,6 +383,11 @@
   if (AIsNoBits != BIsNoBits)
     return BIsNoBits;
 
+  bool AIsRelRo = isRelroSection(A);
+  bool BIsRelRo = isRelroSection(B);
+  if (AIsRelRo != BIsRelRo)
+    return AIsRelRo;
+
   // Some architectures have additional ordering restrictions for sections
   // within the same PT_LOAD.
   if (Config->EMachine == EM_PPC64)
@@ -673,6 +686,23 @@
   return Ret;
 }
 
+template <class ELFT>
+void Writer<ELFT>::updateRelRo(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
+                               OutputSectionBase<ELFT> *Sec, uintX_t VA) {
+
+  if (!Config->ZRelro || !(Cur->p_flags & PF_W))
+    return;
+
+  if (isRelroSection(Sec)) {
+    if (!GnuRelroPhdr->p_type)
+      setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
+              VA - Cur->p_vaddr, 1 /*p_align*/);
+
+    GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
+    GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
+  }
+}
+
 // Visits all sections to create PHDRs and to assign incremental,
 // non-overlapping addresses to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
@@ -699,6 +729,7 @@
   setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
           Target->getPageSize());
 
+  Elf_Phdr GnuRelroPhdr = {};
   Elf_Phdr TlsPhdr{};
   uintX_t ThreadBSSOffset = 0;
   // Create phdrs as we assign VAs and file offsets to all output sections.
@@ -732,6 +763,8 @@
         VA = RoundUpToAlignment(VA, Sec->getAlign());
         Sec->setVA(VA);
         VA += Sec->getSize();
+
+        updateRelRo(&Phdrs[PhdrIdx], &GnuRelroPhdr, Sec, VA);
       }
     }
 
@@ -767,6 +800,11 @@
     copyPhdr(Interp, Out<ELFT>::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);
@@ -798,6 +836,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: 0x
+// 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: .data
+// 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: 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: 11
+// 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: 0x120F8
+// PARTRELRO-NEXT:    Offset: 0x20F8
+// 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: 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: 0x12118
+// PARTRELRO-NEXT:  Offset: 0x2118
+// PARTRELRO-NEXT:  Size: 0
+// PARTRELRO-NEXT:  Link: 0
+// PARTRELRO-NEXT:  Info: 0
+// PARTRELRO-NEXT:  AddressAlignment: 1
+// PARTRELRO-NEXT:  EntrySize: 0
+// PARTRELRO-NEXT:  }
+// 232 + sizeof(.data)(12) + align(4) + sizeof(.got.plt)(32) = 280
+// PARTRELRO:       ProgramHeader {
+// PARTRELRO:       Type: PT_LOAD
+// PARTRELRO:       Offset: 0x2000
+// PARTRELRO-NEXT:  VirtualAddress: [[RWADDR:.*]]
+// PARTRELRO-NEXT:  PhysicalAddress:
+// PARTRELRO-NEXT:  FileSize: 280
+// PARTRELRO-NEXT:  MemSize: 280
+// 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