@@ -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.
20542052TEST_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 < = 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