Skip to content

Commit d1d3366

Browse files
committed
[DebugLine] Sequence HighPC should be LastRow.address + MinInstLength
1 parent 37bcd93 commit d1d3366

File tree

2 files changed

+111
-1
lines changed

2 files changed

+111
-1
lines changed

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ void DWARFDebugLine::ParsingState::appendRowToMatrix() {
581581
LineTable->appendRow(Row);
582582
if (Row.EndSequence) {
583583
// Record the end of instruction sequence.
584-
Sequence.HighPC = Row.Address.Address;
584+
Sequence.HighPC = Row.Address.Address + LineTable->Prologue.MinInstLength;
585585
Sequence.LastRowIndex = RowNumber + 1;
586586
Sequence.SectionIndex = Row.Address.SectionIndex;
587587
if (Sequence.isValid())

llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,4 +2148,114 @@ TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) {
21482148
EXPECT_EQ(Rows[1], 3u);
21492149
}
21502150
}
2151+
2152+
/// Test that HighPC is now inclusive in Sequence containsPC checks.
2153+
//
2154+
/// With the old exclusive HighPC logic, lookups at the last row's address would
2155+
/// fail. With the new inclusive HighPC logic, lookups at the HighPC address
2156+
/// should succeed.
2157+
TEST_F(DebugLineBasicFixture, HighPCInclusiveLookup) {
2158+
if (!setupGenerator())
2159+
GTEST_SKIP();
2160+
2161+
// Create a line table with a sequence that covers addresses [0x1000, 0x1010]
2162+
// We'll test lookups at various addresses including the HighPC (0x1010)
2163+
LineTable &LT = Gen->addLineTable();
2164+
2165+
// Set address to 0x1000 and create first row
2166+
LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}});
2167+
LT.addStandardOpcode(DW_LNS_copy, {});
2168+
2169+
// Advance to 0x1008 and create second row
2170+
LT.addStandardOpcode(DW_LNS_advance_pc, {{0x8, LineTable::ULEB}});
2171+
LT.addStandardOpcode(DW_LNS_copy, {});
2172+
2173+
// Advance to 0x1010 and create third row (this will be the HighPC)
2174+
LT.addStandardOpcode(DW_LNS_advance_pc, {{0x8, LineTable::ULEB}});
2175+
LT.addStandardOpcode(DW_LNS_copy, {});
2176+
2177+
// End the sequence - this makes HighPC = 0x1010
2178+
LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
2179+
2180+
generate();
2181+
2182+
// Parse the line table
2183+
auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
2184+
nullptr, RecordRecoverable);
2185+
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
2186+
const auto *Table = *ExpectedLineTable;
2187+
2188+
// Verify we have one sequence with the expected address range
2189+
ASSERT_EQ(Table->Sequences.size(), 1u);
2190+
const auto &Seq = Table->Sequences[0];
2191+
EXPECT_EQ(Seq.LowPC, 0x1000U);
2192+
EXPECT_EQ(Seq.HighPC, 0x1011U);
2193+
2194+
auto LastRow = Table->Rows.back();
2195+
2196+
// Lookup the last Row - this is the key test for inclusive HighPC
2197+
// With the old exclusive logic, this would return UnknownRowIndex
2198+
// With the new inclusive logic, this should succeed
2199+
{
2200+
uint32_t RowIndex = Table->lookupAddress(
2201+
{LastRow.Address.Address, object::SectionedAddress::UndefSection});
2202+
// EXPECT_NE(RowIndex, Table->UnknownRowIndex) << "Lookup at HighPC found no
2203+
// row";
2204+
EXPECT_EQ(RowIndex, Table->Rows.size() - 2)
2205+
<< "Lookup at HighPC should find the second to the last row";
2206+
}
2207+
}
2208+
2209+
/// Test that a sequence with only one row works correctly with inclusive
2210+
/// HighPC. This is an important edge case where LowPC == HighPC, and the
2211+
/// inclusive HighPC logic should still allow lookups at that single address.
2212+
TEST_F(DebugLineBasicFixture, SingleInstSequenceInclusiveHighPC) {
2213+
if (!setupGenerator())
2214+
GTEST_SKIP();
2215+
2216+
// Create a line table with a sequence that has only one row
2217+
// This creates a sequence where LowPC == HighPC
2218+
LineTable &LT = Gen->addLineTable();
2219+
2220+
// Set address to 0x3000 and create the only row
2221+
LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x3000U, LineTable::Quad}});
2222+
LT.addStandardOpcode(DW_LNS_copy, {});
2223+
2224+
// End the sequence immediately - this makes LowPC == HighPC == 0x3000
2225+
LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
2226+
2227+
generate();
2228+
2229+
// Parse the line table
2230+
auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context,
2231+
nullptr, RecordRecoverable);
2232+
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
2233+
const auto *Table = *ExpectedLineTable;
2234+
2235+
// Verify we have one sequence with LowPC == HighPC
2236+
ASSERT_EQ(Table->Sequences.size(), 1u);
2237+
const auto &Seq = Table->Sequences[0];
2238+
EXPECT_EQ(Seq.LowPC, 0x3000U);
2239+
EXPECT_EQ(Seq.HighPC, 0x3001U);
2240+
2241+
// Verify we have exactly one row (plus the end_sequence row)
2242+
EXPECT_EQ(Table->Rows.size(), 2u);
2243+
EXPECT_EQ(Table->Rows[0].Address.Address, 0x3000U);
2244+
EXPECT_TRUE(Table->Rows[1].EndSequence);
2245+
2246+
auto LastRow = Table->Rows.back();
2247+
2248+
// Lookup the last Row - this is the key test for inclusive HighPC
2249+
// With the old exclusive logic, this would return UnknownRowIndex
2250+
// With the new inclusive logic, this should succeed
2251+
{
2252+
uint32_t RowIndex = Table->lookupAddress(
2253+
{LastRow.Address.Address, object::SectionedAddress::UndefSection});
2254+
// EXPECT_NE(RowIndex, Table->UnknownRowIndex) << "Lookup at HighPC found no
2255+
// row";
2256+
EXPECT_EQ(RowIndex, Table->Rows.size() - 2)
2257+
<< "Lookup at HighPC should find the last row";
2258+
}
2259+
}
2260+
21512261
} // end anonymous namespace

0 commit comments

Comments
 (0)