diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -474,6 +474,7 @@ } OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) << "]\n"; + OS.flush(); if (DumpOpts.Verbose) { Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS); } else { @@ -481,6 +482,7 @@ Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler); LineTable.dump(OS, DumpOpts); } + OS.flush(); } }; 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 @@ -42,6 +42,10 @@ } // end anonymous namespace +static bool versionIsSupported(uint16_t Version) { + return Version >= 2 && Version <= 5; +} + void DWARFDebugLine::ContentTypeTracker::trackContentType( dwarf::LineNumberEntryFormat ContentType) { switch (ContentType) { @@ -100,9 +104,13 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS, DIDumpOptions DumpOptions) const { + if (!totalLengthIsValid()) + return; OS << "Line table prologue:\n" << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength) << format(" version: %u\n", getVersion()); + if (!versionIsSupported(getVersion())) + return; if (getVersion() >= 5) OS << format(" address_size: %u\n", getAddressSize()) << format(" seg_select_size: %u\n", SegSelectorSize); @@ -345,7 +353,7 @@ PrologueOffset, TotalLength); } FormParams.Version = DebugLineData.getU16(OffsetPtr); - if (getVersion() < 2 || getVersion() > 5) + if (!versionIsSupported(getVersion())) // Treat this error as unrecoverable - we cannot be sure what any of // the data represents including the length field, so cannot skip it or make // any reasonable assumptions. 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 @@ -3,42 +3,34 @@ ## Show that a bad length stops parsing of the section. # RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_reserved_length.s -filetype=obj -o %t-reserved.o -# RUN: llvm-dwarfdump -debug-line %t-reserved.o 2> %t-reserved.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL -# RUN: FileCheck %s --input-file=%t-reserved.err --check-prefix=RESERVED -# RUN: llvm-dwarfdump -debug-line %t-reserved.o -verbose 2> %t-reserved-verbose.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL -# RUN: FileCheck %s --input-file=%t-reserved-verbose.err --check-prefix=RESERVED +# RUN: llvm-dwarfdump -debug-line %t-reserved.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED +# RUN: llvm-dwarfdump -debug-line %t-reserved.o -verbose 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,FATAL,RESERVED ## We only produce warnings for malformed tables after the specified unit if ## parsing can continue. -# RUN: llvm-dwarfdump -debug-line=0 %t-reserved.o 2> %t-reserved-off-first.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER -# RUN: FileCheck %s --input-file=%t-reserved-off-first.err --check-prefix=RESERVED +# RUN: llvm-dwarfdump -debug-line=0 %t-reserved.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER,RESERVED ## Stop looking for the specified unit, if a fatally-bad prologue is detected. -# RUN: llvm-dwarfdump -debug-line=0x4b %t-reserved.o 2> %t-reserved-off-last.err \ -# RUN: | FileCheck %s --check-prefixes=NOFIRST,NOLATER -# RUN: FileCheck %s --input-file=%t-reserved-off-last.err --check-prefix=RESERVED +# RUN: llvm-dwarfdump -debug-line=0x4b %t-reserved.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=NOFIRST,NOLATER,RESERVED ## Show that non-fatal errors do not prevent parsing the rest of the section. # RUN: llvm-mc -triple x86_64-pc-linux %S/Inputs/debug_line_malformed.s -filetype=obj -o %t-malformed.o -# RUN: llvm-dwarfdump -debug-line %t-malformed.o 2> %t-malformed.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' -# RUN: FileCheck %s --input-file=%t-malformed.err --check-prefixes=ALL,OTHER -# RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2> %t-malformed-verbose.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' -# RUN: FileCheck %s --input-file=%t-malformed-verbose.err --check-prefixes=ALL,OTHER +# RUN: llvm-dwarfdump -debug-line %t-malformed.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST,ALL,OTHER --implicit-check-not='debug_line[{{.*}}]' +# RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,NONFATAL,LAST,ALL,OTHER --implicit-check-not='debug_line[{{.*}}]' ## We should still produce warnings for malformed tables after the specified unit. -# RUN: llvm-dwarfdump -debug-line=0 %t-malformed.o 2> %t-malformed-off-first.err \ -# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER -# RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL +# RUN: llvm-dwarfdump -debug-line=0 %t-malformed.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=FIRST,NOLATER,ALL ## Don't stop looking for the later unit if non-fatal issues are found. -# RUN: llvm-dwarfdump -debug-line=0x3c9 %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 +# RUN: llvm-dwarfdump -debug-line=0x3c9 %t-malformed.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=LAST,ALL --implicit-check-not='debug_line[{{.*}}]' # FIRST: debug_line[0x00000000] # FIRST: 0x000000000badbeef {{.*}} end_sequence @@ -49,24 +41,23 @@ ## For fatal issues, the following table(s) should not be dumped: # FATAL: debug_line[0x00000048] -# FATAL-NEXT: Line table prologue -# FATAL-NEXT: total_length: 0xfffffffe +# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe # FATAL-NOT: debug_line ## For non-fatal issues, the table data should be dumped: ## Version 0 table. # NONFATAL: debug_line[0x00000048] -# NONFATAL-NEXT: Line table prologue -# NONFATAL-NOT: Address +# ALL: warning: parsing line table prologue at offset 0x00000048 found unsupported version 0 ## Version 1 table. # NONFATAL: debug_line[0x0000004e] -# NONFATAL-NEXT: Line table prologue -# NONFATAL-NOT: Address +# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 1 ## Malformed directory format with no path component. # NONFATAL: debug_line[0x00000054] +# ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073 +# ALL-NEXT: warning: failed to parse entry content descriptions because no path was found # NONFATAL-NEXT: Line table prologue # NONFATAL-NOT: include_directories # NONFATAL-NOT: file_names @@ -74,6 +65,9 @@ ## Prologue with length shorter than parsed. # NONFATAL: debug_line[0x00000081] +# ALL-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba +# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue +# ALL-NEXT: warning: parsing line table prologue at 0x00000081 should have ended at 0x000000b9 but it ended at 0x000000ba # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 2]: # NONFATAL-NEXT: name: "file2" @@ -84,6 +78,7 @@ ## Prologue with length longer than parsed. # NONFATAL: debug_line[0x000000c8] +# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102 # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 2]: # NONFATAL-NEXT: name: "file2" @@ -95,18 +90,22 @@ ## Extended opcode with incorrect length versus expected. # NONFATAL: debug_line[0x00000111] +# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01 +# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02 # NONFATAL-NEXT: Line table prologue # NONFATAL: 0x00000000abbadaba {{.*}} end_sequence # NONFATAL: 0x00000000babb1e45 {{.*}} 10 is_stmt prologue_end end_sequence{{$}} ## No end of sequence. # NONFATAL: debug_line[0x0000016c] +# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated # NONFATAL-NEXT: Line table prologue # NONFATAL: 0x00000000deadfade {{.*}} is_stmt # NONFATAL-NOT: end_sequence ## Very short prologue length for V5 (ends during parameters). # NONFATAL: debug_line[0x000001b2] +# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1 # NONFATAL-NEXT: Line table prologue # NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1 # NONFATAL-NEXT: include_directories[ 0] = "/tmp" @@ -117,6 +116,7 @@ ## V5 prologue ends during file table. # NONFATAL: debug_line[0x000001ee] +# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220 # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NEXT: file_names[ 0]: @@ -127,6 +127,7 @@ ## V5 prologue ends during directory table. # NONFATAL: debug_line[0x0000022f] +# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NEXT: file_names[ 0]: @@ -136,6 +137,8 @@ ## V5 invalid MD5 hash form when there is still data to be read. # NONFATAL: debug_line[0x0000026b] +# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f +# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NOT: file_names @@ -145,6 +148,9 @@ ## V5 invalid MD5 hash form when data beyond the prologue length has ## been read before the MD5 problem is identified. # NONFATAL: debug_line[0x000002ae] +# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0 +# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid +# ALL-NEXT: warning: parsing line table prologue at 0x000002ae should have ended at 0x000002d9 but it ended at 0x000002e0 # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/tmp" # NONFATAL-NOT: file_names @@ -153,6 +159,8 @@ ## V5 invalid directory content description has unsupported form. # NONFATAL: debug_line[0x000002ec] +# 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. # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 0] = "/foo" # NONFATAL-NOT: include_directories @@ -161,6 +169,7 @@ ## Opcode base field of value zero. # NONFATAL: debug_line[0x00000332] +# ALL-NEXT: warning: parsing line table prologue at offset 0x00000332 found opcode base of 0. Assuming no standard opcodes # NONFATAL-NEXT: Line table prologue # NONFATAL: include_directories[ 1] = "dir1" # NONFATAL-NEXT: file_names[ 1]: @@ -173,6 +182,8 @@ ## V4 table with unterminated include directory table. # NONFATAL: debug_line[0x00000361] +# ALL-NEXT: warning: parsing line table prologue at 0x00000361 found an invalid directory or file table description at 0x00000382 +# ALL-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" # NONFATAL-NOT: file_names @@ -180,6 +191,8 @@ ## V4 table with unterminated file name table. # NONFATAL: debug_line[0x00000390] +# ALL-NEXT: warning: parsing line table prologue at 0x00000390 found an invalid directory or file table description at 0x000003bb +# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue # NONFATAL-NEXT: Line table prologue # NONFATAL: file_names[ 1]: # NONFATAL-NEXT: name: "foo.c" @@ -191,34 +204,3 @@ # LAST: debug_line[0x000003c9] # LAST: 0x00000000cafebabe {{.*}} end_sequence - -# RESERVED: warning: parsing line table prologue at offset 0x00000048 unsupported reserved unit length found of value 0xfffffffe - -# ALL-NOT: warning: -# ALL: warning: parsing line table prologue at offset 0x00000048 found unsupported version 0 -# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e found unsupported version 1 -# ALL-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073 -# ALL-NEXT: warning: failed to parse entry content descriptions because no path was found -# ALL-NEXT: warning: parsing line table prologue at 0x00000081 found an invalid directory or file table description at 0x000000ba -# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue -# ALL-NEXT: warning: parsing line table prologue at 0x00000081 should have ended at 0x000000b9 but it ended at 0x000000ba -# ALL-NEXT: warning: parsing line table prologue at 0x000000c8 should have ended at 0x00000103 but it ended at 0x00000102 -# OTHER-NEXT: warning: unexpected line op length at offset 0x00000158 expected 0x02 found 0x01 -# OTHER-NEXT: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02 -# OTHER-NEXT: warning: last sequence in debug line table at offset 0x0000016c is not terminated -# ALL-NEXT: warning: parsing line table prologue at 0x000001b2 should have ended at 0x000001ce but it ended at 0x000001e1 -# ALL-NEXT: warning: parsing line table prologue at 0x000001ee should have ended at 0x00000219 but it ended at 0x00000220 -# ALL-NEXT: warning: parsing line table prologue at 0x0000022f should have ended at 0x00000251 but it ended at 0x0000025e -# ALL-NEXT: warning: parsing line table prologue at 0x0000026b found an invalid directory or file table description at 0x0000029f -# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid -# ALL-NEXT: warning: parsing line table prologue at 0x000002ae found an invalid directory or file table description at 0x000002e0 -# ALL-NEXT: warning: failed to parse file entry because the MD5 hash is invalid -# 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-NEXT: warning: parsing line table prologue at 0x00000361 found an invalid directory or file table description at 0x00000382 -# ALL-NEXT: warning: include directories table was not null terminated before the end of the prologue -# ALL-NEXT: warning: parsing line table prologue at 0x00000390 found an invalid directory or file table description at 0x000003bb -# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue -# ALL-NOT: warning: