[DebugInfo] Support zero-length CIE in the _eh_frame parser

MCJIT emits zero-length CIE at the end of the _eh_frame section. This change
ensures that parser inside DebugInfo will not crash and correctly record such cases.
We are now recording DW_EH_PE_omit as a default value for FDE and LSDA encodings.
Also Offset != EndAugmentationOffset assertion check will only happen if augmentation 
string had 'z' letter in it.

Differential Revision: http://reviews.llvm.org/D16588

llvm-svn: 258931
This commit is contained in:
Igor Laevsky 2016-01-27 14:05:35 +00:00
parent 7124c11ad9
commit ff291b5833
3 changed files with 37 additions and 30 deletions

View File

@ -201,8 +201,8 @@ public:
SmallString<8> Augmentation, uint8_t AddressSize,
uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
SmallString<8> AugmentationData, Optional<uint32_t> FDEPointerEncoding,
Optional<uint32_t> LSDAPointerEncoding)
SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
uint32_t LSDAPointerEncoding)
: FrameEntry(FK_CIE, Offset, Length), Version(Version),
Augmentation(std::move(Augmentation)),
AddressSize(AddressSize),
@ -219,10 +219,10 @@ public:
StringRef getAugmentationString() const { return Augmentation; }
uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
Optional<uint32_t> getFDEPointerEncoding() const {
uint32_t getFDEPointerEncoding() const {
return FDEPointerEncoding;
}
Optional<uint32_t> getLSDAPointerEncoding() const {
uint32_t getLSDAPointerEncoding() const {
return LSDAPointerEncoding;
}
@ -265,8 +265,8 @@ private:
// The following are used when the CIE represents an EH frame entry.
SmallString<8> AugmentationData;
Optional<uint32_t> FDEPointerEncoding;
Optional<uint32_t> LSDAPointerEncoding;
uint32_t FDEPointerEncoding;
uint32_t LSDAPointerEncoding;
};
@ -556,16 +556,16 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
// Parse the augmentation data for EH CIEs
StringRef AugmentationData;
Optional<uint32_t> FDEPointerEncoding;
Optional<uint32_t> LSDAPointerEncoding;
StringRef AugmentationData("");
uint32_t FDEPointerEncoding = DW_EH_PE_omit;
uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
if (IsEH) {
Optional<uint32_t> PersonalityEncoding;
Optional<uint64_t> Personality;
uint64_t AugmentationLength = 0;
uint32_t StartAugmentationOffset = 0;
uint32_t EndAugmentationOffset = 0;
Optional<uint64_t> AugmentationLength;
uint32_t StartAugmentationOffset;
uint32_t EndAugmentationOffset;
// Walk the augmentation string to get all the augmentation data.
for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
@ -573,8 +573,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
default:
ReportError("Unknown augmentation character in entry at %lx");
case 'L':
if (LSDAPointerEncoding)
ReportError("Duplicate LSDA encoding in entry at %lx");
LSDAPointerEncoding = Data.getU8(&Offset);
break;
case 'P': {
@ -585,8 +583,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
break;
}
case 'R':
if (FDEPointerEncoding)
ReportError("Duplicate FDE encoding in entry at %lx");
FDEPointerEncoding = Data.getU8(&Offset);
break;
case 'z':
@ -596,20 +592,22 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
// the string contains a 'z'.
AugmentationLength = Data.getULEB128(&Offset);
StartAugmentationOffset = Offset;
EndAugmentationOffset =
Offset + static_cast<uint32_t>(AugmentationLength);
EndAugmentationOffset = Offset +
static_cast<uint32_t>(*AugmentationLength);
}
}
if (Offset != EndAugmentationOffset)
ReportError("Parsing augmentation data at %lx failed");
if (AugmentationLength.hasValue()) {
if (Offset != EndAugmentationOffset)
ReportError("Parsing augmentation data at %lx failed");
AugmentationData = Data.getData().slice(StartAugmentationOffset,
EndAugmentationOffset);
AugmentationData = Data.getData().slice(StartAugmentationOffset,
EndAugmentationOffset);
}
}
auto Cie = make_unique<CIE>(StartOffset, Length, Version,
StringRef(Augmentation), AddressSize,
AugmentationString, AddressSize,
SegmentDescriptorSize, CodeAlignmentFactor,
DataAlignmentFactor, ReturnAddressRegister,
AugmentationData, FDEPointerEncoding,
@ -628,12 +626,11 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
if (!Cie)
ReportError("Parsing FDE data at %lx failed due to missing CIE");
Optional<uint32_t> FDEPointerEncoding = Cie->getFDEPointerEncoding();
if (!FDEPointerEncoding)
ReportError("Parsing at %lx failed due to missing pointer encoding");
InitialLocation = readPointer(Data, Offset,
Cie->getFDEPointerEncoding());
AddressRange = readPointer(Data, Offset,
Cie->getFDEPointerEncoding());
InitialLocation = readPointer(Data, Offset, *FDEPointerEncoding);
AddressRange = readPointer(Data, Offset, *FDEPointerEncoding);
StringRef AugmentationString = Cie->getAugmentationString();
if (!AugmentationString.empty()) {
// Parse the augmentation length and data for this FDE.
@ -644,8 +641,8 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
// Decode the LSDA if the CIE augmentation string said we should.
uint64_t LSDA = 0;
if (Optional<uint32_t> Encoding = Cie->getLSDAPointerEncoding())
LSDA = readPointer(Data, Offset, *Encoding);
if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
LSDA = readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
if (Offset != EndAugmentationOffset)
ReportError("Parsing augmentation data at %lx failed");

View File

@ -0,0 +1,10 @@
# RUN: llvm-objdump -dwarf=frames %p/Inputs/eh_frame_zero_cie.o 2>/dev/null | FileCheck %s
# CHECK: .eh_frame contents:
# CHECK: 00000000 00000000 ffffffff CIE
# CHECK: Version: 0
# CHECK: Augmentation: ""
# CHECK: Code alignment factor: 0
# CHECK: Data alignment factor: 0
# CHECK: Return address column: 0