From 684d6fdee208a1fa12e9cbe0a45f3c5b4b575ad7 Mon Sep 17 00:00:00 2001 From: James Henderson Date: Tue, 25 Feb 2020 16:07:16 +0000 Subject: [PATCH] [DebugInfo] Add check for .debug_line minimum_instruction_length of 0 If the minimum_instruction_length of a debug line program is 0, no address advancing via special opcodes, DW_LNS_const_add_pc, and DW_LNS_advance_pc can occur, since the minimum_instruction_length is used in a multiplication. This patch adds a warning reporting when this issue occurs. Reviewed by: probinson Differential Revision: https://reviews.llvm.org/D75189 --- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 8 +++++ .../DebugInfo/DWARF/DWARFDebugLineTest.cpp | 35 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index ff23f61..6638474 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -592,6 +592,14 @@ uint64_t DWARFDebugLine::ParsingState::advanceAddr(uint64_t OperationAdvance, ", which is unsupported. Assuming a value of 1 instead", LineTableOffset, OpcodeName.data(), OpcodeOffset, LineTable->Prologue.MaxOpsPerInst)); + if (ReportAdvanceAddrProblem && LineTable->Prologue.MinInstLength == 0) + ErrorHandler( + createStringError(errc::invalid_argument, + "line table program at offset 0x%8.8" PRIx64 + " contains a %s opcode at offset 0x%8.8" PRIx64 + ", but the prologue minimum_instruction_length value " + "is 0, which prevents any address advancing", + LineTableOffset, OpcodeName.data(), OpcodeOffset)); ReportAdvanceAddrProblem = false; uint64_t AddrOffset = OperationAdvance * LineTable->Prologue.MinInstLength; Row.Address.Address += AddrOffset; diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp index 5585a59..2ffad82 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -1001,6 +1001,41 @@ INSTANTIATE_TEST_CASE_P( Values(std::make_tuple(0, true), // Test zero value (error). std::make_tuple(14, false)), ); // Test non-zero value (no error). +struct BadMinInstLenFixture : TestWithParam>, + AdjustAddressFixtureBase { + void SetUp() override { + std::tie(MinInstLength, IsErrorExpected) = GetParam(); + } + + uint64_t editPrologue(LineTable <) override { + DWARFDebugLine::Prologue Prologue = LT.createBasicPrologue(); + Prologue.MinInstLength = MinInstLength; + 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 MinInstLength != 0 ? AdjustAddressFixtureBase::getAdjustedAddr( + Base, ConstIncr, SpecialIncr, AdvanceIncr) + : Base; + } + + uint8_t MinInstLength; +}; + +TEST_P(BadMinInstLenFixture, MinInstLengthProblemsReportedCorrectly) { + runTest(/*CheckAdvancePC=*/true, + "but the prologue minimum_instruction_length value is 0, which " + "prevents any address advancing"); +} + +INSTANTIATE_TEST_CASE_P( + BadMinInstLenParams, BadMinInstLenFixture, + Values(std::make_tuple(0, true), // Test zero value (error). + std::make_tuple(1, false)), ); // Test non-zero value (no error). + TEST_F(DebugLineBasicFixture, ParserParsesCorrectly) { if (!setupGenerator()) return; -- 2.7.4