Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -195,6 +195,7 @@ virtual bool isAbsolute(StringRef S) = 0; virtual const OutputSectionBase *getSymbolSection(StringRef S) = 0; virtual const OutputSectionBase *getOutputSection(StringRef S) = 0; + virtual uint64_t getOutputSectionSize(StringRef S) = 0; }; // ScriptConfiguration holds linker script parse results. @@ -245,6 +246,7 @@ bool isAbsolute(StringRef S) override; const OutputSectionBase *getSymbolSection(StringRef S) override; const OutputSectionBase *getOutputSection(StringRef S) override; + uint64_t getOutputSectionSize(StringRef S) override; std::vector *OutputSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -868,6 +868,20 @@ return &FakeSec; } +// This function is essentially the same as getOutputSection(Name)->Size, +// but it won't print out an error message if a given section is not found. +// +// Linker script does not create an output section if its content is empty. +// We want to allow SIZEOF(.foo) where .foo is a section which happened to +// be empty. That is why this function is different from getOutputSection(). +template +uint64_t LinkerScript::getOutputSectionSize(StringRef Name) { + for (OutputSectionBase *Sec : *OutputSections) + if (Sec->getName() == Name) + return Sec->Size; + return 0; +} + template uint64_t LinkerScript::getHeaderSize() { return elf::getHeaderSize(); } @@ -1719,8 +1733,7 @@ } if (Tok == "SIZEOF") { StringRef Name = readParenLiteral(); - return - [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Size; }; + return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); }; } if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); Index: test/ELF/linkerscript/sizeof.s =================================================================== --- test/ELF/linkerscript/sizeof.s +++ test/ELF/linkerscript/sizeof.s @@ -24,17 +24,17 @@ # 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. +## SIZEOF(.nonexistent_section) should return 0. # 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 +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t -section-headers %t1 | FileCheck -check-prefix=CHECK2 %s + +# CHECK2: 0000000000000000 *ABS* 00000000 _aaa .global _start _start: