Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -131,6 +131,7 @@ int compareSections(StringRef A, StringRef B); void addScriptedSymbols(); bool hasPhdrsCommands(); + uintX_t getOutputSectionSize(StringRef Name); private: std::vector> @@ -150,6 +151,7 @@ size_t getPhdrIndex(StringRef PhdrName); void dispatchAssignment(SymbolAssignment *Cmd); + OutputSectionFactory *Factory = nullptr; uintX_t Dot; }; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -112,6 +112,7 @@ template std::vector *> LinkerScript::createSections(OutputSectionFactory &Factory) { + this->Factory = &Factory; std::vector *> Ret; // Add input section to output section. If there is no output section yet, @@ -380,6 +381,15 @@ return !Opt.PhdrsCommands.empty(); } +template +typename ELFT::uint LinkerScript::getOutputSectionSize(StringRef Name) { + for (const std::unique_ptr>& OutSec : Factory->getOwningSections()) + if (OutSec->getName() == Name) + return OutSec->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. @@ -810,6 +820,22 @@ return 0; } +static uint64_t getSectionSize(StringRef Name) { + switch (Config->EKind) { + case ELF32LEKind: + return Script::X->getOutputSectionSize(Name); + case ELF32BEKind: + return Script::X->getOutputSectionSize(Name); + case ELF64LEKind: + return Script::X->getOutputSectionSize(Name); + case ELF64BEKind: + return Script::X->getOutputSectionSize(Name); + default: + llvm_unreachable("unsupported target"); + } + return 0; +} + // This is a part of the operator-precedence parser. This function // assumes that the remaining token stream starts with an operator. Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { @@ -897,6 +923,12 @@ 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; Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -681,6 +681,9 @@ StringRef OutsecName); OutputSectionBase *lookup(StringRef Name, uint32_t Type, uintX_t Flags); + llvm::ArrayRef>> getOwningSections() { + return OwningSections; + } private: Key createKey(InputSectionBase *C, StringRef OutsecName); Index: test/ELF/linkerscript/linkerscript-sizeof.s =================================================================== --- test/ELF/linkerscript/linkerscript-sizeof.s +++ 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