<div dir="ltr">What happens for something like:<div><br></div><div>```</div><div>SECTIONS {</div><div>  .aaa : {</div><div>    *(.aaa);</div><div>    . = . + SIZEOF(.aaa);</div><div>  }<br>}</div><div>```</div><div><br></div><div>Can you add a test case? (or modify the existing one)</div><div><br></div><div><br></div><div>-- Sean Silva</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 29, 2016 at 9:18 AM, George Rimar via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: grimar<br>
Date: Fri Jul 29 11:18:47 2016<br>
New Revision: 277165<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=277165&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=277165&view=rev</a><br>
Log:<br>
[ELF] - Linkerscript: implemented SIZEOF(section)<br>
<br>
SIZEOF(section)<br>
Return the size in bytes of the named section, if that section has been allocated.<br>
<br>
SIZEOF(section) often used in scripts. Few examples from the wild:<br>
<a href="https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld" rel="noreferrer" target="_blank">https://github.com/chipKIT32/pic32-Arduino-USB-Bootloader-original/blob/master/boot-linkerscript.ld</a><br>
<a href="https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/gba_cart.ld" rel="noreferrer" target="_blank">https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/gba_cart.ld</a><br>
<br>
Patch implements it.<br>
<br>
Differential revision: <a href="https://reviews.llvm.org/D22915" rel="noreferrer" target="_blank">https://reviews.llvm.org/D22915</a><br>
<br>
Added:<br>
    lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s<br>
Modified:<br>
    lld/trunk/ELF/LinkerScript.cpp<br>
    lld/trunk/ELF/LinkerScript.h<br>
    lld/trunk/ELF/Writer.cpp<br>
<br>
Modified: lld/trunk/ELF/LinkerScript.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=277165&r1=277164&r2=277165&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=277165&r1=277164&r2=277165&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/LinkerScript.cpp (original)<br>
+++ lld/trunk/ELF/LinkerScript.cpp Fri Jul 29 11:18:47 2016<br>
@@ -138,9 +138,10 @@ static bool compareByName(InputSectionBa<br>
 }<br>
<br>
 template <class ELFT><br>
-std::vector<OutputSectionBase<ELFT> *><br>
-LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {<br>
-  std::vector<OutputSectionBase<ELFT> *> Ret;<br>
+void LinkerScript<ELFT>::createSections(<br>
+    std::vector<OutputSectionBase<ELFT> *> *Out,<br>
+    OutputSectionFactory<ELFT> &Factory) {<br>
+  OutputSections = Out;<br>
<br>
   for (auto &P : getSectionMap()) {<br>
     std::vector<InputSectionBase<ELFT> *> Sections;<br>
@@ -157,7 +158,7 @@ LinkerScript<ELFT>::createSections(Outpu<br>
     if (I->Sort)<br>
       std::stable_sort(Sections.begin(), Sections.end(), compareByName<ELFT>);<br>
     for (InputSectionBase<ELFT> *S : Sections)<br>
-      addSection(Factory, Ret, S, OutputName);<br>
+      addSection(Factory, *Out, S, OutputName);<br>
   }<br>
<br>
   // Add all other input sections, which are not listed in script.<br>
@@ -165,17 +166,15 @@ LinkerScript<ELFT>::createSections(Outpu<br>
        Symtab<ELFT>::X->getObjectFiles())<br>
     for (InputSectionBase<ELFT> *S : F->getSections())<br>
       if (!isDiscarded(S) && !S->OutSec)<br>
-        addSection(Factory, Ret, S, getOutputSectionName(S));<br>
+        addSection(Factory, *Out, S, getOutputSectionName(S));<br>
<br>
   // Remove from the output all the sections which did not meet<br>
   // the optional constraints.<br>
-  return filter(Ret);<br>
+  filter();<br>
 }<br>
<br>
 // Process ONLY_IF_RO and ONLY_IF_RW.<br>
-template <class ELFT><br>
-std::vector<OutputSectionBase<ELFT> *><br>
-LinkerScript<ELFT>::filter(std::vector<OutputSectionBase<ELFT> *> &Sections) {<br>
+template <class ELFT> void LinkerScript<ELFT>::filter() {<br>
   // In this loop, we remove output sections if they don't satisfy<br>
   // requested properties.<br>
   for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {<br>
@@ -186,10 +185,10 @@ LinkerScript<ELFT>::filter(std::vector<O<br>
     if (Cmd->Constraint == ConstraintKind::NoConstraint)<br>
       continue;<br>
<br>
-    auto It = llvm::find_if(Sections, [&](OutputSectionBase<ELFT> *S) {<br>
+    auto It = llvm::find_if(*OutputSections, [&](OutputSectionBase<ELFT> *S) {<br>
       return S->getName() == Cmd->Name;<br>
     });<br>
-    if (It == Sections.end())<br>
+    if (It == OutputSections->end())<br>
       continue;<br>
<br>
     OutputSectionBase<ELFT> *Sec = *It;<br>
@@ -198,9 +197,8 @@ LinkerScript<ELFT>::filter(std::vector<O<br>
     bool RW = (Cmd->Constraint == ConstraintKind::ReadWrite);<br>
<br>
     if ((RO && Writable) || (RW && !Writable))<br>
-      Sections.erase(It);<br>
+      OutputSections->erase(It);<br>
   }<br>
-  return Sections;<br>
 }<br>
<br>
 template <class ELFT><br>
@@ -396,6 +394,15 @@ template <class ELFT> bool LinkerScript<<br>
   return !Opt.PhdrsCommands.empty();<br>
 }<br>
<br>
+template <class ELFT><br>
+typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {<br>
+  for (OutputSectionBase<ELFT> *Sec : *OutputSections)<br>
+    if (Sec->getName() == Name)<br>
+      return Sec->getSize();<br>
+  error("undefined section " + Name);<br>
+  return 0;<br>
+}<br>
+<br>
 // Returns indices of ELF headers containing specific section, identified<br>
 // by Name. Each index is a zero based number of ELF header listed within<br>
 // PHDRS {} script block.<br>
@@ -838,6 +845,22 @@ static uint64_t getSymbolValue(StringRef<br>
   return 0;<br>
 }<br>
<br>
+static uint64_t getSectionSize(StringRef Name) {<br>
+  switch (Config->EKind) {<br>
+  case ELF32LEKind:<br>
+    return Script<ELF32LE>::X->getOutputSectionSize(Name);<br>
+  case ELF32BEKind:<br>
+    return Script<ELF32BE>::X->getOutputSectionSize(Name);<br>
+  case ELF64LEKind:<br>
+    return Script<ELF64LE>::X->getOutputSectionSize(Name);<br>
+  case ELF64BEKind:<br>
+    return Script<ELF64BE>::X->getOutputSectionSize(Name);<br>
+  default:<br>
+    llvm_unreachable("unsupported target");<br>
+  }<br>
+  return 0;<br>
+}<br>
+<br>
 SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {<br>
   StringRef Op = next();<br>
   assert(Op == "=" || Op == "+=");<br>
@@ -946,6 +969,12 @@ Expr ScriptParser::readPrimary() {<br>
     expect(")");<br>
     return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); };<br>
   }<br>
+  if (Tok == "SIZEOF") {<br>
+    expect("(");<br>
+    StringRef Name = next();<br>
+    expect(")");<br>
+    return [=](uint64_t Dot) { return getSectionSize(Name); };<br>
+  }<br>
<br>
   // Parse a symbol name or a number literal.<br>
   uint64_t V = 0;<br>
<br>
Modified: lld/trunk/ELF/LinkerScript.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=277165&r1=277164&r2=277165&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=277165&r1=277164&r2=277165&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/LinkerScript.h (original)<br>
+++ lld/trunk/ELF/LinkerScript.h Fri Jul 29 11:18:47 2016<br>
@@ -128,8 +128,8 @@ template <class ELFT> class LinkerScript<br>
   typedef typename ELFT::uint uintX_t;<br>
<br>
 public:<br>
-  std::vector<OutputSectionBase<ELFT> *><br>
-  createSections(OutputSectionFactory<ELFT> &Factory);<br>
+  void createSections(std::vector<OutputSectionBase<ELFT> *> *Out,<br>
+                      OutputSectionFactory<ELFT> &Factory);<br>
<br>
   std::vector<PhdrEntry<ELFT>><br>
   createPhdrs(ArrayRef<OutputSectionBase<ELFT> *> S);<br>
@@ -140,6 +140,7 @@ public:<br>
   int compareSections(StringRef A, StringRef B);<br>
   void addScriptedSymbols();<br>
   bool hasPhdrsCommands();<br>
+  uintX_t getOutputSectionSize(StringRef Name);<br>
<br>
 private:<br>
   std::vector<std::pair<StringRef, const InputSectionDescription *>><br>
@@ -151,13 +152,13 @@ private:<br>
   // "ScriptConfig" is a bit too long, so define a short name for it.<br>
   ScriptConfiguration &Opt = *ScriptConfig;<br>
<br>
-  std::vector<OutputSectionBase<ELFT> *><br>
-  filter(std::vector<OutputSectionBase<ELFT> *> &Sections);<br>
+  void filter();<br>
<br>
   int getSectionIndex(StringRef Name);<br>
   std::vector<size_t> getPhdrIndices(StringRef SectionName);<br>
   size_t getPhdrIndex(StringRef PhdrName);<br>
<br>
+  std::vector<OutputSectionBase<ELFT> *> *OutputSections;<br>
   uintX_t Dot;<br>
 };<br>
<br>
<br>
Modified: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=277165&r1=277164&r2=277165&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=277165&r1=277164&r2=277165&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (original)<br>
+++ lld/trunk/ELF/Writer.cpp Fri Jul 29 11:18:47 2016<br>
@@ -48,7 +48,7 @@ private:<br>
<br>
   void copyLocalSymbols();<br>
   void addReservedSymbols();<br>
-  std::vector<OutputSectionBase<ELFT> *> createSections();<br>
+  void createSections();<br>
   void forEachRelSec(<br>
       std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)><br>
           Fn);<br>
@@ -233,9 +233,11 @@ template <class ELFT> void Writer<ELFT>:<br>
   CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());<br>
   CommonInputSection<ELFT>::X = &Common;<br>
<br>
-  OutputSections = ScriptConfig->HasContents<br>
-                       ? Script<ELFT>::X->createSections(Factory)<br>
-                       : createSections();<br>
+  if (ScriptConfig->HasContents)<br>
+    Script<ELFT>::X->createSections(&OutputSections, Factory);<br>
+  else<br>
+    createSections();<br>
+<br>
   finalizeSections();<br>
   if (HasError)<br>
     return;<br>
@@ -635,10 +637,7 @@ void Writer<ELFT>::forEachRelSec(<br>
   }<br>
 }<br>
<br>
-template <class ELFT><br>
-std::vector<OutputSectionBase<ELFT> *> Writer<ELFT>::createSections() {<br>
-  std::vector<OutputSectionBase<ELFT> *> Result;<br>
-<br>
+template <class ELFT> void Writer<ELFT>::createSections() {<br>
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :<br>
        Symtab.getObjectFiles()) {<br>
     for (InputSectionBase<ELFT> *C : F->getSections()) {<br>
@@ -650,11 +649,10 @@ std::vector<OutputSectionBase<ELFT> *> W<br>
       bool IsNew;<br>
       std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));<br>
       if (IsNew)<br>
-        Result.push_back(Sec);<br>
+        OutputSections.push_back(Sec);<br>
       Sec->addSection(C);<br>
     }<br>
   }<br>
-  return Result;<br>
 }<br>
<br>
 // Create output section objects and add them to OutputSections.<br>
<br>
Added: lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s?rev=277165&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s?rev=277165&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s (added)<br>
+++ lld/trunk/test/ELF/linkerscript/linkerscript-sizeof.s Fri Jul 29 11:18:47 2016<br>
@@ -0,0 +1,53 @@<br>
+# REQUIRES: x86<br>
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t<br>
+<br>
+# RUN: echo "SECTIONS { \<br>
+# RUN:   .aaa         : { *(.aaa) } \<br>
+# RUN:   .bbb         : { *(.bbb) } \<br>
+# RUN:   .ccc         : { *(.ccc) } \<br>
+# RUN:   _aaa = SIZEOF(.aaa); \<br>
+# RUN:   _bbb = SIZEOF(.bbb); \<br>
+# RUN:   _ccc = SIZEOF(.ccc); \<br>
+# RUN: }" > %t.script<br>
+# RUN: ld.lld -o %t1 --script %t.script %t<br>
+# RUN: llvm-objdump -t -section-headers %t1 | FileCheck %s<br>
+# CHECK:      Sections:<br>
+# CHECK-NEXT:  Idx Name          Size      Address          Type<br>
+# CHECK-NEXT:    0               00000000 0000000000000000<br>
+# CHECK-NEXT:    1 .aaa          00000008 0000000000000120 DATA<br>
+# CHECK-NEXT:    2 .bbb          00000010 0000000000000128 DATA<br>
+# CHECK-NEXT:    3 .ccc          00000018 0000000000000138 DATA<br>
+# CHECK:      SYMBOL TABLE:<br>
+# CHECK-NEXT:  0000000000000000 *UND* 00000000<br>
+# CHECK-NEXT:  0000000000000150 .text 00000000 _start<br>
+# CHECK-NEXT:  0000000000000008 *ABS* 00000000 _aaa<br>
+# CHECK-NEXT:  0000000000000010 *ABS* 00000000 _bbb<br>
+# CHECK-NEXT:  0000000000000018 *ABS* 00000000 _ccc<br>
+<br>
+## Check that we error out if trying to get size of<br>
+## section that does not exist.<br>
+# RUN: echo "SECTIONS { \<br>
+# RUN:   .aaa         : { *(.aaa) } \<br>
+# RUN:   .bbb         : { *(.bbb) } \<br>
+# RUN:   .ccc         : { *(.ccc) } \<br>
+# RUN:   _aaa = SIZEOF(.foo); \<br>
+# RUN: }" > %t.script<br>
+# RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 \<br>
+# RUN:  | FileCheck -check-prefix=ERR %s<br>
+# ERR: undefined section .foo<br>
+<br>
+.global _start<br>
+_start:<br>
+ nop<br>
+<br>
+.section .aaa,"a"<br>
+ .quad 0<br>
+<br>
+.section .bbb,"a"<br>
+ .quad 0<br>
+ .quad 0<br>
+<br>
+.section .ccc,"a"<br>
+ .quad 0<br>
+ .quad 0<br>
+ .quad 0<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>