Skip to content
Snippets Groups Projects
Commit e8bcf4ef authored by James Henderson's avatar James Henderson
Browse files

[DebugInfo] Add use of truncating data extractor to debug line parsing

This will ensure that nothing can ever start parsing data from a future
sequence and part-read data will be returned as 0 instead.

Reviewed by: aprantl, labath

Differential Revision: https://reviews.llvm.org/D80796
parent 2b37c5b5
No related branches found
No related tags found
No related merge requests found
...@@ -721,14 +721,17 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -721,14 +721,17 @@ Error DWARFDebugLine::LineTable::parse(
ProgramLength = BytesRemaining; ProgramLength = BytesRemaining;
} }
// Create a DataExtractor which can only see the data up to the end of the
// table, to prevent reading past the end.
const uint64_t EndOffset = DebugLineOffset + ProgramLength; const uint64_t EndOffset = DebugLineOffset + ProgramLength;
DWARFDataExtractor TableData(DebugLineData, EndOffset);
// See if we should tell the data extractor the address size. // See if we should tell the data extractor the address size.
if (DebugLineData.getAddressSize() == 0) if (TableData.getAddressSize() == 0)
DebugLineData.setAddressSize(Prologue.getAddressSize()); TableData.setAddressSize(Prologue.getAddressSize());
else else
assert(Prologue.getAddressSize() == 0 || assert(Prologue.getAddressSize() == 0 ||
Prologue.getAddressSize() == DebugLineData.getAddressSize()); Prologue.getAddressSize() == TableData.getAddressSize());
ParsingState State(this, DebugLineOffset, RecoverableErrorHandler); ParsingState State(this, DebugLineOffset, RecoverableErrorHandler);
...@@ -738,7 +741,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -738,7 +741,7 @@ Error DWARFDebugLine::LineTable::parse(
*OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr); *OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);
uint64_t OpcodeOffset = *OffsetPtr; uint64_t OpcodeOffset = *OffsetPtr;
uint8_t Opcode = DebugLineData.getU8(OffsetPtr); uint8_t Opcode = TableData.getU8(OffsetPtr);
if (OS) if (OS)
*OS << format("%02.02" PRIx8 " ", Opcode); *OS << format("%02.02" PRIx8 " ", Opcode);
...@@ -746,7 +749,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -746,7 +749,7 @@ Error DWARFDebugLine::LineTable::parse(
if (Opcode == 0) { if (Opcode == 0) {
// Extended Opcodes always start with a zero opcode followed by // Extended Opcodes always start with a zero opcode followed by
// a uleb128 length so you can skip ones you don't know about // a uleb128 length so you can skip ones you don't know about
uint64_t Len = DebugLineData.getULEB128(OffsetPtr); uint64_t Len = TableData.getULEB128(OffsetPtr);
uint64_t ExtOffset = *OffsetPtr; uint64_t ExtOffset = *OffsetPtr;
// Tolerate zero-length; assume length is correct and soldier on. // Tolerate zero-length; assume length is correct and soldier on.
...@@ -756,7 +759,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -756,7 +759,7 @@ Error DWARFDebugLine::LineTable::parse(
continue; continue;
} }
uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr); uint8_t SubOpcode = TableData.getU8(OffsetPtr);
if (OS) if (OS)
*OS << LNExtendedString(SubOpcode); *OS << LNExtendedString(SubOpcode);
switch (SubOpcode) { switch (SubOpcode) {
...@@ -789,7 +792,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -789,7 +792,7 @@ Error DWARFDebugLine::LineTable::parse(
// Make sure the extractor knows the address size. If not, infer it // Make sure the extractor knows the address size. If not, infer it
// from the size of the operand. // from the size of the operand.
{ {
uint8_t ExtractorAddressSize = DebugLineData.getAddressSize(); uint8_t ExtractorAddressSize = TableData.getAddressSize();
uint64_t OpcodeAddressSize = Len - 1; uint64_t OpcodeAddressSize = Len - 1;
if (ExtractorAddressSize != OpcodeAddressSize && if (ExtractorAddressSize != OpcodeAddressSize &&
ExtractorAddressSize != 0) ExtractorAddressSize != 0)
...@@ -812,13 +815,13 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -812,13 +815,13 @@ Error DWARFDebugLine::LineTable::parse(
OpcodeAddressSize, ExtOffset)); OpcodeAddressSize, ExtOffset));
*OffsetPtr += OpcodeAddressSize; *OffsetPtr += OpcodeAddressSize;
} else { } else {
DebugLineData.setAddressSize(OpcodeAddressSize); TableData.setAddressSize(OpcodeAddressSize);
State.Row.Address.Address = DebugLineData.getRelocatedAddress( State.Row.Address.Address = TableData.getRelocatedAddress(
OffsetPtr, &State.Row.Address.SectionIndex); OffsetPtr, &State.Row.Address.SectionIndex);
// Restore the address size if the extractor already had it. // Restore the address size if the extractor already had it.
if (ExtractorAddressSize != 0) if (ExtractorAddressSize != 0)
DebugLineData.setAddressSize(ExtractorAddressSize); TableData.setAddressSize(ExtractorAddressSize);
} }
if (OS) if (OS)
...@@ -849,12 +852,12 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -849,12 +852,12 @@ Error DWARFDebugLine::LineTable::parse(
// the file register of the state machine. // the file register of the state machine.
{ {
FileNameEntry FileEntry; FileNameEntry FileEntry;
const char *Name = DebugLineData.getCStr(OffsetPtr); const char *Name = TableData.getCStr(OffsetPtr);
FileEntry.Name = FileEntry.Name =
DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name); DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name);
FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr); FileEntry.DirIdx = TableData.getULEB128(OffsetPtr);
FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr); FileEntry.ModTime = TableData.getULEB128(OffsetPtr);
FileEntry.Length = DebugLineData.getULEB128(OffsetPtr); FileEntry.Length = TableData.getULEB128(OffsetPtr);
Prologue.FileNames.push_back(FileEntry); Prologue.FileNames.push_back(FileEntry);
if (OS) if (OS)
*OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time=" *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
...@@ -864,7 +867,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -864,7 +867,7 @@ Error DWARFDebugLine::LineTable::parse(
break; break;
case DW_LNE_set_discriminator: case DW_LNE_set_discriminator:
State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr); State.Row.Discriminator = TableData.getULEB128(OffsetPtr);
if (OS) if (OS)
*OS << " (" << State.Row.Discriminator << ")"; *OS << " (" << State.Row.Discriminator << ")";
break; break;
...@@ -913,7 +916,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -913,7 +916,7 @@ Error DWARFDebugLine::LineTable::parse(
// result to the address register of the state machine. // result to the address register of the state machine.
{ {
uint64_t AddrOffset = State.advanceAddr( uint64_t AddrOffset = State.advanceAddr(
DebugLineData.getULEB128(OffsetPtr), Opcode, OpcodeOffset); TableData.getULEB128(OffsetPtr), Opcode, OpcodeOffset);
if (OS) if (OS)
*OS << " (" << AddrOffset << ")"; *OS << " (" << AddrOffset << ")";
} }
...@@ -922,7 +925,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -922,7 +925,7 @@ Error DWARFDebugLine::LineTable::parse(
case DW_LNS_advance_line: case DW_LNS_advance_line:
// Takes a single signed LEB128 operand and adds that value to // Takes a single signed LEB128 operand and adds that value to
// the line register of the state machine. // the line register of the state machine.
State.Row.Line += DebugLineData.getSLEB128(OffsetPtr); State.Row.Line += TableData.getSLEB128(OffsetPtr);
if (OS) if (OS)
*OS << " (" << State.Row.Line << ")"; *OS << " (" << State.Row.Line << ")";
break; break;
...@@ -930,7 +933,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -930,7 +933,7 @@ Error DWARFDebugLine::LineTable::parse(
case DW_LNS_set_file: case DW_LNS_set_file:
// Takes a single unsigned LEB128 operand and stores it in the file // Takes a single unsigned LEB128 operand and stores it in the file
// register of the state machine. // register of the state machine.
State.Row.File = DebugLineData.getULEB128(OffsetPtr); State.Row.File = TableData.getULEB128(OffsetPtr);
if (OS) if (OS)
*OS << " (" << State.Row.File << ")"; *OS << " (" << State.Row.File << ")";
break; break;
...@@ -938,7 +941,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -938,7 +941,7 @@ Error DWARFDebugLine::LineTable::parse(
case DW_LNS_set_column: case DW_LNS_set_column:
// Takes a single unsigned LEB128 operand and stores it in the // Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine. // column register of the state machine.
State.Row.Column = DebugLineData.getULEB128(OffsetPtr); State.Row.Column = TableData.getULEB128(OffsetPtr);
if (OS) if (OS)
*OS << " (" << State.Row.Column << ")"; *OS << " (" << State.Row.Column << ")";
break; break;
...@@ -986,7 +989,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -986,7 +989,7 @@ Error DWARFDebugLine::LineTable::parse(
// requires the use of DW_LNS_advance_pc. Such assemblers, however, // requires the use of DW_LNS_advance_pc. Such assemblers, however,
// can use DW_LNS_fixed_advance_pc instead, sacrificing compression. // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
{ {
uint16_t PCOffset = DebugLineData.getRelocatedValue(2, OffsetPtr); uint16_t PCOffset = TableData.getRelocatedValue(2, OffsetPtr);
State.Row.Address.Address += PCOffset; State.Row.Address.Address += PCOffset;
if (OS) if (OS)
*OS *OS
...@@ -1009,7 +1012,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -1009,7 +1012,7 @@ Error DWARFDebugLine::LineTable::parse(
case DW_LNS_set_isa: case DW_LNS_set_isa:
// Takes a single unsigned LEB128 operand and stores it in the // Takes a single unsigned LEB128 operand and stores it in the
// column register of the state machine. // column register of the state machine.
State.Row.Isa = DebugLineData.getULEB128(OffsetPtr); State.Row.Isa = TableData.getULEB128(OffsetPtr);
if (OS) if (OS)
*OS << " (" << (uint64_t)State.Row.Isa << ")"; *OS << " (" << (uint64_t)State.Row.Isa << ")";
break; break;
...@@ -1022,7 +1025,7 @@ Error DWARFDebugLine::LineTable::parse( ...@@ -1022,7 +1025,7 @@ Error DWARFDebugLine::LineTable::parse(
assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size()); assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1]; uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
for (uint8_t I = 0; I < OpcodeLength; ++I) { for (uint8_t I = 0; I < OpcodeLength; ++I) {
uint64_t Value = DebugLineData.getULEB128(OffsetPtr); uint64_t Value = TableData.getULEB128(OffsetPtr);
if (OS) if (OS)
*OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n", *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
Value); Value);
......
...@@ -488,6 +488,36 @@ ...@@ -488,6 +488,36 @@
.byte 0, 1, 1 # DW_LNE_end_sequence .byte 0, 1, 1 # DW_LNE_end_sequence
.Lunterminated_files_end: .Lunterminated_files_end:
# Opcode extends past the end of the table, as claimed by the unit length field.
.long .Lextended_past_end_end - .Lextended_past_end_start # Length of Unit
.Lextended_past_end_start:
.short 4 # DWARF version number
.long .Lprologue_extended_past_end_end-.Lprologue_extended_past_end_start # Length of Prologue
.Lprologue_extended_past_end_start:
.byte 1 # Minimum Instruction Length
.byte 1 # Maximum Operations per Instruction
.byte 1 # Default is_stmt
.byte -5 # Line Base
.byte 14 # Line Range
.byte 13 # Opcode Base
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # Standard Opcode Lengths
.asciz "dir1" # Include table
.asciz "dir2"
.byte 0
.asciz "file1" # File table
.byte 0, 0, 0
.asciz "file2"
.byte 1, 0, 0
.byte 0
.Lprologue_extended_past_end_end:
.byte 0, 9, 2 # DW_LNE_set_address
.quad 0xfeedfeed
.byte 1 # DW_LNS_copy
.byte 0, 9, 2 # DW_LNE_set_address
.long 0xf001f000 # Truncated address (should be 8 bytes)
.byte 0xf0, 0, 1
.Lextended_past_end_end:
# Trailing good section. # Trailing good section.
.long .Lunit_good_end - .Lunit_good_start # Length of Unit (DWARF-32 format) .long .Lunit_good_end - .Lunit_good_start # Length of Unit (DWARF-32 format)
.Lunit_good_start: .Lunit_good_start:
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
# RUN: FileCheck %s --input-file=%t-malformed-off-first.err --check-prefix=ALL # 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. ## 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: llvm-dwarfdump -debug-line=0x419 %t-malformed.o 2> %t-malformed-off-last.err \
# RUN: | FileCheck %s --check-prefix=LAST --implicit-check-not='debug_line[{{.*}}]' # 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: FileCheck %s --input-file=%t-malformed-off-last.err --check-prefix=ALL
...@@ -243,7 +243,14 @@ ...@@ -243,7 +243,14 @@
# VERBOSE: DW_LNE_set_address (0xababcdcdefef0909) # VERBOSE: DW_LNE_set_address (0xababcdcdefef0909)
# VERBOSE-NEXT: DW_LNE_end_sequence # VERBOSE-NEXT: DW_LNE_end_sequence
# LAST: debug_line[0x000003c9] ## Table with extended opcode that overruns table end.
# NONFATAL: debug_line[0x000003c9]
# NONFATAL-NEXT: Line table prologue
# VERBOSE: DW_LNE_set_address (0x00000000feedfeed)
# VERBOSE-NEXT: DW_LNS_copy
# VERBOSE: DW_LNE_set_address (0x0000000000000000)
# LAST: debug_line[0x00000419]
# VERBOSE: DW_LNE_set_address (0x00000000cafebabe) # VERBOSE: DW_LNE_set_address (0x00000000cafebabe)
# VERBOSE-NEXT: DW_LNE_end_sequence # VERBOSE-NEXT: DW_LNE_end_sequence
...@@ -272,4 +279,6 @@ ...@@ -272,4 +279,6 @@
# ALL-NEXT: warning: include directories table was not null terminated before the end of the prologue # 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: 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 # ALL-NEXT: warning: file names table was not null terminated before the end of the prologue
# OTHER-NEXT: warning: unexpected line op length at offset 0x00000411 expected 0x09 found 0x01
# OTHER-NEXT: warning: last sequence in debug line table at offset 0x000003c9 is not terminated
# ALL-NOT: warning: # ALL-NOT: warning:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment