summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Hosek <phosek@chromium.org>2017-10-23 00:51:08 +0000
committerPetr Hosek <phosek@chromium.org>2017-10-23 00:51:08 +0000
commit2fd533db9f7b121d19b5f9b9d5a7692e7b2b0fee (patch)
tree4b029e8bd5e235cc18baf58072a56023d154325d
parent8faafa4fb1452b45f7b5bcf77f4e44a6846f6f70 (diff)
downloadbcm5719-llvm-2fd533db9f7b121d19b5f9b9d5a7692e7b2b0fee.tar.gz
bcm5719-llvm-2fd533db9f7b121d19b5f9b9d5a7692e7b2b0fee.zip
[ELF] When placing orphans, handle case when last section is dead
r315292 introduced a change that's supposed to consistently ignore "dead" output sections when placing orphans. Unfortunately, that change doesn't handle the special case when the orphan section is second to last section and the last section is dead (e.g. because it's being discarded) introducing a regression in some cases. This change handles this case by using the same predicate when checking the last section. Differential Revision: https://reviews.llvm.org/D39172 llvm-svn: 316307
-rw-r--r--lld/ELF/Writer.cpp14
-rw-r--r--lld/test/ELF/linkerscript/orphan-discard.s25
2 files changed, 33 insertions, 6 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8570a807d32..836d36a5149 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1010,11 +1010,14 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B,
Sec->SortRank < CurSec->SortRank)
break;
}
+
+ auto IsLiveSection = [](BaseCommand *Cmd) {
+ auto *OS = dyn_cast<OutputSection>(Cmd);
+ return OS && OS->Live;
+ };
+
auto J = std::find_if(llvm::make_reverse_iterator(I),
- llvm::make_reverse_iterator(B), [](BaseCommand *Cmd) {
- auto *OS = dyn_cast<OutputSection>(Cmd);
- return OS && OS->Live;
- });
+ llvm::make_reverse_iterator(B), IsLiveSection);
I = J.base();
// As a special case, if the orphan section is the last section, put
@@ -1022,8 +1025,7 @@ findOrphanPos(std::vector<BaseCommand *>::iterator B,
// This matches bfd's behavior and is convenient when the linker script fully
// specifies the start of the file, but doesn't care about the end (the non
// alloc sections for example).
- auto NextSec = std::find_if(
- I, E, [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); });
+ auto NextSec = std::find_if(I, E, IsLiveSection);
if (NextSec == E)
return E;
diff --git a/lld/test/ELF/linkerscript/orphan-discard.s b/lld/test/ELF/linkerscript/orphan-discard.s
new file mode 100644
index 00000000000..6fd6fafcd7f
--- /dev/null
+++ b/lld/test/ELF/linkerscript/orphan-discard.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+# RUN: llvm-mc -position-independent -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN: . = 0xffffffff80000000; \
+# RUN: .text : ALIGN(4096) { *(.text) } \
+# RUN: .data : ALIGN(4096) { *(.data) } \
+# RUN: .bss : ALIGN(4096) { *(.bss); } \
+# RUN: . = ALIGN(4096); \
+# RUN: _end = .; \
+# RUN: /DISCARD/ : { *(.comment) } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t --script %t.script %t.o
+# RUN: llvm-readelf -s -symbols %t | FileCheck %s
+
+# CHECK: .bss NOBITS ffffffff80002000 002008 000002 00 WA 0 0 4096
+# CHECK: ffffffff80003000 0 NOTYPE GLOBAL DEFAULT 3 _end
+
+.section .text, "ax"
+ ret
+
+.section .data, "aw"
+ .quad 0
+
+.section .bss, "", @nobits
+ .short 0
OpenPOWER on IntegriCloud