[dwarfdump] Verify line table prologue

This patch adds prologue verification, which is already present in
Apple's dwarfdump. It checks for invalid directory indices and warns
about duplicate file paths.

Differential revision: https://reviews.llvm.org/D37511

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312782 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jonas Devlieghere 2017-09-08 09:48:51 +00:00
parent 8277ad7473
commit 1a443ce0dd
2 changed files with 198 additions and 0 deletions

View File

@ -417,10 +417,50 @@ void DWARFVerifier::verifyDebugLineRows() {
// .debug_info verifier or in verifyDebugLineStmtOffsets().
if (!LineTable)
continue;
// Verify prologue.
uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
uint32_t FileIndex = 1;
StringMap<uint16_t> FullPathMap;
for (const auto &FileName : LineTable->Prologue.FileNames) {
// Verify directory index.
if (FileName.DirIdx > MaxDirIndex) {
++NumDebugLineErrors;
OS << "error: .debug_line["
<< format("0x%08" PRIx64,
*toSectionOffset(Die.find(DW_AT_stmt_list)))
<< "].prologue.file_names[" << FileIndex
<< "].dir_idx contains an invalid index: " << FileName.DirIdx
<< "\n";
}
// Check file paths for duplicates.
std::string FullPath;
const bool HasFullPath = LineTable->getFileNameByIndex(
FileIndex, CU->getCompilationDir(),
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
assert(HasFullPath && "Invalid index?");
(void)HasFullPath;
auto It = FullPathMap.find(FullPath);
if (It == FullPathMap.end())
FullPathMap[FullPath] = FileIndex;
else if (It->second != FileIndex) {
OS << "warning: .debug_line["
<< format("0x%08" PRIx64,
*toSectionOffset(Die.find(DW_AT_stmt_list)))
<< "].prologue.file_names[" << FileIndex
<< "] is a duplicate of file_names[" << It->second << "]\n";
}
FileIndex++;
}
// Verify rows.
uint64_t PrevAddress = 0;
uint32_t RowIndex = 0;
for (const auto &Row : LineTable->Rows) {
// Verify row address.
if (Row.Address < PrevAddress) {
++NumDebugLineErrors;
OS << "error: .debug_line["
@ -436,6 +476,7 @@ void DWARFVerifier::verifyDebugLineRows() {
OS << '\n';
}
// Verify file index.
if (Row.File > MaxFileIndex) {
++NumDebugLineErrors;
OS << "error: .debug_line["

View File

@ -1658,6 +1658,13 @@ TEST(DWARFDebugInfo, TestImplicitConstAbbrevs) {
EXPECT_EQ(DIEs.find(Val2)->second, AbbrevPtrVal2);
}
void VerifyWarning(DWARFContext &DwarfContext, StringRef Error) {
SmallString<1024> Str;
raw_svector_ostream Strm(Str);
EXPECT_TRUE(DwarfContext.verify(Strm, DIDT_All));
EXPECT_TRUE(Str.str().contains(Error));
}
void VerifyError(DWARFContext &DwarfContext, StringRef Error) {
SmallString<1024> Str;
raw_svector_ostream Strm(Str);
@ -2062,6 +2069,156 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
"file index 5 (valid values are [1,1]):");
}
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineTablePorlogueDirIndex) {
// Create a single compile unit whose line table has a prologue with an
// invalid dir index.
StringRef yamldata = R"(
debug_str:
- ''
- /tmp/main.c
debug_abbrev:
- Code: 0x00000001
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_stmt_list
Form: DW_FORM_sec_offset
debug_info:
- Length:
TotalLength: 16
Version: 4
AbbrOffset: 0
AddrSize: 8
Entries:
- AbbrCode: 0x00000001
Values:
- Value: 0x0000000000000001
- Value: 0x0000000000000000
debug_line:
- Length:
TotalLength: 61
Version: 2
PrologueLength: 34
MinInstLength: 1
DefaultIsStmt: 1
LineBase: 251
LineRange: 14
OpcodeBase: 13
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
IncludeDirs:
- /tmp
Files:
- Name: main.c
DirIdx: 2
ModTime: 0
Length: 0
Opcodes:
- Opcode: DW_LNS_extended_op
ExtLen: 9
SubOpcode: DW_LNE_set_address
Data: 4096
- Opcode: DW_LNS_advance_line
SData: 9
Data: 4096
- Opcode: DW_LNS_copy
Data: 4096
- Opcode: DW_LNS_advance_pc
Data: 16
- Opcode: DW_LNS_set_file
Data: 1
- Opcode: DW_LNS_extended_op
ExtLen: 1
SubOpcode: DW_LNE_end_sequence
Data: 1
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections);
std::unique_ptr<DWARFContext> DwarfContext =
DWARFContext::create(*ErrOrSections, 8);
VerifyError(*DwarfContext,
"error: .debug_line[0x00000000].prologue."
"file_names[1].dir_idx contains an invalid index: 2");
}
TEST(DWARFDebugInfo, TestDwarfVerifyDuplicateFileWarning) {
// Create a single compile unit whose line table has a prologue with an
// invalid dir index.
StringRef yamldata = R"(
debug_str:
- ''
- /tmp/main.c
debug_abbrev:
- Code: 0x00000001
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_stmt_list
Form: DW_FORM_sec_offset
debug_info:
- Length:
TotalLength: 16
Version: 4
AbbrOffset: 0
AddrSize: 8
Entries:
- AbbrCode: 0x00000001
Values:
- Value: 0x0000000000000001
- Value: 0x0000000000000000
debug_line:
- Length:
TotalLength: 71
Version: 2
PrologueLength: 44
MinInstLength: 1
DefaultIsStmt: 1
LineBase: 251
LineRange: 14
OpcodeBase: 13
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
IncludeDirs:
- /tmp
Files:
- Name: main.c
DirIdx: 1
ModTime: 0
Length: 0
- Name: main.c
DirIdx: 1
ModTime: 0
Length: 0
Opcodes:
- Opcode: DW_LNS_extended_op
ExtLen: 9
SubOpcode: DW_LNE_set_address
Data: 4096
- Opcode: DW_LNS_advance_line
SData: 9
Data: 4096
- Opcode: DW_LNS_copy
Data: 4096
- Opcode: DW_LNS_advance_pc
Data: 16
- Opcode: DW_LNS_set_file
Data: 1
- Opcode: DW_LNS_extended_op
ExtLen: 1
SubOpcode: DW_LNE_end_sequence
Data: 2
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections);
std::unique_ptr<DWARFContext> DwarfContext =
DWARFContext::create(*ErrOrSections, 8);
VerifyWarning(*DwarfContext,
"warning: .debug_line[0x00000000].prologue.file_names[2] is "
"a duplicate of file_names[1]");
}
TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
// Create a two compile units where both compile units share the same
// DW_AT_stmt_list value and verify we report the error correctly.