Error DWARFDebugLine::LineTable::parse(
DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
const DWARFContext &Ctx, const DWARFUnit *U,
- function_ref<void(Error)> RecoverableErrorHandler, raw_ostream *OS) {
+ function_ref<void(Error)> RecoverableErrorHandler, raw_ostream *OS,
+ bool Verbose) {
+ assert((OS || !Verbose) && "cannot have verbose output without stream");
const uint64_t DebugLineOffset = *OffsetPtr;
clear();
Prologue.parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U);
if (OS) {
- // The presence of OS signals verbose dumping.
DIDumpOptions DumpOptions;
- DumpOptions.Verbose = true;
+ DumpOptions.Verbose = Verbose;
Prologue.dump(*OS, DumpOptions);
}
*OffsetPtr = DebugLineOffset + Prologue.getLength();
if (OS && *OffsetPtr < EndOffset) {
*OS << '\n';
- Row::dumpTableHeader(*OS, 12);
+ Row::dumpTableHeader(*OS, /*Indent=*/Verbose ? 12 : 0);
}
while (*OffsetPtr < EndOffset) {
- if (OS)
+ if (Verbose)
*OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);
uint64_t OpcodeOffset = *OffsetPtr;
uint8_t Opcode = TableData.getU8(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << format("%02.02" PRIx8 " ", Opcode);
if (Opcode == 0) {
// Tolerate zero-length; assume length is correct and soldier on.
if (Len == 0) {
- if (OS)
+ if (Verbose)
*OS << "Badly formed extended line op (length 0)\n";
if (!Cursor)
RecoverableErrorHandler(Cursor.takeError());
}
uint8_t SubOpcode = TableData.getU8(Cursor);
- if (OS)
+ if (Verbose)
*OS << LNExtendedString(SubOpcode);
switch (SubOpcode) {
case DW_LNE_end_sequence:
// address is that of the byte after the last target machine instruction
// of the sequence.
State.Row.EndSequence = true;
- if (OS) {
+ if (Verbose) {
*OS << "\n";
OS->indent(12);
- State.Row.dump(*OS);
}
+ if (OS)
+ State.Row.dump(*OS);
State.appendRowToMatrix();
State.resetRowAndSequence();
break;
TableData.setAddressSize(ExtractorAddressSize);
}
- if (OS)
+ if (Verbose)
*OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address);
}
break;
FileEntry.ModTime = TableData.getULEB128(Cursor);
FileEntry.Length = TableData.getULEB128(Cursor);
Prologue.FileNames.push_back(FileEntry);
- if (OS)
+ if (Verbose)
*OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
<< format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)
<< ", length=" << FileEntry.Length << ")";
case DW_LNE_set_discriminator:
State.Row.Discriminator = TableData.getULEB128(Cursor);
- if (OS)
+ if (Verbose)
*OS << " (" << State.Row.Discriminator << ")";
break;
default:
- if (OS)
+ if (Verbose)
*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
ExtOffset, Len, Cursor.tell() - ExtOffset));
*OffsetPtr = End;
} else if (Opcode < Prologue.OpcodeBase) {
- if (OS)
+ if (Verbose)
*OS << LNStandardString(Opcode);
switch (Opcode) {
// Standard Opcodes
case DW_LNS_copy:
// Takes no arguments. Append a row to the matrix using the
// current values of the state-machine registers.
- if (OS) {
+ if (Verbose) {
*OS << "\n";
OS->indent(12);
+ }
+ if (OS)
State.Row.dump(*OS);
+ if (Verbose) // FIXME: Don't print this newline.
*OS << "\n";
- }
State.appendRowToMatrix();
break;
{
uint64_t AddrOffset = State.advanceAddr(
TableData.getULEB128(OffsetPtr), Opcode, OpcodeOffset);
- if (OS)
+ if (Verbose)
*OS << " (" << AddrOffset << ")";
}
break;
// Takes a single signed LEB128 operand and adds that value to
// the line register of the state machine.
State.Row.Line += TableData.getSLEB128(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << " (" << State.Row.Line << ")";
break;
// Takes a single unsigned LEB128 operand and stores it in the file
// register of the state machine.
State.Row.File = TableData.getULEB128(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << " (" << State.Row.File << ")";
break;
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
State.Row.Column = TableData.getULEB128(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << " (" << State.Row.Column << ")";
break;
{
uint64_t AddrOffset =
State.advanceAddrForOpcode(Opcode, OpcodeOffset).AddrDelta;
- if (OS)
+ if (Verbose)
*OS << format(" (0x%16.16" PRIx64 ")", AddrOffset);
}
break;
{
uint16_t PCOffset = TableData.getRelocatedValue(2, OffsetPtr);
State.Row.Address.Address += PCOffset;
- if (OS)
- *OS
- << format(" (0x%4.4" PRIx16 ")", PCOffset);
+ if (Verbose)
+ *OS << format(" (0x%4.4" PRIx16 ")", PCOffset);
}
break;
// Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine.
State.Row.Isa = TableData.getULEB128(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << " (" << (uint64_t)State.Row.Isa << ")";
break;
uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
for (uint8_t I = 0; I < OpcodeLength; ++I) {
uint64_t Value = TableData.getULEB128(OffsetPtr);
- if (OS)
+ if (Verbose)
*OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
Value);
}
ParsingState::AddrAndLineDelta Delta =
State.handleSpecialOpcode(Opcode, OpcodeOffset);
- if (OS) {
+ if (Verbose) {
*OS << "address += " << Delta.Address << ", line += " << Delta.Line
<< "\n";
OS->indent(12);
- State.Row.dump(*OS);
}
+ if (OS)
+ State.Row.dump(*OS);
State.appendRowToMatrix();
}
- if(OS)
+ if(Verbose)
*OS << "\n";
}
// rudimentary sequences for address ranges [0x0, 0xsomething).
}
+ // Terminate the table with a final blank line to clearly delineate it from
+ // later dumps.
+ if (OS)
+ *OS << "\n";
+
return Error::success();
}
DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
function_ref<void(Error)> RecoverableErrorHandler,
- function_ref<void(Error)> UnrecoverableErrorHandler, raw_ostream *OS) {
+ function_ref<void(Error)> UnrecoverableErrorHandler, raw_ostream *OS,
+ bool Verbose) {
assert(DebugLineData.isValidOffset(Offset) &&
"parsing should have terminated");
DWARFUnit *U = prepareToParse(Offset);
uint64_t OldOffset = Offset;
LineTable LT;
if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,
- RecoverableErrorHandler, OS))
+ RecoverableErrorHandler, OS, Verbose))
UnrecoverableErrorHandler(std::move(Err));
moveToNextTable(OldOffset, LT.Prologue);
return LT;
## 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=HEADER,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=HEADER,FIRST,VERBOSE,NONFATAL,LAST --implicit-check-not='debug_line[{{.*}}]' \
-# RUN: --implicit-check-not=' DW_LNS' --implicit-check-not=' DW_LNE' --implicit-check-not='address +='
-# 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=HEADER,FIRST,NONFATAL,LAST,SOME-ERR,MORE-ERR \
+# RUN: --implicit-check-not='debug_line[{{.*}}]' --implicit-check-not='warning:'
+# RUN: llvm-dwarfdump -debug-line %t-malformed.o -verbose 2>&1 \
+# RUN: | FileCheck %s --check-prefixes=HEADER,FIRST,VERBOSE,NONFATAL,LAST,SOME-ERR,MORE-ERR \
+# RUN: --implicit-check-not='debug_line[{{.*}}]' --implicit-check-not=' DW_LNS' \
+# RUN: --implicit-check-not=' DW_LNE' --implicit-check-not='address +=' \
+# RUN: --implicit-check-not='warning:'
## 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=HEADER,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=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> %t-malformed-off-last.err \
-# RUN: | FileCheck %s --check-prefixes=HEADER,LAST --implicit-check-not='debug_line[{{.*}}]'
-# RUN: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL
+# RUN: llvm-dwarfdump -debug-line=0x419 %t-malformed.o 2>&1 \
+# RUN: | FileCheck %s --check-prefixes=HEADER,LAST,SOME-ERR --implicit-check-not='debug_line[{{.*}}]' \
+# RUN: --implicit-check-not='warning:'
# HEADER: .debug_line contents:
# VERBOSE-NEXT: DW_LNE_set_address (0x000000000badbeef)
# VERBOSE-NEXT: DW_LNE_end_sequence
# FIRST: 0x000000000badbeef {{.*}} end_sequence
+# FIRST-EMPTY:
# NOFIRST-NOT: debug_line[0x00000000]
# NOFIRST-NOT: 0x000000000badbeef {{.*}} end_sequence
# NOLATER-NOT: debug_line[{{.*}}]
# NONFATAL-NEXT: total_length: 0x00000002
# NONFATAL-NEXT: format: DWARF32
# NONFATAL-NEXT: version: 0
+# SOME-ERR-NEXT: warning: parsing line table prologue at offset 0x00000048: unsupported version 0
# NONFATAL-NOT: prologue_length
## Version 1 table.
# NONFATAL-NEXT: total_length: 0x00000002
# NONFATAL-NEXT: format: DWARF32
# NONFATAL-NEXT: version: 1
+# SOME-ERR-NEXT: warning: parsing line table prologue at offset 0x0000004e: unsupported version 1
# NONFATAL-NOT: prologue_length
## Malformed directory format with no path component.
# NONFATAL: debug_line[0x00000054]
+# SOME-ERR-NEXT: warning: parsing line table prologue at 0x00000054 found an invalid directory or file table description at 0x00000073
+# SOME-ERR-NEXT: warning: failed to parse entry content descriptions because no path was found
# NONFATAL-NEXT: Line table prologue
# NONFATAL: prologue_length: 0x00000013
# NONFATAL-NOT: include_directories
## 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: 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: "file1"
## 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-NEXT: Line table prologue
# NONFATAL: file_names[ 2]:
# NONFATAL-NEXT: name: "file2"
# 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
# VERBOSE: DW_LNE_set_discriminator (10)
-# VERBOSE-NEXT: DW_LNS_set_prologue_end
+# MORE-ERR: warning: unexpected line op length at offset 0x0000015c expected 0x01 found 0x02
+# VERBOSE: DW_LNS_set_prologue_end
# VERBOSE-NEXT: DW_LNE_set_address (0x00000000babb1e45)
# VERBOSE-NEXT: DW_LNE_end_sequence
# 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
## 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-NEXT: Line table prologue
# NONFATAL: standard_opcode_lengths[DW_LNS_set_isa] = 1
# NONFATAL-NEXT: include_directories[ 0] = "/tmp"
## 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-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NEXT: file_names[ 0]:
## 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-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NEXT: file_names[ 0]:
## 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-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NOT: file_names
## 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
# NONFATAL-NEXT: Line table prologue
# NONFATAL: include_directories[ 0] = "/tmp"
# NONFATAL-NOT: file_names
## 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
+# 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"
# NONFATAL-NOT: include_directories
## 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-NEXT: Line table prologue
# NONFATAL: include_directories[ 1] = "dir1"
# NONFATAL-NEXT: file_names[ 1]:
## 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
+# 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"
# NONFATAL-NOT: file_names
## 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
+# 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]:
# NONFATAL-NEXT: name: "foo.c"
# 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
# LAST: debug_line[0x00000419]
# VERBOSE: DW_LNE_set_address (0x00000000cafebabe)
# VERBOSE-NEXT: DW_LNE_end_sequence
-
-# ALL-NOT: warning:
-# ALL: warning: parsing line table prologue at offset 0x00000048: unsupported version 0
-# ALL-NEXT: warning: parsing line table prologue at offset 0x0000004e: 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 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 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 0x00000383
-# 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 0x000003bf
-# ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
-# OTHER-NEXT: warning: unexpected end of data at offset 0x419 while reading [0x412, 0x41a)
-# OTHER-NEXT: warning: last sequence in debug line table at offset 0x000003c9 is not terminated
-# ALL-NOT: warning: