[lld] r372400 - [ELF] Error if the linked-to section of a SHF_LINK_ORDER section is discarded

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 20 08:03:21 PDT 2019


Author: maskray
Date: Fri Sep 20 08:03:21 2019
New Revision: 372400

URL: http://llvm.org/viewvc/llvm-project?rev=372400&view=rev
Log:
[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

Added:
    lld/trunk/test/ELF/gc-sections-metadata-err.s
Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=372400&r1=372399&r2=372400&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Sep 20 08:03:21 2019
@@ -1500,6 +1500,12 @@ template <class ELFT> void Writer<ELFT>:
     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>:
         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>:
   // 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":

Added: lld/trunk/test/ELF/gc-sections-metadata-err.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gc-sections-metadata-err.s?rev=372400&view=auto
==============================================================================
--- lld/trunk/test/ELF/gc-sections-metadata-err.s (added)
+++ lld/trunk/test/ELF/gc-sections-metadata-err.s Fri Sep 20 08:03:21 2019
@@ -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", at progbits,.foo0,unique,0
+bar0:
+.byte 0
+.section .bar,"ao", at progbits,.foo1,unique,1
+bar1:
+.byte 1
+
+## Another case: the linked-to section of the second input section is discarded.
+.section .baz,"ao", at progbits,.foo1,unique,0
+baz0:
+.byte 0
+.section .baz,"ao", at progbits,.foo0,unique,1
+baz1:
+.byte 1




More information about the llvm-commits mailing list