[lld] r275158 - [ELF] Support for symbol assignment in linker scripts within SECTIONS {} block

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 11 23:39:48 PDT 2016


Author: evgeny777
Date: Tue Jul 12 01:39:48 2016
New Revision: 275158

URL: http://llvm.org/viewvc/llvm-project?rev=275158&view=rev
Log:
[ELF] Support for symbol assignment in linker scripts within SECTIONS {} block

Added:
    lld/trunk/test/ELF/linkerscript-symbols.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=275158&r1=275157&r2=275158&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Jul 12 01:39:48 2016
@@ -20,6 +20,7 @@
 #include "OutputSections.h"
 #include "ScriptParser.h"
 #include "Strings.h"
+#include "Symbols.h"
 #include "SymbolTable.h"
 #include "Target.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -226,16 +227,25 @@ void LinkerScript<ELFT>::assignAddresses
   uintX_t ThreadBssOffset = 0;
 
   for (SectionsCommand &Cmd : Opt.Commands) {
-    if (Cmd.Kind == ExprKind) {
+    switch (Cmd.Kind) {
+    case ExprKind:
       Dot = evalExpr(Cmd.Expr, Dot);
       continue;
+    case SymbolAssignmentKind: {
+      auto *D =
+          cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd.Name));
+      D->Value = evalExpr(Cmd.Expr, Dot);
+      continue;
+    }
+    default:
+      break;
     }
 
     // Find all the sections with required name. There can be more than
     // ont section with such name, if the alignment, flags or type
     // attribute differs.
     for (OutputSectionBase<ELFT> *Sec : Sections) {
-      if (Sec->getName() != Cmd.SectionName)
+      if (Sec->getName() != Cmd.Name)
         continue;
 
       if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
@@ -283,7 +293,7 @@ int LinkerScript<ELFT>::getSectionIndex(
   auto Begin = Opt.Commands.begin();
   auto End = Opt.Commands.end();
   auto I = std::find_if(Begin, End, [&](SectionsCommand &N) {
-    return N.Kind == SectionKind && N.SectionName == Name;
+    return N.Kind == SectionKind && N.Name == Name;
   });
   return I == End ? INT_MAX : (I - Begin);
 }
@@ -299,6 +309,13 @@ int LinkerScript<ELFT>::compareSections(
   return I < J ? -1 : 1;
 }
 
+template <class ELFT>
+void LinkerScript<ELFT>::addScriptedSymbols() {
+  for (SectionsCommand &Cmd : Opt.Commands)
+    if (Cmd.Kind == SymbolAssignmentKind)
+      Symtab<ELFT>::X->addAbsolute(Cmd.Name, STV_DEFAULT);
+}
+
 class elf::ScriptParser : public ScriptParserBase {
   typedef void (ScriptParser::*Handler)();
 
@@ -323,7 +340,9 @@ private:
   void readSections();
 
   void readLocationCounterValue();
-  void readOutputSectionDescription();
+  void readOutputSectionDescription(StringRef OutSec);
+  void readSymbolAssignment(StringRef Name);
+  std::vector<StringRef> readSectionsCommandExpr();
 
   const static StringMap<Handler> Cmd;
   ScriptConfiguration &Opt = *ScriptConfig;
@@ -487,30 +506,29 @@ void ScriptParser::readSections() {
   expect("{");
   while (!Error && !skip("}")) {
     StringRef Tok = peek();
-    if (Tok == ".")
+    if (Tok == ".") {
       readLocationCounterValue();
+      continue;
+    }
+    next();
+    if (peek() == "=")
+      readSymbolAssignment(Tok);
     else
-      readOutputSectionDescription();
+      readOutputSectionDescription(Tok);
   }
 }
 
 void ScriptParser::readLocationCounterValue() {
   expect(".");
   expect("=");
-  Opt.Commands.push_back({ExprKind, {}, ""});
-  SectionsCommand &Cmd = Opt.Commands.back();
-  while (!Error) {
-    StringRef Tok = next();
-    if (Tok == ";")
-      break;
-    Cmd.Expr.push_back(Tok);
-  }
-  if (Cmd.Expr.empty())
+  std::vector<StringRef> Expr = readSectionsCommandExpr();
+  if (Expr.empty())
     error("error in location counter expression");
+  else
+    Opt.Commands.push_back({ExprKind, std::move(Expr), ""});
 }
 
-void ScriptParser::readOutputSectionDescription() {
-  StringRef OutSec = next();
+void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
   Opt.Commands.push_back({SectionKind, {}, OutSec});
   expect(":");
   expect("{");
@@ -548,6 +566,26 @@ void ScriptParser::readOutputSectionDesc
   }
 }
 
+void ScriptParser::readSymbolAssignment(StringRef Name) {
+  expect("=");
+  std::vector<StringRef> Expr = readSectionsCommandExpr();
+  if (Expr.empty())
+    error("error in symbol assignment expression");
+  else
+    Opt.Commands.push_back({SymbolAssignmentKind, std::move(Expr), Name});
+}
+
+std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
+  std::vector<StringRef> Expr;
+  while (!Error) {
+    StringRef Tok = next();
+    if (Tok == ";")
+      break;
+    Expr.push_back(Tok);
+  }
+  return Expr;
+}
+
 static bool isUnderSysroot(StringRef Path) {
   if (Config->Sysroot == "")
     return false;

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=275158&r1=275157&r2=275158&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Tue Jul 12 01:39:48 2016
@@ -40,12 +40,12 @@ struct SectionRule {
 // This enum represents what we can observe in SECTIONS tag of script:
 // ExprKind is a location counter change, like ". = . + 0x1000"
 // SectionKind is a description of output section, like ".data :..."
-enum SectionsCommandKind { ExprKind, SectionKind };
+enum SectionsCommandKind { ExprKind, SectionKind, SymbolAssignmentKind };
 
 struct SectionsCommand {
   SectionsCommandKind Kind;
   std::vector<StringRef> Expr;
-  StringRef SectionName;
+  StringRef Name;
 };
 
 // ScriptConfiguration holds linker script parse results.
@@ -81,6 +81,7 @@ public:
   bool shouldKeep(InputSectionBase<ELFT> *S);
   void assignAddresses(ArrayRef<OutputSectionBase<ELFT> *> S);
   int compareSections(StringRef A, StringRef B);
+  void addScriptedSymbols();
 
 private:
   // "ScriptConfig" is a bit too long, so define a short name for it.

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=275158&r1=275157&r2=275158&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Jul 12 01:39:48 2016
@@ -786,6 +786,10 @@ template <class ELFT> void Writer<ELFT>:
   // Define __rel[a]_iplt_{start,end} symbols if needed.
   addRelIpltSymbols();
 
+  // Add scripted symbols with zero values now.
+  // Real values will be assigned later
+  Script<ELFT>::X->addScriptedSymbols();
+
   if (!Out<ELFT>::EhFrame->empty()) {
     OutputSections.push_back(Out<ELFT>::EhFrame);
     Out<ELFT>::EhFrame->finalize();

Added: lld/trunk/test/ELF/linkerscript-symbols.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-symbols.s?rev=275158&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript-symbols.s (added)
+++ lld/trunk/test/ELF/linkerscript-symbols.s Tue Jul 12 01:39:48 2016
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck %s
+# CHECK: 0000000000000121         *ABS*    00000000 text_end
+
+.global _start
+_start:
+ nop




More information about the llvm-commits mailing list