[lld] r255883 - [ELF] - implement support of extended length field for CIE/FDE records of eh_frame.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 17 01:23:40 PST 2015


Author: grimar
Date: Thu Dec 17 03:23:40 2015
New Revision: 255883

URL: http://llvm.org/viewvc/llvm-project?rev=255883&view=rev
Log:
[ELF] - implement support of extended length field for CIE/FDE records of eh_frame.

Ian Lance Taylor writes: "Read 4 bytes. If they are not 0xffffffff, they are the length of the CIE or FDE record. Otherwise the next 64 bits holds the length, and this is a 64-bit DWARF format. This is like .debug_frame." (http://www.airs.com/blog/archives/460), that also consistent with spec (https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html).

Patch implements support of described extended length field and also adds few more checks for safety.

Differential revision: http://reviews.llvm.org/D15532

Added:
    lld/trunk/test/ELF/invalid-cie-length3.s
    lld/trunk/test/ELF/invalid-cie-length4.s
    lld/trunk/test/ELF/invalid-cie-length5.s
    lld/trunk/test/ELF/valid-cie-length-dw64.s
Modified:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=255883&r1=255882&r2=255883&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Dec 17 03:23:40 2015
@@ -943,16 +943,10 @@ void EHOutputSection<ELFT>::addSectionAu
 
   DenseMap<unsigned, unsigned> OffsetToIndex;
   while (!D.empty()) {
-    if (D.size() < 4)
-      error("Truncated CIE/FDE length");
-    uint32_t Length = read32<E>(D.data());
-    Length += 4;
-
     unsigned Index = S->Offsets.size();
     S->Offsets.push_back(std::make_pair(Offset, -1));
 
-    if (Length > D.size())
-      error("CIE/FIE ends past the end of the section");
+    uintX_t Length = readEntryLength(D);
     StringRef Entry((const char *)D.data(), Length);
 
     while (RelI != RelE && RelI->r_offset < Offset)
@@ -999,6 +993,32 @@ void EHOutputSection<ELFT>::addSectionAu
 }
 
 template <class ELFT>
+typename EHOutputSection<ELFT>::uintX_t
+EHOutputSection<ELFT>::readEntryLength(ArrayRef<uint8_t> D) {
+  const endianness E = ELFT::TargetEndianness;
+
+  if (D.size() < 4)
+    error("Truncated CIE/FDE length");
+  uint64_t Len = read32<E>(D.data());
+  if (Len < UINT32_MAX) {
+    if (Len > (UINT32_MAX - 4))
+      error("CIE/FIE size is too large");
+    if (Len + 4 > D.size())
+      error("CIE/FIE ends past the end of the section");
+    return Len + 4;
+  }
+
+  if (D.size() < 12)
+    error("Truncated CIE/FDE length");
+  Len = read64<E>(D.data() + 4);
+  if (Len > (UINT64_MAX - 12))
+    error("CIE/FIE size is too large");
+  if (Len + 12 > D.size())
+    error("CIE/FIE ends past the end of the section");
+  return Len + 12;
+}
+
+template <class ELFT>
 void EHOutputSection<ELFT>::addSection(EHInputSection<ELFT> *S) {
   const Elf_Shdr *RelSec = S->RelocSection;
   if (!RelSec)

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=255883&r1=255882&r2=255883&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Dec 17 03:23:40 2015
@@ -301,6 +301,8 @@ public:
   void addSection(EHInputSection<ELFT> *S);
 
 private:
+  uintX_t readEntryLength(ArrayRef<uint8_t> D);
+
   std::vector<EHInputSection<ELFT> *> Sections;
   std::vector<Cie<ELFT>> Cies;
 

Added: lld/trunk/test/ELF/invalid-cie-length3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid-cie-length3.s?rev=255883&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid-cie-length3.s (added)
+++ lld/trunk/test/ELF/invalid-cie-length3.s Thu Dec 17 03:23:40 2015
@@ -0,0 +1,9 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
+
+ .section .eh_frame
+ .long 0xFFFFFFFC
+
+// CHECK: CIE/FIE size is too large

Added: lld/trunk/test/ELF/invalid-cie-length4.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid-cie-length4.s?rev=255883&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid-cie-length4.s (added)
+++ lld/trunk/test/ELF/invalid-cie-length4.s Thu Dec 17 03:23:40 2015
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
+
+ .section .eh_frame
+ .long 0xFFFFFFFF
+ .byte 0
+
+// CHECK: Truncated CIE/FDE length

Added: lld/trunk/test/ELF/invalid-cie-length5.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/invalid-cie-length5.s?rev=255883&view=auto
==============================================================================
--- lld/trunk/test/ELF/invalid-cie-length5.s (added)
+++ lld/trunk/test/ELF/invalid-cie-length5.s Thu Dec 17 03:23:40 2015
@@ -0,0 +1,10 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
+
+ .section .eh_frame
+ .long 0xFFFFFFFF
+ .quad 0xFFFFFFFFFFFFFFF4
+
+// CHECK: CIE/FIE size is too large

Added: lld/trunk/test/ELF/valid-cie-length-dw64.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/valid-cie-length-dw64.s?rev=255883&view=auto
==============================================================================
--- lld/trunk/test/ELF/valid-cie-length-dw64.s (added)
+++ lld/trunk/test/ELF/valid-cie-length-dw64.s Thu Dec 17 03:23:40 2015
@@ -0,0 +1,13 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
+
+ .section .eh_frame
+ .long 0xFFFFFFFF
+ .quad 1
+ nop
+
+// CHECK-NOT: Truncated CIE/FDE length
+// CHECK-NOT: CIE/FIE size is too large
+// CHECK-NOT: CIE/FIE ends past the end of the section




More information about the llvm-commits mailing list