mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 19:44:38 +08:00
[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 llvm-svn: 255883
This commit is contained in:
@@ -943,16 +943,10 @@ void EHOutputSection<ELFT>::addSectionAux(
|
||||
|
||||
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)
|
||||
@@ -998,6 +992,32 @@ void EHOutputSection<ELFT>::addSectionAux(
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
9
lld/test/ELF/invalid-cie-length3.s
Normal file
9
lld/test/ELF/invalid-cie-length3.s
Normal file
@@ -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
|
||||
10
lld/test/ELF/invalid-cie-length4.s
Normal file
10
lld/test/ELF/invalid-cie-length4.s
Normal file
@@ -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
|
||||
10
lld/test/ELF/invalid-cie-length5.s
Normal file
10
lld/test/ELF/invalid-cie-length5.s
Normal file
@@ -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
|
||||
13
lld/test/ELF/valid-cie-length-dw64.s
Normal file
13
lld/test/ELF/valid-cie-length-dw64.s
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user