[lld] r276384 - [ELF/LinkerScript] Support ONLY_IF_{RO, RW} directive.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 21 20:36:24 PDT 2016


Author: davide
Date: Thu Jul 21 22:36:24 2016
New Revision: 276384

URL: http://llvm.org/viewvc/llvm-project?rev=276384&view=rev
Log:
[ELF/LinkerScript] Support ONLY_IF_{RO, RW} directive.

Differential Revision:   https://reviews.llvm.org/D22660

Added:
    lld/trunk/test/ELF/linkerscript-sections-constraint.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=276384&r1=276383&r2=276384&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Jul 21 22:36:24 2016
@@ -262,15 +262,26 @@ std::vector<OutputSectionBase<ELFT> *>
 LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
   typedef const std::unique_ptr<ObjectFile<ELFT>> ObjectFile;
   std::vector<OutputSectionBase<ELFT> *> Result;
+  DenseSet<OutputSectionBase<ELFT> *> Removed;
 
   // Add input section to output section. If there is no output section yet,
   // then create it and add to output section list.
-  auto AddInputSec = [&](InputSectionBase<ELFT> *C, StringRef Name) {
+  auto AddInputSec = [&](InputSectionBase<ELFT> *C, StringRef Name,
+                         ConstraintKind Constraint) {
     OutputSectionBase<ELFT> *Sec;
     bool IsNew;
     std::tie(Sec, IsNew) = Factory.create(C, Name);
     if (IsNew)
       Result.push_back(Sec);
+    if ((!(C->getSectionHdr()->sh_flags & SHF_WRITE)) &&
+        Constraint == ReadWrite) {
+      Removed.insert(Sec);
+      return;
+    }
+    if ((C->getSectionHdr()->sh_flags & SHF_WRITE) && Constraint == ReadOnly) {
+      Removed.insert(Sec);
+      return;
+    }
     Sec->addSection(C);
   };
 
@@ -296,7 +307,7 @@ LinkerScript<ELFT>::createSections(Outpu
             if (OutCmd->Name == "/DISCARD/")
               S->Live = false;
             else
-              AddInputSec(S, OutCmd->Name);
+              AddInputSec(S, OutCmd->Name, OutCmd->Constraint);
           }
         }
       }
@@ -308,11 +319,17 @@ LinkerScript<ELFT>::createSections(Outpu
     for (InputSectionBase<ELFT> *S : F->getSections()) {
       if (!isDiscarded(S)) {
         if (!S->OutSec)
-          AddInputSec(S, getOutputSectionName(S));
+          AddInputSec(S, getOutputSectionName(S), NoConstraint);
       } else
         reportDiscarded(S, F);
     }
 
+  // Remove from the output all the sections which did not met the constraints.
+  Result.erase(std::remove_if(Result.begin(), Result.end(),
+                              [&](OutputSectionBase<ELFT> *Sec) {
+                                return Removed.count(Sec);
+                              }),
+               Result.end());
   return Result;
 }
 
@@ -793,6 +810,12 @@ void ScriptParser::readOutputSectionDesc
   OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec);
   Opt.Commands.emplace_back(Cmd);
   expect(":");
+
+  // Parse constraints.
+  if (skip("ONLY_IF_RO"))
+    Cmd->Constraint = ReadOnly;
+  if (skip("ONLY_IF_RW"))
+    Cmd->Constraint = ReadWrite;
   expect("{");
 
   while (!Error && !skip("}")) {

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=276384&r1=276383&r2=276384&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Jul 21 22:36:24 2016
@@ -53,6 +53,13 @@ struct SymbolAssignment : BaseCommand {
   std::vector<StringRef> Expr;
 };
 
+// Linker scripts allow additional constraints to be put on ouput sections.
+// An output section will only be created if all of its input sections are
+// read-only
+// or all of its input sections are read-write by using the keyword ONLY_IF_RO
+// and ONLY_IF_RW respectively.
+enum ConstraintKind { NoConstraint, ReadOnly, ReadWrite };
+
 struct OutputSectionCommand : BaseCommand {
   OutputSectionCommand(StringRef Name)
       : BaseCommand(OutputSectionKind), Name(Name) {}
@@ -61,6 +68,7 @@ struct OutputSectionCommand : BaseComman
   std::vector<std::unique_ptr<BaseCommand>> Commands;
   std::vector<StringRef> Phdrs;
   std::vector<uint8_t> Filler;
+  ConstraintKind Constraint = NoConstraint;
 };
 
 struct InputSectionDescription : BaseCommand {

Added: lld/trunk/test/ELF/linkerscript-sections-constraint.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-sections-constraint.s?rev=276384&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript-sections-constraint.s (added)
+++ lld/trunk/test/ELF/linkerscript-sections-constraint.s Thu Jul 21 22:36:24 2016
@@ -0,0 +1,35 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "SECTIONS { \
+# RUN:  .writable : ONLY_IF_RW { *(.writable) } \
+# RUN:  .readable : ONLY_IF_RO { *(.readable) }}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | \
+# RUN:   FileCheck -check-prefix=BASE %s
+# BASE: Sections:
+# BASE-NEXT: Idx Name          Size      Address          Type
+# BASE-NEXT:   0               00000000 0000000000000000
+# BASE-NEXT:   1 .writable     00000004 0000000000000190 DATA
+# BASE-NEXT:   2 .readable     00000004 0000000000000194 DATA
+
+# RUN: echo "SECTIONS { \
+# RUN:  .writable : ONLY_IF_RO { *(.writable) } \
+# RUN:  .readable : ONLY_IF_RW { *(.readable) }}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | \
+# RUN:   FileCheck -check-prefix=NOSECTIONS %s
+# NOSECTIONS: Sections:
+# NOSECTIONS-NOT: .writable
+# NOSECTIONS-NOT: .readable
+
+.global _start
+_start:
+  nop
+
+.section .writable, "aw"
+writable:
+ .long 1
+
+.section .readable, "a"
+readable:
+ .long 2




More information about the llvm-commits mailing list