diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -355,10 +355,21 @@ LineRange = DebugLineData.getU8(OffsetPtr); OpcodeBase = DebugLineData.getU8(OffsetPtr); - StandardOpcodeLengths.reserve(OpcodeBase - 1); - for (uint32_t I = 1; I < OpcodeBase; ++I) { - uint8_t OpLen = DebugLineData.getU8(OffsetPtr); - StandardOpcodeLengths.push_back(OpLen); + if (OpcodeBase == 0) { + // If the opcode base is 0, we cannot read the standard opcode lengths (of + // which there are supposed to be one fewer than the opcode base). Assume + // there are no standard opcodes and continue parsing. + RecoverableErrorCallback(createStringError( + errc::invalid_argument, + "parsing line table prologue at offset 0x%8.8" PRIx64 + " found opcode base of 0. Assuming no standard opcodes", + PrologueOffset)); + } else { + StandardOpcodeLengths.reserve(OpcodeBase - 1); + for (uint32_t I = 1; I < OpcodeBase; ++I) { + uint8_t OpLen = DebugLineData.getU8(OffsetPtr); + StandardOpcodeLengths.push_back(OpLen); + } } if (getVersion() >= 5) { diff --git a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s --- a/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/Inputs/debug_line_malformed.s @@ -423,6 +423,30 @@ .byte 0, 1, 1 # DW_LNE_end_sequence .Linvalid_dir_form_end0: +# Zero opcode base. +.long .Lzero_opcode_base_end - .Lzero_opcode_base_start # unit length +.Lzero_opcode_base_start: +.short 4 # version +.long .Lzero_opcode_base_prologue_end-.Lzero_opcode_base_prologue_start # Length of Prologue +.Lzero_opcode_base_prologue_start: +.byte 1 # Minimum Instruction Length +.byte 1 # Maximum Operations per Instruction +.byte 1 # Default is_stmt +.byte 0 # Line Base +.byte 1 # Line Range +.byte 0 # Opcode Base +.asciz "dir1" # Include table +.byte 0 +.asciz "file1" +.byte 1, 2, 3 +.byte 0 +.Lzero_opcode_base_prologue_end: +.byte 0, 9, 2 # DW_LNE_set_address +.quad 0xffffeeeeddddcccc +.byte 0x1 # Special opcode +.byte 0, 1, 1 # DW_LNE_end_sequence +.Lzero_opcode_base_end: + # Trailing good section. .long .Lunit_good_end - .Lunit_good_start # Length of Unit (DWARF-32 format) .Lunit_good_start: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_line_invalid.test @@ -36,7 +36,7 @@ # RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL ## Don't stop looking for the later unit if non-fatal issues are found. -# RUN: llvm-dwarfdump -debug-line=0x332 %t-malformed.o 2> %t-malformed-off-last.err \ +# RUN: llvm-dwarfdump -debug-line=0x361 %t-malformed.o 2> %t-malformed-off-last.err \ # RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]' # RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL @@ -158,7 +158,19 @@ # NONFATAL-NOT: file_names # NONFATAL: 0xaaaabbbbccccdddd {{.*}} is_stmt end_sequence -# LAST: debug_line[0x00000332] +## Case 14: Opcode base field of value zero. +# NONFATAL: debug_line[0x00000332] +# NONFATAL-NEXT: Line table prologue +# NONFATAL: include_directories[ 1] = "dir1" +# NONFATAL-NEXT: file_names[ 1]: +# NONFATAL-NEXT: name: "file1" +# NONFATAL-NEXT: dir_index: 1 +# NONFATAL-NEXT: mod_time: 0x00000002 +# NONFATAL-NEXT: length: 0x00000003 +# NONFATAL: 0xffffeeeeddddcccd 1 0 1 0 0 is_stmt{{$}} +# NONFATAL: 0xffffeeeeddddcccd 1 0 1 0 0 is_stmt end_sequence{{$}} + +# LAST: debug_line[0x00000361] # LAST: 0x00000000cafebabe {{.*}} end_sequence # RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe @@ -183,4 +195,5 @@ # ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0 # ALL-NEXT: warning: parsing line table prologue at 0x000002ec found an invalid directory or file table description at 0x00000315 # ALL-NEXT: warning: failed to parse directory entry because skipping the form value failed. +# ALL-NEXT: warning: parsing line table prologue at offset 0x00000332 found opcode base of 0. Assuming no standard opcodes # ALL-NOT: warning: