aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
diff options
context:
space:
mode:
authorDavid Stenberg <david.stenberg@ericsson.com>2023-07-12 12:14:46 +0200
committerDavid Stenberg <david.stenberg@ericsson.com>2023-07-12 13:46:29 +0200
commitfe6cddef2020c8e103cff8180540d4e2e9102c6d (patch)
treea9864b3a0783816f9957e8e20064288c19a99666 /llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
parent593797ab9bedca6e9b0b7a9ed0589cf76023ab00 (diff)
downloadllvm-fe6cddef2020c8e103cff8180540d4e2e9102c6d.zip
llvm-fe6cddef2020c8e103cff8180540d4e2e9102c6d.tar.gz
llvm-fe6cddef2020c8e103cff8180540d4e2e9102c6d.tar.bz2
[DWARF] Allow op-index in line number programs
This extends DWARFDebugLine to properly parse line number programs with maximum_operations_per_instruction > 1 for VLIW targets. No functions that use that parsed output to retrieve line information have been extended to support multiple op-indexes. This means that when retrieving information for an address with multiple op-indexes, e.g. when using llvm-addr2line, the penultimate row for that address will be used, which in most cases is the row for the second largest op-index. This will be addressed in further changes, but this patch at least allows us to correctly parse such line number programs, with a warning saying that the line number information may be incorrect (incomplete). Reviewed By: StephenTozer Differential Revision: https://reviews.llvm.org/D152536
Diffstat (limited to 'llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp')
-rw-r--r--llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp220
1 files changed, 192 insertions, 28 deletions
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
index 8711867..9635011 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp
@@ -1085,41 +1085,201 @@ struct AdjustAddressFixtureBase : public CommonFixture {
bool IsErrorExpected;
};
-struct MaxOpsPerInstFixture
- : TestWithParam<std::tuple<uint16_t, uint8_t, bool>>,
- AdjustAddressFixtureBase {
- void SetUp() override {
- std::tie(Version, MaxOpsPerInst, IsErrorExpected) = GetParam();
- }
-
- uint64_t editPrologue(LineTable &LT) override {
+struct OpIndexFixture : Test, CommonFixture {
+ void createPrologue(LineTable &LT, uint8_t MaxOpsPerInst,
+ uint8_t MinInstLength) {
DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue();
Prologue.MaxOpsPerInst = MaxOpsPerInst;
+ Prologue.MinInstLength = MinInstLength;
LT.setPrologue(Prologue);
- return Prologue.TotalLength + Prologue.sizeofTotalLength();
}
-
- uint8_t MaxOpsPerInst;
};
#ifdef _AIX
-TEST_P(MaxOpsPerInstFixture, DISABLED_MaxOpsPerInstProblemsReportedCorrectly) {
+TEST_F(OpIndexFixture, DISABLED_OpIndexAdvance) {
#else
-TEST_P(MaxOpsPerInstFixture, MaxOpsPerInstProblemsReportedCorrectly) {
+TEST_F(OpIndexFixture, OpIndexAdvance) {
#endif
- runTest(/*CheckAdvancePC=*/true,
- "but the prologue maximum_operations_per_instruction value is " +
- Twine(unsigned(MaxOpsPerInst)) +
- ", which is unsupported. Assuming a value of 1 instead");
+ if (!setupGenerator(4, 4))
+ GTEST_SKIP();
+
+ uint8_t MaxOpsPerInst = 13;
+ uint8_t MinInstLength = 4;
+
+ LineTable &LT = Gen->addLineTable();
+
+ // Row 0-2: Different locations for one bundle set up using special opcodes.
+ LT.addExtendedOpcode(5, DW_LNE_set_address, {{0x20, LineTable::Long}});
+ LT.addByte(0x13); // Special opcode, +1 line.
+ LT.addByte(0x23); // Special opcode, +3 line, +1 op-index.
+ LT.addByte(0x3a); // Special opcode, -2 line, +3 op-index.
+
+ // Row 3: New bundle, set up using DW_LNS_advance pc.
+ // Operation advance 0x84, which gives +40 addr, +2 op-index
+ LT.addStandardOpcode(DW_LNS_advance_line, {{100, LineTable::SLEB}});
+ LT.addStandardOpcode(DW_LNS_advance_pc, {{0x84, LineTable::ULEB}});
+ LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.
+
+ // Row 4: New bundle, set up using a single special opcode.
+ LT.addByte(0x71); // Special opcode, +4 addr, -3 line, -6 op-index.
+
+ // Row 5: New bundle, set up using using DW_LNS_const_add_pc.
+ // Corresponds to advancing address and op-index using special opcode 255,
+ // which gives +4 addr, +4 op-index.
+ LT.addStandardOpcode(DW_LNS_advance_line, {{10, LineTable::SLEB}});
+ LT.addStandardOpcode(DW_LNS_const_add_pc, {});
+ LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.
+
+ // Row 6: End sequence to have the input well-formed.
+ LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
+
+ createPrologue(LT, MaxOpsPerInst, MinInstLength);
+
+ generate();
+
+ auto VerifyRow = [](const DWARFDebugLine::Row &Row, uint64_t Address,
+ uint8_t OpIndex, uint32_t Line) {
+ EXPECT_EQ(Row.Address.Address, Address);
+ EXPECT_EQ(Row.OpIndex, OpIndex);
+ EXPECT_EQ(Row.Line, Line);
+ };
+
+ auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,
+ RecordRecoverable);
+ EXPECT_THAT_ERROR(
+ std::move(Recoverable),
+ FailedWithMessage("line table program at offset 0x00000000 contains a "
+ "special opcode at offset 0x00000035, but the prologue "
+ "maximum_operations_per_instruction value is 13, which "
+ "is experimentally supported, so line number "
+ "information may be incorrect"));
+ EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());
+ ASSERT_THAT_EXPECTED(Table, Succeeded());
+
+ ASSERT_EQ((*Table)->Rows.size(), 7u);
+
+ VerifyRow((*Table)->Rows[0], 0x20, 0, 2);
+ VerifyRow((*Table)->Rows[1], 0x20, 1, 5);
+ VerifyRow((*Table)->Rows[2], 0x20, 4, 3);
+ VerifyRow((*Table)->Rows[3], 0x48, 6, 103);
+ VerifyRow((*Table)->Rows[4], 0x4c, 0, 100);
+ VerifyRow((*Table)->Rows[5], 0x50, 4, 110);
}
-INSTANTIATE_TEST_SUITE_P(
- MaxOpsPerInstParams, MaxOpsPerInstFixture,
- Values(std::make_tuple(3, 0, false), // Test for version < 4 (no error).
- std::make_tuple(4, 0, true), // Test zero value for V4 (error).
- std::make_tuple(4, 1, false), // Test good value for V4 (no error).
- std::make_tuple(
- 4, 2, true))); // Test one higher than permitted V4 (error).
+#ifdef _AIX
+TEST_F(OpIndexFixture, DISABLED_OpIndexReset) {
+#else
+TEST_F(OpIndexFixture, OpIndexReset) {
+#endif
+ if (!setupGenerator(4, 4))
+ GTEST_SKIP();
+
+ uint8_t MaxOpsPerInst = 13;
+ uint8_t MinInstLength = 4;
+
+ LineTable &LT = Gen->addLineTable();
+
+ // Row 0: Just set op-index to some value > 0.
+ LT.addExtendedOpcode(5, DW_LNE_set_address, {{0, LineTable::Long}});
+ LT.addByte(0x20); // Special opcode, +1 op-index
+
+ // Row 1: DW_LNE_fixed_advance_pc should set op-index to 0.
+ LT.addStandardOpcode(DW_LNS_fixed_advance_pc, {{10, LineTable::Half}});
+ LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.
+
+ // Row 2: Just set op-index to some value > 0.
+ LT.addByte(0x66); // Special opcode, +6 op-index
+
+ // Row 3: DW_LNE_set_address should set op-index to 0.
+ LT.addExtendedOpcode(5, DW_LNE_set_address, {{20, LineTable::Long}});
+ LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.
+
+ // Row 4: Just set op-index to some value > 0.
+ LT.addByte(0xba); // Special opcode, +12 op-index
+
+ // Row 5: End sequence (op-index unchanged for this row)...
+ LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
+
+ // Row 6: ... but shall be reset after the DW_LNE_end_sequence row.
+ LT.addStandardOpcode(DW_LNS_copy, {}); // Create new row.
+
+ // Row 7: End sequence to have the input well-formed.
+ LT.addExtendedOpcode(1, DW_LNE_end_sequence, {});
+
+ createPrologue(LT, MaxOpsPerInst, MinInstLength);
+
+ generate();
+
+ auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,
+ RecordRecoverable);
+ EXPECT_THAT_ERROR(
+ std::move(Recoverable),
+ FailedWithMessage("line table program at offset 0x00000000 contains a "
+ "special opcode at offset 0x00000035, but the prologue "
+ "maximum_operations_per_instruction value is 13, which "
+ "is experimentally supported, so line number "
+ "information may be incorrect"));
+ EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());
+ ASSERT_THAT_EXPECTED(Table, Succeeded());
+
+ ASSERT_EQ((*Table)->Rows.size(), 8u);
+ EXPECT_EQ((*Table)->Rows[0].OpIndex, 1u);
+ EXPECT_EQ((*Table)->Rows[1].OpIndex, 0u); // DW_LNS_fixed_advance_pc.
+ EXPECT_EQ((*Table)->Rows[2].OpIndex, 6u);
+ EXPECT_EQ((*Table)->Rows[3].OpIndex, 0u); // DW_LNE_set_address.
+ EXPECT_EQ((*Table)->Rows[4].OpIndex, 12u);
+ EXPECT_EQ((*Table)->Rows[5].OpIndex, 12u);
+ EXPECT_EQ((*Table)->Rows[6].OpIndex, 0u); // row after DW_LNE_end_sequence.
+ EXPECT_EQ((*Table)->Rows[7].OpIndex, 0u);
+}
+
+#ifdef _AIX
+TEST_F(OpIndexFixture, DISABLED_MaxOpsZeroDwarf3) {
+#else
+TEST_F(OpIndexFixture, MaxOpsZeroDwarf3) {
+#endif
+ if (!setupGenerator(3, 4))
+ GTEST_SKIP();
+
+ LineTable &LT = Gen->addLineTable();
+ LT.addStandardOpcode(DW_LNS_const_add_pc, {}); // Just some opcode to advance.
+ LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); //
+ createPrologue(LT, /*MaxOpsPerInst=*/0, /*MinInstLength=*/1);
+ generate();
+
+ auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,
+ RecordRecoverable);
+ EXPECT_THAT_ERROR(std::move(Recoverable), Succeeded());
+ EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());
+ ASSERT_THAT_EXPECTED(Table, Succeeded());
+}
+
+#ifdef _AIX
+TEST_F(OpIndexFixture, DISABLED_MaxOpsZeroDwarf4) {
+#else
+TEST_F(OpIndexFixture, MaxOpsZeroDwarf4) {
+#endif
+ if (!setupGenerator(4, 4))
+ GTEST_SKIP();
+
+ LineTable &LT = Gen->addLineTable();
+ LT.addStandardOpcode(DW_LNS_const_add_pc, {}); // Just some opcode to advance.
+ LT.addExtendedOpcode(1, DW_LNE_end_sequence, {}); //
+ createPrologue(LT, /*MaxOpsPerInst=*/0, /*MinInstLength=*/1);
+ generate();
+
+ auto Table = Line.getOrParseLineTable(LineData, 0, *Context, nullptr,
+ RecordRecoverable);
+ EXPECT_THAT_ERROR(
+ std::move(Recoverable),
+ FailedWithMessage(
+ "line table program at offset 0x00000000 contains a "
+ "DW_LNS_const_add_pc opcode at offset 0x0000002e, but "
+ "the prologue maximum_operations_per_instruction value "
+ "is 0, which is invalid. Assuming a value of 1 instead"));
+ EXPECT_THAT_ERROR(std::move(Unrecoverable), Succeeded());
+ ASSERT_THAT_EXPECTED(Table, Succeeded());
+}
struct LineRangeFixture : TestWithParam<std::tuple<uint8_t, bool>>,
AdjustAddressFixtureBase {
@@ -1572,22 +1732,26 @@ TEST_F(DebugLineBasicFixture, VerboseOutput) {
EXPECT_EQ(NextLine(), "0x00000059: 01 DW_LNS_copy");
EXPECT_EQ(NextLine(), " 0x0123456789abcdef 1 0 1 "
"0 127 0 is_stmt");
- EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (11)");
+ EXPECT_EQ(NextLine(), "0x0000005a: 02 DW_LNS_advance_pc (addr += 11, "
+ "op-index += 0)");
EXPECT_EQ(NextLine(), "0x0000005c: 03 DW_LNS_advance_line (23)");
EXPECT_EQ(NextLine(), "0x0000005e: 04 DW_LNS_set_file (33)");
EXPECT_EQ(NextLine(), "0x00000060: 05 DW_LNS_set_column (44)");
EXPECT_EQ(NextLine(), "0x00000062: 06 DW_LNS_negate_stmt");
EXPECT_EQ(NextLine(), "0x00000063: 07 DW_LNS_set_basic_block");
EXPECT_EQ(NextLine(),
- "0x00000064: 08 DW_LNS_const_add_pc (0x0000000000000011)");
- EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (0x0037)");
+ "0x00000064: 08 DW_LNS_const_add_pc (addr += 0x0000000000000011, "
+ "op-index += 0)");
+ EXPECT_EQ(NextLine(), "0x00000065: 09 DW_LNS_fixed_advance_pc (addr += 0x0037"
+ ", op-index = 0)");
EXPECT_EQ(NextLine(), "0x00000068: 0a DW_LNS_set_prologue_end");
EXPECT_EQ(NextLine(), "0x00000069: 0b DW_LNS_set_epilogue_begin");
EXPECT_EQ(NextLine(), "0x0000006a: 0c DW_LNS_set_isa (66)");
EXPECT_EQ(NextLine(), "0x0000006c: 0d Unrecognized standard opcode "
"(operands: 0x0000000000000001, 0x0123456789abcdef)");
EXPECT_EQ(NextLine(), "0x00000077: 0e Unrecognized standard opcode");
- EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3");
+ EXPECT_EQ(NextLine(), "0x00000078: ff address += 17, line += -3, "
+ "op-index += 0");
EXPECT_EQ(NextLine(),
" 0x0123456789abce53 20 44 33 66 "
" 0 0 basic_block prologue_end epilogue_begin");