[lld] r320668 - [ELF] Prevent crash in writing an .ARM.exidx sentinel entry.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 13 22:23:50 PST 2017


Author: ikudrin
Date: Wed Dec 13 22:23:50 2017
New Revision: 320668

URL: http://llvm.org/viewvc/llvm-project?rev=320668&view=rev
Log:
[ELF] Prevent crash in writing an .ARM.exidx sentinel entry.

We might crash in 'ARMExidxSentinelSection::writeTo()' because it expected
the sentinel entry to be put in the same 'InputSectionDescription' as
the last real entry. This assumption fails if the last output section command
for .ARM.exidx is anything but an input section description, because in this
case 'OutputSection::addSection()' creates a new 'InputSectionDescription'.

Differential Revision: https://reviews.llvm.org/D41105

Added:
    lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=320668&r1=320667&r2=320668&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Dec 13 22:23:50 2017
@@ -2569,16 +2569,22 @@ ARMExidxSentinelSection::ARMExidxSentine
 void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
   // The Sections are sorted in order of ascending PREL31 address with the
   // sentinel last. We need to find the InputSection that precedes the
-  // sentinel. By construction the Sentinel is in the last
-  // InputSectionDescription as the InputSection that precedes it.
+  // sentinel.
   OutputSection *C = getParent();
-  auto ISD =
-      std::find_if(C->SectionCommands.rbegin(), C->SectionCommands.rend(),
-                   [](const BaseCommand *Base) {
-                     return isa<InputSectionDescription>(Base);
-                   });
-  auto L = cast<InputSectionDescription>(*ISD);
-  InputSection *Highest = L->Sections[L->Sections.size() - 2];
+  InputSection *Highest = nullptr;
+  int Skip = 1;
+  for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) {
+    if (!isa<InputSectionDescription>(Base))
+      continue;
+    auto L = cast<InputSectionDescription>(Base);
+    if (Skip >= L->Sections.size()) {
+      Skip -= L->Sections.size();
+      continue;
+    }
+    Highest = L->Sections[L->Sections.size() - Skip - 1];
+    break;
+  }
+  assert(Highest);
   InputSection *LS = Highest->getLinkOrderDep();
   uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize());
   uint64_t P = getVA();

Added: lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s?rev=320668&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s (added)
+++ lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s Wed Dec 13 22:23:50 2017
@@ -0,0 +1,24 @@
+# REQUIRES: arm
+# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+# RUN: echo "SECTIONS {                                        \
+# RUN:         .ARM.exidx 0x1000 : { *(.ARM.exidx*) foo = .; } \
+# RUN:         .text      0x2000 : { *(.text*) }               \
+# RUN:       }" > %t.script
+## We used to crash if the last output section command for .ARM.exidx
+## was anything but an input section description.
+# RUN: ld.lld -T %t.script %t.o -shared -o %t.so
+# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+
+ .syntax unified
+ .text
+ .global _start
+_start:
+ .fnstart
+ .cantunwind
+ bx lr
+ .fnend
+
+// CHECK: Contents of section .ARM.exidx:
+// 1000 + 1000 = 0x2000 = _start
+// 1008 + 0ffc = 0x2004 = _start + sizeof(_start)
+// CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000




More information about the llvm-commits mailing list