[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