Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 1a443ce

Browse files
committed
[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
1 parent 8277ad7 commit 1a443ce

File tree

2 files changed

+198
-0
lines changed

2 files changed

+198
-0
lines changed

lib/DebugInfo/DWARF/DWARFVerifier.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,50 @@ void DWARFVerifier::verifyDebugLineRows() {
417417
// .debug_info verifier or in verifyDebugLineStmtOffsets().
418418
if (!LineTable)
419419
continue;
420+
421+
// Verify prologue.
420422
uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
423+
uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
424+
uint32_t FileIndex = 1;
425+
StringMap<uint16_t> FullPathMap;
426+
for (const auto &FileName : LineTable->Prologue.FileNames) {
427+
// Verify directory index.
428+
if (FileName.DirIdx > MaxDirIndex) {
429+
++NumDebugLineErrors;
430+
OS << "error: .debug_line["
431+
<< format("0x%08" PRIx64,
432+
*toSectionOffset(Die.find(DW_AT_stmt_list)))
433+
<< "].prologue.file_names[" << FileIndex
434+
<< "].dir_idx contains an invalid index: " << FileName.DirIdx
435+
<< "\n";
436+
}
437+
438+
// Check file paths for duplicates.
439+
std::string FullPath;
440+
const bool HasFullPath = LineTable->getFileNameByIndex(
441+
FileIndex, CU->getCompilationDir(),
442+
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
443+
assert(HasFullPath && "Invalid index?");
444+
(void)HasFullPath;
445+
auto It = FullPathMap.find(FullPath);
446+
if (It == FullPathMap.end())
447+
FullPathMap[FullPath] = FileIndex;
448+
else if (It->second != FileIndex) {
449+
OS << "warning: .debug_line["
450+
<< format("0x%08" PRIx64,
451+
*toSectionOffset(Die.find(DW_AT_stmt_list)))
452+
<< "].prologue.file_names[" << FileIndex
453+
<< "] is a duplicate of file_names[" << It->second << "]\n";
454+
}
455+
456+
FileIndex++;
457+
}
458+
459+
// Verify rows.
421460
uint64_t PrevAddress = 0;
422461
uint32_t RowIndex = 0;
423462
for (const auto &Row : LineTable->Rows) {
463+
// Verify row address.
424464
if (Row.Address < PrevAddress) {
425465
++NumDebugLineErrors;
426466
OS << "error: .debug_line["
@@ -436,6 +476,7 @@ void DWARFVerifier::verifyDebugLineRows() {
436476
OS << '\n';
437477
}
438478

479+
// Verify file index.
439480
if (Row.File > MaxFileIndex) {
440481
++NumDebugLineErrors;
441482
OS << "error: .debug_line["

unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,6 +1658,13 @@ TEST(DWARFDebugInfo, TestImplicitConstAbbrevs) {
16581658
EXPECT_EQ(DIEs.find(Val2)->second, AbbrevPtrVal2);
16591659
}
16601660

1661+
void VerifyWarning(DWARFContext &DwarfContext, StringRef Error) {
1662+
SmallString<1024> Str;
1663+
raw_svector_ostream Strm(Str);
1664+
EXPECT_TRUE(DwarfContext.verify(Strm, DIDT_All));
1665+
EXPECT_TRUE(Str.str().contains(Error));
1666+
}
1667+
16611668
void VerifyError(DWARFContext &DwarfContext, StringRef Error) {
16621669
SmallString<1024> Str;
16631670
raw_svector_ostream Strm(Str);
@@ -2062,6 +2069,156 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
20622069
"file index 5 (valid values are [1,1]):");
20632070
}
20642071

2072+
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineTablePorlogueDirIndex) {
2073+
// Create a single compile unit whose line table has a prologue with an
2074+
// invalid dir index.
2075+
StringRef yamldata = R"(
2076+
debug_str:
2077+
- ''
2078+
- /tmp/main.c
2079+
debug_abbrev:
2080+
- Code: 0x00000001
2081+
Tag: DW_TAG_compile_unit
2082+
Children: DW_CHILDREN_no
2083+
Attributes:
2084+
- Attribute: DW_AT_name
2085+
Form: DW_FORM_strp
2086+
- Attribute: DW_AT_stmt_list
2087+
Form: DW_FORM_sec_offset
2088+
debug_info:
2089+
- Length:
2090+
TotalLength: 16
2091+
Version: 4
2092+
AbbrOffset: 0
2093+
AddrSize: 8
2094+
Entries:
2095+
- AbbrCode: 0x00000001
2096+
Values:
2097+
- Value: 0x0000000000000001
2098+
- Value: 0x0000000000000000
2099+
debug_line:
2100+
- Length:
2101+
TotalLength: 61
2102+
Version: 2
2103+
PrologueLength: 34
2104+
MinInstLength: 1
2105+
DefaultIsStmt: 1
2106+
LineBase: 251
2107+
LineRange: 14
2108+
OpcodeBase: 13
2109+
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2110+
IncludeDirs:
2111+
- /tmp
2112+
Files:
2113+
- Name: main.c
2114+
DirIdx: 2
2115+
ModTime: 0
2116+
Length: 0
2117+
Opcodes:
2118+
- Opcode: DW_LNS_extended_op
2119+
ExtLen: 9
2120+
SubOpcode: DW_LNE_set_address
2121+
Data: 4096
2122+
- Opcode: DW_LNS_advance_line
2123+
SData: 9
2124+
Data: 4096
2125+
- Opcode: DW_LNS_copy
2126+
Data: 4096
2127+
- Opcode: DW_LNS_advance_pc
2128+
Data: 16
2129+
- Opcode: DW_LNS_set_file
2130+
Data: 1
2131+
- Opcode: DW_LNS_extended_op
2132+
ExtLen: 1
2133+
SubOpcode: DW_LNE_end_sequence
2134+
Data: 1
2135+
)";
2136+
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
2137+
ASSERT_TRUE((bool)ErrOrSections);
2138+
std::unique_ptr<DWARFContext> DwarfContext =
2139+
DWARFContext::create(*ErrOrSections, 8);
2140+
VerifyError(*DwarfContext,
2141+
"error: .debug_line[0x00000000].prologue."
2142+
"file_names[1].dir_idx contains an invalid index: 2");
2143+
}
2144+
2145+
TEST(DWARFDebugInfo, TestDwarfVerifyDuplicateFileWarning) {
2146+
// Create a single compile unit whose line table has a prologue with an
2147+
// invalid dir index.
2148+
StringRef yamldata = R"(
2149+
debug_str:
2150+
- ''
2151+
- /tmp/main.c
2152+
debug_abbrev:
2153+
- Code: 0x00000001
2154+
Tag: DW_TAG_compile_unit
2155+
Children: DW_CHILDREN_no
2156+
Attributes:
2157+
- Attribute: DW_AT_name
2158+
Form: DW_FORM_strp
2159+
- Attribute: DW_AT_stmt_list
2160+
Form: DW_FORM_sec_offset
2161+
debug_info:
2162+
- Length:
2163+
TotalLength: 16
2164+
Version: 4
2165+
AbbrOffset: 0
2166+
AddrSize: 8
2167+
Entries:
2168+
- AbbrCode: 0x00000001
2169+
Values:
2170+
- Value: 0x0000000000000001
2171+
- Value: 0x0000000000000000
2172+
debug_line:
2173+
- Length:
2174+
TotalLength: 71
2175+
Version: 2
2176+
PrologueLength: 44
2177+
MinInstLength: 1
2178+
DefaultIsStmt: 1
2179+
LineBase: 251
2180+
LineRange: 14
2181+
OpcodeBase: 13
2182+
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2183+
IncludeDirs:
2184+
- /tmp
2185+
Files:
2186+
- Name: main.c
2187+
DirIdx: 1
2188+
ModTime: 0
2189+
Length: 0
2190+
- Name: main.c
2191+
DirIdx: 1
2192+
ModTime: 0
2193+
Length: 0
2194+
Opcodes:
2195+
- Opcode: DW_LNS_extended_op
2196+
ExtLen: 9
2197+
SubOpcode: DW_LNE_set_address
2198+
Data: 4096
2199+
- Opcode: DW_LNS_advance_line
2200+
SData: 9
2201+
Data: 4096
2202+
- Opcode: DW_LNS_copy
2203+
Data: 4096
2204+
- Opcode: DW_LNS_advance_pc
2205+
Data: 16
2206+
- Opcode: DW_LNS_set_file
2207+
Data: 1
2208+
- Opcode: DW_LNS_extended_op
2209+
ExtLen: 1
2210+
SubOpcode: DW_LNE_end_sequence
2211+
Data: 2
2212+
)";
2213+
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
2214+
ASSERT_TRUE((bool)ErrOrSections);
2215+
std::unique_ptr<DWARFContext> DwarfContext =
2216+
DWARFContext::create(*ErrOrSections, 8);
2217+
VerifyWarning(*DwarfContext,
2218+
"warning: .debug_line[0x00000000].prologue.file_names[2] is "
2219+
"a duplicate of file_names[1]");
2220+
}
2221+
20652222
TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
20662223
// Create a two compile units where both compile units share the same
20672224
// DW_AT_stmt_list value and verify we report the error correctly.

0 commit comments

Comments
 (0)