diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 55 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 9 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 18 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/linkerscript-sizeof.s | 53 |
4 files changed, 108 insertions, 27 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ed47c74e7a9..17a5edeff8d 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -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; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 4b1f2671b06..ec1bd8805c9 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -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; }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index baefb308df6..394ae89c497 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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. diff --git a/lld/test/ELF/linkerscript/linkerscript-sizeof.s b/lld/test/ELF/linkerscript/linkerscript-sizeof.s new file mode 100644 index 00000000000..f7420ddfe64 --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-sizeof.s @@ -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 |