[lld] r280788 - Support ABSOLUE keyword in symbol assignments

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 7 00:08:43 PDT 2016


Author: evgeny777
Date: Wed Sep  7 02:08:43 2016
New Revision: 280788

URL: http://llvm.org/viewvc/llvm-project?rev=280788&view=rev
Log:
Support ABSOLUE keyword in symbol assignments

This patch allows making section defined symbols absolute:
.foo : {
  begin_foo = ABSOLUTE(.);
  *(.foo)
}

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

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

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=280788&r1=280787&r2=280788&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Sep  7 02:08:43 2016
@@ -56,6 +56,12 @@ template <class ELFT> static void addSyn
   Cmd->Sym = Sym->body();
 }
 
+template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
+  if (Cmd->IsAbsolute)
+    addRegular<ELFT>(Cmd);
+  else
+    addSynthetic<ELFT>(Cmd);
+}
 // If a symbol was in PROVIDE(), we need to define it only when
 // it is an undefined symbol.
 template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
@@ -184,7 +190,7 @@ LinkerScript<ELFT>::createInputSectionLi
   for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
     if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
       if (shouldDefine<ELFT>(OutCmd))
-        addSynthetic<ELFT>(OutCmd);
+        addSymbol<ELFT>(OutCmd);
       OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
       continue;
     }
@@ -267,6 +273,26 @@ void LinkerScript<ELFT>::createSections(
   }
 }
 
+// Sets value of a section-defined symbol. Two kinds of
+// symbols are processed: synthetic symbols, whose value
+// is an offset from beginning of section and regular
+// symbols whose value is absolute.
+template <class ELFT>
+static void assignSectionSymbol(SymbolAssignment *Cmd,
+                                OutputSectionBase<ELFT> *Sec,
+                                typename ELFT::uint Off) {
+  if (!Cmd->Sym)
+    return;
+
+  if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
+    Body->Section = Sec;
+    Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
+    return;
+  }
+  auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
+  Body->Value = Cmd->Expression(Sec->getVA() + Off);
+}
+
 // Linker script may define start and end symbols for special section types,
 // like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
 // of regular input input sections, therefore our way of defining symbols for
@@ -280,12 +306,7 @@ void addStartEndSymbols(OutputSectionCom
 
   for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
     if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
-      if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
-        Sym->Section = Sec;
-        Sym->Value =
-            AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
-            Sec->getVA();
-      }
+      assignSectionSymbol<ELFT>(AssignCmd, Sec, Start ? 0 : Sec->getSize());
     } else {
       if (!Start && isa<SymbolAssignment>(PrevCmd))
         error("section '" + Sec->getName() +
@@ -322,19 +343,13 @@ void assignOffsets(OutputSectionCommand
       if (D != AssignCmd->GoesAfter)
         break;
 
-      uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
       if (AssignCmd->Name == ".") {
         // Update to location counter means update to section size.
-        Off = Value;
+        Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
         Sec->setSize(Off);
         continue;
       }
-
-      if (DefinedSynthetic<ELFT> *Sym =
-              cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
-        Sym->Section = OutSec;
-        Sym->Value = Value;
-      }
+      assignSectionSymbol<ELFT>(AssignCmd, Sec, Off);
     }
   };
 
@@ -631,7 +646,7 @@ private:
   unsigned readPhdrType();
   SortKind readSortKind();
   SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
-  SymbolAssignment *readProvideOrAssignment(StringRef Tok);
+  SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
   void readSort();
   Expr readAssert();
 
@@ -710,7 +725,7 @@ void ScriptParser::readLinkerScript() {
       readSections();
     } else if (Tok == "VERSION") {
       readVersion();
-    } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
+    } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) {
       if (Opt.HasContents)
         Opt.Commands.emplace_back(Cmd);
       else
@@ -872,7 +887,7 @@ void ScriptParser::readSections() {
   expect("{");
   while (!Error && !skip("}")) {
     StringRef Tok = next();
-    BaseCommand *Cmd = readProvideOrAssignment(Tok);
+    BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
     if (!Cmd) {
       if (Tok == "ASSERT")
         Cmd = new AssertCommand(readAssert());
@@ -1020,7 +1035,7 @@ ScriptParser::readOutputSectionDescripti
 
   while (!Error && !skip("}")) {
     StringRef Tok = next();
-    if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok))
+    if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok, false))
       Cmd->Commands.emplace_back(Assignment);
     else if (Tok == "FILL")
       Cmd->Filler = readFill();
@@ -1063,7 +1078,8 @@ SymbolAssignment *ScriptParser::readProv
   return Cmd;
 }
 
-SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
+SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
+                                                        bool MakeAbsolute) {
   SymbolAssignment *Cmd = nullptr;
   if (peek() == "=" || peek() == "+=") {
     Cmd = readAssignment(Tok);
@@ -1075,6 +1091,8 @@ SymbolAssignment *ScriptParser::readProv
   } else if (Tok == "PROVIDE_HIDDEN") {
     Cmd = readProvideHidden(true, true);
   }
+  if (Cmd && MakeAbsolute)
+    Cmd->IsAbsolute = true;
   return Cmd;
 }
 
@@ -1153,11 +1171,18 @@ static uint64_t getHeaderSize() {
 
 SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
   StringRef Op = next();
+  bool IsAbsolute = false;
+  Expr E;
   assert(Op == "=" || Op == "+=");
-  Expr E = readExpr();
+  if (skip("ABSOLUTE")) {
+    E = readParenExpr();
+    IsAbsolute = true;
+  } else {
+    E = readExpr();
+  }
   if (Op == "+=")
     E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
-  return new SymbolAssignment(Name, E);
+  return new SymbolAssignment(Name, E, IsAbsolute);
 }
 
 // This is an operator-precedence parser to parse a linker

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=280788&r1=280787&r2=280788&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Sep  7 02:08:43 2016
@@ -54,8 +54,9 @@ struct BaseCommand {
 };
 
 struct SymbolAssignment : BaseCommand {
-  SymbolAssignment(StringRef Name, Expr E)
-      : BaseCommand(AssignmentKind), Name(Name), Expression(E) {}
+  SymbolAssignment(StringRef Name, Expr E, bool IsAbsolute)
+      : BaseCommand(AssignmentKind), Name(Name), Expression(E),
+        IsAbsolute(IsAbsolute) {}
   static bool classof(const BaseCommand *C);
 
   // The LHS of an expression. Name is either a symbol name or ".".
@@ -68,6 +69,7 @@ struct SymbolAssignment : BaseCommand {
   // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
   bool Provide = false;
   bool Hidden = false;
+  bool IsAbsolute;
   InputSectionData *GoesAfter = nullptr;
 };
 

Modified: lld/trunk/test/ELF/linkerscript/symbols-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbols-synthetic.s?rev=280788&r1=280787&r2=280788&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbols-synthetic.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbols-synthetic.s Wed Sep  7 02:08:43 2016
@@ -10,7 +10,9 @@
 # RUN:              *(.foo) \
 # RUN:              end_foo = .; \
 # RUN:              PROVIDE_HIDDEN(_end_sec = .); \
+# RUN:              PROVIDE(_end_sec_abs = ABSOLUTE(.)); \
 # RUN:              size_foo_1 = SIZEOF(.foo); \
+# RUN:              size_foo_1_abs = ABSOLUTE(SIZEOF(.foo)); \
 # RUN:              . = ALIGN(0x1000); \
 # RUN:              begin_bar = .; \
 # RUN:              *(.bar) \
@@ -19,10 +21,10 @@
 # RUN:          size_foo_3 = SIZEOF(.foo); \
 # RUN:          .eh_frame_hdr : { \
 # RUN:             __eh_frame_hdr_start = .; \
-# RUN:             __eh_frame_hdr_start2 = ALIGN(0x10); \
+# RUN:             __eh_frame_hdr_start2 = ABSOLUTE(ALIGN(0x10)); \
 # RUN:             *(.eh_frame_hdr) \
 # RUN:             __eh_frame_hdr_end = .; \
-# RUN:             __eh_frame_hdr_end2 = ALIGN(0x10); } \
+# RUN:             __eh_frame_hdr_end2 = ABSOLUTE(ALIGN(0x10)); } \
 # RUN:       }" > %t.script
 # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
 # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
@@ -34,7 +36,7 @@
 # RUN:             PROVIDE_HIDDEN(_begin_sec = .); \
 # RUN:             __eh_frame_hdr_start = .; \
 # RUN:             *(.eh_frame_hdr) \
-# RUN:             __eh_frame_hdr_end = .; \
+# RUN:             PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
 # RUN:             *(.eh_frame_hdr) } \
 # RUN:             PROVIDE_HIDDEN(_end_sec = .); \
 # RUN:         }" > %t.script
@@ -46,23 +48,26 @@
 # RUN:             PROVIDE_HIDDEN(_begin_sec = .); \
 # RUN:             *(.eh_frame_hdr) \
 # RUN:             *(.eh_frame_hdr) \
+# RUN:             PROVIDE_HIDDEN(_end_sec_abs = ABSOLUTE(.)); \
 # RUN:             PROVIDE_HIDDEN(_end_sec = .); } \
 # RUN:         }" > %t.script
 # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
 
 # SIMPLE:      0000000000000160         .foo    00000000 .hidden _end_sec
 # SIMPLE:      0000000000000158         .foo    00000000 _begin_sec
+# SIMPLE-NEXT: 0000000000000160         *ABS*   00000000 _end_sec_abs
 # SIMPLE-NEXT: 0000000000000158         .foo    00000000 begin_foo
 # SIMPLE-NEXT: 0000000000000160         .foo    00000000 end_foo
 # SIMPLE-NEXT: 0000000000000008         .foo    00000000 size_foo_1
+# SIMPLE-NEXT: 0000000000000008         *ABS*   00000000 size_foo_1_abs
 # SIMPLE-NEXT: 0000000000001000         .foo    00000000 begin_bar
 # SIMPLE-NEXT: 0000000000001004         .foo    00000000 end_bar
 # SIMPLE-NEXT: 0000000000000eac         .foo    00000000 size_foo_2
 # SIMPLE-NEXT: 0000000000000eac         *ABS*   00000000 size_foo_3
 # SIMPLE-NEXT: 0000000000001004         .eh_frame_hdr     00000000 __eh_frame_hdr_start
-# SIMPLE-NEXT: 0000000000001010         .eh_frame_hdr     00000000 __eh_frame_hdr_start2
+# SIMPLE-NEXT: 0000000000001010         *ABS*             00000000 __eh_frame_hdr_start2
 # SIMPLE-NEXT: 0000000000001018         .eh_frame_hdr     00000000 __eh_frame_hdr_end
-# SIMPLE-NEXT: 0000000000001020         .eh_frame_hdr     00000000 __eh_frame_hdr_end2
+# SIMPLE-NEXT: 0000000000001020         *ABS*             00000000 __eh_frame_hdr_end2
 # ERROR: section '.eh_frame_hdr' supports only start and end symbols
 
 .global _start
@@ -80,4 +85,4 @@ _start:
  nop
  .cfi_endproc
 
-.global _begin_sec, _end_sec
+.global _begin_sec, _end_sec, _end_sec_abs




More information about the llvm-commits mailing list