diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -129,7 +129,7 @@ void clear(); void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; - Error parse(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, + Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr, function_ref RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U = nullptr); }; 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 @@ -169,14 +169,14 @@ // Parse v2-v4 directory and file tables. static Error parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, - uint64_t *OffsetPtr, uint64_t EndPrologueOffset, + uint64_t *OffsetPtr, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector &IncludeDirectories, std::vector &FileNames) { while (true) { Error Err = Error::success(); StringRef S = DebugLineData.getCStrRef(OffsetPtr, &Err); - if (Err || *OffsetPtr > EndPrologueOffset) { + if (Err) { consumeError(std::move(Err)); return createStringError(errc::invalid_argument, "include directories table was not null " @@ -195,7 +195,7 @@ while (true) { Error Err = Error::success(); StringRef Name = DebugLineData.getCStrRef(OffsetPtr, &Err); - if (!Err && *OffsetPtr <= EndPrologueOffset && Name.empty()) + if (!Err && Name.empty()) break; DWARFDebugLine::FileNameEntry FileEntry; @@ -205,7 +205,7 @@ FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr, &Err); FileEntry.Length = DebugLineData.getULEB128(OffsetPtr, &Err); - if (Err || *OffsetPtr > EndPrologueOffset) { + if (Err) { consumeError(std::move(Err)); return createStringError( errc::invalid_argument, @@ -345,7 +345,7 @@ } Error DWARFDebugLine::Prologue::parse( - const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, + DWARFDataExtractor DebugLineData, uint64_t *OffsetPtr, function_ref RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; @@ -360,6 +360,7 @@ "parsing line table prologue at offset 0x%8.8" PRIx64 ": %s", PrologueOffset, toString(std::move(Err)).c_str()); + DebugLineData = DWARFDataExtractor(DebugLineData, *OffsetPtr + TotalLength); FormParams.Version = DebugLineData.getU16(OffsetPtr); if (!versionIsSupported(getVersion())) // Treat this error as unrecoverable - we cannot be sure what any of @@ -382,6 +383,7 @@ PrologueLength = DebugLineData.getRelocatedValue(sizeofPrologueLength(), OffsetPtr); const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr; + DebugLineData = DWARFDataExtractor(DebugLineData, EndPrologueOffset); MinInstLength = DebugLineData.getU8(OffsetPtr); if (getVersion() >= 4) MaxOpsPerInst = DebugLineData.getU8(OffsetPtr); @@ -411,8 +413,8 @@ getVersion() >= 5 ? parseV5DirFileTables(DebugLineData, OffsetPtr, FormParams, Ctx, U, ContentTypes, IncludeDirectories, FileNames) - : parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - ContentTypes, IncludeDirectories, FileNames); + : parseV2DirFileTables(DebugLineData, OffsetPtr, ContentTypes, + IncludeDirectories, FileNames); if (E) { RecoverableErrorHandler(joinErrors( createStringError( @@ -425,13 +427,14 @@ return Error::success(); } + assert(*OffsetPtr <= EndPrologueOffset); if (*OffsetPtr != EndPrologueOffset) { RecoverableErrorHandler(createStringError( errc::invalid_argument, - "parsing line table prologue at 0x%8.8" PRIx64 - " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64, - PrologueOffset, EndPrologueOffset, *OffsetPtr)); - *OffsetPtr = EndPrologueOffset; + "unknown data in line table prologue at offset 0x%8.8" PRIx64 + ": parsing ended (at offset 0x%8.8" PRIx64 + ") before reaching the prologue at offset 0x%8.8" PRIx64, + PrologueOffset, *OffsetPtr, EndPrologueOffset)); } return Error::success(); } 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 @@ -81,9 +81,6 @@ .asciz "file2" .byte 1, 2 .Lprologue_short_prologue_end: -.byte 6 # Read as part of the prologue, - # then later again as DW_LNS_negate_stmt. -# Header end .byte 0, 9, 2 # DW_LNE_set_address .quad 0x1122334455667788 .byte 0, 1, 1 # DW_LNE_end_sequence @@ -192,27 +189,9 @@ .byte -5 # Line Base .byte 14 # Line Range .byte 13 # Opcode Base -.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0 # Standard Opcode Lengths +.byte 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 # Standard Opcode Lengths .Linvalid_description_header_end0: -# The bytes from here onwards will also be read as part of the main body. - # --- Prologue interpretation --- | --- Main body interpretation --- -.byte 0, 1 # More standard opcodes | First part of DW_LNE_end_sequence -# Directory table format -.byte 1 # One element per directory entry | End of DW_LNE_end_sequence -.byte 1 # DW_LNCT_path | DW_LNS_copy -.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc -# Directory table entries -.byte 1 # 1 directory | DW_LNS_copy -.asciz "/tmp" # Directory name | four special opcodes + start of DW_LNE_end_sequence -# File table format -.byte 1 # 1 element per file entry | DW_LNE_end_sequence length -.byte 1 # DW_LNCT_path | DW_LNE_end_sequence opcode -.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc -# File table entries -.byte 1 # 1 file | DW_LNS_copy -.asciz "xyz" # File name | three special opcodes + start of DW_LNE_set_address -# Header end -.byte 9, 2 # Remainder of DW_LNE_set_address +.byte 0, 9, 2 # DW_LNE_set_address .quad 0xbabb1ebabb1e .byte 0, 1, 1 # DW_LNE_end_sequence .Linvalid_description_end0: @@ -245,15 +224,6 @@ .byte 0x08 # DW_FORM_string .byte 2 # DW_LNCT_directory_index .Linvalid_file_header_end0: -# The bytes from here onwards will also be read as part of the main body. - # --- Prologue interpretation --- | --- Main body interpretation --- -.byte 0x0b # DW_FORM_data1 | DW_LNS_set_epilogue_begin -# File table entries -.byte 1 # 1 file | DW_LNS_copy -.asciz "xyz" # File name | 3 special opcodes + start of DW_LNE_end_sequence -.byte 1 # Dir index | DW_LNE_end_sequence length -# Header end -.byte 1 # DW_LNE_end_sequence opcode .byte 0, 9, 2 # DW_LNE_set_address .quad 0xab4acadab4a .byte 0, 1, 1 # DW_LNE_end_sequence @@ -281,23 +251,12 @@ # Directory table entries .byte 1 # 1 directory .Linvalid_dir_header_end0: -# The bytes from here onwards will also be read as part of the main body. - # --- Prologue interpretation --- | --- Main body interpretation --- -.asciz "/tmp" # Directory name | 4 special opcodes + start of DW_LNE_end_sequence -# File table format -.byte 1 # 1 element per file entry | DW_LNE_end_sequence length -.byte 1 # DW_LNCT_path | DW_LNE_end_sequence length opcode -.byte 0x08 # DW_FORM_string | DW_LNS_const_add_pc -# File table entries -.byte 1 # 1 file | DW_LNS_copy -.asciz "xyz" # File name | start of DW_LNE_set_address -# Header end -.byte 9, 2 # DW_LNE_set_address length + opcode +.byte 0, 9, 2 # DW_LNE_set_address .quad 0x4444333322221111 .byte 0, 1, 1 # DW_LNE_end_sequence .Linvalid_dir_end0: -# Invalid MD5 hash, where there is data still to be read afterwards. +# Header truncated while reading the MD5 data. .long .Linvalid_md5_end0-.Linvalid_md5_start0 # Length of Unit .Linvalid_md5_start0: .short 5 # DWARF version number @@ -324,7 +283,7 @@ .byte 1 # DW_LNCT_path .byte 0x08 # DW_FORM_string .byte 5 # DW_LNCT_MD5 -.byte 0x0b # DW_FORM_data1 +.byte 0x1e # DW_FORM_data16 .byte 2 # DW_LNCT_directory_index .byte 0x0b # DW_FORM_data1 # File table entries @@ -339,8 +298,7 @@ .byte 0, 1, 1 # DW_LNE_end_sequence .Linvalid_md5_end0: -# Invalid MD5 hash, when data beyond the prologue length has -# been read before the MD5 problem is identified. +# Header truncated while reading the MD5 form. .long .Linvalid_md5_end1-.Linvalid_md5_start1 # Length of Unit .Linvalid_md5_start1: .short 5 # DWARF version number @@ -368,15 +326,7 @@ .byte 0x08 # DW_FORM_string .byte 5 # DW_LNCT_MD5 .Linvalid_md5_header_end1: -# The bytes from here onwards will also be read as part of the main body. - # --- Prologue interpretation --- | --- Main body interpretation --- -.byte 0x0b # DW_FORM_data1 | DW_LNS_set_epilogue_begin -# File table entries -.byte 1 # 1 file | DW_LNS_copy -.asciz "xyz" # File name | 3 special opcodes + DW_LNE_set_address start -.byte 9 # MD5 hash value | DW_LNE_set_address length -# Header end -.byte 2 # DW_LNE_set_address opcode +.byte 0, 9, 2 # DW_LNE_set_address .quad 0x4321432143214321 .byte 0, 1, 1 # DW_LNE_end_sequence .Linvalid_md5_end1: 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 @@ -33,7 +33,7 @@ # RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,NOLATER,SOME-ERR --implicit-check-not='warning:' ## Don't stop looking for the later unit if non-fatal issues are found. -# RUN: llvm-dwarfdump -debug-line=0x419 %t-malformed.o 2>&1 \ +# RUN: llvm-dwarfdump -debug-line=0x3ed %t-malformed.o 2>&1 \ # RUN: | FileCheck %s --check-prefixes=HEADER,LAST,SOME-ERR --implicit-check-not='debug_line[{{.*}}]' \ # RUN: --implicit-check-not='warning:' @@ -92,7 +92,7 @@ ## Prologue with length shorter than parsed. # NONFATAL: debug_line[0x00000081] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000b9 # SOME-ERR-NEXT: warning: file names table was not null terminated before the end of the prologue # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 1]: @@ -100,13 +100,12 @@ # NONFATAL-NEXT: dir_index: 1 # NONFATAL-NEXT: mod_time: 0x00000002 # NONFATAL-NEXT: length: 0x00000003 -# VERBOSE: DW_LNS_negate_stmt -# VERBOSE-NEXT: DW_LNE_set_address (0x1122334455667788) +# VERBOSE: DW_LNE_set_address (0x1122334455667788) # VERBOSE-NEXT: DW_LNE_end_sequence ## Prologue with length longer than parsed. -# NONFATAL: debug_line[0x000000c8] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102 +# NONFATAL: debug_line[0x000000c7] +# SOME-ERR-NEXT: warning: unknown data in line table prologue at offset 0x000000c7: parsing ended (at offset 0x00000101) before reaching the prologue at offset 0x00000102 # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 2]: # NONFATAL-NEXT: name: "file2" @@ -118,117 +117,79 @@ # VERBOSE-NEXT: DW_LNE_end_sequence ## Extended opcode with incorrect length versus expected. -# NONFATAL: debug_line[0x00000111] +# NONFATAL: debug_line[0x00000110] # NONFATAL-NEXT: Line table prologue # NONFATAL: prologue_length: 0x00000030 # VERBOSE: DW_LNE_set_address (0x00000000abbadaba) # VERBOSE-NEXT: DW_LNE_end_sequence -# MORE-ERR: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01 +# MORE-ERR: warning: unexpected line op length at offset 0x00000157 expected 0x02 found 0x01 # VERBOSE: DW_LNE_set_discriminator (10) -# MORE-ERR: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02 +# MORE-ERR: warning: unexpected line op length at offset 0x0000015b expected 0x01 found 0x02 # VERBOSE: DW_LNS_set_prologue_end # VERBOSE-NEXT: DW_LNE_set_address (0x00000000babb1e45) # VERBOSE-NEXT: DW_LNE_end_sequence ## No end of sequence. -# NONFATAL: debug_line[0x0000016c] +# NONFATAL: debug_line[0x0000016b] # NONFATAL-NEXT: Line table prologue # NONFATAL: prologue_length: 0x00000030 # VERBOSE: DW_LNE_set_address (0x00000000deadfade) # VERBOSE-NEXT: DW_LNS_copy -# MORE-ERR: warning: last sequence in debug line table at offset 0x0000016c is not terminated +# MORE-ERR: warning: last sequence in debug line table at offset 0x0000016b is not terminated ## Very short prologue length for V5 (ends during parameters). -# NONFATAL: debug_line[0x000001b2] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1 +# NONFATAL: debug_line[0x000001b1] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000001b1 found an invalid directory or file table description at 0x000001cd +# SOME-ERR-NEXT: warning: failed to parse entry content descriptors: unexpected end of data at offset 0x1cd while reading [0x1cd, 0x1ce) # NONFATAL-NEXT: Line table prologue -# NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1 -# NONFATAL-NEXT: include_directories[ 0] = "/tmp" -# NONFATAL-NEXT: file_names[ 0]: -# NONFATAL-NEXT: name: "xyz" -# VERBOSE: DW_LNE_end_sequence -# VERBOSE: DW_LNS_copy -# VERBOSE: DW_LNS_const_add_pc (0x0000000000000011) -# VERBOSE-NEXT: DW_LNS_copy -# VERBOSE: address += 2, line += 1 -# VERBOSE: address += 7, line += 0 -# VERBOSE: address += 6, line += 7 -# VERBOSE: address += 7, line += -4 -# VERBOSE: DW_LNE_end_sequence -# VERBOSE: DW_LNS_const_add_pc (0x0000000000000011) -# VERBOSE-NEXT: DW_LNS_copy -# VERBOSE: address += 7, line += 4 -# VERBOSE: address += 7, line += 5 -# VERBOSE: address += 7, line += 6 +# NONFATAL: standard_opcode_lengths[DW_LNS_set_prologue_end] = 1 +# NONFATAL-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 +# NONFATAL-NOT: include_directories # VERBOSE: DW_LNE_set_address (0x0000babb1ebabb1e) # VERBOSE-NEXT: DW_LNE_end_sequence ## V5 prologue ends during file table. -# NONFATAL: debug_line[0x000001ee] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220 +# NONFATAL: debug_line[0x000001db] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000001db found an invalid directory or file table description at 0x00000206 +# SOME-ERR-NEXT: warning: failed to parse entry content descriptors: unable to decode LEB128 at offset 0x00000206: malformed uleb128, extends past end # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" -# NONFATAL-NEXT: file_names[ 0]: -# NONFATAL-NEXT: name: "xyz" -# NONFATAL-NEXT: dir_index: 1 -# VERBOSE: DW_LNS_set_epilogue_begin -# VERBOSE-NEXT: DW_LNS_copy -# VERBOSE: address += 7, line += 4 -# VERBOSE: address += 7, line += 5 -# VERBOSE: address += 7, line += 6 -# VERBOSE: DW_LNE_end_sequence +# NONFATAL-NOT: file_names # VERBOSE: DW_LNE_set_address (0x00000ab4acadab4a) # VERBOSE-NEXT: DW_LNE_end_sequence ## V5 prologue ends during directory table. -# NONFATAL: debug_line[0x0000022f] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e +# NONFATAL: debug_line[0x00000214] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000214 found an invalid directory or file table description at 0x00000236 +# SOME-ERR-NEXT: warning: failed to parse directory entry because extracting the form value failed. # NONFATAL-NEXT: Line table prologue -# NONFATAL: include_directories[ 0] = "/tmp" -# NONFATAL-NEXT: file_names[ 0]: -# NONFATAL-NEXT: name: "xyz" -# VERBOSE: address += 2, line += 1 -# VERBOSE: address += 7, line += 0 -# VERBOSE: address += 6, line += 7 -# VERBOSE: address += 7, line += -4 -# VERBOSE: DW_LNE_end_sequence -# VERBOSE: DW_LNS_const_add_pc (0x0000000000000011) -# VERBOSE-NEXT: DW_LNS_copy -# VERBOSE: address += 7, line += 4 -# VERBOSE: address += 7, line += 5 -# VERBOSE: address += 7, line += 6 +# NONFATAL-NOT: include_directories # VERBOSE: DW_LNE_set_address (0x4444333322221111) # VERBOSE-NEXT: DW_LNE_end_sequence ## V5 invalid MD5 hash form when there is still data to be read. -# NONFATAL: debug_line[0x0000026b] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f -# SOME-ERR-NEXT: warning: failed to parse file entry because the MD5 hash is invalid +# NONFATAL: debug_line[0x00000244] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000244 found an invalid directory or file table description at 0x00000277 +# SOME-ERR-NEXT: warning: failed to parse file entry because extracting the form value failed. # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NOT: file_names # VERBOSE: DW_LNE_set_address (0x1234123412341234) # VERBOSE-NEXT: DW_LNE_end_sequence -## V5 invalid MD5 hash form when data beyond the prologue length has -## been read before the MD5 problem is identified. -# NONFATAL: debug_line[0x000002ae] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0 -# SOME-ERR-NEXT: warning: failed to parse file entry because the MD5 hash is invalid +## V5 prologue ends while reading an MD5 hash +# NONFATAL: debug_line[0x00000287] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000287 found an invalid directory or file table description at 0x000002b2 +# SOME-ERR-NEXT: warning: failed to parse entry content descriptors: unable to decode LEB128 at offset 0x000002b2: malformed uleb128, extends past end # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NOT: file_names -# VERBOSE: DW_LNS_set_epilogue_begin -# VERBOSE-NEXT: DW_LNS_copy -# VERBOSE: address += 7, line += 4 -# VERBOSE: address += 7, line += 5 -# VERBOSE: address += 7, line += 6 # VERBOSE: DW_LNE_set_address (0x4321432143214321) # VERBOSE-NEXT: DW_LNE_end_sequence ## V5 invalid directory content description has unsupported form. -# NONFATAL: debug_line[0x000002ec] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000002ec found an invalid directory or file table description at 0x00000315 +# NONFATAL: debug_line[0x000002c0] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x000002c0 found an invalid directory or file table description at 0x000002e9 # SOME-ERR-NEXT: warning: failed to parse directory entry because skipping the form value failed. # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/foo" @@ -238,8 +199,8 @@ # VERBOSE-NEXT: DW_LNE_end_sequence ## Opcode base field of value zero. -# NONFATAL: debug_line[0x00000332] -# SOME-ERR-NEXT: warning: parsing line table prologue at offset 0x00000332 found opcode base of 0. Assuming no standard opcodes +# NONFATAL: debug_line[0x00000306] +# SOME-ERR-NEXT: warning: parsing line table prologue at offset 0x00000306 found opcode base of 0. Assuming no standard opcodes # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 1] = "dir1" # NONFATAL-NEXT: file_names[ 1]: @@ -252,8 +213,8 @@ # VERBOSE: DW_LNE_end_sequence ## V4 table with unterminated include directory table. -# NONFATAL: debug_line[0x00000361] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000361 found an invalid directory or file table description at 0x00000383 +# NONFATAL: debug_line[0x00000335] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000335 found an invalid directory or file table description at 0x00000356 # SOME-ERR-NEXT: warning: include directories table was not null terminated before the end of the prologue # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 1] = "dir1" @@ -262,8 +223,8 @@ # VERBOSE-NEXT: DW_LNE_end_sequence ## V4 table with unterminated file name table. -# NONFATAL: debug_line[0x00000390] -# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000390 found an invalid directory or file table description at 0x000003bf +# NONFATAL: debug_line[0x00000364] +# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000364 found an invalid directory or file table description at 0x0000038f # SOME-ERR-NEXT: warning: file names table was not null terminated before the end of the prologue # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 1]: @@ -276,14 +237,14 @@ # VERBOSE-NEXT: DW_LNE_end_sequence ## Table with extended opcode that overruns table end. -# NONFATAL: debug_line[0x000003c9] +# NONFATAL: debug_line[0x0000039d] # NONFATAL-NEXT: Line table prologue # VERBOSE: DW_LNE_set_address (0x00000000feedfeed) # VERBOSE-NEXT: DW_LNS_copy # VERBOSE: DW_LNE_set_address (0x0000000000000000) -# MORE-ERR: warning: unexpected end of data at offset 0x419 while reading [0x412, 0x41a) -# MORE-ERR: warning: last sequence in debug line table at offset 0x000003c9 is not terminated +# MORE-ERR: warning: unexpected end of data at offset 0x3ed while reading [0x3e6, 0x3ee) +# MORE-ERR: warning: last sequence in debug line table at offset 0x0000039d is not terminated -# LAST: debug_line[0x00000419] +# LAST: debug_line[0x000003ed] # VERBOSE: DW_LNE_set_address (0x00000000cafebabe) # VERBOSE-NEXT: DW_LNE_end_sequence diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -423,12 +423,13 @@ Prologue.TotalLength + 1 + Prologue.sizeofTotalLength(); EXPECT_THAT_ERROR( std::move(Recoverable), - FailedWithMessage(("parsing line table prologue at 0x00000000 should " - "have ended at 0x000000" + - Twine::utohexstr(ExpectedEnd) + - " but it ended at 0x000000" + - Twine::utohexstr(ExpectedEnd - 1)) - .str())); + FailedWithMessage( + ("unknown data in line table prologue at offset 0x00000000: " + "parsing ended (at offset 0x000000" + + Twine::utohexstr(ExpectedEnd - 1) + + ") before reaching the prologue at offset 0x000000" + + Twine::utohexstr(ExpectedEnd)) + .str())); } TEST_P(DebugLineParameterisedFixture, ErrorForTooShortPrologueLength) { @@ -450,37 +451,28 @@ ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); DWARFDebugLine::LineTable Result(**ExpectedLineTable); - if (Version != 5) { - // Parsing will stop before reading a complete file entry. - ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); - EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); - EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); - } else { - // Parsing will continue past the presumed end of prologue. - ASSERT_EQ(Result.Prologue.FileNames.size(), 1u); - ASSERT_EQ(Result.Prologue.FileNames[0].Name.getForm(), DW_FORM_string); - ASSERT_EQ(Result.Prologue.FileNames[0].DirIdx, 0u); - EXPECT_EQ(toStringRef(Result.Prologue.FileNames[0].Name), "a file"); - } + // Parsing will stop before reading a complete file entry. + ASSERT_EQ(Result.Prologue.IncludeDirectories.size(), 1u); + EXPECT_EQ(toStringRef(Result.Prologue.IncludeDirectories[0]), "a dir"); + EXPECT_EQ(Result.Prologue.FileNames.size(), 0u); - uint64_t ExpectedEnd = - Prologue.TotalLength - 2 + Prologue.sizeofTotalLength(); + // The exact place where the parsing will stop depends on the structure of the + // prologue and the last complete field we are able to read. Before V5 we stop + // before reading the file length. In V5, we stop before the filename. + uint64_t ExpectedEnd = Prologue.TotalLength + Prologue.sizeofTotalLength() - + (Version < 5 ? 2 : 8); std::vector Errs; - if (Version != 5) { - Errs.emplace_back( - (Twine("parsing line table prologue at 0x00000000 found an invalid " - "directory or file table description at 0x000000") + - Twine::utohexstr(ExpectedEnd + 1)) - .str()); + Errs.emplace_back( + (Twine("parsing line table prologue at 0x00000000 found an invalid " + "directory or file table description at 0x000000") + + Twine::utohexstr(ExpectedEnd)) + .str()); + if (Version < 5) { Errs.emplace_back("file names table was not null terminated before the end " "of the prologue"); } else { Errs.emplace_back( - (Twine("parsing line table prologue at 0x00000000 should have ended at " - "0x000000") + - Twine::utohexstr(ExpectedEnd) + " but it ended at 0x000000" + - Twine::utohexstr(ExpectedEnd + 2)) - .str()); + "failed to parse file entry because extracting the form value failed."); } EXPECT_THAT_ERROR(std::move(Recoverable), FailedWithMessageArray(testing::ElementsAreArray(Errs))); @@ -1514,6 +1506,7 @@ P.FileNames.back().Name = DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); P.FileNames.back().DirIdx = 1; + P.TotalLength += 14; P.PrologueLength += 14; LT.setPrologue(P); generate();