Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -72,6 +72,7 @@ : BaseCommand(OutputSectionKind), Name(Name) {} static bool classof(const BaseCommand *C); StringRef Name; + Expr AlignExpr; std::vector> Commands; std::vector Phdrs; std::vector Filler; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -84,12 +84,14 @@ // Add input section to output section. If there is no output section yet, // then create it and add to output section list. auto AddInputSec = [&](InputSectionBase *C, StringRef Name, - ConstraintKind Constraint) { + ConstraintKind Constraint, uintX_t Align) { OutputSectionBase *Sec; bool IsNew; std::tie(Sec, IsNew) = Factory.create(C, Name); - if (IsNew) + if (IsNew) { Result.push_back(Sec); + Sec->updateAlignment(Align); + } if ((!(C->getSectionHdr()->sh_flags & SHF_WRITE)) && Constraint == ReadWrite) { Removed.insert(Sec); @@ -115,6 +117,7 @@ if (!InCmd) continue; + uint64_t Align = OutCmd->AlignExpr ? OutCmd->AlignExpr(Dot) : 0; for (ObjectFile &F : Symtab::X->getObjectFiles()) { for (InputSectionBase *S : F->getSections()) { if (isDiscarded(S) || S->OutSec) @@ -124,7 +127,7 @@ if (OutCmd->Name == "/DISCARD/") S->Live = false; else - AddInputSec(S, OutCmd->Name, OutCmd->Constraint); + AddInputSec(S, OutCmd->Name, OutCmd->Constraint, Align); } } } @@ -136,7 +139,7 @@ for (InputSectionBase *S : F->getSections()) { if (!isDiscarded(S)) { if (!S->OutSec) - AddInputSec(S, getOutputSectionName(S), NoConstraint); + AddInputSec(S, getOutputSectionName(S), NoConstraint, 0); } else reportDiscarded(S, F); } @@ -420,6 +423,7 @@ std::vector readOutputSectionPhdrs(); unsigned readPhdrType(); void readProvide(bool Hidden); + void readAlign(OutputSectionCommand *Cmd); Expr readExpr(); Expr readExpr1(Expr Lhs, int MinPrec); @@ -645,11 +649,21 @@ .Default(-1); } +void ScriptParser::readAlign(OutputSectionCommand *Cmd) { + expect("ALIGN"); + expect("("); + Cmd->AlignExpr = readExpr(); + expect(")"); +} + void ScriptParser::readOutputSectionDescription(StringRef OutSec) { OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec); Opt.Commands.emplace_back(Cmd); expect(":"); + if (peek() == "ALIGN") + readAlign(Cmd); + // Parse constraints. if (skip("ONLY_IF_RO")) Cmd->Constraint = ReadOnly; Index: test/ELF/linkerscript/linkerscript-align.s =================================================================== --- test/ELF/linkerscript/linkerscript-align.s +++ test/ELF/linkerscript/linkerscript-align.s @@ -1,6 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +## Check that ALIGN command workable using location counter # RUN: echo "SECTIONS { \ # RUN: . = 0x10000; \ # RUN: .aaa : \ @@ -27,6 +28,25 @@ # CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA # CHECK-NEXT: 3 .ccc 00000008 0000000000014000 DATA +## Check output sections ALIGN modificator +# RUN: echo "SECTIONS { \ +# RUN: . = 0x10000; \ +# RUN: .aaa : \ +# RUN: { \ +# RUN: *(.aaa) \ +# RUN: } \ +# RUN: .bbb : ALIGN(4096) \ +# RUN: { \ +# RUN: *(.bbb) \ +# RUN: } \ +# RUN: .ccc : ALIGN(4096 * 4) \ +# RUN: { \ +# RUN: *(.ccc) \ +# RUN: } \ +# RUN: }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + .global _start _start: nop