diff options
author | Fangrui Song <maskray@google.com> | 2019-09-20 15:03:21 +0000 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-09-20 15:03:21 +0000 |
commit | 267205149587595e956db25a12252835a51cd372 (patch) | |
tree | bb4e841a9dd2e00124099adbec65e8ab11e311e8 | |
parent | be428513cb05893e74a7276a21b12b709db53bb9 (diff) | |
download | bcm5719-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.cpp | 18 | ||||
-rw-r--r-- | lld/test/ELF/gc-sections-metadata-err.s | 37 |
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 |