<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>