[lld] r277165 - [ELF] - Linkerscript: implemented SIZEOF(section)

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 09:18:47 PDT 2016


Author: grimar
Date: Fri Jul 29 11:18:47 2016
New Revision: 277165

URL: http://llvm.org/viewvc/llvm-project?rev=277165&view=rev
Log:
[ELF] - Linkerscript: implemented SIZEOF(section)

SIZEOF(section)
Return the size in bytes of the named section, if that section has been allocated.

SIZEOF(section) often used in scripts. Few examples from the wild:
https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld
https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/gba_cart.ld

Patch implements it.

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

Added:
    lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.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=277165&r1=277164&r2=277165&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Jul 29 11:18:47 2016
@@ -138,9 +138,10 @@ static bool compareByName(InputSectionBa
 }
 
 template <class ELFT>
-std::vector<OutputSectionBase<ELFT> *>
-LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
-  std::vector<OutputSectionBase<ELFT> *> Ret;
+void LinkerScript<ELFT>::createSections(
+    std::vector<OutputSectionBase<ELFT> *> *Out,
+    OutputSectionFactory<ELFT> &Factory) {
+  OutputSections = Out;
 
   for (auto &P : getSectionMap()) {
     std::vector<InputSectionBase<ELFT> *> Sections;
@@ -157,7 +158,7 @@ LinkerScript<ELFT>::createSections(Outpu
     if (I->Sort)
       std::stable_sort(Sections.begin(), Sections.end(), compareByName<ELFT>);
     for (InputSectionBase<ELFT> *S : Sections)
-      addSection(Factory, Ret, S, OutputName);
+      addSection(Factory, *Out, S, OutputName);
   }
 
   // Add all other input sections, which are not listed in script.
@@ -165,17 +166,15 @@ LinkerScript<ELFT>::createSections(Outpu
        Symtab<ELFT>::X->getObjectFiles())
     for (InputSectionBase<ELFT> *S : F->getSections())
       if (!isDiscarded(S) && !S->OutSec)
-        addSection(Factory, Ret, S, getOutputSectionName(S));
+        addSection(Factory, *Out, S, getOutputSectionName(S));
 
   // Remove from the output all the sections which did not meet
   // the optional constraints.
-  return filter(Ret);
+  filter();
 }
 
 // Process ONLY_IF_RO and ONLY_IF_RW.
-template <class ELFT>
-std::vector<OutputSectionBase<ELFT> *>
-LinkerScript<ELFT>::filter(std::vector<OutputSectionBase<ELFT> *> &Sections) {
+template <class ELFT> void LinkerScript<ELFT>::filter() {
   // In this loop, we remove output sections if they don't satisfy
   // requested properties.
   for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
@@ -186,10 +185,10 @@ LinkerScript<ELFT>::filter(std::vector<O
     if (Cmd->Constraint == ConstraintKind::NoConstraint)
       continue;
 
-    auto It = llvm::find_if(Sections, [&](OutputSectionBase<ELFT> *S) {
+    auto It = llvm::find_if(*OutputSections, [&](OutputSectionBase<ELFT> *S) {
       return S->getName() == Cmd->Name;
     });
-    if (It == Sections.end())
+    if (It == OutputSections->end())
       continue;
 
     OutputSectionBase<ELFT> *Sec = *It;
@@ -198,9 +197,8 @@ LinkerScript<ELFT>::filter(std::vector<O
     bool RW = (Cmd->Constraint == ConstraintKind::ReadWrite);
 
     if ((RO && Writable) || (RW && !Writable))
-      Sections.erase(It);
+      OutputSections->erase(It);
   }
-  return Sections;
 }
 
 template <class ELFT>
@@ -396,6 +394,15 @@ template <class ELFT> bool LinkerScript<
   return !Opt.PhdrsCommands.empty();
 }
 
+template <class ELFT>
+typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
+  for (OutputSectionBase<ELFT> *Sec : *OutputSections)
+    if (Sec->getName() == Name)
+      return Sec->getSize();
+  error("undefined section " + Name);
+  return 0;
+}
+
 // 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.
@@ -838,6 +845,22 @@ static uint64_t getSymbolValue(StringRef
   return 0;
 }
 
+static uint64_t getSectionSize(StringRef Name) {
+  switch (Config->EKind) {
+  case ELF32LEKind:
+    return Script<ELF32LE>::X->getOutputSectionSize(Name);
+  case ELF32BEKind:
+    return Script<ELF32BE>::X->getOutputSectionSize(Name);
+  case ELF64LEKind:
+    return Script<ELF64LE>::X->getOutputSectionSize(Name);
+  case ELF64BEKind:
+    return Script<ELF64BE>::X->getOutputSectionSize(Name);
+  default:
+    llvm_unreachable("unsupported target");
+  }
+  return 0;
+}
+
 SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
   StringRef Op = next();
   assert(Op == "=" || Op == "+=");
@@ -946,6 +969,12 @@ Expr ScriptParser::readPrimary() {
     expect(")");
     return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); };
   }
+  if (Tok == "SIZEOF") {
+    expect("(");
+    StringRef Name = next();
+    expect(")");
+    return [=](uint64_t Dot) { return getSectionSize(Name); };
+  }
 
   // Parse a symbol name or a number literal.
   uint64_t V = 0;

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=277165&r1=277164&r2=277165&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Jul 29 11:18:47 2016
@@ -128,8 +128,8 @@ template <class ELFT> class LinkerScript
   typedef typename ELFT::uint uintX_t;
 
 public:
-  std::vector<OutputSectionBase<ELFT> *>
-  createSections(OutputSectionFactory<ELFT> &Factory);
+  void createSections(std::vector<OutputSectionBase<ELFT> *> *Out,
+                      OutputSectionFactory<ELFT> &Factory);
 
   std::vector<PhdrEntry<ELFT>>
   createPhdrs(ArrayRef<OutputSectionBase<ELFT> *> S);
@@ -140,6 +140,7 @@ public:
   int compareSections(StringRef A, StringRef B);
   void addScriptedSymbols();
   bool hasPhdrsCommands();
+  uintX_t getOutputSectionSize(StringRef Name);
 
 private:
   std::vector<std::pair<StringRef, const InputSectionDescription *>>
@@ -151,13 +152,13 @@ private:
   // "ScriptConfig" is a bit too long, so define a short name for it.
   ScriptConfiguration &Opt = *ScriptConfig;
 
-  std::vector<OutputSectionBase<ELFT> *>
-  filter(std::vector<OutputSectionBase<ELFT> *> &Sections);
+  void filter();
 
   int getSectionIndex(StringRef Name);
   std::vector<size_t> getPhdrIndices(StringRef SectionName);
   size_t getPhdrIndex(StringRef PhdrName);
 
+  std::vector<OutputSectionBase<ELFT> *> *OutputSections;
   uintX_t Dot;
 };
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=277165&r1=277164&r2=277165&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Jul 29 11:18:47 2016
@@ -48,7 +48,7 @@ private:
 
   void copyLocalSymbols();
   void addReservedSymbols();
-  std::vector<OutputSectionBase<ELFT> *> createSections();
+  void createSections();
   void forEachRelSec(
       std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
           Fn);
@@ -233,9 +233,11 @@ template <class ELFT> void Writer<ELFT>:
   CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
   CommonInputSection<ELFT>::X = &Common;
 
-  OutputSections = ScriptConfig->HasContents
-                       ? Script<ELFT>::X->createSections(Factory)
-                       : createSections();
+  if (ScriptConfig->HasContents)
+    Script<ELFT>::X->createSections(&OutputSections, Factory);
+  else
+    createSections();
+
   finalizeSections();
   if (HasError)
     return;
@@ -635,10 +637,7 @@ void Writer<ELFT>::forEachRelSec(
   }
 }
 
-template <class ELFT>
-std::vector<OutputSectionBase<ELFT> *> Writer<ELFT>::createSections() {
-  std::vector<OutputSectionBase<ELFT> *> Result;
-
+template <class ELFT> void Writer<ELFT>::createSections() {
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
        Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
@@ -650,11 +649,10 @@ std::vector<OutputSectionBase<ELFT> *> W
       bool IsNew;
       std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));
       if (IsNew)
-        Result.push_back(Sec);
+        OutputSections.push_back(Sec);
       Sec->addSection(C);
     }
   }
-  return Result;
 }
 
 // Create output section objects and add them to OutputSections.

Added: lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s?rev=277165&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s (added)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s Fri Jul 29 11:18:47 2016
@@ -0,0 +1,53 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS { \
+# RUN:   .aaa         : { *(.aaa) } \
+# RUN:   .bbb         : { *(.bbb) } \
+# RUN:   .ccc         : { *(.ccc) } \
+# RUN:   _aaa = SIZEOF(.aaa); \
+# RUN:   _bbb = SIZEOF(.bbb); \
+# RUN:   _ccc = SIZEOF(.ccc); \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -t -section-headers %t1 | FileCheck %s
+# CHECK:      Sections:
+# CHECK-NEXT:  Idx Name          Size      Address          Type
+# CHECK-NEXT:    0               00000000 0000000000000000
+# CHECK-NEXT:    1 .aaa          00000008 0000000000000120 DATA
+# CHECK-NEXT:    2 .bbb          00000010 0000000000000128 DATA
+# CHECK-NEXT:    3 .ccc          00000018 0000000000000138 DATA
+# CHECK:      SYMBOL TABLE:
+# CHECK-NEXT:  0000000000000000 *UND* 00000000
+# CHECK-NEXT:  0000000000000150 .text 00000000 _start
+# CHECK-NEXT:  0000000000000008 *ABS* 00000000 _aaa
+# CHECK-NEXT:  0000000000000010 *ABS* 00000000 _bbb
+# CHECK-NEXT:  0000000000000018 *ABS* 00000000 _ccc
+
+## Check that we error out if trying to get size of
+## section that does not exist.
+# RUN: echo "SECTIONS { \
+# RUN:   .aaa         : { *(.aaa) } \
+# RUN:   .bbb         : { *(.bbb) } \
+# RUN:   .ccc         : { *(.ccc) } \
+# RUN:   _aaa = SIZEOF(.foo); \
+# RUN: }" > %t.script
+# RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 \
+# RUN:  | FileCheck -check-prefix=ERR %s
+# ERR: undefined section .foo
+
+.global _start
+_start:
+ nop
+
+.section .aaa,"a"
+ .quad 0
+
+.section .bbb,"a"
+ .quad 0
+ .quad 0
+
+.section .ccc,"a"
+ .quad 0
+ .quad 0
+ .quad 0




More information about the llvm-commits mailing list