[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