@@ -2036,138 +2036,116 @@ TEST_F(DebugLineBasicFixture, PrintPathsProperly) {
2036
2036
}
2037
2037
2038
2038
// / 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) .
2040
2040
// /
2041
2041
// / 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.
2048
2048
// /
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.
2054
2052
TEST_F (DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) {
2055
2053
if (!setupGenerator ())
2056
2054
GTEST_SKIP ();
2057
2055
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
+
2087
2063
LineTable < = Gen->addLineTable ();
2088
2064
2089
- // First sequence with addresses 0x1000(Ln100 ), 0x1004(Ln101 )
2065
+ // First sequence at offset 0x2e: addresses 0x1000(Ln=100 ), 0x1004(Ln=101 )
2090
2066
LT.addExtendedOpcode (9 , DW_LNE_set_address, {{0x1000U , LineTable::Quad}});
2091
2067
LT.addStandardOpcode (DW_LNS_set_prologue_end, {});
2068
+ // Advance the line register by 99 (so line=100) and copy.
2092
2069
LT.addStandardOpcode (DW_LNS_advance_line, {{99 , LineTable::SLEB}});
2093
2070
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.
2095
2074
LT.addExtendedOpcode (1 , DW_LNE_end_sequence, {});
2096
2075
2097
- // Second sequence with addresses 0x1000(Ln200 ), 0x1004(Ln201 )
2076
+ // Second sequence at offset 0x42: addresses 0x1000(Ln=200 ), 0x1004(Ln=201 )
2098
2077
LT.addExtendedOpcode (9 , DW_LNE_set_address, {{0x1000U , LineTable::Quad}});
2099
2078
LT.addStandardOpcode (DW_LNS_set_prologue_end, {});
2100
2079
LT.addStandardOpcode (DW_LNS_advance_line, {{199 , LineTable::SLEB}});
2101
2080
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.
2103
2084
LT.addExtendedOpcode (1 , DW_LNE_end_sequence, {});
2104
2085
2105
- // Generate the DWARF
2086
+ // Generate the DWARF data.
2106
2087
generate ();
2107
2088
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);
2111
2093
ASSERT_THAT_EXPECTED (ExpectedLineTable, Succeeded ());
2112
2094
const auto *Table = *ExpectedLineTable;
2113
2095
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.
2136
2097
ASSERT_EQ (Table->Sequences .size (), 2u );
2137
2098
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.
2139
2101
{
2140
2102
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 (
2147
2104
{0x1000 , object::SectionedAddress::UndefSection}, /* Size=*/ 1 , Rows,
2148
- toSectionOffset (StmtSeqAttr3));
2105
+ /* StmtSequenceOffset= */ 0x66 ); // invalid offset
2149
2106
EXPECT_FALSE (Found);
2107
+ EXPECT_TRUE (Rows.empty ());
2108
+ }
2150
2109
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 (
2155
2115
{0x1000 , object::SectionedAddress::UndefSection}, /* Size=*/ 1 , Rows,
2156
- toSectionOffset (StmtSeqAttr1) );
2116
+ /* StmtSequenceOffset= */ 0x2e );
2157
2117
EXPECT_TRUE (Found);
2158
2118
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
+ }
2160
2122
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 (
2166
2128
{0x1000 , object::SectionedAddress::UndefSection}, /* Size=*/ 1 , Rows,
2167
- toSectionOffset (StmtSeqAttr2) );
2129
+ /* StmtSequenceOffset= */ 0x42 );
2168
2130
EXPECT_TRUE (Found);
2169
2131
ASSERT_EQ (Rows.size (), 1u );
2132
+ // The second sequence's first row is index 2 in the table.
2170
2133
EXPECT_EQ (Rows[0 ], 3u );
2171
2134
}
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
+ }
2172
2150
}
2173
2151
} // end anonymous namespace
0 commit comments