forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2b37c5b560
commit
e8bcf4ef07
|
@ -721,14 +721,17 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
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;
|
||||
DWARFDataExtractor TableData(DebugLineData, EndOffset);
|
||||
|
||||
// See if we should tell the data extractor the address size.
|
||||
if (DebugLineData.getAddressSize() == 0)
|
||||
DebugLineData.setAddressSize(Prologue.getAddressSize());
|
||||
if (TableData.getAddressSize() == 0)
|
||||
TableData.setAddressSize(Prologue.getAddressSize());
|
||||
else
|
||||
assert(Prologue.getAddressSize() == 0 ||
|
||||
Prologue.getAddressSize() == DebugLineData.getAddressSize());
|
||||
Prologue.getAddressSize() == TableData.getAddressSize());
|
||||
|
||||
ParsingState State(this, DebugLineOffset, RecoverableErrorHandler);
|
||||
|
||||
|
@ -738,7 +741,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
*OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);
|
||||
|
||||
uint64_t OpcodeOffset = *OffsetPtr;
|
||||
uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
|
||||
uint8_t Opcode = TableData.getU8(OffsetPtr);
|
||||
|
||||
if (OS)
|
||||
*OS << format("%02.02" PRIx8 " ", Opcode);
|
||||
|
@ -746,7 +749,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
if (Opcode == 0) {
|
||||
// Extended Opcodes always start with a zero opcode followed by
|
||||
// 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;
|
||||
|
||||
// Tolerate zero-length; assume length is correct and soldier on.
|
||||
|
@ -756,7 +759,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
continue;
|
||||
}
|
||||
|
||||
uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
|
||||
uint8_t SubOpcode = TableData.getU8(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << LNExtendedString(SubOpcode);
|
||||
switch (SubOpcode) {
|
||||
|
@ -789,7 +792,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
// Make sure the extractor knows the address size. If not, infer it
|
||||
// from the size of the operand.
|
||||
{
|
||||
uint8_t ExtractorAddressSize = DebugLineData.getAddressSize();
|
||||
uint8_t ExtractorAddressSize = TableData.getAddressSize();
|
||||
uint64_t OpcodeAddressSize = Len - 1;
|
||||
if (ExtractorAddressSize != OpcodeAddressSize &&
|
||||
ExtractorAddressSize != 0)
|
||||
|
@ -812,13 +815,13 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
OpcodeAddressSize, ExtOffset));
|
||||
*OffsetPtr += OpcodeAddressSize;
|
||||
} else {
|
||||
DebugLineData.setAddressSize(OpcodeAddressSize);
|
||||
State.Row.Address.Address = DebugLineData.getRelocatedAddress(
|
||||
TableData.setAddressSize(OpcodeAddressSize);
|
||||
State.Row.Address.Address = TableData.getRelocatedAddress(
|
||||
OffsetPtr, &State.Row.Address.SectionIndex);
|
||||
|
||||
// Restore the address size if the extractor already had it.
|
||||
if (ExtractorAddressSize != 0)
|
||||
DebugLineData.setAddressSize(ExtractorAddressSize);
|
||||
TableData.setAddressSize(ExtractorAddressSize);
|
||||
}
|
||||
|
||||
if (OS)
|
||||
|
@ -849,12 +852,12 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
// the file register of the state machine.
|
||||
{
|
||||
FileNameEntry FileEntry;
|
||||
const char *Name = DebugLineData.getCStr(OffsetPtr);
|
||||
const char *Name = TableData.getCStr(OffsetPtr);
|
||||
FileEntry.Name =
|
||||
DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name);
|
||||
FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
|
||||
FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
|
||||
FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
|
||||
FileEntry.DirIdx = TableData.getULEB128(OffsetPtr);
|
||||
FileEntry.ModTime = TableData.getULEB128(OffsetPtr);
|
||||
FileEntry.Length = TableData.getULEB128(OffsetPtr);
|
||||
Prologue.FileNames.push_back(FileEntry);
|
||||
if (OS)
|
||||
*OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
|
||||
|
@ -864,7 +867,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
break;
|
||||
|
||||
case DW_LNE_set_discriminator:
|
||||
State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
|
||||
State.Row.Discriminator = TableData.getULEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << " (" << State.Row.Discriminator << ")";
|
||||
break;
|
||||
|
@ -913,7 +916,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
// result to the address register of the state machine.
|
||||
{
|
||||
uint64_t AddrOffset = State.advanceAddr(
|
||||
DebugLineData.getULEB128(OffsetPtr), Opcode, OpcodeOffset);
|
||||
TableData.getULEB128(OffsetPtr), Opcode, OpcodeOffset);
|
||||
if (OS)
|
||||
*OS << " (" << AddrOffset << ")";
|
||||
}
|
||||
|
@ -922,7 +925,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
case DW_LNS_advance_line:
|
||||
// Takes a single signed LEB128 operand and adds that value to
|
||||
// the line register of the state machine.
|
||||
State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
|
||||
State.Row.Line += TableData.getSLEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << " (" << State.Row.Line << ")";
|
||||
break;
|
||||
|
@ -930,7 +933,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
case DW_LNS_set_file:
|
||||
// Takes a single unsigned LEB128 operand and stores it in the file
|
||||
// register of the state machine.
|
||||
State.Row.File = DebugLineData.getULEB128(OffsetPtr);
|
||||
State.Row.File = TableData.getULEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << " (" << State.Row.File << ")";
|
||||
break;
|
||||
|
@ -938,7 +941,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
case DW_LNS_set_column:
|
||||
// Takes a single unsigned LEB128 operand and stores it in the
|
||||
// column register of the state machine.
|
||||
State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
|
||||
State.Row.Column = TableData.getULEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << " (" << State.Row.Column << ")";
|
||||
break;
|
||||
|
@ -986,7 +989,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
// requires the use of DW_LNS_advance_pc. Such assemblers, however,
|
||||
// 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;
|
||||
if (OS)
|
||||
*OS
|
||||
|
@ -1009,7 +1012,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
case DW_LNS_set_isa:
|
||||
// Takes a single unsigned LEB128 operand and stores it in the
|
||||
// column register of the state machine.
|
||||
State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
|
||||
State.Row.Isa = TableData.getULEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << " (" << (uint64_t)State.Row.Isa << ")";
|
||||
break;
|
||||
|
@ -1022,7 +1025,7 @@ Error DWARFDebugLine::LineTable::parse(
|
|||
assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
|
||||
uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
|
||||
for (uint8_t I = 0; I < OpcodeLength; ++I) {
|
||||
uint64_t Value = DebugLineData.getULEB128(OffsetPtr);
|
||||
uint64_t Value = TableData.getULEB128(OffsetPtr);
|
||||
if (OS)
|
||||
*OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
|
||||
Value);
|
||||
|
|
|
@ -488,6 +488,36 @@
|
|||
.byte 0, 1, 1 # DW_LNE_end_sequence
|
||||
.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.
|
||||
.long .Lunit_good_end - .Lunit_good_start # Length of Unit (DWARF-32 format)
|
||||
.Lunit_good_start:
|
||||
|
|
|
@ -33,7 +33,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=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 --input-file=%t-malformed-off-last.err --check-prefix=ALL
|
||||
|
||||
|
@ -243,7 +243,14 @@
|
|||
# VERBOSE: DW_LNE_set_address (0xababcdcdefef0909)
|
||||
# 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-NEXT: DW_LNE_end_sequence
|
||||
|
||||
|
@ -272,4 +279,6 @@
|
|||
# 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 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:
|
||||
|
|
Loading…
Reference in New Issue