Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -151,6 +151,7 @@ void assignAddresses(); int compareSections(StringRef A, StringRef B); bool hasPhdrsCommands(); + uintX_t getOutputSectionAddress(StringRef Name); uintX_t getOutputSectionSize(StringRef Name); uintX_t getHeaderSize(); Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -533,6 +533,16 @@ } template +typename ELFT::uint +LinkerScript::getOutputSectionAddress(StringRef Name) { + for (OutputSectionBase *Sec : *OutputSections) + if (Sec->getName() == Name) + return Sec->getVA(); + error("undefined section " + Name); + return 0; +} + +template typename ELFT::uint LinkerScript::getOutputSectionSize(StringRef Name) { for (OutputSectionBase *Sec : *OutputSections) if (Sec->getName() == Name) @@ -1044,6 +1054,21 @@ } } +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"); + } +} + static uint64_t getHeaderSize() { switch (Config->EKind) { case ELF32LEKind: @@ -1154,6 +1179,12 @@ // Built-in functions are parsed here. // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. + if (Tok == "ADDR") { + expect("("); + StringRef Name = next(); + expect(")"); + return [=](uint64_t Dot) { return getSectionAddress(Name); }; + } if (Tok == "ASSERT") return readAssert(); if (Tok == "ALIGN") { Index: lld/trunk/test/ELF/linkerscript/linkerscript-addr.s =================================================================== --- lld/trunk/test/ELF/linkerscript/linkerscript-addr.s +++ lld/trunk/test/ELF/linkerscript/linkerscript-addr.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; \ +# RUN: .text : { *(.text*) } \ +# RUN: .foo.1 : { *(.foo.1) } \ +# RUN: .foo.2 ADDR(.foo.1) + 0x100 : { *(.foo.2) } \ +# RUN: .foo.3 : { *(.foo.3) } \ +# RUN: }" > %t.script +# RUN: ld.lld %t --script %t.script -o %t1 +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000000 0000000000001000 TEXT DATA +# CHECK-NEXT: 2 .foo.1 00000008 0000000000001000 DATA +# CHECK-NEXT: 3 .foo.2 00000008 0000000000001100 DATA +# CHECK-NEXT: 4 .foo.3 00000008 0000000000001108 DATA + +.text +.globl _start +_start: + +.section .foo.1,"a" + .quad 1 + +.section .foo.2,"a" + .quad 2 + +.section .foo.3,"a" + .quad 3