Index: lld/ELF/LinkerScript.h =================================================================== --- lld/ELF/LinkerScript.h +++ lld/ELF/LinkerScript.h @@ -212,6 +212,7 @@ std::vector getPhdrIndices(OutputSection *Sec); MemoryRegion *findMemoryRegion(OutputSection *Sec); + MemoryRegion *findMemoryRegion(StringRef Name); void switchTo(OutputSection *Sec); uint64_t advance(uint64_t Size, unsigned Align); Index: lld/ELF/LinkerScript.cpp =================================================================== --- lld/ELF/LinkerScript.cpp +++ lld/ELF/LinkerScript.cpp @@ -539,9 +539,8 @@ // If a memory region name was specified in the output section command, // then try to find that region first. if (!Sec->MemoryRegionName.empty()) { - auto It = MemoryRegions.find(Sec->MemoryRegionName); - if (It != MemoryRegions.end()) - return It->second; + if (MemoryRegion *M = findMemoryRegion(Sec->MemoryRegionName)) + return M; error("memory region '" + Sec->MemoryRegionName + "' not declared"); return nullptr; } @@ -565,6 +564,13 @@ return nullptr; } +MemoryRegion *LinkerScript::findMemoryRegion(StringRef Name) { + auto It = MemoryRegions.find(Name); + if (It != MemoryRegions.end()) + return It->second; + return nullptr; +} + // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). void LinkerScript::assignOffsets(OutputSection *Sec) { @@ -582,6 +588,11 @@ Ctx->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; }; } + if (!Sec->LMARegionName.empty()) + Ctx->LMAOffset = [=] { + return Ctx->MemRegionOffset[findMemoryRegion(Sec->LMARegionName)]; + }; + switchTo(Sec); // We do not support custom layout for compressed debug sectons. Index: lld/ELF/OutputSections.h =================================================================== --- lld/ELF/OutputSections.h +++ lld/ELF/OutputSections.h @@ -95,6 +95,7 @@ ConstraintKind Constraint = ConstraintKind::NoConstraint; std::string Location; std::string MemoryRegionName; + std::string LMARegionName; bool Noload = false; template void finalize(); Index: lld/ELF/ScriptParser.cpp =================================================================== --- lld/ELF/ScriptParser.cpp +++ lld/ELF/ScriptParser.cpp @@ -695,6 +695,13 @@ else if (peek().startswith(">")) Cmd->MemoryRegionName = next().drop_front(); + if (consume("AT")) { + if (consume(">")) + Cmd->LMARegionName = next(); + else if (peek().startswith(">")) + Cmd->LMARegionName = next().drop_front(); + } + Cmd->Phdrs = readOutputSectionPhdrs(); if (consume("=")) Index: lld/test/ELF/linkerscript/lma.s =================================================================== --- /dev/null +++ lld/test/ELF/linkerscript/lma.s @@ -0,0 +1,54 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "MEMORY { \ +# RUN: ram (rwx) : ORIGIN = 0, LENGTH = 1024M \ +# RUN: rom (rx) : org = (0x80 * 0x1000 * 0x1000), len = 64M \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: . = 0x1000; \ +# RUN: .foo : { \ +# RUN: _foo = .; \ +# RUN: *(.foo*); \ +# RUN: _efoo = .; \ +# RUN: } >ram AT >rom \ +# RUN: .end = .; \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x80000000 +# CHECK-NEXT: PhysicalAddress: 0x80000000 +# CHECK-NEXT: FileSize: 1 +# CHECK-NEXT: MemSize: 1 +# CHECK-NEXT: Flags [ (0x5) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x0 +# CHECK-NEXT: PhysicalAddress: 0x0 +# CHECK-NEXT: FileSize: 0 +# CHECK-NEXT: MemSize: 0 +# CHECK-NEXT: Flags [ (0x6) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.global _start +_start: + nop + +.section .foo +.string "fighters" +.quad 0