diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -575,10 +575,23 @@ }; static AdvanceAddrProperties -getOperationAdvance(uint8_t Opcode, uint8_t OpcodeBase, uint8_t LineRange) { +getOperationAdvance(uint8_t Opcode, uint8_t OpcodeBase, uint8_t LineRange, + uint64_t OpcodeOffset, StringRef OpcodeName, + uint64_t TableOffset, bool &ReportBadLineRange, + function_ref ErrorHandler) { + if (ReportBadLineRange && LineRange == 0) + ErrorHandler(createStringError( + errc::not_supported, + "line table program at offset 0x%8.8" PRIx64 + " contains a %s opcode at offset 0x%8.8" PRIx64 + ", but the prologue line_range value is 0. The address and line will " + "not be adjusted", + TableOffset, OpcodeName.data(), OpcodeOffset)); + ReportBadLineRange = false; AdvanceAddrProperties Result; Result.AdjustedOpcode = Opcode - OpcodeBase; - Result.OperationAdvance = Result.AdjustedOpcode / LineRange; + Result.OperationAdvance = + LineRange != 0 ? Result.AdjustedOpcode / LineRange : 0; return Result; } @@ -652,6 +665,7 @@ ParsingState State(this); + bool ReportBadLineRange = true; bool ReportAdvanceAddrProblem = true; while (*OffsetPtr < EndOffset) { @@ -892,8 +906,10 @@ // than twice that range will it need to use both DW_LNS_advance_pc // and a special opcode, requiring three or more bytes. { - AdvanceAddrProperties AdvanceAddr = - getOperationAdvance(255, Prologue.OpcodeBase, Prologue.LineRange); + AdvanceAddrProperties AdvanceAddr = getOperationAdvance( + 255, Prologue.OpcodeBase, Prologue.LineRange, OpcodeOffset, + "DW_LNS_const_add_pc", DebugLineOffset, ReportBadLineRange, + RecoverableErrorHandler); uint64_t AddrOffset = advanceAddr(AdvanceAddr.OperationAdvance, Prologue, OpcodeOffset, "DW_LNS_const_add_pc", DebugLineOffset, @@ -994,12 +1010,17 @@ // line increment = line_base + (adjusted opcode % line_range) AdvanceAddrProperties AdvanceAddr = - getOperationAdvance(Opcode, Prologue.OpcodeBase, Prologue.LineRange); + getOperationAdvance(Opcode, Prologue.OpcodeBase, Prologue.LineRange, + OpcodeOffset, "special", DebugLineOffset, + ReportBadLineRange, RecoverableErrorHandler); uint64_t AddrOffset = advanceAddr( AdvanceAddr.OperationAdvance, Prologue, OpcodeOffset, "special", DebugLineOffset, ReportAdvanceAddrProblem, RecoverableErrorHandler); int32_t LineOffset = - Prologue.LineBase + (AdvanceAddr.AdjustedOpcode % Prologue.LineRange); + Prologue.LineRange != 0 + ? Prologue.LineBase + + (AdvanceAddr.AdjustedOpcode % Prologue.LineRange) + : 0; State.Row.Line += LineOffset; State.Row.Address.Address += AddrOffset; diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -954,6 +954,45 @@ std::make_tuple( 4, 2, true)), ); // Test one higher than permitted V4 (error). +struct LineRangeFixture : public TestWithParam>, + public AdjustAddressFixtureBase { + void SetUp() { std::tie(LineRange, IsErrorExpected) = GetParam(); } + + uint64_t editPrologue(LineTable <) override { + DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); + Prologue.LineRange = LineRange; + LT.setPrologue(Prologue); + return Prologue.TotalLength + Prologue.sizeofTotalLength(); + } + + uint64_t getAdjustedAddr(uint64_t Base, uint64_t ConstIncr, + uint64_t SpecialIncr, + uint64_t AdvanceIncr) override { + return LineRange != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( + Base, ConstIncr, SpecialIncr, AdvanceIncr) + : Base + AdvanceIncr; + } + + uint64_t getAdjustedLine(uint64_t Base, uint64_t Incr) override { + return LineRange != 0 + ? AdjustAddressFixtureBase::getAdjustedLine(Base, Incr) + : Base; + } + + uint8_t LineRange; +}; + +TEST_P(LineRangeFixture, LineRangeProblemsReportedCorrectly) { + runTest(/*CheckAdvancePC=*/false, + "but the prologue line_range value is 0. The address and line will " + "not be adjusted"); +} + +INSTANTIATE_TEST_CASE_P( + LineRangeParams, LineRangeFixture, + Values(std::make_tuple(0, true), // Test zero value (error). + std::make_tuple(14, false)), ); // Test non-zero value (no error). + TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { if (!setupGenerator()) return;