diff --git a/lld/test/ELF/undef.s b/lld/test/ELF/undef.s index 5762d3b7a689c..616c41e0537fa 100644 --- a/lld/test/ELF/undef.s +++ b/lld/test/ELF/undef.s @@ -75,7 +75,7 @@ # Show that a problem in a line table that prevents further parsing of that # table means that no line information is displayed in the wardning. # CHECK: error: undefined symbol: zed7 -# CHECK-NEXT: >>> referenced by {{.*}}4.o:(.text+0x10) +# CHECK-NEXT: >>> referenced by undef-bad-debug.s:21 # Show that a problem with one line table's information doesn't affect getting information from # a different one in the same object. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 08b58669b3eb3..33469c0f0d681 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -580,8 +580,9 @@ void DWARFDebugLine::ParsingState::appendRowToMatrix() { } LineTable->appendRow(Row); if (Row.EndSequence) { - // Record the end of instruction sequence. - Sequence.HighPC = Row.Address.Address; + // Proposed change, without this the added test will fail. With this + // GSYMTest/TestDWARFNoLines will fail + Sequence.HighPC = Row.Address.Address + LineTable->Prologue.MinInstLength; Sequence.LastRowIndex = RowNumber + 1; Sequence.SectionIndex = Row.Address.SectionIndex; if (Sequence.isValid()) @@ -1311,7 +1312,7 @@ uint32_t DWARFDebugLine::LineTable::findRowInSeq( RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex; RowIter LastRow = Rows.begin() + Seq.LastRowIndex; assert(FirstRow->Address.Address <= Row.Address.Address && - Row.Address.Address < LastRow[-1].Address.Address); + Row.Address.Address <= LastRow[-1].Address.Address); RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1, Row, DWARFDebugLine::Row::orderByAddress) - 1; diff --git a/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll b/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll index cb5908976fb6c..380dcbfa9b11d 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll +++ b/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll @@ -95,7 +95,7 @@ ; CHECK-NEXT: "#local vars - entry values with [80%,90%) of parent scope covered by DW_AT_location": 1, ; CHECK-NEXT: "#local vars - entry values with [90%,100%) of parent scope covered by DW_AT_location": 0, ; CHECK-NEXT: "#local vars - entry values with 100% of parent scope covered by DW_AT_location": 1 -; CHECK-NEXT: "#bytes with line information": 51, +; CHECK-NEXT: "#bytes with line information": 52, ; CHECK-NEXT: "#bytes with line-0 locations": 3, ; CHECK-NEXT: "#line entries": 7, ; CHECK-NEXT: "#line entries (is_stmt)": 5, diff --git a/llvm/test/tools/llvm-symbolizer/symbol-search.test b/llvm/test/tools/llvm-symbolizer/symbol-search.test index bb07c54e100b5..c3f16c887a760 100644 --- a/llvm/test/tools/llvm-symbolizer/symbol-search.test +++ b/llvm/test/tools/llvm-symbolizer/symbol-search.test @@ -73,7 +73,7 @@ RUN: llvm-addr2line --obj=%p/Inputs/symbols.so +0x1138 | FileCheck --check-prefi RUN: llvm-addr2line --obj=%p/Inputs/symbols.so _ZL14static_func_01i | FileCheck --check-prefix=MULTI-CXX %s RUN: llvm-symbolizer --obj=%p/Inputs/symbols.so _ZL14static_func_01i | FileCheck --check-prefix=MULTI-CXX %s MULTI-CXX: /tmp/dbginfo{{[/\]+}}symbols.part1.cpp:7 -MULTI-CXX: /tmp/dbginfo{{[/\]+}}symbols.part2.cpp:5 +MULTI-CXX: /tmp/dbginfo/symbols.h:19 # Show that containing function name can be printed in mangled form. RUN: llvm-symbolizer --obj=%p/Inputs/symbols.so --no-demangle _Z7func_04i | FileCheck --check-prefix=MANGLED %s diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp index 2fe52600df923..6c0b0f5eb91f9 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -2148,4 +2148,112 @@ TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) { EXPECT_EQ(Rows[1], 3u); } } + +/// Test that HighPC is now inclusive in Sequence containsPC checks. +// +/// With the old exclusive HighPC logic, lookups at the last row's address would +/// fail. With the new inclusive HighPC logic, lookups at the HighPC address +/// should succeed. +TEST_F(DebugLineBasicFixture, LookupLastRow) { + if (!setupGenerator()) + GTEST_SKIP(); + + // Create a line table with a sequence that covers addresses [0x1000, 0x1010] + // We'll test lookups at various addresses including the HighPC (0x1010) + LineTable < = Gen->addLineTable(); + + // Set address to 0x1000 and create first row + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}}); + LT.addStandardOpcode(DW_LNS_copy, {}); + + // Advance to 0x1008 and create second row + LT.addStandardOpcode(DW_LNS_advance_pc, {{0x8, LineTable::ULEB}}); + LT.addStandardOpcode(DW_LNS_copy, {}); + + // Advance to 0x1010 and create third row (this will be the HighPC) + LT.addStandardOpcode(DW_LNS_advance_pc, {{0x8, LineTable::ULEB}}); + LT.addStandardOpcode(DW_LNS_copy, {}); + + // End the sequence - this makes HighPC = 0x1010 + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); + + generate(); + + // Parse the line table + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); + ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); + const auto *Table = *ExpectedLineTable; + + // Verify we have one sequence with the expected address range + ASSERT_EQ(Table->Sequences.size(), 1u); + const auto &Seq = Table->Sequences[0]; + EXPECT_EQ(Seq.LowPC, 0x1000U); + EXPECT_EQ(Seq.HighPC, 0x1011U); + + auto LastRow = Table->Rows.back(); + + // Lookup the last Row - this is the key test for inclusive HighPC + // With the old exclusive logic, this would return UnknownRowIndex + // With the new inclusive logic, this should succeed + { + uint32_t RowIndex = Table->lookupAddress( + {LastRow.Address.Address, object::SectionedAddress::UndefSection}); + // Both last and the second to the last row have the same PC, so the second + // to the second to the last should pop up first. + EXPECT_EQ(RowIndex, Table->Rows.size() - 2) + << "Lookup at HighPC should find the second to the last row"; + } +} + +/// Test that a sequence with only one row works correctly with inclusive +/// HighPC. This is an important edge case where LowPC == HighPC, and the +/// inclusive HighPC logic should still allow lookups at that single address. +TEST_F(DebugLineBasicFixture, SingleInstSeq) { + if (!setupGenerator()) + GTEST_SKIP(); + + // Create a line table with a sequence that has only one row + // This creates a sequence where LowPC == HighPC + LineTable < = Gen->addLineTable(); + + // Set address to 0x3000 and create the only row + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x3000U, LineTable::Quad}}); + LT.addStandardOpcode(DW_LNS_copy, {}); + + // End the sequence immediately - this makes LowPC == HighPC == 0x3000 + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); + + generate(); + + // Parse the line table + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); + ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); + const auto *Table = *ExpectedLineTable; + + // Verify we have one sequence with LowPC == HighPC + ASSERT_EQ(Table->Sequences.size(), 1u); + const auto &Seq = Table->Sequences[0]; + EXPECT_EQ(Seq.LowPC, 0x3000U); + EXPECT_EQ(Seq.HighPC, 0x3001U); + + // Verify we have exactly one row (plus the end_sequence row) + EXPECT_EQ(Table->Rows.size(), 2u); + EXPECT_EQ(Table->Rows[0].Address.Address, 0x3000U); + EXPECT_TRUE(Table->Rows[1].EndSequence); + + auto LastRow = Table->Rows.back(); + + // Lookup the last Row - this is the key test for inclusive HighPC + // With the old exclusive logic, this would return UnknownRowIndex + // With the new inclusive logic, this should succeed + { + uint32_t RowIndex = Table->lookupAddress( + {LastRow.Address.Address, object::SectionedAddress::UndefSection}); + EXPECT_EQ(RowIndex, Table->Rows.size() - 2) + << "Lookup at HighPC should find the last row"; + } +} + } // end anonymous namespace