[lld] r327003 - [ELF] - Support "INSERT AFTER" statement.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 8 06:54:38 PST 2018


Author: grimar
Date: Thu Mar  8 06:54:38 2018
New Revision: 327003

URL: http://llvm.org/viewvc/llvm-project?rev=327003&view=rev
Log:
[ELF] - Support "INSERT AFTER" statement.

This implements INSERT AFTER in a following way:

During reading scripts it collects all insert statements.
After we done and read all files it inserts statements into script commands list.

With that:
* Rest of code does know nothing about INSERT.
* Approach is straightforward and have no visible limitations.
* It is also easy to support INSERT BEFORE (was seen in clang code once).
* Should work for PR35877 and similar cases.

Cons:
* It assumes we have "main" scripts that describes sections.

Differential revision: https://reviews.llvm.org/D43468

Added:
    lld/trunk/test/ELF/linkerscript/Inputs/insert-after.s
    lld/trunk/test/ELF/linkerscript/Inputs/insert-after.script
    lld/trunk/test/ELF/linkerscript/insert-after.test
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/ScriptParser.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=327003&r1=327002&r2=327003&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Mar  8 06:54:38 2018
@@ -1087,6 +1087,10 @@ template <class ELFT> void LinkerDriver:
   if (errorCount())
     return;
 
+  // Now when we read all script files, we want to finalize order of linker
+  // script commands, which can be not yet final because of INSERT commands.
+  Script->processInsertCommands();
+
   // We want to declare linker script's symbols early,
   // so that we can version them.
   // They also might be exported if referenced by DSOs.

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=327003&r1=327002&r2=327003&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Mar  8 06:54:38 2018
@@ -203,6 +203,26 @@ static void declareSymbol(SymbolAssignme
   Cmd->Provide = false;
 }
 
+// This method is used to handle INSERT AFTER statement. Here we rebuild
+// the list of script commands to mix sections inserted into.
+void LinkerScript::processInsertCommands() {
+  std::vector<BaseCommand *> V;
+  for (BaseCommand *Base : SectionCommands) {
+    V.push_back(Base);
+    if (auto *Cmd = dyn_cast<OutputSection>(Base)) {
+      std::vector<BaseCommand *> &W = InsertAfterCommands[Cmd->Name];
+      V.insert(V.end(), W.begin(), W.end());
+      W.clear();
+    }
+  }
+  for (std::pair<StringRef, std::vector<BaseCommand *>> &P :
+       InsertAfterCommands)
+    if (!P.second.empty())
+      error("unable to INSERT AFTER " + P.first + ": section not defined");
+
+  SectionCommands = std::move(V);
+}
+
 // Symbols defined in script should not be inlined by LTO. At the same time
 // we don't know their final values until late stages of link. Here we scan
 // over symbol assignment commands and create placeholder symbols if needed.

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=327003&r1=327002&r2=327003&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Mar  8 06:54:38 2018
@@ -267,6 +267,9 @@ public:
   void processSectionCommands();
   void declareSymbols();
 
+  // Used to handle INSERT AFTER statements.
+  void processInsertCommands();
+
   // SECTIONS command list.
   std::vector<BaseCommand *> SectionCommands;
 
@@ -285,6 +288,10 @@ public:
 
   // A list of symbols referenced by the script.
   std::vector<llvm::StringRef> ReferencedSymbols;
+
+  // Used to implement INSERT AFTER. Contains commands that need
+  // to be inserted into SECTIONS commands list.
+  llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;
 };
 
 extern LinkerScript *Script;

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=327003&r1=327002&r2=327003&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Thu Mar  8 06:54:38 2018
@@ -436,6 +436,7 @@ void ScriptParser::readSections() {
   Config->SingleRoRx = true;
 
   expect("{");
+  std::vector<BaseCommand *> V;
   while (!errorCount() && !consume("}")) {
     StringRef Tok = next();
     BaseCommand *Cmd = readProvideOrAssignment(Tok);
@@ -445,8 +446,18 @@ void ScriptParser::readSections() {
       else
         Cmd = readOutputSectionDescription(Tok);
     }
-    Script->SectionCommands.push_back(Cmd);
+    V.push_back(Cmd);
   }
+
+  if (!atEOF() && consume("INSERT")) {
+    consume("AFTER");
+    std::vector<BaseCommand *> &Dest = Script->InsertAfterCommands[next()];
+    Dest.insert(Dest.end(), V.begin(), V.end());
+    return;
+  }
+
+  Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),
+                                 V.end());
 }
 
 static int precedence(StringRef Op) {

Added: lld/trunk/test/ELF/linkerscript/Inputs/insert-after.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/insert-after.s?rev=327003&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/insert-after.s (added)
+++ lld/trunk/test/ELF/linkerscript/Inputs/insert-after.s Thu Mar  8 06:54:38 2018
@@ -0,0 +1,11 @@
+.section .foo.text,"ax"
+.quad 0
+
+.section .foo.data,"aw"
+.quad 0
+
+.section .text.1,"ax"
+.quad 0
+
+.section .data.1,"aw"
+.quad 0

Added: lld/trunk/test/ELF/linkerscript/Inputs/insert-after.script
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/insert-after.script?rev=327003&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/insert-after.script (added)
+++ lld/trunk/test/ELF/linkerscript/Inputs/insert-after.script Thu Mar  8 06:54:38 2018
@@ -0,0 +1,4 @@
+SECTIONS {
+  .text  : { *(.text.*) }
+  .data  : { *(.data.*) }
+}

Added: lld/trunk/test/ELF/linkerscript/insert-after.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/insert-after.test?rev=327003&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/insert-after.test (added)
+++ lld/trunk/test/ELF/linkerscript/insert-after.test Thu Mar  8 06:54:38 2018
@@ -0,0 +1,29 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/insert-after.s -o %t1.o
+
+## Main linker script contains .text and .data sections. Here
+## we check that can use INSERT AFTER to insert sections .foo.data
+## and .foo.text at the right places.
+
+SECTIONS {
+  .foo.data : { *(.foo.data) }
+} INSERT AFTER .data;
+
+SECTIONS {
+  .foo.text : { *(.foo.text) }
+} INSERT AFTER .text;
+
+# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
+# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
+# CHECK:      Sections:
+# CHECK-NEXT: Idx Name          Size      Address          Type
+# CHECK-NEXT:   0               00000000 0000000000000000
+# CHECK-NEXT:   1 .text         00000008 0000000000000000 TEXT DATA
+# CHECK-NEXT:   2 .foo.text     00000008 0000000000000008 TEXT DATA
+# CHECK-NEXT:   3 .data         00000008 0000000000000010 DATA
+# CHECK-NEXT:   4 .foo.data     00000008 0000000000000018 DATA
+
+# RUN: not ld.lld %t1.o -o %t1 --script %s 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=ERR
+# ERR-DAG: error: unable to INSERT AFTER .text: section not defined
+# ERR-DAG: error: unable to INSERT AFTER .data: section not defined




More information about the llvm-commits mailing list