summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-09-20 15:03:21 +0000
committerFangrui Song <maskray@google.com>2019-09-20 15:03:21 +0000
commit267205149587595e956db25a12252835a51cd372 (patch)
treebb4e841a9dd2e00124099adbec65e8ab11e311e8
parentbe428513cb05893e74a7276a21b12b709db53bb9 (diff)
downloadbcm5719-llvm-267205149587595e956db25a12252835a51cd372.tar.gz
bcm5719-llvm-267205149587595e956db25a12252835a51cd372.zip
[ELF] Error if the linked-to section of a SHF_LINK_ORDER section is discarded
Summary: If st_link(A)=B, and A has the SHF_LINK_ORDER flag, we may dereference a null pointer if B is garbage collected (PR43147): 1. In Wrter.cpp:compareByFilePosition, `aOut->sectionIndex` or `bOut->sectionIndex` 2. In OutputSections::finalize, `d->getParent()->sectionIndex` Simply error and bail out to avoid null pointer dereferences. ld.bfd has a similar error: sh_link of section `.bar' points to discarded section `.foo0' of `a.o' ld.bfd is more permissive in that it just checks whether the linked-to section of the first input section is discarded. This is likely because it sets sh_link of the output section according to the first input section. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D67761 llvm-svn: 372400
-rw-r--r--lld/ELF/Writer.cpp18
-rw-r--r--lld/test/ELF/gc-sections-metadata-err.s37
2 files changed, 51 insertions, 4 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 9a618830cbf..f0334470e5e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1500,6 +1500,12 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
if (!(sec->flags & SHF_LINK_ORDER))
continue;
+ // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
+ // this processing inside the ARMExidxsyntheticsection::finalizeContents().
+ if (!config->relocatable && config->emachine == EM_ARM &&
+ sec->type == SHT_ARM_EXIDX)
+ continue;
+
// Link order may be distributed across several InputSectionDescriptions
// but sort must consider them all at once.
std::vector<InputSection **> scriptSections;
@@ -1509,14 +1515,16 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
for (InputSection *&isec : isd->sections) {
scriptSections.push_back(&isec);
sections.push_back(isec);
+
+ InputSection *link = isec->getLinkOrderDep();
+ if (!link->getParent())
+ error(toString(isec) + ": sh_link points to discarded section " +
+ toString(link));
}
}
}
- // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
- // this processing inside the ARMExidxsyntheticsection::finalizeContents().
- if (!config->relocatable && config->emachine == EM_ARM &&
- sec->type == SHT_ARM_EXIDX)
+ if (errorCount())
continue;
llvm::stable_sort(sections, compareByFilePosition);
@@ -1894,6 +1902,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// SHFLinkOrder processing must be processed after relative section placements are
// known but before addresses are allocated.
resolveShfLinkOrder();
+ if (errorCount())
+ return;
// This is used to:
// 1) Create "thunks":
diff --git a/lld/test/ELF/gc-sections-metadata-err.s b/lld/test/ELF/gc-sections-metadata-err.s
new file mode 100644
index 00000000000..0f96e4157df
--- /dev/null
+++ b/lld/test/ELF/gc-sections-metadata-err.s
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+
+## Error if the linked-to section of an input section is discarded.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: not ld.lld --gc-sections --print-gc-sections %t.o -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK: removing unused section {{.*}}.o:(.foo0)
+# CHECK-NEXT: error: {{.*}}.o:(.bar): sh_link points to discarded section {{.*}}.o:(.foo0)
+# CHECK-NEXT: error: {{.*}}.o:(.baz): sh_link points to discarded section {{.*}}.o:(.foo0)
+
+.globl _start
+_start:
+ call .foo1
+ call bar0
+ call bar1
+ call baz0
+ call baz1
+
+.section .foo0,"a"
+.section .foo1,"a"
+
+## The linked-to section of the first input section is discarded.
+.section .bar,"ao",@progbits,.foo0,unique,0
+bar0:
+.byte 0
+.section .bar,"ao",@progbits,.foo1,unique,1
+bar1:
+.byte 1
+
+## Another case: the linked-to section of the second input section is discarded.
+.section .baz,"ao",@progbits,.foo1,unique,0
+baz0:
+.byte 0
+.section .baz,"ao",@progbits,.foo0,unique,1
+baz1:
+.byte 1
OpenPOWER on IntegriCloud