Skip to content

Commit 16e8e20

Browse files
committed
Address Feedback Nr.3
1 parent 7aa8cae commit 16e8e20

File tree

3 files changed

+136
-125
lines changed

3 files changed

+136
-125
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,6 @@ class DWARFDebugLine {
227227
return SectionIndex == PC.SectionIndex &&
228228
(LowPC <= PC.Address && PC.Address < HighPC);
229229
}
230-
231-
void SetSequenceOffset(uint64_t Offset) { StmtSeqOffset = Offset; }
232230
};
233231

234232
struct LineTable {

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ DWARFDebugLine::ParsingState::ParsingState(
567567
void DWARFDebugLine::ParsingState::resetRowAndSequence(uint64_t Offset) {
568568
Row.reset(LineTable->Prologue.DefaultIsStmt);
569569
Sequence.reset();
570-
Sequence.SetSequenceOffset(Offset);
570+
Sequence.StmtSeqOffset = Offset;
571571
}
572572

573573
void DWARFDebugLine::ParsingState::appendRowToMatrix() {
@@ -1391,51 +1391,86 @@ bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
13911391
std::optional<uint64_t> StmtSequenceOffset) const {
13921392
if (Sequences.empty())
13931393
return false;
1394-
uint64_t EndAddr = Address.Address + Size;
1395-
// First, find an instruction sequence containing the given address.
1396-
DWARFDebugLine::Sequence Sequence;
1397-
Sequence.SectionIndex = Address.SectionIndex;
1398-
Sequence.HighPC = Address.Address;
1399-
SequenceIter LastSeq = Sequences.end();
1400-
SequenceIter SeqPos = llvm::upper_bound(
1401-
Sequences, Sequence, DWARFDebugLine::Sequence::orderByHighPC);
1402-
if (SeqPos == LastSeq || !SeqPos->containsPC(Address))
1403-
return false;
14041394

1405-
SequenceIter StartPos = SeqPos;
1395+
const uint64_t EndAddr = Address.Address + Size;
14061396

1407-
// Add the rows from the first sequence to the vector, starting with the
1408-
// index we just calculated
1409-
1410-
while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
1411-
const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
1412-
1413-
// Skip sequences that don't match our stmt_sequence offset if one was
1414-
// provided
1415-
if (StmtSequenceOffset && CurSeq.StmtSeqOffset != *StmtSequenceOffset) {
1416-
++SeqPos;
1417-
continue;
1418-
}
1397+
// Helper: Given a sequence and a starting address, find the subset
1398+
// of rows within [Address, EndAddr) and append them to `Result`.
1399+
auto addRowsFromSequence = [&](const Sequence &Seq,
1400+
object::SectionedAddress StartAddr,
1401+
uint64_t EndAddress, bool IsFirstSequence) {
1402+
// If this sequence does not intersect our [StartAddr, EndAddress) range,
1403+
// do nothing.
1404+
if (Seq.HighPC <= StartAddr.Address || Seq.LowPC >= EndAddress)
1405+
return;
14191406

1420-
// For the first sequence, we need to find which row in the sequence is the
1421-
// first in our range.
1422-
uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
1423-
if (SeqPos == StartPos)
1424-
FirstRowIndex = findRowInSeq(CurSeq, Address);
1407+
// For the "first" sequence in the search, we must figure out which row
1408+
// actually starts within our address range.
1409+
uint32_t FirstRowIndex = Seq.FirstRowIndex;
1410+
if (IsFirstSequence)
1411+
FirstRowIndex = findRowInSeq(Seq, StartAddr);
14251412

1426-
// Figure out the last row in the range.
1413+
// Similarly, compute the last row that is within [StartAddr, EndAddress).
14271414
uint32_t LastRowIndex =
1428-
findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex});
1415+
findRowInSeq(Seq, {EndAddress - 1, StartAddr.SectionIndex});
14291416
if (LastRowIndex == UnknownRowIndex)
1430-
LastRowIndex = CurSeq.LastRowIndex - 1;
1417+
LastRowIndex = Seq.LastRowIndex - 1;
14311418

14321419
assert(FirstRowIndex != UnknownRowIndex);
14331420
assert(LastRowIndex != UnknownRowIndex);
14341421

1422+
// Append all row indices in [FirstRowIndex, LastRowIndex].
14351423
for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
14361424
Result.push_back(I);
14371425
}
1426+
};
1427+
1428+
// If a stmt_sequence_offset was provided, do a binary search to find the
1429+
// single sequence that matches that offset. Then add only its relevant rows.
1430+
if (StmtSequenceOffset) {
1431+
// Binary-search the Sequences by their StmtSeqOffset:
1432+
auto It = llvm::lower_bound(Sequences, *StmtSequenceOffset,
1433+
[](const Sequence &Seq, uint64_t OffsetVal) {
1434+
return Seq.StmtSeqOffset < OffsetVal;
1435+
});
1436+
1437+
// If not found or mismatched, there’s no match to return.
1438+
if (It == Sequences.end() || It->StmtSeqOffset != *StmtSequenceOffset)
1439+
return false;
1440+
1441+
// Now add rows from the discovered sequence if it intersects [Address,
1442+
// EndAddr).
1443+
addRowsFromSequence(*It, Address, EndAddr, /*IsFirstSequence=*/true);
1444+
return !Result.empty();
1445+
}
14381446

1447+
// Otherwise, fall back to logic of walking sequences by Address.
1448+
// We first find a sequence containing `Address` (via upper_bound on HighPC),
1449+
// then proceed forward through overlapping sequences in ascending order.
1450+
1451+
// Construct a dummy Sequence to find where `Address` fits by HighPC.
1452+
DWARFDebugLine::Sequence SearchSeq;
1453+
SearchSeq.SectionIndex = Address.SectionIndex;
1454+
SearchSeq.HighPC = Address.Address;
1455+
1456+
auto LastSeq = Sequences.end();
1457+
auto SeqPos = llvm::upper_bound(Sequences, SearchSeq,
1458+
DWARFDebugLine::Sequence::orderByHighPC);
1459+
if (SeqPos == LastSeq || !SeqPos->containsPC(Address))
1460+
return false;
1461+
1462+
// This marks the first sequence we found that might contain Address.
1463+
const auto StartPos = SeqPos;
1464+
1465+
// Walk forward until sequences no longer intersect [Address, EndAddr).
1466+
while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
1467+
// Add rows only if the sequence is in the same section:
1468+
if (SeqPos->SectionIndex == Address.SectionIndex) {
1469+
// For the very first sequence, we need the row that lines up with
1470+
// `Address`.
1471+
bool IsFirst = (SeqPos == StartPos);
1472+
addRowsFromSequence(*SeqPos, Address, EndAddr, IsFirst);
1473+
}
14391474
++SeqPos;
14401475
}
14411476

llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp

Lines changed: 69 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,138 +2036,116 @@ TEST_F(DebugLineBasicFixture, PrintPathsProperly) {
20362036
}
20372037

20382038
/// Test that lookupAddressRange correctly filters rows based on
2039-
/// DW_AT_LLVM_stmt_sequence.
2039+
/// a statement-sequence offset (simulating DW_AT_LLVM_stmt_sequence).
20402040
///
20412041
/// This test verifies that:
2042-
/// 1. When a DIE has a DW_AT_LLVM_stmt_sequence attribute, lookupAddressRange
2043-
/// only returns rows from the sequence starting at the specified offset
2044-
/// 2. When a DIE has an invalid DW_AT_LLVM_stmt_sequence offset, no rows are
2045-
/// returned
2046-
/// 3. When no DW_AT_LLVM_stmt_sequence is present, all matching rows are
2047-
/// returned
2042+
/// 1. When a statement-sequence offset is provided, lookupAddressRange
2043+
/// only returns rows from the sequence starting at that offset.
2044+
/// 2. When an invalid statement-sequence offset is provided, no rows
2045+
/// are returned.
2046+
/// 3. When no statement-sequence offset is provided, all matching rows
2047+
/// in the table are returned.
20482048
///
2049-
/// The test creates a line table with two sequences at the same address range
2050-
/// but different line numbers. It then creates three subprogram DIEs:
2051-
/// - One with DW_AT_LLVM_stmt_sequence pointing to the first sequence
2052-
/// - One with DW_AT_LLVM_stmt_sequence pointing to the second sequence
2053-
/// - One with an invalid DW_AT_LLVM_stmt_sequence offset
2049+
/// We build a line table with two sequences at the same address range
2050+
/// but different line numbers. Then we try lookups with various statement-
2051+
/// sequence offsets to check the filtering logic.
20542052
TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) {
20552053
if (!setupGenerator())
20562054
GTEST_SKIP();
20572055

2058-
// Create new DWARF with the subprogram DIE
2059-
dwarfgen::CompileUnit &CU = Gen->addCompileUnit();
2060-
dwarfgen::DIE CUDie = CU.getUnitDIE();
2061-
2062-
CUDie.addAttribute(DW_AT_name, DW_FORM_string, "/tmp/main.c");
2063-
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
2064-
2065-
dwarfgen::DIE SD1 = CUDie.addChild(DW_TAG_subprogram);
2066-
SD1.addAttribute(DW_AT_name, DW_FORM_string, "sub1");
2067-
SD1.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
2068-
SD1.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x1032U);
2069-
// DW_AT_LLVM_stmt_sequence points to the first sequence
2070-
SD1.addAttribute(DW_AT_LLVM_stmt_sequence, DW_FORM_sec_offset, 0x2e);
2071-
2072-
dwarfgen::DIE SD2 = CUDie.addChild(DW_TAG_subprogram);
2073-
SD2.addAttribute(DW_AT_name, DW_FORM_string, "sub2");
2074-
SD2.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
2075-
SD2.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x1032U);
2076-
// DW_AT_LLVM_stmt_sequence points to the second sequence
2077-
SD2.addAttribute(DW_AT_LLVM_stmt_sequence, DW_FORM_sec_offset, 0x42);
2078-
2079-
dwarfgen::DIE SD3 = CUDie.addChild(DW_TAG_subprogram);
2080-
SD3.addAttribute(DW_AT_name, DW_FORM_string, "sub3");
2081-
SD3.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
2082-
SD3.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x1032U);
2083-
// Invalid DW_AT_LLVM_stmt_sequence
2084-
SD3.addAttribute(DW_AT_LLVM_stmt_sequence, DW_FORM_sec_offset, 0x66);
2085-
2086-
// Create a line table with multiple sequences
2056+
// Create a line table that has two sequences covering [0x1000, 0x1004).
2057+
// Each sequence has two rows: addresses at 0x1000 and 0x1004, but
2058+
// they differ by line numbers (100 vs. 200, etc.).
2059+
//
2060+
// We'll pretend the first sequence starts at offset 0x2e in the line table,
2061+
// the second at 0x42, and we'll also test an invalid offset 0x66.
2062+
20872063
LineTable &LT = Gen->addLineTable();
20882064

2089-
// First sequence with addresses 0x1000(Ln100), 0x1004(Ln101)
2065+
// First sequence at offset 0x2e: addresses 0x1000(Ln=100), 0x1004(Ln=101)
20902066
LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}});
20912067
LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
2068+
// Advance the line register by 99 (so line=100) and copy.
20922069
LT.addStandardOpcode(DW_LNS_advance_line, {{99, LineTable::SLEB}});
20932070
LT.addStandardOpcode(DW_LNS_copy, {});
2094-
LT.addByte(0x4b); // Special opcode: address += 4, line += 1
2071+
// 0x4b is a special opcode: address += 4, line += 1 (so line=101).
2072+
LT.addByte(0x4b);
2073+
// End this sequence.
20952074
LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
20962075

2097-
// Second sequence with addresses 0x1000(Ln200), 0x1004(Ln201)
2076+
// Second sequence at offset 0x42: addresses 0x1000(Ln=200), 0x1004(Ln=201)
20982077
LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}});
20992078
LT.addStandardOpcode(DW_LNS_set_prologue_end, {});
21002079
LT.addStandardOpcode(DW_LNS_advance_line, {{199, LineTable::SLEB}});
21012080
LT.addStandardOpcode(DW_LNS_copy, {});
2102-
LT.addByte(0x4b); // Special opcode: address += 4, line += 1
2081+
// 0x4b again: address += 4, line += 1 (so line=201).
2082+
LT.addByte(0x4b);
2083+
// End this second sequence.
21032084
LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
21042085

2105-
// Generate the DWARF
2086+
// Generate the DWARF data.
21062087
generate();
21072088

2108-
// Parse the line table to get the sequence offset
2109-
auto ExpectedLineTable = Line.getOrParseLineTable(
2110-
LineData, /*Offset=*/0, *Context, nullptr, RecordRecoverable);
2089+
// Parse the line table.
2090+
auto ExpectedLineTable =
2091+
Line.getOrParseLineTable(LineData, /*Offset=*/0, *Context,
2092+
/*DwarfUnit=*/nullptr, RecordRecoverable);
21112093
ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded());
21122094
const auto *Table = *ExpectedLineTable;
21132095

2114-
uint32_t NumCUs = Context->getNumCompileUnits();
2115-
ASSERT_EQ(NumCUs, 1u);
2116-
DWARFUnit *Unit = Context->getUnitAtIndex(0);
2117-
auto DwarfCUDie = Unit->getUnitDIE(false);
2118-
2119-
auto Sub1Die = DwarfCUDie.getFirstChild();
2120-
auto Sub2Die = Sub1Die.getSibling();
2121-
auto Sub3Die = Sub2Die.getSibling();
2122-
2123-
// Verify Sub1Die is the DIE generated from SD1
2124-
auto NameAttr1 = Sub1Die.find(DW_AT_name);
2125-
EXPECT_STREQ(*dwarf::toString(*NameAttr1), "sub1");
2126-
2127-
// Verify Sub2Die is the DIE generated from SD2
2128-
auto NameAttr2 = Sub2Die.find(DW_AT_name);
2129-
EXPECT_STREQ(*dwarf::toString(*NameAttr2), "sub2");
2130-
2131-
// Verify Sub2Die is the DIE generated from SD3
2132-
auto NameAttr3 = Sub3Die.find(DW_AT_name);
2133-
EXPECT_STREQ(*dwarf::toString(*NameAttr3), "sub3");
2134-
2135-
// Ensure there are two sequences
2096+
// The table should have two sequences, each starting at our chosen offsets.
21362097
ASSERT_EQ(Table->Sequences.size(), 2u);
21372098

2138-
// Lookup addresses in the first sequence with the second sequence's filter
2099+
// 1) Try looking up with an invalid offset (simulating an invalid
2100+
// DW_AT_LLVM_stmt_sequence). We expect no rows.
21392101
{
21402102
std::vector<uint32_t> Rows;
2141-
bool Found;
2142-
2143-
// Look up using Sub3Die's invalid stmt_sequence offset
2144-
auto StmtSeqAttr3 = Sub3Die.find(dwarf::DW_AT_LLVM_stmt_sequence);
2145-
ASSERT_TRUE(StmtSeqAttr3);
2146-
Found = Table->lookupAddressRange(
2103+
bool Found = Table->lookupAddressRange(
21472104
{0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,
2148-
toSectionOffset(StmtSeqAttr3));
2105+
/*StmtSequenceOffset=*/0x66); // invalid offset
21492106
EXPECT_FALSE(Found);
2107+
EXPECT_TRUE(Rows.empty());
2108+
}
21502109

2151-
// Look up using Sub1Die's valid stmt_sequence offset
2152-
auto StmtSeqAttr1 = Sub1Die.find(dwarf::DW_AT_LLVM_stmt_sequence);
2153-
ASSERT_TRUE(StmtSeqAttr1);
2154-
Found = Table->lookupAddressRange(
2110+
// 2) Look up using the offset 0x2e (our first sequence). We expect
2111+
// to get the rows from that sequence only (which for 0x1000 is row #0).
2112+
{
2113+
std::vector<uint32_t> Rows;
2114+
bool Found = Table->lookupAddressRange(
21552115
{0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,
2156-
toSectionOffset(StmtSeqAttr1));
2116+
/*StmtSequenceOffset=*/0x2e);
21572117
EXPECT_TRUE(Found);
21582118
ASSERT_EQ(Rows.size(), 1u);
2159-
EXPECT_EQ(Rows[0], 0U);
2119+
// The first sequence's first row is index 0.
2120+
EXPECT_EQ(Rows[0], 0u);
2121+
}
21602122

2161-
// Look up using Sub2Die's valid stmt_sequence offset
2162-
Rows.clear();
2163-
auto StmtSeqAttr2 = Sub2Die.find(dwarf::DW_AT_LLVM_stmt_sequence);
2164-
ASSERT_TRUE(StmtSeqAttr2);
2165-
Found = Table->lookupAddressRange(
2123+
// 3) Look up using the offset 0x42 (second sequence). For address 0x1000
2124+
// in that second sequence, we should see row #2.
2125+
{
2126+
std::vector<uint32_t> Rows;
2127+
bool Found = Table->lookupAddressRange(
21662128
{0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,
2167-
toSectionOffset(StmtSeqAttr2));
2129+
/*StmtSequenceOffset=*/0x42);
21682130
EXPECT_TRUE(Found);
21692131
ASSERT_EQ(Rows.size(), 1u);
2132+
// The second sequence's first row is index 2 in the table.
21702133
EXPECT_EQ(Rows[0], 3u);
21712134
}
2135+
2136+
// 4) Look up with no statement-sequence offset specified.
2137+
// We should get rows from both sequences for address 0x1000.
2138+
{
2139+
std::vector<uint32_t> Rows;
2140+
bool Found = Table->lookupAddressRange(
2141+
{0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows,
2142+
std::nullopt /* no filter */);
2143+
EXPECT_TRUE(Found);
2144+
// The first sequence's row is #0, second's row is #2, so both should
2145+
// appear.
2146+
ASSERT_EQ(Rows.size(), 2u);
2147+
EXPECT_EQ(Rows[0], 0u);
2148+
EXPECT_EQ(Rows[1], 3u);
2149+
}
21722150
}
21732151
} // end anonymous namespace

0 commit comments

Comments
 (0)