Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lld/test/ELF/undef.s
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-dwarfdump/X86/locstats.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-symbolizer/symbol-search.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
108 changes: 108 additions & 0 deletions llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &LT = 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 &LT = 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
Loading