|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
| 9 | +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
9 | 10 | #include "DwarfGenerator.h"
|
10 | 11 | #include "DwarfUtils.h"
|
11 | 12 | #include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
12 |
| -#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
13 | 13 | #include "llvm/Object/ObjectFile.h"
|
14 | 14 | #include "llvm/Testing/Support/Error.h"
|
15 | 15 | #include "gtest/gtest.h"
|
@@ -2035,4 +2035,117 @@ TEST_F(DebugLineBasicFixture, PrintPathsProperly) {
|
2035 | 2035 | EXPECT_THAT(Result.c_str(), MatchesRegex("a dir.b dir.b file"));
|
2036 | 2036 | }
|
2037 | 2037 |
|
| 2038 | +/// Test that lookupAddressRange correctly filters rows based on |
| 2039 | +/// a statement-sequence offset (simulating DW_AT_LLVM_stmt_sequence). |
| 2040 | +/// |
| 2041 | +/// This test verifies that: |
| 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 | +/// |
| 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. |
| 2052 | +TEST_F(DebugLineBasicFixture, LookupAddressRangeWithStmtSequenceOffset) { |
| 2053 | + if (!setupGenerator()) |
| 2054 | + GTEST_SKIP(); |
| 2055 | + |
| 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 | + |
| 2063 | + LineTable < = Gen->addLineTable(); |
| 2064 | + |
| 2065 | + // First sequence at offset 0x2e: addresses 0x1000(Ln=100), 0x1004(Ln=101) |
| 2066 | + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}}); |
| 2067 | + LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); |
| 2068 | + // Advance the line register by 99 (so line=100) and copy. |
| 2069 | + LT.addStandardOpcode(DW_LNS_advance_line, {{99, LineTable::SLEB}}); |
| 2070 | + LT.addStandardOpcode(DW_LNS_copy, {}); |
| 2071 | + // 0x4b is a special opcode: address += 4, line += 1 (so line=101). |
| 2072 | + LT.addByte(0x4b); |
| 2073 | + // End this sequence. |
| 2074 | + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); |
| 2075 | + |
| 2076 | + // Second sequence at offset 0x42: addresses 0x1000(Ln=200), 0x1004(Ln=201) |
| 2077 | + LT.addExtendedOpcode(9, DW_LNE_set_address, {{0x1000U, LineTable::Quad}}); |
| 2078 | + LT.addStandardOpcode(DW_LNS_set_prologue_end, {}); |
| 2079 | + LT.addStandardOpcode(DW_LNS_advance_line, {{199, LineTable::SLEB}}); |
| 2080 | + LT.addStandardOpcode(DW_LNS_copy, {}); |
| 2081 | + // 0x4b again: address += 4, line += 1 (so line=201). |
| 2082 | + LT.addByte(0x4b); |
| 2083 | + // End this second sequence. |
| 2084 | + LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); |
| 2085 | + |
| 2086 | + // Generate the DWARF data. |
| 2087 | + generate(); |
| 2088 | + |
| 2089 | + // Parse the line table. |
| 2090 | + auto ExpectedLineTable = |
| 2091 | + Line.getOrParseLineTable(LineData, /*Offset=*/0, *Context, |
| 2092 | + /*DwarfUnit=*/nullptr, RecordRecoverable); |
| 2093 | + ASSERT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); |
| 2094 | + const auto *Table = *ExpectedLineTable; |
| 2095 | + |
| 2096 | + // The table should have two sequences, each starting at our chosen offsets. |
| 2097 | + ASSERT_EQ(Table->Sequences.size(), 2u); |
| 2098 | + |
| 2099 | + // 1) Try looking up with an invalid offset (simulating an invalid |
| 2100 | + // DW_AT_LLVM_stmt_sequence). We expect no rows. |
| 2101 | + { |
| 2102 | + std::vector<uint32_t> Rows; |
| 2103 | + bool Found = Table->lookupAddressRange( |
| 2104 | + {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows, |
| 2105 | + /*StmtSequenceOffset=*/0x66); // invalid offset |
| 2106 | + EXPECT_FALSE(Found); |
| 2107 | + EXPECT_TRUE(Rows.empty()); |
| 2108 | + } |
| 2109 | + |
| 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( |
| 2115 | + {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows, |
| 2116 | + /*StmtSequenceOffset=*/0x2e); |
| 2117 | + EXPECT_TRUE(Found); |
| 2118 | + ASSERT_EQ(Rows.size(), 1u); |
| 2119 | + // The first sequence's first row is index 0. |
| 2120 | + EXPECT_EQ(Rows[0], 0u); |
| 2121 | + } |
| 2122 | + |
| 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( |
| 2128 | + {0x1000, object::SectionedAddress::UndefSection}, /*Size=*/1, Rows, |
| 2129 | + /*StmtSequenceOffset=*/0x42); |
| 2130 | + EXPECT_TRUE(Found); |
| 2131 | + ASSERT_EQ(Rows.size(), 1u); |
| 2132 | + // The second sequence's first row is index 2 in the table. |
| 2133 | + EXPECT_EQ(Rows[0], 3u); |
| 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 | + } |
| 2150 | +} |
2038 | 2151 | } // end anonymous namespace
|
0 commit comments