aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-01-24 15:48:26 +0000
committerHans Wennborg <hans@hanshq.net>2018-01-24 15:48:26 +0000
commita4e0f76208b2d56ee4b92735bf28275f8d5ff819 (patch)
treeca8d214d4071945e6bfb8df8f352ae767942165a
parent29428941e27149f45d47b77da00b80b2438bbca7 (diff)
Merging r322359, r322421, and r322801:
------------------------------------------------------------------------ r322359 | grimar | 2018-01-12 10:07:35 +0100 (Fri, 12 Jan 2018) | 8 lines [ELF] - Fix for ld.lld does not accept "AT" syntax for declaring LMA region AT> lma_region expression allows to specify the memory region for section load address. Should fix PR35684. Differential revision: https://reviews.llvm.org/D41397 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r322421 | rafael | 2018-01-13 00:26:25 +0100 (Sat, 13 Jan 2018) | 9 lines Fix incorrect physical address on self-referencing AT command. When a section placement (AT) command references the section itself, the physical address of the section in the ELF header was calculated incorrectly due to alignment happening right after the location pointer's value was captured. The problem was diagnosed and the first version of the patch written by Erick Reyes. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r322801 | rafael | 2018-01-18 02:14:57 +0100 (Thu, 18 Jan 2018) | 5 lines Handle parsing AT(ADDR(.foo-bar)). The problem we had with it is that anything inside an AT is an expression, so we failed to parse the section name because of the - in it. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/lld/branches/release_60@323336 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--ELF/LinkerScript.cpp25
-rw-r--r--ELF/OutputSections.h1
-rw-r--r--ELF/ScriptParser.cpp11
-rw-r--r--test/ELF/linkerscript/at-self-reference.s63
-rw-r--r--test/ELF/linkerscript/at2.s81
-rw-r--r--test/ELF/linkerscript/parse-section-in-addr.s10
6 files changed, 183 insertions, 8 deletions
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 16b306da4..33a618952 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -608,13 +608,6 @@ void LinkerScript::switchTo(OutputSection *Sec) {
Ctx->OutSec = Sec;
Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment);
-
- // If neither AT nor AT> is specified for an allocatable section, the linker
- // will set the LMA such that the difference between VMA and LMA for the
- // section is the same as the preceding output section in the same region
- // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
- if (Ctx->LMAOffset)
- Ctx->OutSec->LMAOffset = Ctx->LMAOffset();
}
// This function searches for a memory region to place the given output
@@ -662,12 +655,28 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
if (Ctx->MemRegion)
Dot = Ctx->MemRegionOffset[Ctx->MemRegion];
+ switchTo(Sec);
+
if (Sec->LMAExpr) {
uint64_t D = Dot;
Ctx->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; };
}
- switchTo(Sec);
+ if (!Sec->LMARegionName.empty()) {
+ if (MemoryRegion *MR = MemoryRegions.lookup(Sec->LMARegionName)) {
+ uint64_t Offset = MR->Origin - Dot;
+ Ctx->LMAOffset = [=] { return Offset; };
+ } else {
+ error("memory region '" + Sec->LMARegionName + "' not declared");
+ }
+ }
+
+ // If neither AT nor AT> is specified for an allocatable section, the linker
+ // will set the LMA such that the difference between VMA and LMA for the
+ // section is the same as the preceding output section in the same region
+ // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
+ if (Ctx->LMAOffset)
+ Ctx->OutSec->LMAOffset = Ctx->LMAOffset();
// The Size previously denoted how many InputSections had been added to this
// section, and was used for sorting SHF_LINK_ORDER sections. Reset it to
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index b2845773e..009f45c03 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -99,6 +99,7 @@ public:
ConstraintKind Constraint = ConstraintKind::NoConstraint;
std::string Location;
std::string MemoryRegionName;
+ std::string LMARegionName;
bool Noload = false;
template <class ELFT> void finalize();
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index 426394498..e068beeee 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -709,6 +709,14 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
if (consume(">"))
Cmd->MemoryRegionName = next();
+ if (consume("AT")) {
+ expect(">");
+ Cmd->LMARegionName = next();
+ }
+
+ if (Cmd->LMAExpr && !Cmd->LMARegionName.empty())
+ error("section can't have both LMA and a load region");
+
Cmd->Phdrs = readOutputSectionPhdrs();
if (consume("="))
@@ -922,7 +930,10 @@ ByteCommand *ScriptParser::readByteCommand(StringRef Tok) {
StringRef ScriptParser::readParenLiteral() {
expect("(");
+ bool Orig = InExpr;
+ InExpr = false;
StringRef Tok = next();
+ InExpr = Orig;
expect(")");
return Tok;
}
diff --git a/test/ELF/linkerscript/at-self-reference.s b/test/ELF/linkerscript/at-self-reference.s
new file mode 100644
index 000000000..7208a4b9f
--- /dev/null
+++ b/test/ELF/linkerscript/at-self-reference.s
@@ -0,0 +1,63 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "SECTIONS { \
+# RUN: . = 0x1000; \
+# RUN: .aaa : AT(ADDR(.aaa)) { *(.aaa) } \
+# RUN: .bbb : AT(ADDR(.bbb)) { *(.bbb) } \
+# 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: 0x1000
+# CHECK-NEXT: PhysicalAddress: 0x1000
+# CHECK-NEXT: FileSize: 3
+# CHECK-NEXT: MemSize: 3
+# 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_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x1008
+# CHECK-NEXT: VirtualAddress: 0x1008
+# CHECK-NEXT: PhysicalAddress: 0x1008
+# CHECK-NEXT: FileSize: 9
+# CHECK-NEXT: MemSize: 9
+# 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 .aaa, "a"
+.asciz "aa"
+
+.section .bbb, "a"
+.align 8
+.quad 0
diff --git a/test/ELF/linkerscript/at2.s b/test/ELF/linkerscript/at2.s
new file mode 100644
index 000000000..1545b1d82
--- /dev/null
+++ b/test/ELF/linkerscript/at2.s
@@ -0,0 +1,81 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "MEMORY { \
+# RUN: AX (ax) : ORIGIN = 0x2000, LENGTH = 0x100 \
+# RUN: AW (aw) : ORIGIN = 0x3000, LENGTH = 0x100 \
+# RUN: FLASH (ax) : ORIGIN = 0x6000, LENGTH = 0x100 \
+# RUN: RAM (aw) : ORIGIN = 0x7000, LENGTH = 0x100 } \
+# RUN: SECTIONS { \
+# RUN: .foo1 : { *(.foo1) } > AX AT>FLASH \
+# RUN: .foo2 : { *(.foo2) } > AX \
+# RUN: .bar1 : { *(.bar1) } > AW AT> RAM \
+# RUN: .bar2 : { *(.bar2) } > AW AT > RAM \
+# RUN: .bar3 : { *(.bar3) } > AW AT >RAM \
+# RUN: }" > %t.script
+# RUN: ld.lld %t --script %t.script -o %t2
+# RUN: llvm-readobj -program-headers %t2 | FileCheck %s
+# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=SECTIONS
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: VirtualAddress: 0x2000
+# CHECK-NEXT: PhysicalAddress: 0x6000
+# CHECK-NEXT: FileSize: 16
+# CHECK-NEXT: MemSize: 16
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_X
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment:
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x2000
+# CHECK-NEXT: VirtualAddress: 0x3000
+# CHECK-NEXT: PhysicalAddress: 0x7000
+# CHECK-NEXT: FileSize: 24
+# CHECK-NEXT: MemSize: 24
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+
+# SECTIONS: Sections:
+# SECTIONS-NEXT: Idx Name Size Address
+# SECTIONS-NEXT: 0 00000000 0000000000000000
+# SECTIONS-NEXT: 1 .foo1 00000008 0000000000002000
+# SECTIONS-NEXT: 2 .foo2 00000008 0000000000002008
+# SECTIONS-NEXT: 3 .text 00000000 0000000000002010
+# SECTIONS-NEXT: 4 .bar1 00000008 0000000000003000
+# SECTIONS-NEXT: 5 .bar2 00000008 0000000000003008
+# SECTIONS-NEXT: 6 .bar3 00000008 0000000000003010
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "MEMORY { \
+# RUN: FLASH (ax) : ORIGIN = 0x2000, LENGTH = 0x100 \
+# RUN: RAM (aw) : ORIGIN = 0x5000, LENGTH = 0x100 } \
+# RUN: SECTIONS { \
+# RUN: .foo1 : AT(0x500) { *(.foo1) } > FLASH AT>FLASH \
+# RUN: }" > %t2.script
+# RUN: not ld.lld %t --script %t2.script -o %t2 2>&1 | \
+# RUN: FileCheck %s --check-prefix=ERR
+# ERR: error: section can't have both LMA and a load region
+
+.section .foo1, "ax"
+.quad 0
+
+.section .foo2, "ax"
+.quad 0
+
+.section .bar1, "aw"
+.quad 0
+
+.section .bar2, "aw"
+.quad 0
+
+.section .bar3, "aw"
+.quad 0
diff --git a/test/ELF/linkerscript/parse-section-in-addr.s b/test/ELF/linkerscript/parse-section-in-addr.s
new file mode 100644
index 000000000..7a79f6463
--- /dev/null
+++ b/test/ELF/linkerscript/parse-section-in-addr.s
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# RUN: echo "SECTIONS { \
+# RUN: .foo-bar : AT(ADDR(.foo-bar)) { *(.text) } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
+# RUN: llvm-readelf -S %t.so | FileCheck %s
+
+# CHECK: .foo-bar