forked from OSchip/llvm-project
[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 llvm-svn: 277165
This commit is contained in:
parent
5831cc28b5
commit
9e69450ec7
|
@ -138,9 +138,10 @@ static bool compareByName(InputSectionBase<ELFT> *A,
|
|||
}
|
||||
|
||||
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(OutputSectionFactory<ELFT> &Factory) {
|
|||
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(OutputSectionFactory<ELFT> &Factory) {
|
|||
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<OutputSectionBase<ELFT> *> &Sections) {
|
|||
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<OutputSectionBase<ELFT> *> &Sections) {
|
|||
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<ELFT>::hasPhdrsCommands() {
|
|||
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 S, uint64_t Dot) {
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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>::run() {
|
|||
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> *> Writer<ELFT>::createSections() {
|
|||
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.
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue