[PATCH] D58892: [ELF] Split RW PT_LOAD on the PT_GNU_RELRO boundary

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 3 22:41:28 PST 2019


MaskRay created this revision.
Herald added subscribers: llvm-commits, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

Old: PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) .data .bss)
New: PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro)) PT_LOAD(.data. .bss)

By having two PT_LOAD segments, we can utilize NOBITS and save bytes for
.bss.rel.ro.

.bss.rel.ro is currently small and only used by copy relocations of
symbols in read-only segments, but it can be used for other purposes in
the future, e.g. if a relro section's statically relocated data is all
zeros, we can move it to .bss.rel.ro.


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D58892

Files:
  ELF/Writer.cpp


Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1945,6 +1945,29 @@
   Load->add(Out::ElfHeader);
   Load->add(Out::ProgramHeaders);
 
+  // PT_GNU_RELRO includes all sections that should be marked as
+  // read-only by dynamic linker after proccessing relocations.
+  // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
+  // an error message if more than one PT_GNU_RELRO PHDR is required.
+  PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
+  bool InRelroPhdr = false;
+  OutputSection *RelroEnd = nullptr;
+  for (OutputSection *Sec : OutputSections) {
+    if (!needsPtLoad(Sec))
+      continue;
+    if (isRelroSection(Sec)) {
+      InRelroPhdr = true;
+      if (!RelroEnd)
+        RelRo->add(Sec);
+      else
+        error("section: " + Sec->Name + " is not contiguous with other relro" +
+              " sections");
+    } else if (InRelroPhdr) {
+      InRelroPhdr = false;
+      RelroEnd = Sec;
+    }
+  }
+
   for (OutputSection *Sec : OutputSections) {
     if (!(Sec->Flags & SHF_ALLOC))
       break;
@@ -1962,7 +1985,8 @@
     if (((Sec->LMAExpr ||
           (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) &&
          Load->LastSec != Out::ProgramHeaders) ||
-        Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {
+        Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags ||
+        Sec == RelroEnd) {
 
       Load = AddHdr(PT_LOAD, NewFlags);
       Flags = NewFlags;
@@ -1983,28 +2007,6 @@
   if (OutputSection *Sec = In.Dynamic->getParent())
     AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec);
 
-  // PT_GNU_RELRO includes all sections that should be marked as
-  // read-only by dynamic linker after proccessing relocations.
-  // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
-  // an error message if more than one PT_GNU_RELRO PHDR is required.
-  PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
-  bool InRelroPhdr = false;
-  bool IsRelroFinished = false;
-  for (OutputSection *Sec : OutputSections) {
-    if (!needsPtLoad(Sec))
-      continue;
-    if (isRelroSection(Sec)) {
-      InRelroPhdr = true;
-      if (!IsRelroFinished)
-        RelRo->add(Sec);
-      else
-        error("section: " + Sec->Name + " is not contiguous with other relro" +
-              " sections");
-    } else if (InRelroPhdr) {
-      InRelroPhdr = false;
-      IsRelroFinished = true;
-    }
-  }
   if (RelRo->FirstSec)
     Ret.push_back(RelRo);
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D58892.189118.patch
Type: text/x-patch
Size: 2573 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190304/883db68d/attachment.bin>


More information about the llvm-commits mailing list