[ELF] Add Section() to expression object
authorEugene Leviant <eleviant@accesssoftek.com>
Wed, 16 Nov 2016 09:49:39 +0000 (09:49 +0000)
committerEugene Leviant <eleviant@accesssoftek.com>
Wed, 16 Nov 2016 09:49:39 +0000 (09:49 +0000)
This allows making symbols containing ADDR(section) synthetic,
and defining synthetic symbols outside SECTIONS block.

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

llvm-svn: 287090

lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/ELF/SymbolTable.cpp
lld/ELF/SymbolTable.h
lld/ELF/Symbols.cpp
lld/ELF/Symbols.h
lld/test/ELF/linkerscript/symbols-synthetic.s

index 1f65c37..5bf3692 100644 (file)
@@ -75,9 +75,17 @@ template <class ELFT> static void addRegular(SymbolAssignment *Cmd) {
 }
 
 template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
+  // If we have SECTIONS block then output sections haven't been created yet.
+  const OutputSectionBase *Sec =
+      ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
   Symbol *Sym = Symtab<ELFT>::X->addSynthetic(
-      Cmd->Name, nullptr, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
+      Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
   Cmd->Sym = Sym->body();
+
+  // If we already know section then we can calculate symbol value immediately.
+  if (Sec)
+    cast<DefinedSynthetic<ELFT>>(Cmd->Sym)->Value =
+        Cmd->Expression(0) - Sec->Addr;
 }
 
 template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
@@ -373,14 +381,14 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
 // is an offset from beginning of section and regular
 // symbols whose value is absolute.
 template <class ELFT>
-static void assignSectionSymbol(SymbolAssignment *Cmd, OutputSectionBase *Sec,
+static void assignSectionSymbol(SymbolAssignment *Cmd,
                                 typename ELFT::uint Value) {
   if (!Cmd->Sym)
     return;
 
   if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
-    Body->Section = Sec;
-    Body->Value = Cmd->Expression(Value) - Sec->Addr;
+    Body->Section = Cmd->Expression.Section();
+    Body->Value = Cmd->Expression(Value) - Body->Section->Addr;
     return;
   }
   auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
@@ -452,7 +460,7 @@ template <class ELFT> void LinkerScript<ELFT>::process(BaseCommand &Base) {
       CurOutSec->Size = Dot - CurOutSec->Addr;
       return;
     }
-    assignSectionSymbol<ELFT>(AssignCmd, CurOutSec, Dot);
+    assignSectionSymbol<ELFT>(AssignCmd, Dot);
     return;
   }
 
@@ -667,8 +675,7 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
       if (Cmd->Name == ".") {
         Dot = Cmd->Expression(Dot);
       } else if (Cmd->Sym) {
-        assignSectionSymbol<ELFT>(
-            Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0], Dot);
+        assignSectionSymbol<ELFT>(Cmd, Dot);
       }
       continue;
     }
@@ -849,39 +856,14 @@ template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
 }
 
 template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) {
-  for (OutputSectionBase *Sec : *OutputSections)
-    if (Sec->getName() == Name)
-      return Sec->Addr;
-  error("undefined section " + Name);
-  return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionLMA(StringRef Name) {
-  for (OutputSectionBase *Sec : *OutputSections)
-    if (Sec->getName() == Name)
-      return Sec->getLMA();
-  error("undefined section " + Name);
-  return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
-  for (OutputSectionBase *Sec : *OutputSections)
-    if (Sec->getName() == Name)
-      return Sec->Size;
-  error("undefined section " + Name);
-  return 0;
-}
+const OutputSectionBase *LinkerScript<ELFT>::getOutputSection(StringRef Name) {
+  static OutputSectionBase FakeSec("", 0, 0);
 
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAlign(StringRef Name) {
   for (OutputSectionBase *Sec : *OutputSections)
     if (Sec->getName() == Name)
-      return Sec->Addralign;
+      return Sec;
   error("undefined section " + Name);
-  return 0;
+  return &FakeSec;
 }
 
 template <class ELFT> uint64_t LinkerScript<ELFT>::getHeaderSize() {
@@ -905,6 +887,26 @@ template <class ELFT> bool LinkerScript<ELFT>::isAbsolute(StringRef S) {
   return DR && !DR->Section;
 }
 
+// Gets section symbol belongs to. Symbol "." doesn't belong to any
+// specific section but isn't absolute at the same time, so we try
+// to find suitable section for it as well.
+template <class ELFT>
+const OutputSectionBase *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
+  SymbolBody *Sym = Symtab<ELFT>::X->find(S);
+  if (!Sym) {
+    if (OutputSections->empty())
+      return nullptr;
+    return CurOutSec ? CurOutSec : (*OutputSections)[0];
+  }
+
+  if (auto *DR = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
+    return DR->Section ? DR->Section->OutSec : nullptr;
+  if (auto *DS = dyn_cast_or_null<DefinedSynthetic<ELFT>>(Sym))
+    return DS->Section;
+
+  return nullptr;
+}
+
 // Returns indices of ELF headers containing specific section, identified
 // by Name. Each index is a zero based number of ELF header listed within
 // PHDRS {} script block.
@@ -1511,7 +1513,11 @@ static Expr combine(StringRef Op, Expr L, Expr R) {
   }
   if (Op == "+")
     return {[=](uint64_t Dot) { return L(Dot) + R(Dot); },
-            [=]() { return L.IsAbsolute() && R.IsAbsolute(); }};
+            [=]() { return L.IsAbsolute() && R.IsAbsolute(); },
+            [=]() {
+              const OutputSectionBase *S = L.Section();
+              return S ? S : R.Section();
+            }};
   if (Op == "-")
     return [=](uint64_t Dot) { return L(Dot) - R(Dot); };
   if (Op == "<<")
@@ -1650,12 +1656,16 @@ Expr ScriptParser::readPrimary() {
   // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
   if (Tok == "ADDR") {
     StringRef Name = readParenLiteral();
-    return
-        [=](uint64_t Dot) { return ScriptBase->getOutputSectionAddress(Name); };
+    return {
+        [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Addr; },
+        [=]() { return false; },
+        [=]() { return ScriptBase->getOutputSection(Name); }};
   }
   if (Tok == "LOADADDR") {
     StringRef Name = readParenLiteral();
-    return [=](uint64_t Dot) { return ScriptBase->getOutputSectionLMA(Name); };
+    return [=](uint64_t Dot) {
+      return ScriptBase->getOutputSection(Name)->getLMA();
+    };
   }
   if (Tok == "ASSERT")
     return readAssert();
@@ -1708,12 +1718,14 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "SIZEOF") {
     StringRef Name = readParenLiteral();
-    return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); };
+    return
+        [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Size; };
   }
   if (Tok == "ALIGNOF") {
     StringRef Name = readParenLiteral();
-    return
-        [=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); };
+    return [=](uint64_t Dot) {
+      return ScriptBase->getOutputSection(Name)->Addralign;
+    };
   }
   if (Tok == "SIZEOF_HEADERS")
     return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); };
@@ -1727,7 +1739,8 @@ Expr ScriptParser::readPrimary() {
   if (Tok != "." && !isValidCIdentifier(Tok))
     setError("malformed number: " + Tok);
   return {[=](uint64_t Dot) { return getSymbolValue(Tok, Dot); },
-          [=]() { return isAbsolute(Tok); }};
+          [=]() { return isAbsolute(Tok); },
+          [=]() { return ScriptBase->getSymbolSection(Tok); }};
 }
 
 Expr ScriptParser::readTernary(Expr Cond) {
index ce64526..0f10d6b 100644 (file)
@@ -43,12 +43,19 @@ class InputSectionData;
 struct Expr {
   std::function<uint64_t(uint64_t)> Val;
   std::function<bool()> IsAbsolute;
+
+  // If expression is section-relative the function below is used
+  // to get the output section pointer.
+  std::function<const OutputSectionBase *()> Section;
+
   uint64_t operator()(uint64_t Dot) const { return Val(Dot); }
   operator bool() const { return (bool)Val; }
 
-  Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute)
-      : Val(Val), IsAbsolute(IsAbsolute) {}
-  template <typename T> Expr(T V) : Expr(V, []() { return true; }) {}
+  Expr(std::function<uint64_t(uint64_t)> Val, std::function<bool()> IsAbsolute,
+       std::function<const OutputSectionBase *()> Section)
+      : Val(Val), IsAbsolute(IsAbsolute), Section(Section) {}
+  template <typename T>
+  Expr(T V) : Expr(V, []() { return true; }, []() { return nullptr; }) {}
   Expr() : Expr(nullptr) {}
 };
 
@@ -182,14 +189,12 @@ protected:
   ~LinkerScriptBase() = default;
 
 public:
-  virtual uint64_t getOutputSectionAddress(StringRef Name) = 0;
-  virtual uint64_t getOutputSectionSize(StringRef Name) = 0;
-  virtual uint64_t getOutputSectionAlign(StringRef Name) = 0;
-  virtual uint64_t getOutputSectionLMA(StringRef Name) = 0;
   virtual uint64_t getHeaderSize() = 0;
   virtual uint64_t getSymbolValue(StringRef S) = 0;
   virtual bool isDefined(StringRef S) = 0;
   virtual bool isAbsolute(StringRef S) = 0;
+  virtual const OutputSectionBase *getSymbolSection(StringRef S) = 0;
+  virtual const OutputSectionBase *getOutputSection(StringRef S) = 0;
 };
 
 // ScriptConfiguration holds linker script parse results.
@@ -234,14 +239,12 @@ public:
   void placeOrphanSections();
   void assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs);
   bool hasPhdrsCommands();
-  uint64_t getOutputSectionAddress(StringRef Name) override;
-  uint64_t getOutputSectionSize(StringRef Name) override;
-  uint64_t getOutputSectionAlign(StringRef Name) override;
-  uint64_t getOutputSectionLMA(StringRef Name) override;
   uint64_t getHeaderSize() override;
   uint64_t getSymbolValue(StringRef S) override;
   bool isDefined(StringRef S) override;
   bool isAbsolute(StringRef S) override;
+  const OutputSectionBase *getSymbolSection(StringRef S) override;
+  const OutputSectionBase *getOutputSection(StringRef S) override;
 
   std::vector<OutputSectionBase *> *OutputSections;
 
index efbcba9..80b830e 100644 (file)
@@ -423,7 +423,8 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther,
 }
 
 template <typename ELFT>
-Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, OutputSectionBase *Section,
+Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N,
+                                        const OutputSectionBase *Section,
                                         uintX_t Value, uint8_t StOther) {
   Symbol *S;
   bool WasInserted;
index d78287c..8a637f8 100644 (file)
@@ -64,8 +64,8 @@ public:
   Symbol *addRegular(StringRef Name, const Elf_Sym &Sym,
                      InputSectionBase<ELFT> *Section, InputFile *File);
 
-  Symbol *addSynthetic(StringRef N, OutputSectionBase *Section, uintX_t Value,
-                       uint8_t StOther);
+  Symbol *addSynthetic(StringRef N, const OutputSectionBase *Section,
+                       uintX_t Value, uint8_t StOther);
 
   void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym,
                  const typename ELFT::Verdef *Verdef);
index e6572c7..89053d1 100644 (file)
@@ -216,7 +216,7 @@ Undefined::Undefined(uint32_t NameOffset, uint8_t StOther, uint8_t Type,
 
 template <typename ELFT>
 DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
-                                         OutputSectionBase *Section)
+                                         const OutputSectionBase *Section)
     : Defined(SymbolBody::DefinedSyntheticKind, N, STV_HIDDEN, 0 /* Type */),
       Value(Value), Section(Section) {}
 
index a3e2027..9bde9ca 100644 (file)
@@ -244,7 +244,8 @@ InputSectionBase<ELFT> *DefinedRegular<ELFT>::NullInputSection;
 template <class ELFT> class DefinedSynthetic : public Defined {
 public:
   typedef typename ELFT::uint uintX_t;
-  DefinedSynthetic(StringRef N, uintX_t Value, OutputSectionBase *Section);
+  DefinedSynthetic(StringRef N, uintX_t Value,
+                   const OutputSectionBase *Section);
 
   static bool classof(const SymbolBody *S) {
     return S->kind() == SymbolBody::DefinedSyntheticKind;
index 7f39655..35f489b 100644 (file)
 # RUN:         }" > %t.script
 # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
 
+# Check that we can specify synthetic symbols without defining SECTIONS.
+# RUN: echo "PROVIDE_HIDDEN(_begin_sec = _start); \
+# RUN:       PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text));" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=NO-SEC %s
+
+# Check that we can do the same as above inside SECTIONS block.
+# RUN: echo "SECTIONS { \
+# RUN:        . = 0x11000; \
+# RUN:        .text : { *(.text) } \
+# RUN:        PROVIDE_HIDDEN(_begin_sec = ADDR(.text)); \
+# RUN:        PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text)); }" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=IN-SEC %s
+
 # SIMPLE:      0000000000000128         .foo    00000000 .hidden _end_sec
 # SIMPLE-NEXT: 0000000000000120         .foo    00000000 _begin_sec
 # SIMPLE-NEXT: 0000000000000128         *ABS*   00000000 _end_sec_abs
 # SIMPLE-NEXT: 0000000000001018         .eh_frame_hdr     00000000 __eh_frame_hdr_end
 # SIMPLE-NEXT: 0000000000001020         *ABS*             00000000 __eh_frame_hdr_end2
 
+# NO-SEC:       0000000000011000         .text     00000000 .hidden _begin_sec
+# NO-SEC-NEXT:  0000000000011001         .text     00000000 .hidden _end_sec
+
+# IN-SEC:       0000000000011000         .text     00000000 .hidden _begin_sec
+# IN-SEC-NEXT:  0000000000011001         .text     00000000 .hidden _end_sec
+
 .global _start
 _start:
  nop