[DWARF] Fix handling of extended line-number opcodes
Differential Revision: https://reviews.llvm.org/D40200
llvm-svn: 318838
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index c99c7a9..1753d57 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -427,9 +427,15 @@
if (Opcode == 0) {
// Extended Opcodes always start with a zero opcode followed by
// a uleb128 length so you can skip ones you don't know about
- uint32_t ExtOffset = *OffsetPtr;
uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
- uint32_t ArgSize = Len - (*OffsetPtr - ExtOffset);
+ uint32_t ExtOffset = *OffsetPtr;
+
+ // Tolerate zero-length; assume length is correct and soldier on.
+ if (Len == 0) {
+ if (OS)
+ *OS << "Badly formed extended line op (length 0)\n";
+ continue;
+ }
uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
if (OS)
@@ -508,11 +514,24 @@
break;
default:
- // Length doesn't include the zero opcode byte or the length itself, but
- // it does include the sub_opcode, so we have to adjust for that below
- (*OffsetPtr) += ArgSize;
+ if (OS)
+ *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
+ << format(" length %" PRIx64, Len);
+ // Len doesn't include the zero opcode byte or the length itself, but
+ // it does include the sub_opcode, so we have to adjust for that.
+ (*OffsetPtr) += Len - 1;
break;
}
+ // Make sure the stated and parsed lengths are the same.
+ // Otherwise we have an unparseable line-number program.
+ if (*OffsetPtr - ExtOffset != Len) {
+ fprintf(stderr, "Unexpected line op length at offset 0x%8.8" PRIx32
+ " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32 "\n",
+ ExtOffset, Len, *OffsetPtr - ExtOffset);
+ // Skip the rest of the line-number program.
+ *OffsetPtr = EndOffset;
+ return false;
+ }
} else if (Opcode < Prologue.OpcodeBase) {
if (OS)
*OS << LNStandardString(Opcode);