[PATCH] D67848: [LLD][ELF][ARM] Fix crash when discarding all of the InputSections that have .ARM.exidx sections

Peter Smith via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 20 11:00:56 PDT 2019


peter.smith created this revision.
peter.smith added reviewers: ruiu, grimar, MaskRay.
Herald added subscribers: kristof.beyls, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

While experimenting with some test cases for D67761 <https://reviews.llvm.org/D67761> earlier today I found that I could crash the linker when I discarded all the InputSections, but not the .ARM.exidx sections that had a dependency on them. This was ostensibly down to the OutputSection code using a non-existing InputSection to obtain a OutputSection for the OutputSection link order dependency. Attempts to clumsily fix this resulted in other crashes as the executableSections and exidxSections weren't in synch.

The fix makes sure that we only add to the exidxSections when the section it depends on would be added to the executableSections. This allows us to remove the empty flag and then implement a more sophisticated needed() so that we discard the .ARM.exidx section if it wouldn't be valid to write it.

This is independent of the fix for D67761 <https://reviews.llvm.org/D67761>.


https://reviews.llvm.org/D67848

Files:
  lld/ELF/SyntheticSections.cpp
  lld/ELF/SyntheticSections.h
  lld/test/ELF/arm-exidx-discard-all.s


Index: lld/test/ELF/arm-exidx-discard-all.s
===================================================================
--- /dev/null
+++ lld/test/ELF/arm-exidx-discard-all.s
@@ -0,0 +1,19 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o
+// RUN: echo "ENTRY(__entrypoint) SECTIONS { /DISCARD/ : { *(.text.1) } }" > %t.script
+// RUN: ld.lld -T %t.script %t.o -o %t.elf
+// RUN: llvm-readobj --sections %t.elf | FileCheck %s
+
+/// Test that when we /DISCARD/ all the input sections with associated
+/// .ARM.exidx sections then we also discard all the .ARM.exidx sections.
+
+ .section .text.1, "ax", %progbits
+ .global foo
+ .type foo, %function
+ .fnstart
+foo:
+  bx lr
+  .cantunwind
+  .fnend
+
+// CHECK-NOT: .ARM.exidx
Index: lld/ELF/SyntheticSections.h
===================================================================
--- lld/ELF/SyntheticSections.h
+++ lld/ELF/SyntheticSections.h
@@ -994,7 +994,7 @@
 
   size_t getSize() const override { return size; }
   void writeTo(uint8_t *buf) override;
-  bool isNeeded() const override { return !empty; }
+  bool isNeeded() const override;
   // Sort and remove duplicate entries.
   void finalizeContents() override;
   InputSection *getLinkOrderDep() const;
@@ -1008,9 +1008,6 @@
 private:
   size_t size;
 
-  // Empty if ExecutableSections contains no dependent .ARM.exidx sections.
-  bool empty = true;
-
   // Instead of storing pointers to the .ARM.exidx InputSections from
   // InputObjects, we store pointers to the executable sections that need
   // .ARM.exidx sections. We can then use the dependentSections of these to
Index: lld/ELF/SyntheticSections.cpp
===================================================================
--- lld/ELF/SyntheticSections.cpp
+++ lld/ELF/SyntheticSections.cpp
@@ -3218,17 +3218,23 @@
   return nullptr;
 }
 
+static bool isValidExidxSectionDep(InputSection *isec) {
+  return (isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
+         isec->getSize() > 0;
+}
+
 bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
   if (isec->type == SHT_ARM_EXIDX) {
-    exidxSections.push_back(isec);
-    return true;
+    if (InputSection* dep = isec->getLinkOrderDep())
+      if (isValidExidxSectionDep(dep)) {
+        exidxSections.push_back(isec);
+        return true;
+      }
+    return false;
   }
 
-  if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
-      isec->getSize() > 0) {
+  if (isValidExidxSectionDep(isec)) {
     executableSections.push_back(isec);
-    if (empty && findExidxSection(isec))
-      empty = false;
     return false;
   }
 
@@ -3395,6 +3401,12 @@
   assert(size == offset + 8);
 }
 
+bool ARMExidxSyntheticSection::isNeeded() const {
+  return llvm::find_if(exidxSections, [](InputSection *isec) {
+           return isec->isLive();
+         }) != exidxSections.end();
+}
+
 bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
   return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67848.221068.patch
Type: text/x-patch
Size: 3070 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190920/36d15d5c/attachment.bin>


More information about the llvm-commits mailing list