Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -163,6 +163,7 @@ bool hasPhdrsCommands(); uintX_t getOutputSectionAddress(StringRef Name); uintX_t getOutputSectionSize(StringRef Name); + uintX_t getOutputSectionAlignment(StringRef Name); uintX_t getHeaderSize(); std::vector *> *OutputSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -560,7 +560,16 @@ } template -typename ELFT::uint LinkerScript::getHeaderSize() { +typename ELFT::uint +LinkerScript::getOutputSectionAlignment(StringRef Name) { + for (OutputSectionBase *Sec : *OutputSections) + if (Sec->getName() == Name) + return Sec->getAlignment(); + error("undefined section " + Name); + return 0; +} + +template typename ELFT::uint LinkerScript::getHeaderSize() { return Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); } @@ -1094,46 +1103,35 @@ 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"); - } -} +struct ScriptMethods { + std::function getSectionSize; + std::function getSectionAlignment; + std::function getSectionAddress; + std::function getHeaderSize; + + template static ScriptMethods &get() { + typedef LinkerScript LS; + using std::placeholders::_1; + static ScriptMethods Methods = { + std::bind(&LS::getOutputSectionSize, Script::X, _1), + std::bind(&LS::getOutputSectionAlignment, Script::X, _1), + std::bind(&LS::getOutputSectionAddress, Script::X, _1), + std::bind(&LS::getHeaderSize, Script::X)}; -static uint64_t getSectionAddress(StringRef Name) { - switch (Config->EKind) { - case ELF32LEKind: - return Script::X->getOutputSectionAddress(Name); - case ELF32BEKind: - return Script::X->getOutputSectionAddress(Name); - case ELF64LEKind: - return Script::X->getOutputSectionAddress(Name); - case ELF64BEKind: - return Script::X->getOutputSectionAddress(Name); - default: - llvm_unreachable("unsupported target"); + return Methods; } -} +}; -static uint64_t getHeaderSize() { +static ScriptMethods &getScriptMethods() { switch (Config->EKind) { case ELF32LEKind: - return Script::X->getHeaderSize(); + return ScriptMethods::get(); case ELF32BEKind: - return Script::X->getHeaderSize(); + return ScriptMethods::get(); case ELF64LEKind: - return Script::X->getHeaderSize(); + return ScriptMethods::get(); case ELF64BEKind: - return Script::X->getHeaderSize(); + return ScriptMethods::get(); default: llvm_unreachable("unsupported target"); } @@ -1277,7 +1275,9 @@ expect("("); StringRef Name = next(); expect(")"); - return [=](uint64_t Dot) { return getSectionAddress(Name); }; + return [=](uint64_t Dot) { + return getScriptMethods().getSectionAddress(Name); + }; } if (Tok == "ASSERT") return readAssert(); @@ -1329,10 +1329,19 @@ expect("("); StringRef Name = next(); expect(")"); - return [=](uint64_t Dot) { return getSectionSize(Name); }; + return + [=](uint64_t Dot) { return getScriptMethods().getSectionSize(Name); }; + } + if (Tok == "ALIGNOF") { + expect("("); + StringRef Name = next(); + expect(")"); + return [=](uint64_t Dot) { + return getScriptMethods().getSectionAlignment(Name); + }; } if (Tok == "SIZEOF_HEADERS") - return [=](uint64_t Dot) { return getHeaderSize(); }; + return [=](uint64_t Dot) { return getScriptMethods().getHeaderSize(); }; // Tok is a literal number. uint64_t V; Index: test/ELF/linkerscript/alignof.s =================================================================== --- test/ELF/linkerscript/alignof.s +++ test/ELF/linkerscript/alignof.s @@ -0,0 +1,41 @@ +# 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 = ALIGNOF(.aaa); \ +# RUN: _bbb = ALIGNOF(.bbb); \ +# RUN: _ccc = ALIGNOF(.ccc); \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s +# CHECK: SYMBOL TABLE: +# CHECK: 0000000000000008 *ABS* 00000000 _aaa +# CHECK-NEXT: 0000000000000010 *ABS* 00000000 _bbb +# CHECK-NEXT: 0000000000000020 *ABS* 00000000 _ccc + +## Check that we error out if trying to get alignment of +## section that does not exist. +# RUN: echo "SECTIONS { \ +# RUN: _aaa = ALIGNOF(.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" + .align 8 + .quad 0 + +.section .bbb,"a" + .align 16 + .quad 0 + +.section .ccc,"a" + .align 32 + .quad 0