summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-09-22 18:05:49 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-09-22 18:05:49 +0000
commit15c579518dee3425921bacef5acd17a34a71f772 (patch)
tree4a99e243c74a2670567bdf4cbbcbe7d36f5edd03
parent5edef42e7f2b2fe7070e59b1540e8b7c2eca3e27 (diff)
downloadbcm5719-llvm-15c579518dee3425921bacef5acd17a34a71f772.tar.gz
bcm5719-llvm-15c579518dee3425921bacef5acd17a34a71f772.zip
Don't move orphan sections past assignments.
This fixes a case where we would produce an unaligned PT_LOAD. llvm-svn: 282180
-rw-r--r--lld/ELF/LinkerScript.cpp36
-rw-r--r--lld/test/ELF/linkerscript/orphan-align.s27
2 files changed, 58 insertions, 5 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index cfb1fb30e91..74712a27f8c 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -514,6 +514,29 @@ template <class ELFT> void LinkerScript<ELFT>::adjustSectionsBeforeSorting() {
}
}
+// When placing orphan sections, we want to place them after symbol assignments
+// so that an orphan after
+// begin_foo = .;
+// foo : { *(foo) }
+// end_foo = .;
+// doesn't break the intended meaning of the begin/end symbols.
+// We don't want to go over sections since Writer<ELFT>::sortSections is the
+// one in charge of deciding the order of the sections.
+// We don't want to go over alignments, since doing so in
+// rx_sec : { *(rx_sec) }
+// . = ALIGN(0x1000);
+// /* The RW PT_LOAD starts here*/
+// rw_sec : { *(rw_sec) }
+// would mean that the RW PT_LOAD would become unaligned.
+static bool shouldSkip(const BaseCommand &Cmd) {
+ if (isa<OutputSectionCommand>(Cmd))
+ return false;
+ const auto *Assign = dyn_cast<SymbolAssignment>(&Cmd);
+ if (!Assign)
+ return true;
+ return Assign->Name != ".";
+}
+
template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
// Orphan sections are sections present in the input files which
// are not explicitly placed into the output file by the linker script.
@@ -529,10 +552,10 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
StringRef Name = Sec->getName();
// Find the last spot where we can insert a command and still get the
- // correct order.
+ // correct result.
auto CmdIter = Opt.Commands.begin() + CmdIndex;
auto E = Opt.Commands.end();
- while (CmdIter != E && !isa<OutputSectionCommand>(**CmdIter)) {
+ while (CmdIter != E && shouldSkip(**CmdIter)) {
++CmdIter;
++CmdIndex;
}
@@ -545,10 +568,13 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
if (Pos == E) {
Opt.Commands.insert(CmdIter,
llvm::make_unique<OutputSectionCommand>(Name));
- } else {
- assert(Pos == CmdIter && "Section order doesn't match the linker script");
+ ++CmdIndex;
+ continue;
}
- ++CmdIndex;
+
+ // Continue from where we found it.
+ CmdIndex = (Pos - Opt.Commands.begin()) + 1;
+ continue;
}
// Assign addresses as instructed by linker script SECTIONS sub-commands.
diff --git a/lld/test/ELF/linkerscript/orphan-align.s b/lld/test/ELF/linkerscript/orphan-align.s
new file mode 100644
index 00000000000..7539a8d0f80
--- /dev/null
+++ b/lld/test/ELF/linkerscript/orphan-align.s
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: . = ALIGN(0x1000); \
+# RUN: .data.rel.ro : { *(.data.rel.ro) } \
+# RUN: }" \ > %t.script
+# RUN: ld.lld -o %t -T %t.script %t.o -shared
+# RUN: llvm-readobj -l %t | FileCheck %s
+
+
+# Test that the orphan section foo is placed before the ALIGN and so the second
+# PT_LOAD is aligned.
+
+
+# CHECK: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x0
+
+# CHECK: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x1000
+
+nop
+.section .data.rel.ro, "aw"
+.byte 0
+
+.section foo, "ax"
+nop
OpenPOWER on IntegriCloud