Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -215,6 +215,7 @@ void addSymbol(SymbolAssignment *Cmd); void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); + void expandOutputSection(uint64_t Size); std::vector computeInputSections(const InputSectionDescription *); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -102,16 +102,36 @@ return CmdRef; } +// Expands the memory region by the specified size. +static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size, + StringRef RegionName, StringRef SecName) { + MemRegion->CurPos += Size; + uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin; + if (NewSize > MemRegion->Length) + error("section '" + SecName + "' will not fit in region '" + RegionName + + "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes"); +} + +void LinkerScript::expandOutputSection(uint64_t Size) { + Ctx->OutSec->Size += Size; + if (Ctx->MemRegion) + expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, + Ctx->OutSec->Name); + // FIXME: check LMA region overflow too. + if (Ctx->LMARegion) + Ctx->LMARegion->CurPos += Size; +} + void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { uint64_t Val = E().getValue(); if (Val < Dot && InSec) error(Loc + ": unable to move location counter backward for: " + Ctx->OutSec->Name); - Dot = Val; // Update to location counter means update to section size. if (InSec) - Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; + expandOutputSection(Val - Dot); + Dot = Val; } // Used for handling linker symbol assignments, for both finalizing @@ -621,16 +641,6 @@ return End; } -// Expands the memory region by the specified size. -static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size, - StringRef RegionName, StringRef SecName) { - MemRegion->CurPos += Size; - uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin; - if (NewSize > MemRegion->Length) - error("section '" + SecName + "' will not fit in region '" + RegionName + - "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes"); -} - void LinkerScript::output(InputSection *S) { uint64_t Before = advance(0, 1); uint64_t Pos = advance(S->getSize(), S->Alignment); @@ -639,17 +649,7 @@ // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } - Ctx->OutSec->Size = Pos - Ctx->OutSec->Addr; - - // If there is a memory region associated with this input section, then - // place the section in that region and update the region index. - if (Ctx->LMARegion) - Ctx->LMARegion->CurPos += Pos - Before; - // FIXME: should we also produce overflow errors for LMARegion? - - if (Ctx->MemRegion) - expandMemoryRegion(Ctx->MemRegion, Pos - Before, Ctx->MemRegion->Name, - Ctx->OutSec->Name); + expandOutputSection(Pos - Before); } void LinkerScript::switchTo(OutputSection *Sec) { @@ -739,12 +739,7 @@ if (auto *Cmd = dyn_cast(Base)) { Cmd->Offset = Dot - Ctx->OutSec->Addr; Dot += Cmd->Size; - if (Ctx->MemRegion) - expandMemoryRegion(Ctx->MemRegion, Cmd->Size, Ctx->MemRegion->Name, - Ctx->OutSec->Name); - if (Ctx->LMARegion) - Ctx->LMARegion->CurPos += Cmd->Size; - Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; + expandOutputSection(Cmd->Size); continue; } Index: test/ELF/linkerscript/memory-loc-counter.test =================================================================== --- test/ELF/linkerscript/memory-loc-counter.test +++ test/ELF/linkerscript/memory-loc-counter.test @@ -0,0 +1,37 @@ +# REQUIRES: x86 + +# RUN: echo ".section .foo,\"a\"" > %t.s +# RUN: echo ".quad 1" >> %t.s +# RUN: echo ".section .bar,\"a\"" >> %t.s +# RUN: echo ".quad 1" >> %t.s +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o + +# RUN: ld.lld -o %t %t.o --script %s +# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s + +## Check that we can produce output without errors, +## and .foo section has proper size. +# CHECK: Section Headers: +# CHECK-NEXT: [Nr] Name Type Address Off Size +# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 +# CHECK-NEXT: [ 1] .foo PROGBITS 0000000000001000 001000 000108 +# CHECK-NEXT: [ 2] .bar PROGBITS 0000000000001108 001108 000008 + +## Check that load address is correct. +# CHECK: Program Headers: +# CHECK-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz +# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000002000 0x000110 0x000110 + +MEMORY { + ram (rwx) : org = 0x1000, len = 0x200 + flash (rwx) : org = 0x2000, len = 0x200 +} +SECTIONS { + .foo : { + *(.foo) + . += 0x100; + } > ram AT>flash + .bar : { + *(.bar) + } > ram AT>flash +}