summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2019-04-18 02:32:12 +0000
committerRui Ueyama <ruiu@google.com>2019-04-18 02:32:12 +0000
commit14ef9b30b6833358bc8adceec9231121fe17c1a3 (patch)
treeb46b96f56ffab41cbbfea4655a819bb612fab007
parent92663376563d69d96399116050b2f7b2ffe9b8d0 (diff)
downloadbcm5719-llvm-14ef9b30b6833358bc8adceec9231121fe17c1a3.tar.gz
bcm5719-llvm-14ef9b30b6833358bc8adceec9231121fe17c1a3.zip
lld: elf: Fix sections with explict addresses in regions
Patch by Gabriel Smith. The address for a section would be evaluated before the region was switched to. Because of this, the position within the region would not be updated. After the region is swapped to the dot would be set to the out of date position within the region, undoing the section address evaluation. To fix this, the region is swapped to before the section's address is evaluated. As part of the fallout of this, expandMemoryRegions needed to be gated in setDot on the condition that the evaluated address is less than the dot. This is for the case where sections are not listed from lowest address to highest address. Finally, a test for the case where sections are listed "out of order" was added. Differential Revision: https://reviews.llvm.org/D60744 llvm-svn: 358638
-rw-r--r--lld/ELF/LinkerScript.cpp7
-rw-r--r--lld/test/ELF/linkerscript/out-of-order-section-in-region.s22
2 files changed, 26 insertions, 3 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index e4b843621ec..c4a63f5c852 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -135,7 +135,7 @@ void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
// Update to location counter means update to section size.
if (InSec)
expandOutputSection(Val - Dot);
- else
+ else if (Val > Dot)
expandMemoryRegions(Val - Dot);
Dot = Val;
@@ -760,14 +760,15 @@ static OutputSection *findFirstSection(PhdrEntry *Load) {
void LinkerScript::assignOffsets(OutputSection *Sec) {
if (!(Sec->Flags & SHF_ALLOC))
Dot = 0;
- else if (Sec->AddrExpr)
- setDot(Sec->AddrExpr, Sec->Location, false);
Ctx->MemRegion = Sec->MemRegion;
Ctx->LMARegion = Sec->LMARegion;
if (Ctx->MemRegion)
Dot = Ctx->MemRegion->CurPos;
+ if ((Sec->Flags & SHF_ALLOC) && Sec->AddrExpr)
+ setDot(Sec->AddrExpr, Sec->Location, false);
+
switchTo(Sec);
if (Sec->LMAExpr)
diff --git a/lld/test/ELF/linkerscript/out-of-order-section-in-region.s b/lld/test/ELF/linkerscript/out-of-order-section-in-region.s
new file mode 100644
index 00000000000..fa514e152f5
--- /dev/null
+++ b/lld/test/ELF/linkerscript/out-of-order-section-in-region.s
@@ -0,0 +1,22 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+# RUN: echo "MEMORY { \
+# RUN: REGION (rwx) : ORIGIN = 0x1000, LENGTH = 0x100 \
+# RUN: } \
+# RUN: \
+# RUN: SECTIONS { \
+# RUN: .aaa ORIGIN(REGION) + 0x8 : { *(.aaa) } > REGION \
+# RUN: _stext = .; \
+# RUN: .bbb ORIGIN(REGION) : { *(.bbb) } > REGION \
+# RUN: . = _stext; \
+# RUN: }" > %t.script
+# RUN: ld.lld %t --script %t.script -o %t2
+# RUN: llvm-objdump -section-headers %t2 | FileCheck %s
+# CHECK: .aaa 00000008 0000000000001008 DATA
+# CHECK: .bbb 00000008 0000000000001000 DATA
+
+.section .aaa, "a"
+.quad 0
+
+.section .bbb, "a"
+.quad 0
OpenPOWER on IntegriCloud