llvm.org GIT mirror llvm / cfa02bf
Add line table verification to lldb-dwarfdump --verify This patch verifies the .debug_line: - verify all addresses in a line table sequence have ascending addresses - verify that all line table file indexes are valid Unit tests added for both cases. Differential Revision: https://reviews.llvm.org/D32765 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301984 91177308-0d34-0410-b5e6-96231b3b80d8 Greg Clayton 3 years ago
4 changed file(s) with 254 addition(s) and 80 deletion(s). Raw diff Collapse all Expand all
103103 void postAppend();
104104 void reset(bool DefaultIsStmt);
105105 void dump(raw_ostream &OS) const;
106
106 static void dumpTableHeader(raw_ostream &OS);
107107 static bool orderByAddress(const Row &LHS, const Row &RHS) {
108108 return LHS.Address < RHS.Address;
109109 }
444444 }
445445 return Success;
446446 }
447
448 bool HandleDebugLine() {
449 bool Success = true;
450 OS << "Verifying .debug_line...\n";
451 for (const auto &CU : DCtx.compile_units()) {
452 uint32_t LineTableOffset = 0;
453 auto StmtFormValue = CU->getUnitDIE().find(DW_AT_stmt_list);
454 if (!StmtFormValue) {
455 // No line table for this compile unit.
456 continue;
457 }
458 // Get the attribute value as a section offset. No need to produce an
459 // error here if the encoding isn't correct because we validate this in
460 // the .debug_info verifier.
461 if (auto StmtSectionOffset = toSectionOffset(StmtFormValue)) {
462 LineTableOffset = *StmtSectionOffset;
463 if (LineTableOffset >= DCtx.getLineSection().Data.size()) {
464 // Make sure we don't get a valid line table back if the offset
465 // is wrong.
466 assert(DCtx.getLineTableForUnit(CU.get()) == nullptr);
467 // Skip this line table as it isn't valid. No need to create an error
468 // here because we validate this in the .debug_info verifier.
469 continue;
470 }
471 }
472 auto LineTable = DCtx.getLineTableForUnit(CU.get());
473 if (!LineTable) {
474 Success = false;
475 OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
476 << "] was not able to be parsed for CU:\n";
477 CU->getUnitDIE().dump(OS, 0);
478 OS << '\n';
479 continue;
480 }
481 uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
482 uint64_t PrevAddress = 0;
483 uint32_t RowIndex = 0;
484 for (const auto &Row : LineTable->Rows) {
485 if (Row.Address < PrevAddress) {
486 Success = false;
487 OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
488 << "] row[" << RowIndex
489 << "] decreases in address from previous row:\n";
490
491 DWARFDebugLine::Row::dumpTableHeader(OS);
492 if (RowIndex > 0)
493 LineTable->Rows[RowIndex - 1].dump(OS);
494 Row.dump(OS);
495 OS << '\n';
496 }
497
498 if (Row.File > MaxFileIndex) {
499 Success = false;
500 OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
501 << "][" << RowIndex << "] has invalid file index " << Row.File
502 << " (valid values are [1," << MaxFileIndex << "]):\n";
503 DWARFDebugLine::Row::dumpTableHeader(OS);
504 Row.dump(OS);
505 OS << '\n';
506 }
507 if (Row.EndSequence)
508 PrevAddress = 0;
509 else
510 PrevAddress = Row.Address;
511 ++RowIndex;
512 }
513 }
514 return Success;
515 }
447516 };
448517
449518 } // anonymous namespace
453522 Verifier verifier(OS, *this);
454523 if (DumpType == DIDT_All || DumpType == DIDT_Info) {
455524 if (!verifier.HandleDebugInfo())
525 Success = false;
526 }
527 if (DumpType == DIDT_All || DumpType == DIDT_Line) {
528 if (!verifier.HandleDebugLine())
456529 Success = false;
457530 }
458531 return Success;
286286 EpilogueBegin = false;
287287 }
288288
289 void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
290 OS << "Address Line Column File ISA Discriminator Flags\n"
291 << "------------------ ------ ------ ------ --- ------------- "
292 "-------------\n";
293 }
294
289295 void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
290296 OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
291297 << format(" %6u %3u %13u ", File, Isa, Discriminator)
312318 OS << '\n';
313319
314320 if (!Rows.empty()) {
315 OS << "Address Line Column File ISA Discriminator Flags\n"
316 << "------------------ ------ ------ ------ --- ------------- "
317 "-------------\n";
321 Row::dumpTableHeader(OS);
318322 for (const Row &R : Rows) {
319323 R.dump(OS);
320324 }
99 #include "DwarfGenerator.h"
1010 #include "llvm/ADT/ArrayRef.h"
1111 #include "llvm/ADT/Optional.h"
12 #include "llvm/ADT/SmallString.h"
1213 #include "llvm/ADT/StringRef.h"
1314 #include "llvm/ADT/Triple.h"
1415 #include "llvm/Config/llvm-config.h"
1718 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
1819 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
1920 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/ObjectYAML/DWARFEmitter.h"
2022 #include "llvm/ObjectYAML/DWARFYAML.h"
21 #include "llvm/ObjectYAML/DWARFEmitter.h"
2223 #include "llvm/Support/Dwarf.h"
2324 #include "llvm/Support/Error.h"
2425 #include "llvm/Support/MemoryBuffer.h"
11901191
11911192 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
11921193 ASSERT_TRUE((bool)ErrOrSections);
1193
1194 auto &DebugSections = *ErrOrSections;
1195
1196 DWARFContextInMemory DwarfContext(DebugSections, 8);
1194 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
11971195
11981196 // Verify the number of compile units is correct.
11991197 uint32_t NumCUs = DwarfContext.getNumCompileUnits();
16641662 for (auto it = Val1Range.first; it != Val1Range.second; ++it)
16651663 EXPECT_EQ(it->second, AbbrevPtrVal1);
16661664 EXPECT_EQ(DIEs.find(Val2)->second, AbbrevPtrVal2);
1665 }
1666
1667 void VerifyError(DWARFContext &DwarfContext, StringRef Error) {
1668 SmallString<1024> Str;
1669 raw_svector_ostream Strm(Str);
1670 EXPECT_FALSE(DwarfContext.verify(Strm, DIDT_All));
1671 EXPECT_TRUE(Str.str().contains(Error));
16671672 }
16681673
16691674 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidCURef) {
17101715 )";
17111716 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
17121717 ASSERT_TRUE((bool)ErrOrSections);
1713
1714 auto &DebugSections = *ErrOrSections;
1715
1716 DWARFContextInMemory DwarfContext(DebugSections, 8);
1717
1718 std::string str;
1719 raw_string_ostream strm(str);
1720 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1721 const char *err = "error: DW_FORM_ref4 CU offset 0x00001234 is invalid "
1722 "(must be less than CU size of 0x0000001a):";
1723 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1718 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1719 VerifyError(DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is "
1720 "invalid (must be less than CU size of "
1721 "0x0000001a):");
17241722 }
17251723
17261724 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) {
17651763 )";
17661764 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
17671765 ASSERT_TRUE((bool)ErrOrSections);
1768
1769 auto &DebugSections = *ErrOrSections;
1770
1771 DWARFContextInMemory DwarfContext(DebugSections, 8);
1772
1773 std::string str;
1774 raw_string_ostream strm(str);
1775 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1776 strm.flush();
1777 const char *err = "error: DW_FORM_ref_addr offset beyond .debug_info bounds:";
1778 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1766 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1767 VerifyError(DwarfContext,
1768 "error: DW_FORM_ref_addr offset beyond .debug_info bounds:");
17791769 }
17801770
17811771 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRanges) {
18091799 )";
18101800 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
18111801 ASSERT_TRUE((bool)ErrOrSections);
1812
1813 auto &DebugSections = *ErrOrSections;
1814
1815 DWARFContextInMemory DwarfContext(DebugSections, 8);
1816
1817 std::string str;
1818 raw_string_ostream strm(str);
1819 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1820 strm.flush();
1821 const char *err = "error: DW_AT_ranges offset is beyond .debug_ranges "
1822 "bounds:";
1823 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1802 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1803 VerifyError(DwarfContext,
1804 "error: DW_AT_ranges offset is beyond .debug_ranges bounds:");
18241805 }
18251806
18261807 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidStmtList) {
18541835 )";
18551836 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
18561837 ASSERT_TRUE((bool)ErrOrSections);
1857
1858 auto &DebugSections = *ErrOrSections;
1859
1860 DWARFContextInMemory DwarfContext(DebugSections, 8);
1861
1862 std::string str;
1863 raw_string_ostream strm(str);
1864 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1865 strm.flush();
1866 const char *err = "error: DW_AT_stmt_list offset is beyond .debug_line "
1867 "bounds: 0x00001000";
1868 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1838 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1839 VerifyError(
1840 DwarfContext,
1841 "error: DW_AT_stmt_list offset is beyond .debug_line bounds: 0x00001000");
18691842 }
18701843
18711844 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidStrp) {
18941867 )";
18951868 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
18961869 ASSERT_TRUE((bool)ErrOrSections);
1897
1898 auto &DebugSections = *ErrOrSections;
1899
1900 DWARFContextInMemory DwarfContext(DebugSections, 8);
1901
1902 std::string str;
1903 raw_string_ostream strm(str);
1904 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1905 strm.flush();
1906 const char *err = "error: DW_FORM_strp offset beyond .debug_str bounds:";
1907 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1870 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1871 VerifyError(DwarfContext,
1872 "error: DW_FORM_strp offset beyond .debug_str bounds:");
19081873 }
19091874
19101875 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddrBetween) {
19491914 )";
19501915 auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
19511916 ASSERT_TRUE((bool)ErrOrSections);
1952
1953 auto &DebugSections = *ErrOrSections;
1954
1955 DWARFContextInMemory DwarfContext(DebugSections, 8);
1956
1957 std::string str;
1958 raw_string_ostream strm(str);
1959 EXPECT_FALSE(DwarfContext.verify(strm, DIDT_All));
1960 strm.flush();
1961 const char *err = "error: invalid DIE reference 0x00000011. Offset is in "
1962 "between DIEs:";
1963 EXPECT_TRUE(strm.str().find(err) != std::string::npos);
1964 }
1965
1917 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1918 VerifyError(
1919 DwarfContext,
1920 "error: invalid DIE reference 0x00000011. Offset is in between DIEs:");
1921 }
1922
1923 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineSequence) {
1924 // Create a single compile unit whose line table has a sequence in it where
1925 // the address decreases.
1926 StringRef yamldata = R"(
1927 debug_str:
1928 - ''
1929 - /tmp/main.c
1930 debug_abbrev:
1931 - Code: 0x00000001
1932 Tag: DW_TAG_compile_unit
1933 Children: DW_CHILDREN_no
1934 Attributes:
1935 - Attribute: DW_AT_name
1936 Form: DW_FORM_strp
1937 - Attribute: DW_AT_stmt_list
1938 Form: DW_FORM_sec_offset
1939 debug_info:
1940 - Length:
1941 TotalLength: 16
1942 Version: 4
1943 AbbrOffset: 0
1944 AddrSize: 8
1945 Entries:
1946 - AbbrCode: 0x00000001
1947 Values:
1948 - Value: 0x0000000000000001
1949 - Value: 0x0000000000000000
1950 debug_line:
1951 - Length:
1952 TotalLength: 68
1953 Version: 2
1954 PrologueLength: 34
1955 MinInstLength: 1
1956 DefaultIsStmt: 1
1957 LineBase: 251
1958 LineRange: 14
1959 OpcodeBase: 13
1960 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
1961 IncludeDirs:
1962 - /tmp
1963 Files:
1964 - Name: main.c
1965 DirIdx: 1
1966 ModTime: 0
1967 Length: 0
1968 Opcodes:
1969 - Opcode: DW_LNS_extended_op
1970 ExtLen: 9
1971 SubOpcode: DW_LNE_set_address
1972 Data: 4112
1973 - Opcode: DW_LNS_advance_line
1974 SData: 9
1975 Data: 4112
1976 - Opcode: DW_LNS_copy
1977 Data: 4112
1978 - Opcode: DW_LNS_advance_pc
1979 Data: 18446744073709551600
1980 - Opcode: DW_LNS_extended_op
1981 ExtLen: 1
1982 SubOpcode: DW_LNE_end_sequence
1983 Data: 18446744073709551600
1984 )";
1985 auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
1986 ASSERT_TRUE((bool)ErrOrSections);
1987 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
1988 VerifyError(DwarfContext, "error: .debug_line[0x00000000] row[1] decreases "
1989 "in address from previous row:");
1990 }
1991
1992 TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
1993 // Create a single compile unit whose line table has a line table row with
1994 // an invalid file index.
1995 StringRef yamldata = R"(
1996 debug_str:
1997 - ''
1998 - /tmp/main.c
1999 debug_abbrev:
2000 - Code: 0x00000001
2001 Tag: DW_TAG_compile_unit
2002 Children: DW_CHILDREN_no
2003 Attributes:
2004 - Attribute: DW_AT_name
2005 Form: DW_FORM_strp
2006 - Attribute: DW_AT_stmt_list
2007 Form: DW_FORM_sec_offset
2008 debug_info:
2009 - Length:
2010 TotalLength: 16
2011 Version: 4
2012 AbbrOffset: 0
2013 AddrSize: 8
2014 Entries:
2015 - AbbrCode: 0x00000001
2016 Values:
2017 - Value: 0x0000000000000001
2018 - Value: 0x0000000000000000
2019 debug_line:
2020 - Length:
2021 TotalLength: 61
2022 Version: 2
2023 PrologueLength: 34
2024 MinInstLength: 1
2025 DefaultIsStmt: 1
2026 LineBase: 251
2027 LineRange: 14
2028 OpcodeBase: 13
2029 StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
2030 IncludeDirs:
2031 - /tmp
2032 Files:
2033 - Name: main.c
2034 DirIdx: 1
2035 ModTime: 0
2036 Length: 0
2037 Opcodes:
2038 - Opcode: DW_LNS_extended_op
2039 ExtLen: 9
2040 SubOpcode: DW_LNE_set_address
2041 Data: 4096
2042 - Opcode: DW_LNS_advance_line
2043 SData: 9
2044 Data: 4096
2045 - Opcode: DW_LNS_copy
2046 Data: 4096
2047 - Opcode: DW_LNS_advance_pc
2048 Data: 16
2049 - Opcode: DW_LNS_set_file
2050 Data: 5
2051 - Opcode: DW_LNS_extended_op
2052 ExtLen: 1
2053 SubOpcode: DW_LNE_end_sequence
2054 Data: 5
2055 )";
2056 auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
2057 ASSERT_TRUE((bool)ErrOrSections);
2058 DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
2059 VerifyError(DwarfContext, "error: .debug_line[0x00000000][1] has invalid "
2060 "file index 5 (valid values are [1,1]):");
2061 }
2062
19662063 } // end anonymous namespace